diff --git a/docs/function.rst b/docs/function.rst index b112323..21ba2a9 100644 --- a/docs/function.rst +++ b/docs/function.rst @@ -54,7 +54,7 @@ forms: pyws supports the following types: .. automodule:: pyws.functions.args.types - :members: String,Integer,Float,Boolean,Date,DateTime,Dict,List + :members: String,Integer,Long,Float,Boolean,Date,DateTime,Dict,List,FunctionPointerDict Three helper functions are also at your disposal: diff --git a/src/pyws/functions/args/types/__init__.py b/src/pyws/functions/args/types/__init__.py index c3dfb51..c158909 100644 --- a/src/pyws/functions/args/types/__init__.py +++ b/src/pyws/functions/args/types/__init__.py @@ -15,7 +15,9 @@ def __str__(self): # The order matters: DateTime should be placed before Date. # date is a superclass of datetime, thus Date will catch all DateTime fields. -__types__ = (String, Boolean, Integer, Float, DateTime, Date, Dict, List) +__types__ = ( + String, Boolean, Long, Integer, Float, DateTime, Date, Dict, List, + FunctionPointerDict) def TypeFactory(type_): diff --git a/src/pyws/functions/args/types/complex.py b/src/pyws/functions/args/types/complex.py index 265b5a9..aec6a3e 100644 --- a/src/pyws/functions/args/types/complex.py +++ b/src/pyws/functions/args/types/complex.py @@ -1,14 +1,68 @@ from pyws.functions.args.types.base import Type -__all__ = ('DICT_NAME_KEY', 'Dict', 'List', 'DictOf', 'ListOf') - +__all__ = ( + 'DICT_NAME_KEY', 'Dict', 'List', 'DictOf', 'ListOf', 'FunctionPointerDict') +__cached_function_pointer_dict_type__ = {} DICT_NAME_KEY = 0 + class BadType(Exception): pass +class FunctionPointerDict(Type): + """ + Represents dicts, returned by a function pointer, like lambda. + Refer to type ``Dict`` for additionnal informations. + """ + + fields = [] + + @classmethod + def represents(cls, type_): + import operator + if operator.isCallable(type_) and not isinstance(type_, type): + return isinstance(type_(), dict) + return False + + @classmethod + def get(cls, type_): + type_ = type_() + try: + dict_name = type_[DICT_NAME_KEY] + except KeyError: + raise BadType('%s is required for Dict type' % repr(DICT_NAME_KEY)) + + if dict_name in __cached_function_pointer_dict_type__: + return __cached_function_pointer_dict_type__[dict_name] + + ret = type(dict_name, (Dict,), {'fields': []}) + __cached_function_pointer_dict_type__[dict_name] = ret + + fields = [ + isinstance(type_, tuple) and (name,) + type_ or (name, type_) + for name, type_ in type_.iteritems() if name != DICT_NAME_KEY] + + ret.add_fields(*fields) + + return ret + + @classmethod + def add_fields(cls, *fields): + from pyws.functions.args.field import FieldFactory + fields_ = [] + for field in fields: + fields_.append(FieldFactory(field)) + cls.fields += fields_ + + @classmethod + def _validate(cls, value): + return dict( + (field.name, field.validate(field.get_value(value))) + for field in cls.fields) + + class Dict(Type): """ Represents dicts, simplified form is @@ -100,7 +154,7 @@ def DictOf(name, *fields): 2 """ ret = type(name, (Dict,), {'fields': []}) - #noinspection PyUnresolvedReferences + # noinspection PyUnresolvedReferences ret.add_fields(*fields) return ret diff --git a/src/pyws/functions/args/types/simple.py b/src/pyws/functions/args/types/simple.py index c377e5d..e3b5491 100644 --- a/src/pyws/functions/args/types/simple.py +++ b/src/pyws/functions/args/types/simple.py @@ -5,7 +5,8 @@ from pyws.functions.args.types.base import Type -__all__ = ('String', 'Boolean', 'Integer', 'Float', 'Date', 'DateTime', ) +__all__ = ( + 'String', 'Boolean', 'Long', 'Integer', 'Float', 'Date', 'DateTime',) class String(Type): @@ -27,6 +28,7 @@ def _validate(cls, value): except UnicodeDecodeError: return unicode(value, 'utf-8') + class Boolean(Type): """ Represents boolean values, simplified form is ``bool``, default @@ -49,6 +51,19 @@ def serialize(cls, value): return unicode(value).lower() +class Long(Type): + """ + Represents long numbers, simplified form is ``long``, default + ``none_value`` is ``None``. + """ + + _represents = long + + @classmethod + def _validate(cls, value): + return long(value) + + class Integer(Type): """ Represents integer numbers, simplified form is ``int``, default @@ -99,6 +114,7 @@ def serialize(cls, value): tz_re = re.compile('((\\+|-)(\d\d):?(\d\d))$') + class DateTime(Date): """ Represents datetime values, simplified form is ``datetime``, default diff --git a/src/pyws/protocols/soap/xsd.py b/src/pyws/protocols/soap/xsd.py index 8731f14..1c89554 100644 --- a/src/pyws/protocols/soap/xsd.py +++ b/src/pyws/protocols/soap/xsd.py @@ -48,6 +48,7 @@ class String(SimpleType): def get_name(self): return 'string', 'http://www.w3.org/2001/XMLSchema' + class Boolean(SimpleType): _represents = args.Boolean @@ -55,6 +56,15 @@ class Boolean(SimpleType): def get_name(self): return 'boolean', 'http://www.w3.org/2001/XMLSchema' + +class Long(SimpleType): + + _represents = args.Long + + def get_name(self): + return 'long', 'http://www.w3.org/2001/XMLSchema' + + class Integer(SimpleType): _represents = args.Integer @@ -142,7 +152,8 @@ def get_children(self, sequence, types): # The order matters: DateTime should be placed before Date. # Date is a superclass of DateTime, thus Date will catch all DateTime fields. -__types__ = (String, Boolean, Integer, Float, DateTime, Date, Dict, List) +__types__ = (String, Boolean, Long, Integer, Float, DateTime, Date, Dict, List) + def TypeFactory(type, ns=None, nsmap=None): for x in __types__: