release: 0.2.2

This commit is contained in:
Romain Dorgueil
2017-04-28 08:04:48 +02:00
parent 9a3fa98723
commit bb5fc22f5e
21 changed files with 56 additions and 63 deletions

View File

@ -24,7 +24,6 @@ from bonobo.strategies import create_strategy
__all__ += ['create_strategy'] __all__ += ['create_strategy']
# Extract and loads from stdlib. # Extract and loads from stdlib.
from bonobo.io import * from bonobo.io import *
from bonobo.io import __all__ as _all_io from bonobo.io import __all__ as _all_io

View File

@ -1 +1 @@
__version__ = '0.2.1' __version__ = '0.2.2'

View File

@ -59,7 +59,13 @@ def execute(file, quiet=False):
# todo if console and not quiet, then add the console plugin # todo if console and not quiet, then add the console plugin
# todo when better console plugin, add it if console and just disable display # 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): def register(parser):

View File

@ -11,6 +11,7 @@ def validate_service_name(name):
raise ValueError('Invalid service name {!r}.'.format(name)) raise ValueError('Invalid service name {!r}.'.format(name))
return name return name
class Service(Option): class Service(Option):
""" """
A Service is a special kind of option defining a dependency to something that will be resolved at runtime, using an 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): def __new__(cls, *args, **kwargs):
if len(args) == 1: if len(args) == 1:
assert not len(kwargs), 'only one usage at a time, my dear.' assert not len(kwargs), 'only one usage at a time, my dear.'
if not(args[0]): if not (args[0]):
return super().__new__(cls) return super().__new__(cls)
if isinstance(args[0], cls): if isinstance(args[0], cls):
return cls return cls
@ -67,11 +68,7 @@ class Container(dict):
except AttributeError: except AttributeError:
options = {} options = {}
return tuple( return tuple(option.resolve(mixed, self) for name, option in options.items() if isinstance(option, Service))
option.resolve(mixed, self)
for name, option in options.items()
if isinstance(option, Service)
)
def get(self, name, default=None): def get(self, name, default=None):
if not name in self: if not name in self:
@ -82,7 +79,3 @@ class Container(dict):
if isinstance(value, types.LambdaType): if isinstance(value, types.LambdaType):
value = value(self) value = value(self)
return value return value

View File

@ -1,2 +1 @@
""" Core required libraries. """ """ Core required libraries. """

View File

@ -4,6 +4,4 @@ import bonobo
def get_services(): def get_services():
return { return {'fs': bonobo.open_fs(dirname(__file__))}
'fs': bonobo.open_fs(dirname(__file__))
}

View File

@ -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 # 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' 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( graph = bonobo.Graph(bonobo.JsonReader(path=url), print)
bonobo.JsonReader(path=url),
print
)
if __name__ == '__main__': if __name__ == '__main__':
bonobo.run(graph, services=get_default_services(__file__)) bonobo.run(graph, services=get_default_services(__file__))

View File

@ -2,6 +2,4 @@ from bonobo import get_examples_path, open_fs
def get_services(): def get_services():
return { return {'fs': open_fs(get_examples_path())}
'fs': open_fs(get_examples_path())
}

View File

@ -8,10 +8,8 @@ graph = bonobo.Graph(
def get_services(): def get_services():
return { return {'fs': bonobo.open_fs(bonobo.get_examples_path())}
'fs': bonobo.open_fs(bonobo.get_examples_path())
}
if __name__ == '__main__': if __name__ == '__main__':
bonobo.run(graph, services=get_default_services(__file__, get_services())) bonobo.run(graph, services=get_default_services(__file__, get_services()))

View File

@ -1,3 +1 @@
from bonobo.execution.graph import GraphExecutionContext, NodeExecutionContext, PluginExecutionContext from bonobo.execution.graph import GraphExecutionContext, NodeExecutionContext, PluginExecutionContext

View File

@ -30,7 +30,8 @@ class LoopingExecutionContext(Wrapper):
if services: if services:
if parent: if parent:
raise RuntimeError( 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() self.services = Container(services) if services else Container()
else: else:
self.services = None self.services = None

View File

@ -55,7 +55,7 @@ class CsvReader(CsvHandler, FileReader):
for row in reader: for row in reader:
if len(row) != field_count: 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)) yield dict(zip(headers.value, row))

View File

@ -2,6 +2,4 @@ from bonobo.structs.bags import Bag
from bonobo.structs.graphs import Graph from bonobo.structs.graphs import Graph
from bonobo.structs.tokens import Token from bonobo.structs.tokens import Token
__all__ = [ __all__ = ['Bag', 'Graph', 'Token']
'Bag', 'Graph', 'Token'
]

View File

