release: 0.5.1
This commit is contained in:
@ -1 +1 @@
|
||||
__version__ = '0.5.0'
|
||||
__version__ = '0.5.1'
|
||||
|
||||
@ -3,7 +3,10 @@ import os
|
||||
import bonobo
|
||||
from bonobo.constants import DEFAULT_SERVICES_ATTR, DEFAULT_SERVICES_FILENAME
|
||||
|
||||
DEFAULT_GRAPH_FILENAMES = ('__main__.py', 'main.py', )
|
||||
DEFAULT_GRAPH_FILENAMES = (
|
||||
'__main__.py',
|
||||
'main.py',
|
||||
)
|
||||
DEFAULT_GRAPH_ATTR = 'get_graph'
|
||||
|
||||
|
||||
|
||||
@ -50,7 +50,10 @@ class ConfigurableMeta(type):
|
||||
return (processor for _, processor in cls.__processors)
|
||||
|
||||
def __repr__(self):
|
||||
return ' '.join(('<Configurable', super(ConfigurableMeta, self).__repr__().split(' ', 1)[1], ))
|
||||
return ' '.join((
|
||||
'<Configurable',
|
||||
super(ConfigurableMeta, self).__repr__().split(' ', 1)[1],
|
||||
))
|
||||
|
||||
|
||||
try:
|
||||
|
||||
@ -133,8 +133,9 @@ class Method(Option):
|
||||
def __set__(self, inst, value):
|
||||
if not hasattr(value, '__call__'):
|
||||
raise TypeError(
|
||||
'Option of type {!r} is expecting a callable value, got {!r} object (which is not).'.
|
||||
format(type(self).__name__, type(value).__name__)
|
||||
'Option of type {!r} is expecting a callable value, got {!r} object (which is not).'.format(
|
||||
type(self).__name__, type(value).__name__
|
||||
)
|
||||
)
|
||||
inst._options_values[self.name] = self.type(value) if self.type else value
|
||||
|
||||
|
||||
@ -61,22 +61,27 @@ def display(row):
|
||||
row.get('city', None)
|
||||
)
|
||||
)
|
||||
), row.get('county', None), row.get('country'),
|
||||
),
|
||||
row.get('county', None),
|
||||
row.get('country'),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
print(
|
||||
' - {}address{}: {address}'.
|
||||
format(Fore.BLUE, Style.RESET_ALL, address=', '.join(address))
|
||||
' - {}address{}: {address}'.format(
|
||||
Fore.BLUE, Style.RESET_ALL, address=', '.join(address)
|
||||
)
|
||||
)
|
||||
print(
|
||||
' - {}links{}: {links}'.
|
||||
format(Fore.BLUE, Style.RESET_ALL, links=', '.join(row['links']))
|
||||
' - {}links{}: {links}'.format(
|
||||
Fore.BLUE, Style.RESET_ALL, links=', '.join(row['links'])
|
||||
)
|
||||
)
|
||||
print(
|
||||
' - {}geometry{}: {geometry}'.
|
||||
format(Fore.BLUE, Style.RESET_ALL, **row)
|
||||
' - {}geometry{}: {geometry}'.format(
|
||||
Fore.BLUE, Style.RESET_ALL, **row
|
||||
)
|
||||
)
|
||||
print(
|
||||
' - {}source{}: {source}'.format(
|
||||
|
||||
@ -89,15 +89,32 @@ class ConsoleOutputPlugin(Plugin):
|
||||
if node.alive:
|
||||
_line = ''.join(
|
||||
(
|
||||
' ', alive_color, '+', Style.RESET_ALL, ' ', node.name, name_suffix, ' ',
|
||||
node.get_statistics_as_string(), Style.RESET_ALL, ' ',
|
||||
' ',
|
||||
alive_color,
|
||||
'+',
|
||||
Style.RESET_ALL,
|
||||
' ',
|
||||
node.name,
|
||||
name_suffix,
|
||||
' ',
|
||||
node.get_statistics_as_string(),
|
||||
Style.RESET_ALL,
|
||||
' ',
|
||||
)
|
||||
)
|
||||
else:
|
||||
_line = ''.join(
|
||||
(
|
||||
' ', dead_color, '-', ' ', node.name, name_suffix, ' ', node.get_statistics_as_string(),
|
||||
Style.RESET_ALL, ' ',
|
||||
' ',
|
||||
dead_color,
|
||||
'-',
|
||||
' ',
|
||||
node.name,
|
||||
name_suffix,
|
||||
' ',
|
||||
node.get_statistics_as_string(),
|
||||
Style.RESET_ALL,
|
||||
' ',
|
||||
)
|
||||
)
|
||||
print(prefix + _line + '\033[0K', file=sys.stderr)
|
||||
@ -107,8 +124,8 @@ class ConsoleOutputPlugin(Plugin):
|
||||
print(
|
||||
''.join(
|
||||
(
|
||||
' `-> ', ' '.join('{}{}{}: {}'.format(Style.BRIGHT, k, Style.RESET_ALL, v)
|
||||
for k, v in append), CLEAR_EOL
|
||||
' `-> ', ' '.join('{}{}{}: {}'.format(Style.BRIGHT, k, Style.RESET_ALL, v) for k, v in append),
|
||||
CLEAR_EOL
|
||||
)
|
||||
),
|
||||
file=sys.stderr
|
||||
|
||||
@ -60,7 +60,10 @@ class CsvReader(IOFormatEnabled, FileReader, CsvHandler):
|
||||
|
||||
for row in reader:
|
||||
if len(row) != field_count:
|
||||
raise ValueError('Got a line with %d fields, expecting %d.' % (len(row), field_count, ))
|
||||
raise ValueError('Got a line with %d fields, expecting %d.' % (
|
||||
len(row),
|
||||
field_count,
|
||||
))
|
||||
|
||||
yield self.get_output(dict(zip(_headers, row)))
|
||||
|
||||
|
||||
@ -52,7 +52,10 @@ class PickleReader(IOFormatEnabled, FileReader, PickleHandler):
|
||||
|
||||
for i in iterator:
|
||||
if len(i) != item_count:
|
||||
raise ValueError('Received an object with %d items, expecting %d.' % (len(i), item_count, ))
|
||||
raise ValueError('Received an object with %d items, expecting %d.' % (
|
||||
len(i),
|
||||
item_count,
|
||||
))
|
||||
|
||||
yield self.get_output(dict(zip(i)) if is_dict else dict(zip(pickle_headers.value, i)))
|
||||
|
||||
|
||||
@ -45,7 +45,10 @@ class Bag:
|
||||
def args(self):
|
||||
if self._parent is None:
|
||||
return self._args
|
||||
return (*self._parent.args, *self._args, )
|
||||
return (
|
||||
*self._parent.args,
|
||||
*self._args,
|
||||
)
|
||||
|
||||
@property
|
||||
def kwargs(self):
|
||||
@ -100,11 +103,12 @@ class Bag:
|
||||
|
||||
def __repr__(self):
|
||||
return '<{} ({})>'.format(
|
||||
type(self).__name__, ', '.
|
||||
join(itertools.chain(
|
||||
map(repr, self.args),
|
||||
('{}={}'.format(k, repr(v)) for k, v in self.kwargs.items()),
|
||||
))
|
||||
type(self).__name__, ', '.join(
|
||||
itertools.chain(
|
||||
map(repr, self.args),
|
||||
('{}={}'.format(k, repr(v)) for k, v in self.kwargs.items()),
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@ -38,6 +38,11 @@ def tuplize(generator):
|
||||
|
||||
|
||||
def iter_if_not_sequence(mixed):
|
||||
if isinstance(mixed, (dict, list, str, bytes, )):
|
||||
if isinstance(mixed, (
|
||||
dict,
|
||||
list,
|
||||
str,
|
||||
bytes,
|
||||
)):
|
||||
raise TypeError(type(mixed).__name__)
|
||||
return iter(mixed)
|
||||
|
||||
4
docs/_templates/alabaster/__init__.py
vendored
4
docs/_templates/alabaster/__init__.py
vendored
@ -14,11 +14,11 @@ def get_path():
|
||||
def update_context(app, pagename, templatename, context, doctree):
|
||||
context['alabaster_version'] = version.__version__
|
||||
|
||||
|
||||
def setup(app):
|
||||
# add_html_theme is new in Sphinx 1.6+
|
||||
if hasattr(app, 'add_html_theme'):
|
||||
theme_path = os.path.abspath(os.path.dirname(__file__))
|
||||
app.add_html_theme('alabaster', theme_path)
|
||||
app.connect('html-page-context', update_context)
|
||||
return {'version': version.__version__,
|
||||
'parallel_read_safe': True}
|
||||
return {'version': version.__version__, 'parallel_read_safe': True}
|
||||
|
||||
130
docs/_templates/alabaster/support.py
vendored
130
docs/_templates/alabaster/support.py
vendored
@ -7,82 +7,74 @@ from pygments.token import Keyword, Name, Comment, String, Error, \
|
||||
|
||||
# Originally based on FlaskyStyle which was based on 'tango'.
|
||||
class Alabaster(Style):
|
||||
background_color = "#f8f8f8" # doesn't seem to override CSS 'pre' styling?
|
||||
background_color = "#f8f8f8" # doesn't seem to override CSS 'pre' styling?
|
||||
default_style = ""
|
||||
|
||||
styles = {
|
||||
# No corresponding class for the following:
|
||||
#Text: "", # class: ''
|
||||
Whitespace: "underline #f8f8f8", # class: 'w'
|
||||
Error: "#a40000 border:#ef2929", # class: 'err'
|
||||
Other: "#000000", # class 'x'
|
||||
|
||||
Comment: "italic #8f5902", # class: 'c'
|
||||
Comment.Preproc: "noitalic", # class: 'cp'
|
||||
|
||||
Keyword: "bold #004461", # class: 'k'
|
||||
Keyword.Constant: "bold #004461", # class: 'kc'
|
||||
Keyword.Declaration: "bold #004461", # class: 'kd'
|
||||
Keyword.Namespace: "bold #004461", # class: 'kn'
|
||||
Keyword.Pseudo: "bold #004461", # class: 'kp'
|
||||
Keyword.Reserved: "bold #004461", # class: 'kr'
|
||||
Keyword.Type: "bold #004461", # class: 'kt'
|
||||
|
||||
Operator: "#582800", # class: 'o'
|
||||
Operator.Word: "bold #004461", # class: 'ow' - like keywords
|
||||
|
||||
Punctuation: "bold #000000", # class: 'p'
|
||||
Whitespace: "underline #f8f8f8", # class: 'w'
|
||||
Error: "#a40000 border:#ef2929", # class: 'err'
|
||||
Other: "#000000", # class 'x'
|
||||
Comment: "italic #8f5902", # class: 'c'
|
||||
Comment.Preproc: "noitalic", # class: 'cp'
|
||||
Keyword: "bold #004461", # class: 'k'
|
||||
Keyword.Constant: "bold #004461", # class: 'kc'
|
||||
Keyword.Declaration: "bold #004461", # class: 'kd'
|
||||
Keyword.Namespace: "bold #004461", # class: 'kn'
|
||||
Keyword.Pseudo: "bold #004461", # class: 'kp'
|
||||
Keyword.Reserved: "bold #004461", # class: 'kr'
|
||||
Keyword.Type: "bold #004461", # class: 'kt'
|
||||
Operator: "#582800", # class: 'o'
|
||||
Operator.Word: "bold #004461", # class: 'ow' - like keywords
|
||||
Punctuation: "bold #000000", # class: 'p'
|
||||
|
||||
# because special names such as Name.Class, Name.Function, etc.
|
||||
# are not recognized as such later in the parsing, we choose them
|
||||
# to look the same as ordinary variables.
|
||||
Name: "#000000", # class: 'n'
|
||||
Name.Attribute: "#c4a000", # class: 'na' - to be revised
|
||||
Name.Builtin: "#004461", # class: 'nb'
|
||||
Name.Builtin.Pseudo: "#3465a4", # class: 'bp'
|
||||
Name.Class: "#000000", # class: 'nc' - to be revised
|
||||
Name.Constant: "#000000", # class: 'no' - to be revised
|
||||
Name.Decorator: "#888", # class: 'nd' - to be revised
|
||||
Name.Entity: "#ce5c00", # class: 'ni'
|
||||
Name.Exception: "bold #cc0000", # class: 'ne'
|
||||
Name.Function: "#000000", # class: 'nf'
|
||||
Name.Property: "#000000", # class: 'py'
|
||||
Name.Label: "#f57900", # class: 'nl'
|
||||
Name.Namespace: "#000000", # class: 'nn' - to be revised
|
||||
Name.Other: "#000000", # class: 'nx'
|
||||
Name.Tag: "bold #004461", # class: 'nt' - like a keyword
|
||||
Name.Variable: "#000000", # class: 'nv' - to be revised
|
||||
Name.Variable.Class: "#000000", # class: 'vc' - to be revised
|
||||
Name.Variable.Global: "#000000", # class: 'vg' - to be revised
|
||||
Name.Variable.Instance: "#000000", # class: 'vi' - to be revised
|
||||
|
||||
Number: "#990000", # class: 'm'
|
||||
|
||||
Literal: "#000000", # class: 'l'
|
||||
Literal.Date: "#000000", # class: 'ld'
|
||||
|
||||
String: "#4e9a06", # class: 's'
|
||||
String.Backtick: "#4e9a06", # class: 'sb'
|
||||
String.Char: "#4e9a06", # class: 'sc'
|
||||
String.Doc: "italic #8f5902", # class: 'sd' - like a comment
|
||||
String.Double: "#4e9a06", # class: 's2'
|
||||
String.Escape: "#4e9a06", # class: 'se'
|
||||
String.Heredoc: "#4e9a06", # class: 'sh'
|
||||
String.Interpol: "#4e9a06", # class: 'si'
|
||||
String.Other: "#4e9a06", # class: 'sx'
|
||||
String.Regex: "#4e9a06", # class: 'sr'
|
||||
String.Single: "#4e9a06", # class: 's1'
|
||||
String.Symbol: "#4e9a06", # class: 'ss'
|
||||
|
||||
Generic: "#000000", # class: 'g'
|
||||
Generic.Deleted: "#a40000", # class: 'gd'
|
||||
Generic.Emph: "italic #000000", # class: 'ge'
|
||||
Generic.Error: "#ef2929", # class: 'gr'
|
||||
Generic.Heading: "bold #000080", # class: 'gh'
|
||||
Generic.Inserted: "#00A000", # class: 'gi'
|
||||
Generic.Output: "#888", # class: 'go'
|
||||
Generic.Prompt: "#745334", # class: 'gp'
|
||||
Generic.Strong: "bold #000000", # class: 'gs'
|
||||
Generic.Subheading: "bold #800080", # class: 'gu'
|
||||
Generic.Traceback: "bold #a40000", # class: 'gt'
|
||||
Name: "#000000", # class: 'n'
|
||||
Name.Attribute: "#c4a000", # class: 'na' - to be revised
|
||||
Name.Builtin: "#004461", # class: 'nb'
|
||||
Name.Builtin.Pseudo: "#3465a4", # class: 'bp'
|
||||
Name.Class: "#000000", # class: 'nc' - to be revised
|
||||
Name.Constant: "#000000", # class: 'no' - to be revised
|
||||
Name.Decorator: "#888", # class: 'nd' - to be revised
|
||||
Name.Entity: "#ce5c00", # class: 'ni'
|
||||
Name.Exception: "bold #cc0000", # class: 'ne'
|
||||
Name.Function: "#000000", # class: 'nf'
|
||||
Name.Property: "#000000", # class: 'py'
|
||||
Name.Label: "#f57900", # class: 'nl'
|
||||
Name.Namespace: "#000000", # class: 'nn' - to be revised
|
||||
Name.Other: "#000000", # class: 'nx'
|
||||
Name.Tag: "bold #004461", # class: 'nt' - like a keyword
|
||||
Name.Variable: "#000000", # class: 'nv' - to be revised
|
||||
Name.Variable.Class: "#000000", # class: 'vc' - to be revised
|
||||
Name.Variable.Global: "#000000", # class: 'vg' - to be revised
|
||||
Name.Variable.Instance: "#000000", # class: 'vi' - to be revised
|
||||
Number: "#990000", # class: 'm'
|
||||
Literal: "#000000", # class: 'l'
|
||||
Literal.Date: "#000000", # class: 'ld'
|
||||
String: "#4e9a06", # class: 's'
|
||||
String.Backtick: "#4e9a06", # class: 'sb'
|
||||
String.Char: "#4e9a06", # class: 'sc'
|
||||
String.Doc: "italic #8f5902", # class: 'sd' - like a comment
|
||||
String.Double: "#4e9a06", # class: 's2'
|
||||
String.Escape: "#4e9a06", # class: 'se'
|
||||
String.Heredoc: "#4e9a06", # class: 'sh'
|
||||
String.Interpol: "#4e9a06", # class: 'si'
|
||||
String.Other: "#4e9a06", # class: 'sx'
|
||||
String.Regex: "#4e9a06", # class: 'sr'
|
||||
String.Single: "#4e9a06", # class: 's1'
|
||||
String.Symbol: "#4e9a06", # class: 'ss'
|
||||
Generic: "#000000", # class: 'g'
|
||||
Generic.Deleted: "#a40000", # class: 'gd'
|
||||
Generic.Emph: "italic #000000", # class: 'ge'
|
||||
Generic.Error: "#ef2929", # class: 'gr'
|
||||
Generic.Heading: "bold #000080", # class: 'gh'
|
||||
Generic.Inserted: "#00A000", # class: 'gi'
|
||||
Generic.Output: "#888", # class: 'go'
|
||||
Generic.Prompt: "#745334", # class: 'gp'
|
||||
Generic.Strong: "bold #000000", # class: 'gs'
|
||||
Generic.Subheading: "bold #800080", # class: 'gu'
|
||||
Generic.Traceback: "bold #a40000", # class: 'gt'
|
||||
}
|
||||
|
||||
@ -50,7 +50,10 @@ def test_define_with_decorator():
|
||||
calls = []
|
||||
|
||||
def my_handler(*args, **kwargs):
|
||||
calls.append((args, kwargs, ))
|
||||
calls.append((
|
||||
args,
|
||||
kwargs,
|
||||
))
|
||||
|
||||
Concrete = MethodBasedConfigurable(my_handler)
|
||||
|
||||
@ -74,7 +77,10 @@ def test_late_binding_method_decoration():
|
||||
|
||||
@MethodBasedConfigurable(foo='foo')
|
||||
def Concrete(*args, **kwargs):
|
||||
calls.append((args, kwargs, ))
|
||||
calls.append((
|
||||
args,
|
||||
kwargs,
|
||||
))
|
||||
|
||||
assert callable(Concrete.handler)
|
||||
t = Concrete(bar='baz')
|
||||
@ -89,7 +95,10 @@ def test_define_with_argument():
|
||||
calls = []
|
||||
|
||||
def concrete_handler(*args, **kwargs):
|
||||
calls.append((args, kwargs, ))
|
||||
calls.append((
|
||||
args,
|
||||
kwargs,
|
||||
))
|
||||
|
||||
t = MethodBasedConfigurable(concrete_handler, 'foo', bar='baz')
|
||||
assert callable(t.handler)
|
||||
@ -103,7 +112,10 @@ def test_define_with_inheritance():
|
||||
|
||||
class Inheriting(MethodBasedConfigurable):
|
||||
def handler(self, *args, **kwargs):
|
||||
calls.append((args, kwargs, ))
|
||||
calls.append((
|
||||
args,
|
||||
kwargs,
|
||||
))
|
||||
|
||||
t = Inheriting('foo', bar='baz')
|
||||
assert callable(t.handler)
|
||||
@ -120,7 +132,10 @@ def test_inheritance_then_decorate():
|
||||
|
||||
@Inheriting
|
||||
def Concrete(*args, **kwargs):
|
||||
calls.append((args, kwargs, ))
|
||||
calls.append((
|
||||
args,
|
||||
kwargs,
|
||||
))
|
||||
|
||||
assert callable(Concrete.handler)
|
||||
t = Concrete('foo', bar='baz')
|
||||
|
||||
@ -53,7 +53,10 @@ def test_partial():
|
||||
assert len(ci.options) == 4
|
||||
assert len(ci.processors) == 1
|
||||
assert ci.partial
|
||||
assert ci.partial[0] == (f1, f2, )
|
||||
assert ci.partial[0] == (
|
||||
f1,
|
||||
f2,
|
||||
)
|
||||
assert not len(ci.partial[1])
|
||||
|
||||
c = C('foo')
|
||||
|
||||
@ -28,9 +28,7 @@ SERVICES = Container(
|
||||
|
||||
|
||||
class MyServiceDependantConfigurable(Configurable):
|
||||
printer = Service(
|
||||
PrinterInterface,
|
||||
)
|
||||
printer = Service(PrinterInterface, )
|
||||
|
||||
def __call__(self, printer: PrinterInterface, *args):
|
||||
return printer.print(*args)
|
||||
|
||||
@ -24,9 +24,12 @@ def test_write_csv_to_file_arg0(tmpdir):
|
||||
getattr(context, 'file')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('add_kwargs', ({}, {
|
||||
'ioformat': settings.IOFORMAT_KWARGS,
|
||||
}, ))
|
||||
@pytest.mark.parametrize('add_kwargs', (
|
||||
{},
|
||||
{
|
||||
'ioformat': settings.IOFORMAT_KWARGS,
|
||||
},
|
||||
))
|
||||
def test_write_csv_to_file_kwargs(tmpdir, add_kwargs):
|
||||
fs, filename, services = csv_tester.get_services_for_writer(tmpdir)
|
||||
|
||||
|
||||
@ -20,9 +20,12 @@ def test_write_json_arg0(tmpdir):
|
||||
assert fp.read() == '[{"foo": "bar"}]'
|
||||
|
||||
|
||||
@pytest.mark.parametrize('add_kwargs', ({}, {
|
||||
'ioformat': settings.IOFORMAT_KWARGS,
|
||||
}, ))
|
||||
@pytest.mark.parametrize('add_kwargs', (
|
||||
{},
|
||||
{
|
||||
'ioformat': settings.IOFORMAT_KWARGS,
|
||||
},
|
||||
))
|
||||
def test_write_json_kwargs(tmpdir, add_kwargs):
|
||||
fs, filename, services = json_tester.get_services_for_writer(tmpdir)
|
||||
|
||||
|
||||
@ -5,7 +5,10 @@ from bonobo import Bag
|
||||
from bonobo.constants import INHERIT_INPUT
|
||||
from bonobo.structs import Token
|
||||
|
||||
args = ('foo', 'bar', )
|
||||
args = (
|
||||
'foo',
|
||||
'bar',
|
||||
)
|
||||
kwargs = dict(acme='corp')
|
||||
|
||||
|
||||
@ -38,11 +41,17 @@ def test_inherit():
|
||||
assert bag.kwargs == {'a': 1}
|
||||
assert bag.flags is ()
|
||||
|
||||
assert bag2.args == ('a', 'b', )
|
||||
assert bag2.args == (
|
||||
'a',
|
||||
'b',
|
||||
)
|
||||
assert bag2.kwargs == {'a': 1, 'b': 2}
|
||||
assert INHERIT_INPUT in bag2.flags
|
||||
|
||||
assert bag3.args == ('a', 'c', )
|
||||
assert bag3.args == (
|
||||
'a',
|
||||
'c',
|
||||
)
|
||||
assert bag3.kwargs == {'a': 1, 'c': 3}
|
||||
assert bag3.flags is ()
|
||||
|
||||
@ -51,12 +60,19 @@ def test_inherit():
|
||||
assert bag4.flags is ()
|
||||
|
||||
bag4.set_parent(bag)
|
||||
assert bag4.args == ('a', 'd', )
|
||||
assert bag4.args == (
|
||||
'a',
|
||||
'd',
|
||||
)
|
||||
assert bag4.kwargs == {'a': 1, 'd': 4}
|
||||
assert bag4.flags is ()
|
||||
|
||||
bag4.set_parent(bag3)
|
||||
assert bag4.args == ('a', 'c', 'd', )
|
||||
assert bag4.args == (
|
||||
'a',
|
||||
'c',
|
||||
'd',
|
||||
)
|
||||
assert bag4.kwargs == {'a': 1, 'c': 3, 'd': 4}
|
||||
assert bag4.flags is ()
|
||||
|
||||
|
||||
@ -3,7 +3,10 @@ from bonobo.util.statistics import WithStatistics
|
||||
|
||||
class MyThingWithStats(WithStatistics):
|
||||
def get_statistics(self, *args, **kwargs):
|
||||
return (('foo', 42), ('bar', 69), )
|
||||
return (
|
||||
('foo', 42),
|
||||
('bar', 69),
|
||||
)
|
||||
|
||||
|
||||
def test_with_statistics():
|
||||
|
||||
Reference in New Issue
Block a user