Skip to content

Commit 2dfeb7d

Browse files
committedMay 18, 2020
STCC-251 Jython Libraries
Updated the libraries that are used in jython. docopt from 0.6.1 to 0.6.2 progressbar from 2.3 to 2.5
1 parent 3edfa42 commit 2dfeb7d

File tree

5 files changed

+144
-147
lines changed

5 files changed

+144
-147
lines changed
 

‎src/docopt.py

+118-120
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212

1313
__all__ = ['docopt']
14-
__version__ = '0.6.1'
14+
__version__ = '0.6.2'
1515

1616

1717
class DocoptLanguageError(Exception):
@@ -47,18 +47,18 @@ def fix_identities(self, uniq=None):
4747
if not hasattr(self, 'children'):
4848
return self
4949
uniq = list(set(self.flat())) if uniq is None else uniq
50-
for i, child in enumerate(self.children):
51-
if not hasattr(child, 'children'):
52-
assert child in uniq
53-
self.children[i] = uniq[uniq.index(child)]
50+
for i, c in enumerate(self.children):
51+
if not hasattr(c, 'children'):
52+
assert c in uniq
53+
self.children[i] = uniq[uniq.index(c)]
5454
else:
55-
child.fix_identities(uniq)
55+
c.fix_identities(uniq)
5656

5757
def fix_repeating_arguments(self):
5858
"""Fix elements that should accumulate/increment values."""
59-
either = [list(child.children) for child in transform(self).children]
59+
either = [list(c.children) for c in self.either.children]
6060
for case in either:
61-
for e in [child for child in case if case.count(child) > 1]:
61+
for e in [c for c in case if case.count(c) > 1]:
6262
if type(e) is Argument or type(e) is Option and e.argcount:
6363
if e.value is None:
6464
e.value = []
@@ -68,40 +68,47 @@ def fix_repeating_arguments(self):
6868
e.value = 0
6969
return self
7070

71-
72-
def transform(pattern):
73-
"""Expand pattern into an (almost) equivalent one, but with single Either.
74-
75-
Example: ((-a | -b) (-c | -d)) => (-a -c | -a -d | -b -c | -b -d)
76-
Quirks: [-a] => (-a), (-a...) => (-a -a)
77-
78-
"""
79-
result = []
80-
groups = [[pattern]]
81-
while groups:
82-
children = groups.pop(0)
83-
parents = [Required, Optional, OptionsShortcut, Either, OneOrMore]
84-
if any(t in map(type, children) for t in parents):
85-
child = [c for c in children if type(c) in parents][0]
86-
children.remove(child)
87-
if type(child) is Either:
88-
for c in child.children:
71+
@property
72+
def either(self):
73+
"""Transform pattern into an equivalent, with only top-level Either."""
74+
# Currently the pattern will not be equivalent, but more "narrow",
75+
# although good enough to reason about list arguments.
76+
ret = []
77+
groups = [[self]]
78+
while groups:
79+
children = groups.pop(0)
80+
types = [type(c) for c in children]
81+
if Either in types:
82+
either = [c for c in children if type(c) is Either][0]
83+
children.pop(children.index(either))
84+
for c in either.children:
8985
groups.append([c] + children)
90-
elif type(child) is OneOrMore:
91-
groups.append(child.children * 2 + children)
86+
elif Required in types:
87+
required = [c for c in children if type(c) is Required][0]
88+
children.pop(children.index(required))
89+
groups.append(list(required.children) + children)
90+
elif Optional in types:
91+
optional = [c for c in children if type(c) is Optional][0]
92+
children.pop(children.index(optional))
93+
groups.append(list(optional.children) + children)
94+
elif AnyOptions in types:
95+
optional = [c for c in children if type(c) is AnyOptions][0]
96+
children.pop(children.index(optional))
97+
groups.append(list(optional.children) + children)
98+
elif OneOrMore in types:
99+
oneormore = [c for c in children if type(c) is OneOrMore][0]
100+
children.pop(children.index(oneormore))
101+
groups.append(list(oneormore.children) * 2 + children)
92102
else:
93-
groups.append(child.children + children)
94-
else:
95-
result.append(children)
96-
return Either(*[Required(*e) for e in result])
103+
ret.append(children)
104+
return Either(*[Required(*e) for e in ret])
97105

