Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(152)

Side by Side Diff: vpython/python/python.go

Issue 2702873002: vpython: Add primary execution package. (Closed)
Patch Set: more windows signals Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « vpython/python/interpreter.go ('k') | vpython/python/python_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2017 The LUCI Authors. All rights reserved. 1 // Copyright 2017 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0 2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file. 3 // that can be found in the LICENSE file.
4 4
5 package python 5 package python
6 6
7 import ( 7 import (
8 "fmt"
9 "strings" 8 "strings"
10 "unicode/utf8" 9 "unicode/utf8"
11 10
12 "github.com/luci/luci-go/common/errors" 11 "github.com/luci/luci-go/common/errors"
13 ) 12 )
14 13
15 // Error is a Python error return code. 14 // Target describes a Python invocation target.
16 type Error int
17
18 func (err Error) Error() string {
19 » return fmt.Sprintf("python interpreter returned non-zero error: %d", err )
20 }
21
22 // TargetType is an enumeration of possible Python invocation targets.
23 // 15 //
24 // Targets are identified by parsing a Python command-line using 16 // Targets are identified by parsing a Python command-line using
25 // ParseCommandLine. 17 // ParseCommandLine.
26 type TargetType int 18 //
19 // A Target is identified through type assertion, and will be one of:
20 //
21 //» - NoTarget
22 //» - ScriptTarget
23 //» - CommandTarget
24 //» - ModuleTarget
25 type Target interface {
26 » // implementsTarget is an internal method used to constrain Target
27 » // implementations to internal packages.
28 » implementsTarget()
29 }
27 30
28 const ( 31 // NoTarget is a Target implementation indicating no Python target (i.e.,
29 » // TargetNone means no Python target (i.e., interactive). 32 // interactive).
30 » TargetNone TargetType = iota 33 type NoTarget struct{}
31 » // TargetScript is a Python executable script target. 34
32 » TargetScript 35 func (st NoTarget) implementsTarget() {}
33 » // TargetCommand runs a command-line string (-c ...). 36
34 » TargetCommand 37 // ScriptTarget is a Python executable script target.
35 » // TargetModule runs a Python module (-m ...). 38 type ScriptTarget struct {
36 » TargetModule 39 » // Path is the path to the script that is being invoked.
37 ) 40 » //
41 » // This may be "-", indicating that the script is being read from STDIN.
42 » Path string
43 }
44
45 func (st ScriptTarget) implementsTarget() {}
46
47 // CommandTarget is a Target implementation for a command-line string
48 // (-c ...).
49 type CommandTarget struct {
50 » // Command is the command contents.
51 » Command string
52 }
53
54 func (st CommandTarget) implementsTarget() {}
55
56 // ModuleTarget is a Target implementating indicating a Python module (-m ...).
57 type ModuleTarget struct {
58 » // Module is the name of the target module.
59 » Module string
60 }
61
62 func (st ModuleTarget) implementsTarget() {}
38 63
39 // CommandLine is a parsed Python command-line. 64 // CommandLine is a parsed Python command-line.
40 // 65 //
41 // CommandLine can be parsed from arguments via ParseCommandLine. 66 // CommandLine can be parsed from arguments via ParseCommandLine.
42 type CommandLine struct { 67 type CommandLine struct {
43 » // Type is the Python target type. 68 » // Target is the Python target type.
44 » Type TargetType 69 » Target Target
45 » // Value is the execution value for Type.
46 » Value string
47 70
48 // Flags are flags to the Python interpreter. 71 // Flags are flags to the Python interpreter.
49 Flags []string 72 Flags []string
50 // Args are arguments passed to the Python script. 73 // Args are arguments passed to the Python script.
51 Args []string 74 Args []string
52 } 75 }
53 76
54 // ParseCommandLine parses Python command-line arguments and returns a 77 // ParseCommandLine parses Python command-line arguments and returns a
55 // structured representation. 78 // structured representation.
56 func ParseCommandLine(args []string) (cmd CommandLine, err error) { 79 func ParseCommandLine(args []string) (cmd CommandLine, err error) {
57 flags := 0 80 flags := 0
58 i := 0 81 i := 0
59 » for i < len(args) && cmd.Type == TargetNone { 82 » for i < len(args) && cmd.Target == nil {
60 arg := args[i] 83 arg := args[i]
61 i++ 84 i++
62 85
63 flag, has := trimPrefix(arg, "-") 86 flag, has := trimPrefix(arg, "-")
64 if !has { 87 if !has {
65 // Non-flag argument, so path to script. 88 // Non-flag argument, so path to script.
66 » » » cmd.Type = TargetScript 89 » » » cmd.Target = ScriptTarget{
67 » » » cmd.Value = flag 90 » » » » Path: flag,
91 » » » }
68 break 92 break
69 } 93 }
70 94
71 // -<flag> 95 // -<flag>
72 if len(flag) == 0 { 96 if len(flag) == 0 {
73 // "-" instructs Python to load the script from STDIN. 97 // "-" instructs Python to load the script from STDIN.
74 » » » cmd.Type, cmd.Value = TargetScript, "-" 98 » » » cmd.Target = ScriptTarget{
99 » » » » Path: "-",
100 » » » }
75 break 101 break
76 } 102 }
77 103
78 » » // Extract the flag value. -f<lag> 104 » » // Extract the flag Target. -f<lag>
79 r, l := utf8.DecodeRuneInString(flag) 105 r, l := utf8.DecodeRuneInString(flag)
80 if r == utf8.RuneError { 106 if r == utf8.RuneError {
81 err = errors.Reason("invalid rune in flag #%(index)d").D ("index", i).Err() 107 err = errors.Reason("invalid rune in flag #%(index)d").D ("index", i).Err()
82 return 108 return
83 } 109 }
84 110
85 // Is this a combined flag/value (e.g., -c'paoskdpo') ? 111 // Is this a combined flag/value (e.g., -c'paoskdpo') ?
86 flag = flag[l:] 112 flag = flag[l:]
87 » » twoVarType := func() error { 113 » » twoVarType := func() (string, error) {
88 if len(flag) > 0 { 114 if len(flag) > 0 {
89 » » » » cmd.Value = flag 115 » » » » return flag, nil
90 » » » » return nil
91 } 116 }
92 117
93 if i >= len(args) { 118 if i >= len(args) {
94 » » » » return errors.Reason("two-value flag -%(flag)c m issing second value at %(index)d"). 119 » » » » return "", errors.Reason("two-value flag -%(flag )c missing second value at %(index)d").
95 D("flag", r). 120 D("flag", r).
96 D("index", i). 121 D("index", i).
97 Err() 122 Err()
98 } 123 }
99 » » » cmd.Value = args[i] 124
125 » » » value := args[i]
100 i++ 126 i++
101 » » » return nil 127 » » » return value, nil
102 } 128 }
103 129
104 switch r { 130 switch r {
105 // Two-variable execution flags. 131 // Two-variable execution flags.
106 case 'c': 132 case 'c':
107 » » » cmd.Type = TargetCommand 133 » » » var target CommandTarget
108 » » » if err = twoVarType(); err != nil { 134 » » » if target.Command, err = twoVarType(); err != nil {
109 return 135 return
110 } 136 }
137 cmd.Target = target
111 138
112 case 'm': 139 case 'm':
113 » » » cmd.Type = TargetModule 140 » » » var target ModuleTarget
114 » » » if err = twoVarType(); err != nil { 141 » » » if target.Module, err = twoVarType(); err != nil {
115 return 142 return
116 } 143 }
144 cmd.Target = target
117 145
118 case 'Q', 'W', 'X': 146 case 'Q', 'W', 'X':
119 // Random two-argument Python flags. 147 // Random two-argument Python flags.
120 if len(flag) == 0 { 148 if len(flag) == 0 {
121 flags++ 149 flags++
122 i++ 150 i++
123 } 151 }
124 fallthrough 152 fallthrough
125 153
126 default: 154 default:
127 // One-argument Python flags. 155 // One-argument Python flags.
128 flags++ 156 flags++
129 } 157 }
130 } 158 }
131 159
132 if i > len(args) { 160 if i > len(args) {
133 err = errors.New("truncated two-variable argument") 161 err = errors.New("truncated two-variable argument")
134 return 162 return
135 } 163 }
136 164
165 // If no target was specified, use NoTarget.
166 if cmd.Target == nil {
167 cmd.Target = NoTarget{}
168 }
169
137 cmd.Flags = args[:flags] 170 cmd.Flags = args[:flags]
138 cmd.Args = args[i:] 171 cmd.Args = args[i:]
139 return 172 return
140 } 173 }
141 174
142 func trimPrefix(v, pfx string) (string, bool) { 175 func trimPrefix(v, pfx string) (string, bool) {
143 if strings.HasPrefix(v, pfx) { 176 if strings.HasPrefix(v, pfx) {
144 return v[len(pfx):], true 177 return v[len(pfx):], true
145 } 178 }
146 return v, false 179 return v, false
147 } 180 }
OLDNEW
« no previous file with comments | « vpython/python/interpreter.go ('k') | vpython/python/python_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698