annotate treepkg/cmdexpand.py @ 575:87a0be76b5b7

Revert ugly hack for the command from config file problem
author Bjoern Ricks <bricks@intevation.de>
date Sat, 03 Sep 2011 10:55:32 +0000
parents 19d10022b2de
children
rev   line source
44
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
1 # Copyright (C) 2007 by Intevation GmbH
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
2 # Authors:
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
3 # Bernhard Herzog <bh@intevation.de>
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
4 #
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
5 # This program is free software under the GPL (>=v2)
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
6 # Read the file COPYING coming with the software for details.
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
7
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
8 """Shell like string splitting and expansion"""
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
9
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
10 import re
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
11 import shlex
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
12
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
13
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
14 # helper for the other regular expression matching a python identifier
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
15 match_identifier = "[_a-zA-Z][_a-zA-Z0-9]*"
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
16
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
17 # regular expression to use for word expansion matching a dollar
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
18 # followed by exactly one of these:
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
19 # a) another dollar sign or the at-sign (for quoting of these characters)
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
20 # b) a python identifier
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
21 # c) a python identifier enclosed in braces
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
22 # d) something else which indicates invalid use of the dollar sign
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
23 rx_word_expansion = re.compile(r"\$((?P<delim>[$@])"
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
24 r"|(?P<named>%(identifier)s)"
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
25 r"|\{(?P<braced>%(identifier)s)\}"
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
26 r"|(?P<invalid>))"
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
27 % dict(identifier=match_identifier))
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
28
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
29 # regular expression matching an entire word that has to be list
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
30 # expanded. The regex matches if the word starts with an at-sign. The
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
31 # part of the word that followes the at-sign either matches an
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
32 # identifier with the named group "named" or anything else which
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
33 # indicates invalid use the at-sign.
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
34 rx_list_expansion = re.compile(r"^@((?P<named>%(identifier)s)|(?P<invalid>.+))$"
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
35 % dict(identifier=match_identifier))
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
36
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
37 # match an unquoted at-sign.
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
38 rx_unquoted_at = re.compile("[^$]@")
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
39
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
40 def expandword(word, mapping):
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
41 def replacment(match):
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
42 key = match.group("named") or match.group("braced")
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
43 if key:
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
44 return str(mapping[key])
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
45
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
46 delim = match.group("delim")
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
47 if delim:
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
48 return delim
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
49
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
50 # otherwise invalid has matched and we raise a value error
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
51 assert match.group("invalid") != None
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
52 raise ValueError
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
53
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
54 return rx_word_expansion.sub(replacment, word)
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
55
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
56 def cmdexpand(string, **kw):
56
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
57 """Split the string into 'words' and expand variable references.
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
58
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
59 The string is first split into words with shlex.split. Each of the
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
60 words is then subjected to either word expansion or list expansion.
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
61 Word expansion is very similar to what the Template class in Python's
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
62 string module provides:
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
63
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
64 '$$' is expanded to '$'
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
65
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
66 '$@' is expanded to '@'
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
67
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
68 '$identifier' is expanded to the value of the variable given by
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
69 identifier. The identifier has the same syntax as a normal Python
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
70 identifier. The identifier stops at the first non-identifier
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
71 character. The value is converted to a string with str.
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
72
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
73 '${identifier}' is treated like '$identifier' and provides a way to
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
74 delimit the identifier in cases where the identifier is followed by
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
75 characters that would otherwise be interpreted as part of the
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
76 identifier.
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
77
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
78 A word will remain a single word after the expansion even if the
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
79 expanded string would be treated as multiple words by shlex.
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
80
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
81 A list expansion is applied to words that consist of a '@' followed by
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
82 an identifier. Nothing else must be in the word. The variable the
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
83 identifier refers to must be a sequence and the word will be replaced by
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
84 the sequence with each element of the sequence converted to a string
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
85 with str.
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
86
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
87 The variables known to the function are the keyword arguments.
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
88
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
89 Examples:
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
90
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
91 >>> from cmdexpand import cmdexpand
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
92 >>> cmdexpand("ssh $user$@$host", user="john", host="python")
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
93 ['ssh', 'john@python']
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
94
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
95 >>> cmdexpand("scp @files $user$@$host:$remotedir", user="john",
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
96 ... host="python", files=["main.py", "cmdexpand.py"],
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
97 ... remotedir="/home/john/files")
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
98 ['scp', 'main.py', 'cmdexpand.py', 'john@python:/home/john/files']
83e1aa122ad0 upgrade cmdexpand to newer version
Bernhard Herzog <bh@intevation.de>
parents: 44
diff changeset
99 """
44
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
100 words = shlex.split(string)
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
101 for index, word in reversed(list(enumerate(words))):
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
102 match = rx_unquoted_at.search(word)
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
103 if match:
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
104 raise ValueError("%r contains an unquoted '@'" % word)
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
105 match = rx_list_expansion.match(word)
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
106 if match:
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
107 key = match.group("named")
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
108 if key:
574
19d10022b2de Lists must not be converted to lists
Bjoern Ricks <bricks@intevation.de>
parents: 573
diff changeset
109 words[index:index + 1] = (str(item) for item in kw[key])
44
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
110 else:
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
111 assert match.group("invalid") != None
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
112 raise ValueError("In %r the characters after the '@'"
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
113 " do not match a python identifier" % word)
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
114 else:
575
87a0be76b5b7 Revert ugly hack for the command from config file problem
Bjoern Ricks <bricks@intevation.de>
parents: 574
diff changeset
115 words[index] = expandword(word, kw)
44
a2ce575ce82b add cmdexpand function and tests
Bernhard Herzog <bh@intevation.de>
parents:
diff changeset
116 return words
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)