[config/dx] bundle a default fs (and http?) service if none is provided (#179)
This commit is contained in:
@ -1,10 +1,10 @@
|
||||
import logging
|
||||
|
||||
from bonobo.structs import Bag, ErrorBag, Graph, Token
|
||||
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
|
||||
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__ = []
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
from bonobo.config.configurables import Configurable
|
||||
from bonobo.config.options import Method, Option
|
||||
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
|
||||
|
||||
@ -14,6 +14,7 @@ __all__ = [
|
||||
'Method',
|
||||
'Option',
|
||||
'Service',
|
||||
'create_container',
|
||||
'requires',
|
||||
'use',
|
||||
]
|
||||
|
||||
@ -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.util.collections import sortedlist
|
||||
|
||||
__all__ = [
|
||||
'Configurable',
|
||||
|
||||
@ -95,6 +95,30 @@ class Container(dict):
|
||||
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):
|
||||
"""
|
||||
Decorator and context manager used to require exclusive usage of an object, most probably a service. It's usefull
|
||||
|
||||
@ -6,4 +6,4 @@ INHERIT_INPUT = Token('InheritInput')
|
||||
LOOPBACK = Token('Loopback')
|
||||
NOT_MODIFIED = Token('NotModified')
|
||||
DEFAULT_SERVICES_FILENAME = '_services.py'
|
||||
DEFAULT_SERVICES_ATTR = 'get_services'
|
||||
DEFAULT_SERVICES_ATTR = 'get_services'
|
||||
|
||||
@ -2,7 +2,7 @@ import traceback
|
||||
from contextlib import contextmanager
|
||||
from time import sleep
|
||||
|
||||
from bonobo.config import Container
|
||||
from bonobo.config import create_container
|
||||
from bonobo.config.processors import ContextCurrifier
|
||||
from bonobo.plugins import get_enhancers
|
||||
from bonobo.util.errors import print_error
|
||||
@ -48,7 +48,7 @@ class LoopingExecutionContext(Wrapper):
|
||||
raise RuntimeError(
|
||||
'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:
|
||||
self.services = None
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
from functools import partial
|
||||
|
||||
from bonobo.config.services import Container
|
||||
from bonobo.config import create_container
|
||||
from bonobo.constants import BEGIN, END
|
||||
from bonobo.execution.node import NodeExecutionContext
|
||||
from bonobo.execution.plugin import PluginExecutionContext
|
||||
@ -23,7 +23,7 @@ class GraphExecutionContext:
|
||||
self.graph = graph
|
||||
self.nodes = [NodeExecutionContext(node, parent=self) for node in self.graph]
|
||||
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.
|
||||
self.services['__graph_context'] = self
|
||||
|
||||
@ -4,11 +4,12 @@ import itertools
|
||||
from bonobo import settings
|
||||
from bonobo.config import Configurable, Option
|
||||
from bonobo.config.processors import ContextProcessor
|
||||
from bonobo.constants import NOT_MODIFIED
|
||||
from bonobo.structs.bags import Bag
|
||||
from bonobo.util.objects import ValueHolder
|
||||
from bonobo.util.term import CLEAR_EOL
|
||||
|
||||
from bonobo.constants import NOT_MODIFIED
|
||||
|
||||
__all__ = [
|
||||
'Limit',
|
||||
'PrettyPrinter',
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
from bonobo.util.collections import sortedlist
|
||||
from bonobo.util.inspect import (
|
||||
inspect_node,
|
||||
isbag,
|
||||
@ -10,11 +11,18 @@ from bonobo.util.inspect import (
|
||||
isoption,
|
||||
istype,
|
||||
)
|
||||
from bonobo.util.objects import (
|
||||
get_name,
|
||||
get_attribute_or_create,
|
||||
ValueHolder
|
||||
)
|
||||
from bonobo.util.python import require
|
||||
|
||||
# Bonobo's util API
|
||||
__all__ = [
|
||||
'require',
|
||||
'ValueHolder',
|
||||
'get_attribute_or_create',
|
||||
'get_name',
|
||||
'inspect_node',
|
||||
'isbag',
|
||||
'isconfigurable',
|
||||
@ -25,4 +33,5 @@ __all__ = [
|
||||
'ismethod',
|
||||
'isoption',
|
||||
'istype',
|
||||
'require',
|
||||
]
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
from collections import namedtuple
|
||||
|
||||
from bonobo.constants import LOOPBACK
|
||||
|
||||
|
||||
def isconfigurable(mixed):
|
||||
@ -99,6 +98,7 @@ def isloopbackbag(mixed):
|
||||
:param mixed:
|
||||
:return: bool
|
||||
"""
|
||||
from bonobo.constants import LOOPBACK
|
||||
return isbag(mixed) and LOOPBACK in mixed.flags
|
||||
|
||||
|
||||
|
||||
@ -3,8 +3,9 @@ import time
|
||||
|
||||
import pytest
|
||||
|
||||
from bonobo.util import get_name
|
||||
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():
|
||||
@ -108,3 +109,23 @@ def test_requires():
|
||||
svcargs = services.args_for(append)
|
||||
assert len(svcargs) == 1
|
||||
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'
|
||||
|
||||
|
||||
|
||||
@ -5,7 +5,6 @@ import pytest
|
||||
import bonobo
|
||||
from bonobo.config.processors import ContextCurrifier
|
||||
from bonobo.constants import NOT_MODIFIED
|
||||
from bonobo.util.inspect import inspect_node
|
||||
|
||||
|
||||
def test_count():
|
||||
|
||||
@ -3,7 +3,6 @@ import runpy
|
||||
import sys
|
||||
from unittest.mock import patch
|
||||
|
||||
import pathlib
|
||||
import pkg_resources
|
||||
import pytest
|
||||
|
||||
|
||||
Reference in New Issue
Block a user