98106

99-
class LeafPattern(Pattern):
100-
101-
"""Leaf/terminal node of a pattern tree."""
107+
class ChildPattern(Pattern):
102108

103109
def __init__(self, name, value=None):
104-
self.name, self.value = name, value
110+
self.name = name
111+
self.value = value
105112

106113
def __repr__(self):
107114
return '%s(%r, %r)' % (self.__class__.__name__, self.name, self.value)
@@ -130,9 +137,7 @@ def match(self, left, collected=None):
130137
return True, left_, collected + [match]
131138

132139

133-
class BranchPattern(Pattern):
134-
135-
"""Branch/inner node of a pattern tree."""
140+
class ParentPattern(Pattern):
136141

137142
def __init__(self, *children):
138143
self.children = list(children)
@@ -144,15 +149,15 @@ def __repr__(self):
144149
def flat(self, *types):
145150
if type(self) in types:
146151
return [self]
147-
return sum([child.flat(*types) for child in self.children], [])
152+
return sum([c.flat(*types) for c in self.children], [])
148153

149154

150-
class Argument(LeafPattern):
155+
class Argument(ChildPattern):
151156

152157
def single_match(self, left):
153-
for n, pattern in enumerate(left):
154-
if type(pattern) is Argument:
155-
return n, Argument(self.name, pattern.value)
158+
for n, p in enumerate(left):
159+
if type(p) is Argument:
160+
return n, Argument(self.name, p.value)
156161
return None, None
157162

158163
@classmethod
@@ -165,23 +170,25 @@ def parse(class_, source):
165170
class Command(Argument):
166171

167172
def __init__(self, name, value=False):
168-
self.name, self.value = name, value
173+
self.name = name
174+
self.value = value
169175

170176
def single_match(self, left):
171-
for n, pattern in enumerate(left):
172-
if type(pattern) is Argument:
173-
if pattern.value == self.name:
177+
for n, p in enumerate(left):
178+
if type(p) is Argument:
179+
if p.value == self.name:
174180
return n, Command(self.name, True)
175181
else:
176182
break
177183
return None, None
178184

179185

180-
class Option(LeafPattern):
186+
class Option(ChildPattern):
181187

182188
def __init__(self, short=None, long=None, argcount=0, value=False):
183189
assert argcount in (0, 1)
184-
self.short, self.long, self.argcount = short, long, argcount
190+
self.short, self.long = short, long
191+
self.argcount, self.value = argcount, value
185192
self.value = None if value is False and argcount else value
186193

187194
@classmethod
@@ -202,9 +209,9 @@ def parse(class_, option_description):
202209
return class_(short, long, argcount, value)
203210

204211
def single_match(self, left):
205-
for n, pattern in enumerate(left):
206-
if self.name == pattern.name:
207-
return n, pattern
212+
for n, p in enumerate(left):
213+
if self.name == p.name:
214+
return n, p
208215
return None, None
209216

210217
@property
@@ -216,34 +223,34 @@ def __repr__(self):
216223
self.argcount, self.value)
217224

218225

219-
class Required(BranchPattern):
226+
class Required(ParentPattern):
220227

221228
def match(self, left, collected=None):
222229
collected = [] if collected is None else collected
223230
l = left
224231
c = collected
225-
for pattern in self.children:
226-
matched, l, c = pattern.match(l, c)
232+
for p in self.children:
233+
matched, l, c = p.match(l, c)
227234
if not matched:
228235
return False, left, collected
229236
return True, l, c
230237

231238

232-
class Optional(BranchPattern):
239+
class Optional(ParentPattern):
233240

234241
def match(self, left, collected=None):
235242
collected = [] if collected is None else collected
236-
for pattern in self.children:
237-
m, left, collected = pattern.match(left, collected)
243+
for p in self.children:
244+
m, left, collected = p.match(left, collected)
238245
return True, left, collected
239246

240247

241-
class OptionsShortcut(Optional):
248+
class AnyOptions(Optional):
242249

243250
"""Marker/placeholder for [options] shortcut."""
244251

245252

246-
class OneOrMore(BranchPattern):
253+
class OneOrMore(ParentPattern):
247254

248255
def match(self, left, collected=None):
249256
assert len(self.children) == 1
@@ -265,32 +272,26 @@ def match(self, left, collected=None):
265272
return False, left, collected
266273

267274

268-
class Either(BranchPattern):
275+
class Either(ParentPattern):
269276

270277
def match(self, left, collected=None):
271278
collected = [] if collected is None else collected
272279
outcomes = []
273-
for pattern in self.children:
274-
matched, _, _ = outcome = pattern.match(left, collected)
280+
for p in self.children:
281+
matched, _, _ = outcome = p.match(left, collected)
275282
if matched:
276283
outcomes.append(outcome)
277284
if outcomes:
278285
return min(outcomes, key=lambda outcome: len(outcome[1]))
279286
return False, left, collected
280287

281288

282-
class Tokens(list):
289+
class TokenStream(list):
283290

284-
def __init__(self, source, error=DocoptExit):
291+
def __init__(self, source, error):
285292
self += source.split() if hasattr(source, 'split') else source
286293
self.error = error
287294

288-
@staticmethod
289-
def from_pattern(source):
290-
source = re.sub(r'([\[\]\(\)\|]|\.\.\.)', r' \1 ', source)
291-
source = [s for s in re.split('\s+|(\S*<.*?>)', source) if s]
292-
return Tokens(source, error=DocoptLanguageError)
293-
294295
def move(self):
295296
return self.pop(0) if len(self) else None
296297

@@ -323,7 +324,7 @@ def parse_long(tokens, options):
323324
raise tokens.error('%s must not have an argument' % o.long)
324325
else:
325326
if value is None:
326-
if tokens.current() in [None, '--']:
327+
if tokens.current() is None:
327328
raise tokens.error('%s requires argument' % o.long)
328329
value = tokens.move()
329330
if tokens.error is DocoptExit:
@@ -354,7 +355,7 @@ def parse_shorts(tokens, options):
354355
value = None
355356
if o.argcount != 0:
356357
if left == '':
357-
if tokens.current() in [None, '--']:
358+
if tokens.current() is None:
358359
raise tokens.error('%s requires argument' % short)
359360
value = tokens.move()
360361
else:
@@ -367,7 +368,8 @@ def parse_shorts(tokens, options):
367368

368369

369370
def parse_pattern(source, options):
370-
tokens = Tokens.from_pattern(source)
371+
tokens = TokenStream(re.sub(r'([\[\]\(\)\|]|\.\.\.)', r' \1 ', source),
372+
DocoptLanguageError)
371373
result = parse_expr(tokens, options)
372374
if tokens.current() is not None:
373375
raise tokens.error('unexpected ending: %r' % ' '.join(tokens))
@@ -414,7 +416,7 @@ def parse_atom(tokens, options):
414416
return [result]
415417
elif token == 'options':
416418
tokens.move()
417-
return [OptionsShortcut()]
419+
return [AnyOptions()]
418420
elif token.startswith('--') and token != '--':
419421
return parse_long(tokens, options)
420422
elif token.startswith('-') and token not in ('-', '--'):
@@ -450,26 +452,27 @@ def parse_argv(tokens, options, options_first=False):
450452

451453

