Positional options (WIP).

This commit is contained in:
Romain Dorgueil
2017-05-01 15:26:57 +02:00
parent b4716f9cee
commit 25253cf119
5 changed files with 46 additions and 6 deletions

View File

@ -1,7 +1,7 @@
# bonobo (see github.com/python-edgy/project) # bonobo (see github.com/python-edgy/project)
name = 'bonobo' name = 'bonobo'
description = 'Bonobo' description = 'Bonobo, a simple, modern and atomic extract-transform-load toolkit for python 3.5+.'
license = 'Apache License, Version 2.0' license = 'Apache License, Version 2.0'
url = 'https://www.bonobo-project.org/' url = 'https://www.bonobo-project.org/'

View File

@ -1,5 +1,32 @@
from bonobo.config.options import Option from bonobo.config.options import Option
__all__ = [
'Configurable',
'Option',
]
_options_insert_order = 0
class Option:
def __init__(self, type=None, *, required=False, positional=False, default=None):
self.name = None
self.type = type
self.required = required
self.positional = positional
self.default = default
global _options_insert_order
self.order = _options_insert_order
_options_insert_order += 1
def __get__(self, inst, typ):
if not self.name in inst.__options_values__:
inst.__options_values__[self.name] = self.default() if callable(self.default) else self.default
return inst.__options_values__[self.name]
def __set__(self, inst, value):
inst.__options_values__[self.name] = self.type(value) if self.type else value
class ConfigurableMeta(type): class ConfigurableMeta(type):
""" """
@ -25,15 +52,18 @@ class Configurable(metaclass=ConfigurableMeta):
""" """
def __init__(self, **kwargs): def __init__(self, *args, **kwargs):
super().__init__() super().__init__()
self.__options_values__ = {} self.__options_values__ = {}
missing = set() missing = list()
for name, option in type(self).__options__.items(): for name, option in type(self).__options__.items():
if option.required and not option.name in kwargs: if option.required and not option.name in kwargs:
missing.add(name) missing.append(name)
for i in range(min(len(args), len(missing))):
kwargs
if len(missing): if len(missing):
raise TypeError( raise TypeError(

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

@ -8,7 +8,7 @@ __all__ = [
] ]
class JsonHandler: class JsonHandler():
eol = ',\n' eol = ',\n'
prefix, suffix = '[', ']' prefix, suffix = '[', ']'

View File

@ -18,6 +18,11 @@ class MyHarderConfigurable(MyConfigurable):
class MyBetterConfigurable(MyConfigurable): class MyBetterConfigurable(MyConfigurable):
required_str = Option(str, required=False, default='kaboom') required_str = Option(str, required=False, default='kaboom')
class MyConfigurableUsingPositionalOptions(MyConfigurable):
first = Option(str, required=True, positional=True)
second = Option(str, required=True, positional=True)
third = Option(str, required=False, positional=True)
class PrinterInterface(): class PrinterInterface():
def print(self, *args): def print(self, *args):
@ -133,3 +138,8 @@ def test_service_dependency_unavailable():
o = MyServiceDependantConfigurable(printer='printer2') o = MyServiceDependantConfigurable(printer='printer2')
with pytest.raises(KeyError): with pytest.raises(KeyError):
SERVICES.args_for(o) SERVICES.args_for(o)
def test_option_positional():
o = MyConfigurableUsingPositionalOptions('1', '2', '3', required_str='hello')