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

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

Issue 2701073002: vpython: Add Python interpreter handling package. (Closed)
Patch Set: Created 3 years, 10 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
OLDNEW
(Empty)
1 // Copyright 2017 The LUCI Authors. All rights reserved.
2 // Use of this source code is governed under the Apache License, Version 2.0
3 // that can be found in the LICENSE file.
4
5 package python
6
7 import (
8 "fmt"
9 "strings"
10 "unicode/utf8"
11
12 "github.com/luci/luci-go/common/errors"
13 )
14
15 // Error is a Python error return code.
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 //
24 // Targets are identified by parsing a Python command-line using
25 // ParseCommandLine.
26 type TargetType int
27
28 const (
29 // TargetNone means no Python target (i.e., interactive).
30 TargetNone TargetType = iota
31 // TargetScript is a Python executable script target.
32 TargetScript
33 // TargetCommand runs a command-line string (-c ...).
34 TargetCommand
35 // TargetModule runs a Python module (-m ...).
36 TargetModule
37 )
38
39 // CommandLine is a parsed Python command-line.
40 //
41 // CommandLine can be parsed from arguments via ParseCommandLine.
42 type CommandLine struct {
43 // Type is the Python target type.
44 Type TargetType
45 // Value is the execution value for Type.
46 Value string
47
48 // Flags are flags to the Python interpreter.
49 Flags []string
50 // Args are arguments passed to the Python script.
51 Args []string
52 }
53
54 // ParseCommandLine parses Python command-line arguments and returns a
55 // structured representation.
56 func ParseCommandLine(args []string) (cmd CommandLine, err error) {
57 flags := 0
58 i := 0
59 for i < len(args) && cmd.Type == TargetNone {
60 arg := args[i]
61 i++
62
63 flag, has := trimPrefix(arg, "-")
64 if !has {
65 // Non-flag argument, so path to script.
66 cmd.Type = TargetScript
67 cmd.Value = flag
68 break
69 }
70
71 // -<flag>
72 if len(flag) == 0 {
73 // "-" instructs Python to load the script from STDIN.
74 cmd.Type, cmd.Value = TargetScript, "-"
75 break
76 }
77
78 // Extract the flag value. -f<lag>
79 r, l := utf8.DecodeRuneInString(flag)
80 if r == utf8.RuneError {
81 err = errors.Reason("invalid rune in flag #%(index)d").D ("index", i).Err()
82 return
83 }
84
85 // Is this a combined flag/value (e.g., -c'paoskdpo') ?
86 flag = flag[l:]
87 twoVarType := func() error {
88 if len(flag) > 0 {
89 cmd.Value = flag
90 return nil
91 }
92
93 if i >= len(args) {
94 return errors.Reason("two-value flag -%(flag)c m issing second value at %(index)d").
95 D("flag", r).
96 D("index", i).
97 Err()
98 }
99 cmd.Value = args[i]
100 i++
101 return nil
102 }
103
104 switch r {
105 // Two-variable execution flags.
106 case 'c':
107 cmd.Type = TargetCommand
108 if err = twoVarType(); err != nil {
109 return
110 }
111
112 case 'm':
113 cmd.Type = TargetModule
114 if err = twoVarType(); err != nil {
115 return
116 }
117
118 case 'Q', 'W', 'X':
119 // Random two-argument Python flags.
120 if len(flag) == 0 {
121 flags++
122 i++
123 }
124 fallthrough
125
126 default:
127 // One-argument Python flags.
128 flags++
129 }
130 }
131
132 if i > len(args) {
133 err = errors.New("truncated two-variable argument")
134 return
135 }
136
137 cmd.Flags = args[:flags]
138 cmd.Args = args[i:]
139 return
140 }
141
142 func trimPrefix(v, pfx string) (string, bool) {
143 if strings.HasPrefix(v, pfx) {
144 return v[len(pfx):], true
145 }
146 return v, false
147 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698