452454
def parse_defaults(doc):
453-
defaults = []
454-
for s in parse_section('options:', doc):
455-
# FIXME corner case "bla: options: --foo"
456-
_, _, s = s.partition(':') # get rid of "options:"
457-
split = re.split('\n[ \t]*(-\S+?)', '\n' + s)[1:]
458-
split = [s1 + s2 for s1, s2 in zip(split[::2], split[1::2])]
459-
options = [Option.parse(s) for s in split if s.startswith('-')]
460-
defaults += options
461-
return defaults
462-
463-
464-
def parse_section(name, source):
465-
pattern = re.compile('^([^\n]*' + name + '[^\n]*\n?(?:[ \t].*?(?:\n|$))*)',
466-
re.IGNORECASE | re.MULTILINE)
467-
return [s.strip() for s in pattern.findall(source)]
468-
469-
470-
def formal_usage(section):
471-
_, _, section = section.partition(':') # drop "usage:"
472-
pu = section.split()
455+
# in python < 2.7 you can't pass flags=re.MULTILINE
456+
split = re.split('\n *(<\S+?>|-\S+?)', doc)[1:]
457+
split = [s1 + s2 for s1, s2 in zip(split[::2], split[1::2])]
458+
options = [Option.parse(s) for s in split if s.startswith('-')]
459+
#arguments = [Argument.parse(s) for s in split if s.startswith('<')]
460+
#return options, arguments
461+
return options
462+
463+
464+
def printable_usage(doc):
465+
# in python < 2.7 you can't pass flags=re.IGNORECASE
466+
usage_split = re.split(r'([Uu][Ss][Aa][Gg][Ee]:)', doc)
467+
if len(usage_split) < 3:
468+
raise DocoptLanguageError('"usage:" (case-insensitive) not found.')
469+
if len(usage_split) > 3:
470+
raise DocoptLanguageError('More than one "usage:" (case-insensitive).')
471+
return re.split(r'\n\s*\n', ''.join(usage_split[1:]))[0].strip()
472+
473+
474+
def formal_usage(printable_usage):
475+
pu = printable_usage.split()[1:] # split and drop "usage:"
473476
return '( ' + ' '.join(') | (' if s == pu[0] else s for s in pu[1:]) + ' )'
474477

475478

