diff --git a/bonobo/_api.py b/bonobo/_api.py index a566c58..c57a255 100644 --- a/bonobo/_api.py +++ b/bonobo/_api.py @@ -24,7 +24,6 @@ from bonobo.strategies import create_strategy __all__ += ['create_strategy'] - # Extract and loads from stdlib. from bonobo.io import * from bonobo.io import __all__ as _all_io diff --git a/bonobo/_version.py b/bonobo/_version.py index fc79d63..020ed73 100644 --- a/bonobo/_version.py +++ b/bonobo/_version.py @@ -1 +1 @@ -__version__ = '0.2.1' +__version__ = '0.2.2' diff --git a/bonobo/commands/run.py b/bonobo/commands/run.py index aa232d4..62f15c4 100644 --- a/bonobo/commands/run.py +++ b/bonobo/commands/run.py @@ -59,7 +59,13 @@ def execute(file, quiet=False): # todo if console and not quiet, then add the console plugin # todo when better console plugin, add it if console and just disable display - return bonobo.run(graph, plugins=[], services=get_default_services(file.name, context.get(DEFAULT_SERVICES_ATTR)() if DEFAULT_SERVICES_ATTR in context else None)) + return bonobo.run( + graph, + plugins=[], + services=get_default_services( + file.name, context.get(DEFAULT_SERVICES_ATTR)() if DEFAULT_SERVICES_ATTR in context else None + ) + ) def register(parser): diff --git a/bonobo/config/services.py b/bonobo/config/services.py index 8634868..86bc06b 100644 --- a/bonobo/config/services.py +++ b/bonobo/config/services.py @@ -11,6 +11,7 @@ def validate_service_name(name): raise ValueError('Invalid service name {!r}.'.format(name)) return name + class Service(Option): """ A Service is a special kind of option defining a dependency to something that will be resolved at runtime, using an @@ -55,7 +56,7 @@ class Container(dict): def __new__(cls, *args, **kwargs): if len(args) == 1: assert not len(kwargs), 'only one usage at a time, my dear.' - if not(args[0]): + if not (args[0]): return super().__new__(cls) if isinstance(args[0], cls): return cls @@ -67,11 +68,7 @@ class Container(dict): except AttributeError: options = {} - return tuple( - option.resolve(mixed, self) - for name, option in options.items() - if isinstance(option, Service) - ) + return tuple(option.resolve(mixed, self) for name, option in options.items() if isinstance(option, Service)) def get(self, name, default=None): if not name in self: @@ -82,7 +79,3 @@ class Container(dict): if isinstance(value, types.LambdaType): value = value(self) return value - - - - diff --git a/bonobo/core/__init__.py b/bonobo/core/__init__.py index f5f8416..086efcc 100644 --- a/bonobo/core/__init__.py +++ b/bonobo/core/__init__.py @@ -1,2 +1 @@ """ Core required libraries. """ - diff --git a/bonobo/examples/datasets/_services.py b/bonobo/examples/datasets/_services.py index 9998961..36d3b18 100644 --- a/bonobo/examples/datasets/_services.py +++ b/bonobo/examples/datasets/_services.py @@ -4,6 +4,4 @@ import bonobo def get_services(): - return { - 'fs': bonobo.open_fs(dirname(__file__)) - } + return {'fs': bonobo.open_fs(dirname(__file__))} diff --git a/bonobo/examples/files/_fixme_json_handlers.py b/bonobo/examples/files/_fixme_json_handlers.py index 37300f4..26d42c4 100644 --- a/bonobo/examples/files/_fixme_json_handlers.py +++ b/bonobo/examples/files/_fixme_json_handlers.py @@ -4,10 +4,7 @@ from bonobo.commands.run import get_default_services # XXX does not work anymore because of filesystem service, can't read HTTP url = 'https://data.toulouse-metropole.fr/explore/dataset/theatres-et-salles-de-spectacles/download?format=json&timezone=Europe/Berlin&use_labels_for_header=true' -graph = bonobo.Graph( - bonobo.JsonReader(path=url), - print -) +graph = bonobo.Graph(bonobo.JsonReader(path=url), print) if __name__ == '__main__': bonobo.run(graph, services=get_default_services(__file__)) diff --git a/bonobo/examples/files/_services.py b/bonobo/examples/files/_services.py index 27eb71a..337bf6b 100644 --- a/bonobo/examples/files/_services.py +++ b/bonobo/examples/files/_services.py @@ -2,6 +2,4 @@ from bonobo import get_examples_path, open_fs def get_services(): - return { - 'fs': open_fs(get_examples_path()) - } + return {'fs': open_fs(get_examples_path())} diff --git a/bonobo/examples/tutorials/tut02_01_read.py b/bonobo/examples/tutorials/tut02_01_read.py index 1c11a32..64816ce 100644 --- a/bonobo/examples/tutorials/tut02_01_read.py +++ b/bonobo/examples/tutorials/tut02_01_read.py @@ -8,10 +8,8 @@ graph = bonobo.Graph( def get_services(): - return { - 'fs': bonobo.open_fs(bonobo.get_examples_path()) - } + return {'fs': bonobo.open_fs(bonobo.get_examples_path())} + if __name__ == '__main__': bonobo.run(graph, services=get_default_services(__file__, get_services())) - diff --git a/bonobo/execution/__init__.py b/bonobo/execution/__init__.py index ad2defc..b8a83dd 100644 --- a/bonobo/execution/__init__.py +++ b/bonobo/execution/__init__.py @@ -1,3 +1 @@ from bonobo.execution.graph import GraphExecutionContext, NodeExecutionContext, PluginExecutionContext - - diff --git a/bonobo/execution/base.py b/bonobo/execution/base.py index c8357d6..9a96cb1 100644 --- a/bonobo/execution/base.py +++ b/bonobo/execution/base.py @@ -30,7 +30,8 @@ class LoopingExecutionContext(Wrapper): if services: if parent: raise RuntimeError( - 'Having services defined both in GraphExecutionContext and child NodeExecutionContext is not supported, for now.') + 'Having services defined both in GraphExecutionContext and child NodeExecutionContext is not supported, for now.' + ) self.services = Container(services) if services else Container() else: self.services = None diff --git a/bonobo/io/csv.py b/bonobo/io/csv.py index df84557..9192fc3 100644 --- a/bonobo/io/csv.py +++ b/bonobo/io/csv.py @@ -55,7 +55,7 @@ class CsvReader(CsvHandler, FileReader): 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 dict(zip(headers.value, row)) diff --git a/bonobo/structs/__init__.py b/bonobo/structs/__init__.py index bd9361e..15e76a9 100644 --- a/bonobo/structs/__init__.py +++ b/bonobo/structs/__init__.py @@ -2,6 +2,4 @@ from bonobo.structs.bags import Bag from bonobo.structs.graphs import Graph from bonobo.structs.tokens import Token -__all__ = [ - 'Bag', 'Graph', 'Token' -] +__all__ = ['Bag', 'Graph', 'Token'] diff --git a/bonobo/util/compat.py b/bonobo/util/compat.py index 35b2500..68c4c9c 100644 --- a/bonobo/util/compat.py +++ b/bonobo/util/compat.py @@ -32,7 +32,8 @@ def deprecated_alias(alias, func): warnings.simplefilter('always', DeprecationWarning) # turn off filter warnings.warn( "Call to deprecated function alias {}, use {} instead.".format(alias, func.__name__), - category=DeprecationWarning, stacklevel=2 + category=DeprecationWarning, + stacklevel=2 ) warnings.simplefilter('default', DeprecationWarning) # reset filter return func(*args, **kwargs) diff --git a/bonobo/util/iterators.py b/bonobo/util/iterators.py index cdf02a7..142b35a 100644 --- a/bonobo/util/iterators.py +++ b/bonobo/util/iterators.py @@ -20,10 +20,10 @@ def force_iterator(mixed): def ensure_tuple(tuple_or_mixed): if isinstance(tuple_or_mixed, tuple): return tuple_or_mixed - return (tuple_or_mixed,) + return (tuple_or_mixed, ) def iter_if_not_sequence(mixed): if isinstance(mixed, (dict, list, str)): raise TypeError(type(mixed).__name__) - return iter(mixed) \ No newline at end of file + return iter(mixed) diff --git a/docs/changelog.rst b/docs/changelog.rst index ea9eaa0..f9e2145 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,8 +1,18 @@ Changelog ========= -v.0.2.1 -::::::: +v.0.2.2 - 28 apr 2017 +::::::::::::::::::::: + +* First implementation of services and basic injection. +* Default service configuration for directories and files. +* Code structure refactoring. +* Critical bug fix in default strategy causing end of pipeline not to terminate correctly. +* Force tighter dependency management to avoid unexpected upgrade problems. +* Filesystems are now injected as a service, using new filesystem2 (fs) dependency. + +v.0.2.1 - 25 apr 2017 +::::::::::::::::::::: * Plugins (jupyter, console) are now auto-activated depending on the environment when using bonobo.run(...). * Remove dependencies to toolz (which was unused) and blessings (which caused problems on windows). diff --git a/setup.py b/setup.py index ed9b4da..5b276f8 100644 --- a/setup.py +++ b/setup.py @@ -40,40 +40,36 @@ setup( name='bonobo', description='Bonobo', license='Apache License, Version 2.0', - install_requires=[ - 'colorama ==0.3.9', 'fs ==2.0.3', 'psutil ==5.2.2', - 'requests ==2.13.0', 'stevedore ==1.21.0' - ], + install_requires=['colorama ==0.3.9', 'fs ==2.0.3', 'psutil ==5.2.2', 'requests ==2.13.0', 'stevedore ==1.21.0'], version=version, long_description=read('README.rst'), classifiers=read('classifiers.txt', tolines), packages=find_packages(exclude=['ez_setup', 'example', 'test']), include_package_data=True, - data_files=[('share/jupyter/nbextensions/bonobo-jupyter', [ - 'bonobo/ext/jupyter/static/extension.js', - 'bonobo/ext/jupyter/static/index.js', - 'bonobo/ext/jupyter/static/index.js.map' - ])], + data_files=[ + ( + 'share/jupyter/nbextensions/bonobo-jupyter', [ + 'bonobo/ext/jupyter/static/extension.js', 'bonobo/ext/jupyter/static/index.js', + 'bonobo/ext/jupyter/static/index.js.map' + ] + ) + ], extras_require={ 'dev': [ - 'coverage >=4,<5', 'pylint >=1,<2', 'pytest >=3,<4', - 'pytest-cov >=2,<3', 'pytest-timeout >=1,<2', 'sphinx', + 'coverage >=4,<5', 'pylint >=1,<2', 'pytest >=3,<4', 'pytest-cov >=2,<3', 'pytest-timeout >=1,<2', 'sphinx', 'sphinx_rtd_theme', 'yapf' ], 'jupyter': ['jupyter >=1.0,<1.1', 'ipywidgets >=6.0.0.beta5'] }, entry_points={ 'bonobo.commands': [ - 'init = bonobo.commands.init:register', - 'run = bonobo.commands.run:register', + 'init = bonobo.commands.init:register', 'run = bonobo.commands.run:register', 'version = bonobo.commands.version:register' ], 'console_scripts': ['bonobo = bonobo.commands:entrypoint'], - 'edgy.project.features': - ['bonobo = ' - 'bonobo.ext.edgy.project.feature:BonoboFeature'] + 'edgy.project.features': ['bonobo = ' + 'bonobo.ext.edgy.project.feature:BonoboFeature'] }, url='https://www.bonobo-project.org/', - download_url= - 'https://github.com/python-bonobo/bonobo/tarball/{version}'.format( - version=version), ) + download_url='https://github.com/python-bonobo/bonobo/tarball/{version}'.format(version=version), +) diff --git a/tests/io/test_file.py b/tests/io/test_file.py index 75740e9..dc011a1 100644 --- a/tests/io/test_file.py +++ b/tests/io/test_file.py @@ -9,7 +9,7 @@ from bonobo.util.testing import CapturingNodeExecutionContext @pytest.mark.parametrize( 'lines,output', [ - (('ACME',), 'ACME'), # one line... + (('ACME', ), 'ACME'), # one line... (('Foo', 'Bar', 'Baz'), 'Foo\nBar\nBaz'), # more than one line... ] ) diff --git a/tests/test_config.py b/tests/test_config.py index e8cf2b9..3c46fbc 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -33,7 +33,9 @@ class ConcretePrinter(PrinterInterface): class MyServiceDependantConfigurable(Configurable): - printer = Service(PrinterInterface, ) + printer = Service( + PrinterInterface, + ) def __call__(self, printer: PrinterInterface, *args): return printer.print(*args) diff --git a/tests/test_execution.py b/tests/test_execution.py index 921e8d9..5f9067b 100644 --- a/tests/test_execution.py +++ b/tests/test_execution.py @@ -10,7 +10,7 @@ def generate_integers(): def square(i: int) -> int: - return i ** 2 + return i**2 @contextual diff --git a/tests/test_publicapi.py b/tests/test_publicapi.py index 888e462..0ce6323 100644 --- a/tests/test_publicapi.py +++ b/tests/test_publicapi.py @@ -14,4 +14,3 @@ def test_wildcard_import(): continue assert name in bonobo.__all__ -