[config/dx] bundle a default fs (and http?) service if none is provided (#179)

This commit is contained in:
Romain Dorgueil
2017-10-05 07:17:16 +02:00
parent f7cf7ca482
commit b2f93b2416
13 changed files with 69 additions and 16 deletions

View File

@ -1,10 +1,10 @@
import logging import logging
from bonobo.structs import Bag, ErrorBag, Graph, Token
from bonobo.nodes import CsvReader, CsvWriter, FileReader, FileWriter, Filter, JsonReader, JsonWriter, Limit, \ from bonobo.nodes import CsvReader, CsvWriter, FileReader, FileWriter, Filter, JsonReader, JsonWriter, Limit, \
PickleReader, PickleWriter, PrettyPrinter, RateLimited, Tee, arg0_to_kwargs, count, identity, kwargs_to_arg0, noop PickleReader, PickleWriter, PrettyPrinter, RateLimited, Tee, arg0_to_kwargs, count, identity, kwargs_to_arg0, noop
from bonobo.strategies import create_strategy from bonobo.strategies import create_strategy
from bonobo.util.objects import get_name from bonobo.structs import Bag, ErrorBag, Graph, Token
from bonobo.util import get_name
__all__ = [] __all__ = []

View File

@ -1,7 +1,7 @@
from bonobo.config.configurables import Configurable from bonobo.config.configurables import Configurable
from bonobo.config.options import Method, Option from bonobo.config.options import Method, Option
from bonobo.config.processors import ContextProcessor from bonobo.config.processors import ContextProcessor
from bonobo.config.services import Container, Exclusive, Service, requires from bonobo.config.services import Container, Exclusive, Service, requires, create_container
use = requires use = requires
@ -14,6 +14,7 @@ __all__ = [
'Method', 'Method',
'Option', 'Option',
'Service', 'Service',
'create_container',
'requires', 'requires',
'use', 'use',
] ]

View File