@@ -509,7 +512,7 @@ def docopt(doc, argv=None, help=True, version=None, options_first=False):
509512
If passed, the object will be printed if --version is in
510513
`argv`.
511514
options_first : bool (default: False)
512-
Set to True to require options precede positional arguments,
515+
Set to True to require options preceed positional arguments,
513516
i.e. to forbid options and positional arguments intermix.
514517
515518
Returns
@@ -523,15 +526,15 @@ def docopt(doc, argv=None, help=True, version=None, options_first=False):
523526
-------
524527
>>> from docopt import docopt
525528
>>> doc = '''
526-
... Usage:
527-
... my_program tcp <host> <port> [--timeout=<seconds>]
528-
... my_program serial <port> [--baud=<n>] [--timeout=<seconds>]
529-
... my_program (-h | --help | --version)
530-
...
531-
... Options:
532-
... -h, --help Show this screen and exit.
533-
... --baud=<n> Baudrate [default: 9600]
534-
... '''
529+
Usage:
530+
my_program tcp <host> <port> [--timeout=<seconds>]
531+
my_program serial <port> [--baud=<n>] [--timeout=<seconds>]
532+
my_program (-h | --help | --version)
533+
534+
Options:
535+
-h, --help Show this screen and exit.
536+
--baud=<n> Baudrate [default: 9600]
537+
'''
535538
>>> argv = ['tcp', '127.0.0.1', '80', '--timeout', '30']
536539
>>> docopt(doc, argv)
537540
{'--baud': '9600',
@@ -550,32 +553,27 @@ def docopt(doc, argv=None, help=True, version=None, options_first=False):
550553
at https://github.com/docopt/docopt#readme
551554
552555
"""
553-
argv = sys.argv[1:] if argv is None else argv
554-
555-
usage_sections = parse_section('usage:', doc)
556-
if len(usage_sections) == 0:
557-
raise DocoptLanguageError('"usage:" (case-insensitive) not found.')
558-
if len(usage_sections) > 1:
559-
raise DocoptLanguageError('More than one "usage:" (case-insensitive).')
560-
DocoptExit.usage = usage_sections[0]
561-
556+
if argv is None:
557+
argv = sys.argv[1:]
558+
DocoptExit.usage = printable_usage(doc)
562559
options = parse_defaults(doc)
563560
pattern = parse_pattern(formal_usage(DocoptExit.usage), options)
564561
# [default] syntax for argument is disabled
565562
#for a in pattern.flat(Argument):
566563
# same_name = [d for d in arguments if d.name == a.name]
567564
# if same_name:
568565
# a.value = same_name[0].value
569-
argv = parse_argv(Tokens(argv), list(options), options_first)
566+
argv = parse_argv(TokenStream(argv, DocoptExit), list(options),
567+
options_first)
570568
pattern_options = set(pattern.flat(Option))
571-
for options_shortcut in pattern.flat(OptionsShortcut):
569+
for ao in pattern.flat(AnyOptions):
572570
doc_options = parse_defaults(doc)
573-
options_shortcut.children = list(set(doc_options) - pattern_options)
571+
ao.children = list(set(doc_options) - pattern_options)
574572
#if any_options:
575-
# options_shortcut.children += [Option(o.short, o.long, o.argcount)
573+
# ao.children += [Option(o.short, o.long, o.argcount)
576574
# for o in argv if type(o) is Option]
577575
extras(help, version, argv, doc)
578576
matched, left, collected = pattern.fix().match(argv)
579577
if matched and left == []: # better error message if left?
580578
return Dict((a.name, a.value) for a in (pattern.flat() + collected))
581-
raise DocoptExit()
579+
raise DocoptExit()

‎src/progressbar/__init__.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@
4040
"""
4141

4242
__author__ = 'Nilton Volpato'
43-
__author_email__ = 'first-name dot last-name @ gmail.com'
43+
__author_email__ = 'nilton.volpato@gmail.com'
4444
__date__ = '2011-05-14'
45-
__version__ = '2.3'
45+
__version__ = '2.5'
4646

47-
from compat import *
48-
from widgets import *
49-
from progressbar import *
47+
from .compat import *
48+
from .widgets import *
49+
from .progressbar import *

‎src/progressbar/compat.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#!/usr/bin/python
21
# -*- coding: utf-8 -*-
32
#
43
# progressbar - Text progress bar library for Python.

‎src/progressbar/progressbar.py

+12-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#!/usr/bin/python
21
# -*- coding: utf-8 -*-
32
#
43
# progressbar - Text progress bar library for Python.
@@ -35,11 +34,8 @@
3534
except ImportError:
3635
pass
3736

38-
from compat import * # for: any, next
39-
import widgets
40-
41-
42-
class UnknownLength: pass
37+
from .compat import * # for: any, next
38+
from . import widgets
4339

4440

4541
class ProgressBar(object):
@@ -96,7 +92,7 @@ class ProgressBar(object):
9692
_DEFAULT_WIDGETS = [widgets.Percentage(), ' ', widgets.Bar()]
9793

9894
def __init__(self, maxval=None, widgets=None, term_width=None, poll=1,
99-
left_justify=True, fd=sys.stderr):
95+
left_justify=True, fd=None):
10096
"""Initializes a progress bar with sane defaults."""
10197

10298
# Don't share a reference with any other progress bars
@@ -105,7 +101,7 @@ def __init__(self, maxval=None, widgets=None, term_width=None, poll=1,
105101

106102
self.maxval = maxval
107103
self.widgets = widgets
108-
self.fd = fd
104+
self.fd = fd if fd is not None else sys.stderr
109105
self.left_justify = left_justify
110106

111107
self.signal_set = False
@@ -139,7 +135,7 @@ def __call__(self, iterable):
139135
self.maxval = len(iterable)
140136
except:
141137
if self.maxval is None:
142-
self.maxval = UnknownLength
138+
self.maxval = widgets.UnknownLength
143139

144140
self.__iterable = iter(iterable)
145141
return self
@@ -184,9 +180,11 @@ def _handle_resize(self, signum=None, frame=None):
184180

185181
def percentage(self):
186182
"""Returns the progress as a percentage."""
183+
if self.maxval is widgets.UnknownLength:
184+
return float("NaN")
187185
if self.currval >= self.maxval:
188186
return 100.0
189-
return self.currval * 100.0 / self.maxval
187+
return (self.currval * 100.0 / self.maxval) if self.maxval else 100.00
190188

191189
percent = property(percentage)
192190

@@ -245,8 +243,8 @@ def _update_widgets(self):
245243
def update(self, value=None):
246244
"""Updates the ProgressBar to a new value."""
247245

248-
if value is not None and value is not UnknownLength:
249-
if (self.maxval is not UnknownLength
246+
if value is not None and value is not widgets.UnknownLength:
247+
if (self.maxval is not widgets.UnknownLength
250248
and not 0 <= value <= self.maxval):
251249

252250
raise ValueError('Value out of range')
@@ -262,6 +260,7 @@ def update(self, value=None):
262260
self.seconds_elapsed = now - self.start_time
263261
self.next_update = self.currval + self.update_interval
264262
self.fd.write(self._format_line() + '\r')
263+
self.fd.flush()
265264
self.last_update_time = now
266265

267266

@@ -283,7 +282,7 @@ def start(self):
283282
self.num_intervals = max(100, self.term_width)
284283
self.next_update = 0
285284

286-
if self.maxval is not UnknownLength:
285+
if self.maxval is not widgets.UnknownLength:
287286
if self.maxval < 0: raise ValueError('Value out of range')
288287
self.update_interval = self.maxval / self.num_intervals
289288

‎src/progressbar/widgets.py

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
#!/usr/bin/python
21
# -*- coding: utf-8 -*-
32
#
43
# progressbar - Text progress bar library for Python.
@@ -33,6 +32,8 @@
3332
else:
3433
AbstractWidget = ABCMeta('AbstractWidget', (object,), {})
3534

35+
class UnknownLength:
36+
pass
3637

3738
def format_updatable(updatable, pbar):
3839
if hasattr(updatable, 'update'): return updatable.update(pbar)
@@ -108,7 +109,7 @@ class ETA(Timer):
108109
def update(self, pbar):
109110
"""Updates the widget to show the ETA or total time when finished."""
110111

111-
if pbar.currval == 0:
112+
if pbar.maxval is UnknownLength or pbar.currval == 0:
112113
return 'ETA: --:--:--'
113114
elif pbar.finished:
114115
return 'Time: %s' % self.format_time(pbar.seconds_elapsed)
@@ -123,7 +124,7 @@ class AdaptiveETA(Timer):
123124
124125
Uses a weighted average of two estimates:
125126
1) ETA based on the total progress and time elapsed so far
126-
2) ETA based on the progress as per tha last 10 update reports
127+
2) ETA based on the progress as per the last 10 update reports
127128
128129
The weight depends on the current progress so that to begin with the
129130
total progress is used and at the end only the most recent progress is
@@ -146,7 +147,7 @@ def _eta(self, maxval, currval, elapsed):
146147

147148
def update(self, pbar):
148149
"""Updates the widget to show the ETA or total time when finished."""
149-
if pbar.currval == 0:
150+
if pbar.maxval is UnknownLength or pbar.currval == 0:
150151
return 'ETA: --:--:--'
151152
elif pbar.finished:
152153
return 'Time: %s' % self.format_time(pbar.seconds_elapsed)
@@ -166,7 +167,7 @@ def update(self, pbar):
166167
class FileTransferSpeed(Widget):
167168
"""Widget for showing the transfer speed (useful for file transfers)."""
168169

169-
FORMAT = '%6.2f %s%s/s'
170+
FMT = '%6.2f %s%s/s'
170171
PREFIXES = ' kMGTPEZY'
171172
__slots__ = ('unit',)
172173

@@ -183,7 +184,7 @@ def update(self, pbar):
183184
power = int(math.log(speed, 1000))
184185
scaled = speed / 1000.**power
185186

186-
return self.FORMAT % (scaled, self.PREFIXES[power], self.unit)
187+
return self.FMT % (scaled, self.PREFIXES[power], self.unit)
187188

188189

189190
class AnimatedMarker(Widget):
@@ -270,7 +271,7 @@ def __init__(self, sep=' of '):
270271
self.sep = sep
271272

272273
def update(self, pbar):
273-
return '%d%s%d' % (pbar.currval, self.sep, pbar.maxval)
274+
return '%d%s%s' % (pbar.currval, self.sep, pbar.maxval)
274275

275276

276277
class Bar(WidgetHFill):
@@ -303,7 +304,7 @@ def update(self, pbar, width):
303304

304305
width -= len(left) + len(right)
305306
# Marked must *always* have length of 1
306-
if pbar.maxval:
307+
if pbar.maxval is not UnknownLength and pbar.maxval:
307308
marked *= int(pbar.currval / pbar.maxval * width)
308309
else:
309310
marked = ''

0 commit comments

Comments
 (0)
Please sign in to comment.