@ -32,7 +32,8 @@ def deprecated_alias(alias, func):
warnings.simplefilter('always', DeprecationWarning) # turn off filter warnings.simplefilter('always', DeprecationWarning) # turn off filter
warnings.warn( warnings.warn(
"Call to deprecated function alias {}, use {} instead.".format(alias, func.__name__), "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 warnings.simplefilter('default', DeprecationWarning) # reset filter
return func(*args, **kwargs) return func(*args, **kwargs)

View File

@ -20,7 +20,7 @@ def force_iterator(mixed):
def ensure_tuple(tuple_or_mixed): def ensure_tuple(tuple_or_mixed):
if isinstance(tuple_or_mixed, tuple): if isinstance(tuple_or_mixed, tuple):
return tuple_or_mixed return tuple_or_mixed
return (tuple_or_mixed,) return (tuple_or_mixed, )
def iter_if_not_sequence(mixed): def iter_if_not_sequence(mixed):

View File

@ -1,8 +1,18 @@
Changelog 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(...). * 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). * Remove dependencies to toolz (which was unused) and blessings (which caused problems on windows).

View File

@ -40,40 +40,36 @@ setup(
name='bonobo', name='bonobo',
description='Bonobo', description='Bonobo',
license='Apache License, Version 2.0', license='Apache License, Version 2.0',
install_requires=[ install_requires=['colorama ==0.3.9', 'fs ==2.0.3', 'psutil ==5.2.2', 'requests ==2.13.0', 'stevedore ==1.21.0'],
'colorama ==0.3.9', 'fs ==2.0.3', 'psutil ==5.2.2',
'requests ==2.13.0', 'stevedore ==1.21.0'
],
version=version, version=version,
long_description=read('README.rst'), long_description=read('README.rst'),
classifiers=read('classifiers.txt', tolines), classifiers=read('classifiers.txt', tolines),
packages=find_packages(exclude=['ez_setup', 'example', 'test']), packages=find_packages(exclude=['ez_setup', 'example', 'test']),
include_package_data=True, include_package_data=True,
data_files=[('share/jupyter/nbextensions/bonobo-jupyter', [ data_files=[
'bonobo/ext/jupyter/static/extension.js', (
'bonobo/ext/jupyter/static/index.js', 'share/jupyter/nbextensions/bonobo-jupyter', [
'bonobo/ext/jupyter/static/index.js.map' 'bonobo/ext/jupyter/static/extension.js', 'bonobo/ext/jupyter/static/index.js',
])], 'bonobo/ext/jupyter/static/index.js.map'
]
)
],
extras_require={ extras_require={
'dev': [ 'dev': [
'coverage >=4,<5', 'pylint >=1,<2', 'pytest >=3,<4', 'coverage >=4,<5', 'pylint >=1,<2', 'pytest >=3,<4', 'pytest-cov >=2,<3', 'pytest-timeout >=1,<2', 'sphinx',
'pytest-cov >=2,<3', 'pytest-timeout >=1,<2', 'sphinx',
'sphinx_rtd_theme', 'yapf' 'sphinx_rtd_theme', 'yapf'
], ],
'jupyter': ['jupyter >=1.0,<1.1', 'ipywidgets >=6.0.0.beta5'] 'jupyter': ['jupyter >=1.0,<1.1', 'ipywidgets >=6.0.0.beta5']
}, },
entry_points={ entry_points={
'bonobo.commands': [ 'bonobo.commands': [
'init = bonobo.commands.init:register', 'init = bonobo.commands.init:register', 'run = bonobo.commands.run:register',
'run = bonobo.commands.run:register',
'version = bonobo.commands.version:register' 'version = bonobo.commands.version:register'
], ],
'console_scripts': ['bonobo = bonobo.commands:entrypoint'], 'console_scripts': ['bonobo = bonobo.commands:entrypoint'],
'edgy.project.features': 'edgy.project.features': ['bonobo = '
['bonobo = ' 'bonobo.ext.edgy.project.feature:BonoboFeature']
'bonobo.ext.edgy.project.feature:BonoboFeature']
}, },
url='https://www.bonobo-project.org/', url='https://www.bonobo-project.org/',
download_url= download_url='https://github.com/python-bonobo/bonobo/tarball/{version}'.format(version=version),
'https://github.com/python-bonobo/bonobo/tarball/{version}'.format( )
version=version), )

View File

@ -9,7 +9,7 @@ from bonobo.util.testing import CapturingNodeExecutionContext
@pytest.mark.parametrize( @pytest.mark.parametrize(
'lines,output', 'lines,output',
[ [
(('ACME',), 'ACME'), # one line... (('ACME', ), 'ACME'), # one line...
(('Foo', 'Bar', 'Baz'), 'Foo\nBar\nBaz'), # more than one line... (('Foo', 'Bar', 'Baz'), 'Foo\nBar\nBaz'), # more than one line...
] ]
) )

View File

@ -33,7 +33,9 @@ class ConcretePrinter(PrinterInterface):
class MyServiceDependantConfigurable(Configurable): class MyServiceDependantConfigurable(Configurable):
printer = Service(PrinterInterface, ) printer = Service(
PrinterInterface,
)
def __call__(self, printer: PrinterInterface, *args): def __call__(self, printer: PrinterInterface, *args):
return printer.print(*args) return printer.print(*args)

View File

@ -10,7 +10,7 @@ def generate_integers():
def square(i: int) -> int: def square(i: int) -> int:
return i ** 2 return i**2
@contextual @contextual

View File

@ -14,4 +14,3 @@ def test_wildcard_import():
continue continue
assert name in bonobo.__all__ assert name in bonobo.__all__