11from __future__ import absolute_import
22
33import os
4+ import re
5+ import itertools
46from datetime import datetime
57
68import smartdispatch
79from smartdispatch import utils
10+ from smartdispatch .argument import EnumerationArgument , RangeArgument
811
912UID_TAG = "{UID}"
1013
@@ -98,48 +101,29 @@ def get_commands_from_file(fileobj):
98101
99102
100103def get_commands_from_arguments (arguments ):
101- unfolded_commands = [arguments ]
102- unfolded_commands_stard_idx = [0 ]
103-
104- while True :
105- new_unfolded_commands = []
106- new_unfolded_commands_stard_idx = []
107-
108- for idx in range (len (unfolded_commands )):
109- start_bracket_idx = unfolded_commands [idx ].find ("[" , unfolded_commands_stard_idx [idx ])
110-
111- if start_bracket_idx == - 1 :
112- new_unfolded_commands_stard_idx = [- 1 ]
113- break
114-
115- while unfolded_commands [idx ][start_bracket_idx + 1 ] == "[" :
116- start_bracket_idx += 1
117-
118- stop_bracket_idx = unfolded_commands [idx ].find ("]" , start_bracket_idx )
119-
120- for argument in unfolded_commands [idx ][start_bracket_idx + 1 :stop_bracket_idx ].split (" " ):
121- new_unfolded_commands_stard_idx += [start_bracket_idx + len (argument )]
122- new_unfolded_commands += [unfolded_commands [idx ][0 :start_bracket_idx ] + argument + unfolded_commands [idx ][stop_bracket_idx + 1 :]]
123-
124- if - 1 in new_unfolded_commands_stard_idx :
125- break
126-
127- unfolded_commands = new_unfolded_commands
128- unfolded_commands_stard_idx = new_unfolded_commands_stard_idx
129-
130- return unfolded_commands
104+ ''' Obtains commands from the product of every unfolded arguments.
105+ Parameters
106+ ----------
107+ arguments : list of list of str
108+ list of unfolded arguments
109+ Returns
110+ -------
111+ commands : list of str
112+ commands resulting from the product of every unfolded arguments
113+ '''
114+ return ["" .join (argvalues ) for argvalues in itertools .product (* arguments )]
131115
132116
133- def unfold_argument ( argument ):
134- ''' Unfolds a folded argument into a list of unfolded arguments.
117+ def unfold_arguments ( arguments ):
118+ ''' Unfolds folded arguments into a list of unfolded arguments.
135119
136- An argument can be folded e.g. a list of unfolded arguments separated by spaces .
120+ An argument can be folded e.g. a list of unfolded arguments separated by commas .
137121 An unfolded argument unfolds to itself.
138122
139123 Parameters
140124 ----------
141- argument : str
142- argument to unfold
125+ arguments : list of str
126+ arguments to unfold
143127
144128 Returns
145129 -------
@@ -148,11 +132,34 @@ def unfold_argument(argument):
148132
149133 Complex arguments
150134 -----------------
151- *list (space)*: "item1 item2 ... itemN"
135+ *enumeration*: "[item1,item2,...,itemN]"
136+ *range*: "[start:end]" or "[start:end:step]"
152137 '''
138+ text = utils .escape (" " .join (arguments ))
139+
140+ # Order matter, if some regex is more greedy than another, the it should go after
141+ arguments = [EnumerationArgument (), RangeArgument ()]
142+
143+ # Build the master regex with all argument's regex
144+ regex = "(" + "|" .join (["(?P<{0}>{1})" .format (arg .name , arg .regex ) for arg in arguments ]) + ")"
145+
146+ pos = 0
147+ unfolded_arguments = []
148+ for match in re .finditer (regex , text ):
149+ # Add already unfolded argument
150+ unfolded_arguments .append ([text [pos :match .start ()]])
151+
152+ # Unfold argument
153+ groupdict = match .groupdict ()
154+ for argument in arguments :
155+ if groupdict [argument .name ] is not None :
156+ unfolded_arguments .append (argument .unfold (groupdict [argument .name ]))
157+
158+ pos = match .end ()
153159
154- # Suppose `argument`is a space separated list
155- return argument .split (" " )
160+ unfolded_arguments .append ([text [pos :]]) # Add remaining unfolded arguments
161+ unfolded_arguments = [map (utils .hex2str , argvalues ) for argvalues in unfolded_arguments ]
162+ return unfolded_arguments
156163
157164
158165def replace_uid_tag (commands ):
0 commit comments