@ -1,6 +1,5 @@
from bonobo.util.inspect import isoption, iscontextprocessor from bonobo.util import isoption, iscontextprocessor, sortedlist
from bonobo.errors import AbstractError from bonobo.errors import AbstractError
from bonobo.util.collections import sortedlist
__all__ = [ __all__ = [
'Configurable', 'Configurable',

View File

@ -95,6 +95,30 @@ class Container(dict):
return value return value
def create_container(services=None, factory=Container):
"""
Create a container with reasonable default service implementations for commonly use, standard-named, services.
Services:
- `fs` defaults to a fs2 instance based on current working directory
- `http`defaults to requests
:param services:
:return:
"""
container = factory(services) if services else factory()
if not 'fs' in container:
import bonobo
container.setdefault('fs', bonobo.open_fs())
if not 'http' in container:
import requests
container.setdefault('http', requests)
return container
class Exclusive(ContextDecorator): class Exclusive(ContextDecorator):
""" """
Decorator and context manager used to require exclusive usage of an object, most probably a service. It's usefull Decorator and context manager used to require exclusive usage of an object, most probably a service. It's usefull

View File

@ -2,7 +2,7 @@ import traceback
from contextlib import contextmanager from contextlib import contextmanager
from time import sleep from time import sleep
from bonobo.config import Container from bonobo.config import create_container
from bonobo.config.processors import ContextCurrifier from bonobo.config.processors import ContextCurrifier
from bonobo.plugins import get_enhancers from bonobo.plugins import get_enhancers
from bonobo.util.errors import print_error from bonobo.util.errors import print_error
@ -48,7 +48,7 @@ class LoopingExecutionContext(Wrapper):
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 = create_container(services)
else: else:
self.services = None self.services = None

View File

@ -1,6 +1,6 @@
from functools import partial from functools import partial
from bonobo.config.services import Container from bonobo.config import create_container
from bonobo.constants import BEGIN, END from bonobo.constants import BEGIN, END
from bonobo.execution.node import NodeExecutionContext from bonobo.execution.node import NodeExecutionContext
from bonobo.execution.plugin import PluginExecutionContext from bonobo.execution.plugin import PluginExecutionContext
@ -23,7 +23,7 @@ class GraphExecutionContext:
self.graph = graph self.graph = graph
self.nodes = [NodeExecutionContext(node, parent=self) for node in self.graph] self.nodes = [NodeExecutionContext(node, parent=self) for node in self.graph]
self.plugins = [PluginExecutionContext(plugin, parent=self) for plugin in plugins or ()] self.plugins = [PluginExecutionContext(plugin, parent=self) for plugin in plugins or ()]
self.services = Container(services) if services else Container() self.services = create_container(services)
# Probably not a good idea to use it unless you really know what you're doing. But you can access the context. # Probably not a good idea to use it unless you really know what you're doing. But you can access the context.
self.services['__graph_context'] = self self.services['__graph_context'] = self

View File

@ -4,11 +4,12 @@ import itertools
from bonobo import settings from bonobo import settings
from bonobo.config import Configurable, Option from bonobo.config import Configurable, Option
from bonobo.config.processors import ContextProcessor from bonobo.config.processors import ContextProcessor
from bonobo.constants import NOT_MODIFIED
from bonobo.structs.bags import Bag from bonobo.structs.bags import Bag
from bonobo.util.objects import ValueHolder from bonobo.util.objects import ValueHolder
from bonobo.util.term import CLEAR_EOL from bonobo.util.term import CLEAR_EOL
from bonobo.constants import NOT_MODIFIED
__all__ = [ __all__ = [
'Limit', 'Limit',
'PrettyPrinter', 'PrettyPrinter',

View File

@ -1,3 +1,4 @@
from bonobo.util.collections import sortedlist
from bonobo.util.inspect import ( from bonobo.util.inspect import (
inspect_node, inspect_node,
isbag, isbag,
@ -10,11 +11,18 @@ from bonobo.util.inspect import (
isoption, isoption,
istype, istype,
) )
from bonobo.util.objects import (
get_name,
get_attribute_or_create,
ValueHolder
)
from bonobo.util.python import require from bonobo.util.python import require
# Bonobo's util API # Bonobo's util API
__all__ = [ __all__ = [
'require', 'ValueHolder',
'get_attribute_or_create',
'get_name',
'inspect_node', 'inspect_node',
'isbag', 'isbag',
'isconfigurable', 'isconfigurable',
@ -25,4 +33,5 @@ __all__ = [
'ismethod', 'ismethod',
'isoption', 'isoption',
'istype', 'istype',
'require',
] ]

View File

@ -1,6 +1,5 @@
from collections import namedtuple from collections import namedtuple
from bonobo.constants import LOOPBACK
def isconfigurable(mixed): def isconfigurable(mixed):
@ -99,6 +98,7 @@ def isloopbackbag(mixed):
:param mixed: :param mixed:
:return: bool :return: bool
""" """
from bonobo.constants import LOOPBACK
return isbag(mixed) and LOOPBACK in mixed.flags return isbag(mixed) and LOOPBACK in mixed.flags

View File

@ -3,8 +3,9 @@ import time
import pytest import pytest
from bonobo.util import get_name
from bonobo.config import Configurable, Container, Exclusive, Service, requires from bonobo.config import Configurable, Container, Exclusive, Service, requires
from bonobo.config.services import validate_service_name from bonobo.config.services import validate_service_name, create_container
class PrinterInterface(): class PrinterInterface():
@ -108,3 +109,23 @@ def test_requires():
svcargs = services.args_for(append) svcargs = services.args_for(append)
assert len(svcargs) == 1 assert len(svcargs) == 1
assert svcargs[0] == vcr.append assert svcargs[0] == vcr.append
@pytest.mark.parametrize('services', [None, {}])
def test_create_container_empty_values(services):
c = create_container(services)
assert len(c) == 2
assert 'fs' in c and get_name(c['fs']) == 'OSFS'
assert 'http' in c and get_name(c['http']) == 'requests'
def test_create_container_override():
c = create_container({
'http': 'http',
'fs': 'fs',
})
assert len(c) == 2
assert 'fs' in c and c['fs'] == 'fs'
assert 'http' in c and c['http'] == 'http'

View File

@ -5,7 +5,6 @@ import pytest
import bonobo import bonobo
from bonobo.config.processors import ContextCurrifier from bonobo.config.processors import ContextCurrifier
from bonobo.constants import NOT_MODIFIED from bonobo.constants import NOT_MODIFIED
from bonobo.util.inspect import inspect_node
def test_count(): def test_count():

View File

@ -3,7 +3,6 @@ import runpy
import sys import sys
from unittest.mock import patch from unittest.mock import patch
import pathlib
import pkg_resources import pkg_resources
import pytest import pytest