Skip to content

Commit 0ff1e35

Browse files
authored
Merge pull request #596 from maxim-belkin/reporter
bin/util.py: Factor out reporter class. Define __all__
2 parents 9448b99 + 5e8d059 commit 0ff1e35

File tree

3 files changed

+80
-76
lines changed

3 files changed

+80
-76
lines changed

bin/lesson_check.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
import re
99
from argparse import ArgumentParser
1010

11-
from util import (Reporter, read_markdown, load_yaml, check_unwanted_files,
12-
require)
11+
# This uses the `__all__` list in `util.py` to determine what objects to import
12+
# see https://docs.python.org/3/tutorial/modules.html#importing-from-a-package
13+
from util import *
14+
from reporter import Reporter
1315

1416
__version__ = '0.3'
1517

bin/reporter.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import sys
2+
3+
class Reporter:
4+
"""Collect and report errors."""
5+
6+
# Marker to show that an expected value hasn't been provided.
7+
# (Can't use 'None' because that might be a legitimate value.)
8+
_DEFAULT_REPORTER = []
9+
10+
def __init__(self):
11+
"""Constructor."""
12+
self.messages = []
13+
14+
def check_field(self, filename, name, values, key, expected=_DEFAULT_REPORTER):
15+
"""Check that a dictionary has an expected value."""
16+
17+
if key not in values:
18+
self.add(filename, '{0} does not contain {1}', name, key)
19+
elif expected is self._DEFAULT_REPORTER:
20+
pass
21+
elif type(expected) in (tuple, set, list):
22+
if values[key] not in expected:
23+
self.add(
24+
filename, '{0} {1} value {2} is not in {3}', name, key, values[key], expected)
25+
elif values[key] != expected:
26+
self.add(filename, '{0} {1} is {2} not {3}',
27+
name, key, values[key], expected)
28+
29+
def check(self, condition, location, fmt, *args):
30+
"""Append error if condition not met."""
31+
32+
if not condition:
33+
self.add(location, fmt, *args)
34+
35+
def add(self, location, fmt, *args):
36+
"""Append error unilaterally."""
37+
38+
self.messages.append((location, fmt.format(*args)))
39+
40+
@staticmethod
41+
def pretty(item):
42+
location, message = item
43+
if isinstance(location, type(None)):
44+
return message
45+
elif isinstance(location, str):
46+
return location + ': ' + message
47+
elif isinstance(location, tuple):
48+
return '{0}:{1}: '.format(*location) + message
49+
50+
print('Unknown item "{0}"'.format(item), file=sys.stderr)
51+
return NotImplemented
52+
53+
@staticmethod
54+
def key(item):
55+
location, message = item
56+
if isinstance(location, type(None)):
57+
return ('', -1, message)
58+
elif isinstance(location, str):
59+
return (location, -1, message)
60+
elif isinstance(location, tuple):
61+
return (location[0], location[1], message)
62+
63+
print('Unknown item "{0}"'.format(item), file=sys.stderr)
64+
return NotImplemented
65+
66+
def report(self, stream=sys.stdout):
67+
"""Report all messages in order."""
68+
69+
if not self.messages:
70+
return
71+
72+
for m in sorted(self.messages, key=self.key):
73+
print(self.pretty(m), file=stream)
74+
75+

bin/util.py

Lines changed: 1 addition & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -10,86 +10,13 @@
1010
print('Unable to import YAML module: please install PyYAML', file=sys.stderr)
1111
sys.exit(1)
1212

13+
__all__ = ['check_unwanted_files', 'load_yaml', 'read_markdown', 'require']
1314

1415
# Files that shouldn't be present.
1516
UNWANTED_FILES = [
1617
'.nojekyll'
1718
]
1819

19-
# Marker to show that an expected value hasn't been provided.
20-
# (Can't use 'None' because that might be a legitimate value.)
21-
REPORTER_NOT_SET = []
22-
23-
24-
class Reporter:
25-
"""Collect and report errors."""
26-
27-
def __init__(self):
28-
"""Constructor."""
29-
self.messages = []
30-
31-
def check_field(self, filename, name, values, key, expected=REPORTER_NOT_SET):
32-
"""Check that a dictionary has an expected value."""
33-
34-
if key not in values:
35-
self.add(filename, '{0} does not contain {1}', name, key)
36-
elif expected is REPORTER_NOT_SET:
37-
pass
38-
elif type(expected) in (tuple, set, list):
39-
if values[key] not in expected:
40-
self.add(
41-
filename, '{0} {1} value {2} is not in {3}', name, key, values[key], expected)
42-
elif values[key] != expected:
43-
self.add(filename, '{0} {1} is {2} not {3}',
44-
name, key, values[key], expected)
45-
46-
def check(self, condition, location, fmt, *args):
47-
"""Append error if condition not met."""
48-
49-
if not condition:
50-
self.add(location, fmt, *args)
51-
52-
def add(self, location, fmt, *args):
53-
"""Append error unilaterally."""
54-
55-
self.messages.append((location, fmt.format(*args)))
56-
57-
@staticmethod
58-
def pretty(item):
59-
location, message = item
60-
if isinstance(location, type(None)):
61-
return message
62-
elif isinstance(location, str):
63-
return location + ': ' + message
64-
elif isinstance(location, tuple):
65-
return '{0}:{1}: '.format(*location) + message
66-
67-
print('Unknown item "{0}"'.format(item), file=sys.stderr)
68-
return NotImplemented
69-
70-
@staticmethod
71-
def key(item):
72-
location, message = item
73-
if isinstance(location, type(None)):
74-
return ('', -1, message)
75-
elif isinstance(location, str):
76-
return (location, -1, message)
77-
elif isinstance(location, tuple):
78-
return (location[0], location[1], message)
79-
80-
print('Unknown item "{0}"'.format(item), file=sys.stderr)
81-
return NotImplemented
82-
83-
def report(self, stream=sys.stdout):
84-
"""Report all messages in order."""
85-
86-
if not self.messages:
87-
return
88-
89-
for m in sorted(self.messages, key=self.key):
90-
print(self.pretty(m), file=stream)
91-
92-
9320
def read_markdown(parser, path):
9421
"""
9522
Get YAML and AST for Markdown file, returning

0 commit comments

Comments
 (0)