class User(properties.HasProperties): """Class representing a user instance""" _model_api_location = "user" email = properties.GettableProperty(doc='Email', ) name = properties.GettableProperty(doc='Name', ) url = properties.GettableProperty(doc='URL', ) affiliation = properties.GettableProperty(doc='Affiliation', ) location = properties.GettableProperty(doc='Location', ) username = properties.GettableProperty(doc='Username', ) devel_key = properties.GettableProperty(doc='Developer API Key', ) file_size_limit = properties.GettableProperty( doc='Inidividual file limit', ) project_size_limit = properties.GettableProperty( doc='Project size limit', ) project_resource_limit = properties.GettableProperty( doc='Maximum resources in a project', ) def login_with_json(self, login_json): self._backend['username'] = login_json['uid'] self._backend['email'] = login_json['email'] self._backend['name'] = login_json['name'] self._backend['url'] = login_json['url'] self._backend['affiliation'] = login_json['affiliation'] self._backend['location'] = login_json['location'] self._backend['file_size_limit'] = login_json.get( 'file_size_limit', 26214400) self._backend['project_size_limit'] = login_json.get( 'project_size_limit', 104857600) self._backend['project_resource_limit'] = login_json.get( 'project_resource_limit', 100) def set_key(self, devel_key): self._backend['devel_key'] = devel_key def logout(self): self._backend.pop('username', None) self._backend.pop('email', None) self._backend.pop('name', None) self._backend.pop('url', None) self._backend.pop('affiliation', None) self._backend.pop('location', None) self._backend.pop('devel_key', None) self._backend.pop('file_size_limit', None) self._backend.pop('project_size_limit', None) self._backend.pop('project_resource_limit', None) @property def logged_in(self): return self.username is not None
class HasProps2(properties.HasProperties): my_list = properties.List('my list', properties.Bool('')) five = properties.GettableProperty('five', default=5) my_array = properties.Vector3Array('my array')
class GettablePropOpt(properties.HasProperties): mygp = properties.GettableProperty('gettable prop', default=twelve)
class GettablePropOpt(properties.HasProperties): mygp = properties.GettableProperty('gettable prop')
def test_base_functionality(self): with self.assertRaises(AttributeError): properties.GettableProperty('bad kwarg', _default=5) with self.assertRaises(AttributeError): properties.GettableProperty('bad kwarg', defualt=5) with self.assertRaises(TypeError): properties.Property('bad kwarg', required=5) class GettablePropOpt(properties.HasProperties): mygp = properties.GettableProperty('gettable prop') with self.assertRaises(TypeError): GettablePropOpt._props['mygp'].name = 5 with self.assertRaises(TypeError): GettablePropOpt._props['mygp'].doc = 5 with self.assertRaises(TypeError): GettablePropOpt._props['mygp'].terms = 5 with self.assertRaises(TypeError): GettablePropOpt._props['mygp'].terms = {'one': 1, 'two': 2} with self.assertRaises(TypeError): GettablePropOpt._props['mygp'].doc = {'args': (1,), 'otherargs': 5} gpo = GettablePropOpt() with self.assertRaises(AttributeError): setattr(gpo, 'mygp', 5) with self.assertRaises(AttributeError): GettablePropOpt(not_mygp=0) with self.assertRaises(AttributeError): GettablePropOpt(help='help') assert gpo.validate() assert gpo._props['mygp'].terms.name == 'mygp' assert gpo._props['mygp'].terms.cls is properties.GettableProperty assert gpo._props['mygp'].terms.args == ('gettable prop',) assert gpo._props['mygp'].terms.kwargs == {} assert gpo._props['mygp'].terms.meta == {} def twelve(): return 12 class GettablePropOpt(properties.HasProperties): mygp = properties.GettableProperty('gettable prop', default=twelve) assert GettablePropOpt().validate() assert GettablePropOpt().mygp == 12 class PropOpts(properties.HasProperties): myprop = properties.Property('empty property') maybe_none = properties.Property('maybe None', required=False) with self.assertRaises(ValueError): PropOpts().validate() assert PropOpts(myprop=5).validate() with warnings.catch_warnings(record=True) as w: assert PropOpts().equal(PropOpts()) assert len(w) == 1 assert issubclass(w[0].category, FutureWarning) assert properties.equal(PropOpts(), PropOpts()) assert properties.equal(PropOpts(myprop=5), PropOpts(myprop=5)) assert not properties.equal(PropOpts(myprop=5, maybe_none=3), PropOpts(myprop=5)) assert properties.equal(PropOpts(myprop=5, maybe_none=3), PropOpts(myprop=5, maybe_none=3)) assert not properties.equal(PropOpts(myprop=5), PropOpts()) assert not properties.equal(PropOpts(myprop=5), PropOpts(myprop=6)) assert not properties.equal(None, PropOpts(myprop=6)) assert not properties.equal(PropOpts(myprop=5), None) assert properties.equal(None, None) assert properties.Property('').equal(5, 5) assert not properties.Property('').equal(5, 'hi') assert properties.Property('').equal(np.array([1., 2.]), np.array([1., 2.])) assert not properties.Property('').equal(np.array([1., 2.]), np.array([3., 4.])) class NoAttributes(properties.HasProperties): a = properties.Integer('a') def __setattr__(self, attr, value): if attr[0] != '_' and value is not properties.undefined: raise AttributeError() return super(NoAttributes, self).__setattr__(attr, value) na = NoAttributes() with self.assertRaises(AttributeError): na.a = 5
class PrivateProperty(properties.HasProperties): _secret = properties.GettableProperty('secret prop')
def test_base_functionality(self): with self.assertRaises(AttributeError): properties.GettableProperty('bad kwarg', _default=5) with self.assertRaises(AttributeError): properties.GettableProperty('bad kwarg', defualt=5) with self.assertRaises(TypeError): properties.Property('bad kwarg', required=5) with self.assertRaises(AttributeError): class PrivateProperty(properties.HasProperties): _secret = properties.GettableProperty('secret prop') class GettablePropOpt(properties.HasProperties): mygp = properties.GettableProperty('gettable prop') with self.assertRaises(TypeError): GettablePropOpt._props['mygp'].name = 5 with self.assertRaises(TypeError): GettablePropOpt._props['mygp'].doc = 5 with self.assertRaises(TypeError): GettablePropOpt._props['mygp'].terms = 5 with self.assertRaises(TypeError): GettablePropOpt._props['mygp'].terms = {'one': 1, 'two': 2} with self.assertRaises(TypeError): GettablePropOpt._props['mygp'].doc = { 'args': (1, ), 'otherargs': 5 } gpo = GettablePropOpt() with self.assertRaises(AttributeError): setattr(gpo, 'mygp', 5) with self.assertRaises(AttributeError): GettablePropOpt(not_mygp=0) with self.assertRaises(AttributeError): GettablePropOpt(help='help') assert gpo.validate() assert gpo._props['mygp'].terms.name == 'mygp' assert gpo._props['mygp'].terms.cls is properties.GettableProperty assert gpo._props['mygp'].terms.args == ('gettable prop', ) assert gpo._props['mygp'].terms.kwargs == {} assert gpo._props['mygp'].terms.meta == {} def twelve(): return 12 class GettablePropOpt(properties.HasProperties): mygp = properties.GettableProperty('gettable prop', default=twelve) assert GettablePropOpt().validate() assert GettablePropOpt().mygp == 12 class PropOpts(properties.HasProperties): myprop = properties.Property('empty property') with self.assertRaises(ValueError): PropOpts().validate() assert PropOpts(myprop=5).validate() with warnings.catch_warnings(record=True) as w: assert PropOpts().equal(PropOpts()) assert len(w) == 1 assert issubclass(w[0].category, FutureWarning) assert properties.equal(PropOpts(), PropOpts()) assert properties.equal(PropOpts(myprop=5), PropOpts(myprop=5)) assert not properties.equal(PropOpts(myprop=5), PropOpts()) assert not properties.equal(PropOpts(myprop=5), PropOpts(myprop=6)) with self.assertRaises(AttributeError): class BadDocOrder(properties.HasProperties): _doc_order = 5 with self.assertRaises(AttributeError): class BadDocOrder(properties.HasProperties): _doc_order = ['myprop', 'another_prop'] myprop = properties.Property('empty property') class WithDocOrder(properties.HasProperties): _doc_order = ['myprop1', 'myprop3', 'myprop2'] myprop1 = properties.Property('empty property') myprop2 = properties.Property('empty property') myprop3 = properties.Property('empty property') assert WithDocOrder().__doc__ == ( '\n\n**Required Properties:**\n\n' '* **myprop1** (:class:`Property <properties.Property>`): ' 'empty property\n' '* **myprop3** (:class:`Property <properties.Property>`): ' 'empty property\n' '* **myprop2** (:class:`Property <properties.Property>`): ' 'empty property') class NoMoreDocOrder(WithDocOrder): _doc_order = None assert properties.Property('').equal(5, 5) assert not properties.Property('').equal(5, 'hi') assert properties.Property('').equal(np.array([1., 2.]), np.array([1., 2.])) assert not properties.Property('').equal(np.array([1., 2.]), np.array([3., 4.]))
class UidModel(properties.HasProperties): """UidModel is a HasProperties object with uid""" _REGISTRY = OrderedDict() uid = properties.Uuid('Unique identifier', serializer=lambda val, **kwargs: None, deserializer=lambda val, **kwargs: None) date_created = properties.GettableProperty( 'Date project was created', default=datetime.datetime.utcnow, serializer=properties.DateTime.to_json, deserializer=lambda val, **kwargs: None) date_modified = properties.GettableProperty( 'Date project was modified', default=datetime.datetime.utcnow, serializer=properties.DateTime.to_json, deserializer=lambda val, **kwargs: None) @properties.observer(properties.everything) def _modify(self, _): """Update date_modified whenever anything changes""" self._backend['date_modified'] = datetime.datetime.utcnow() @properties.validator def _update_date_modified(self): """Update date_modified if any contained UidModel has been modified""" for val in self._backend.values(): if (isinstance(val, UidModel) and val.date_modified > self.date_modified): self._backend['date_modified'] = val.date_modified def serialize( self, include_class=True, registry=None, #pylint: disable=arguments-differ skip_validation=False, **kwargs): """Serialize nested UidModels to a flat dictionary with pointers""" if registry is None: if not skip_validation: self.validate() registry = dict() root = True else: root = False if str(self.uid) not in registry: registry.update({ str(self.uid): super(UidModel, self).serialize(include_class, registry=registry, **kwargs) }) if root: return registry return str(self.uid) @classmethod def deserialize(cls, uid, trusted=True, registry=None, **kwargs): #pylint: disable=arguments-differ """Deserialize nested UidModels from flat pointer dictionary""" if registry is None: raise ValueError('no registry provided') if uid not in registry: raise ValueError('uid not found: {}'.format(uid)) if not isinstance(registry[uid], UidModel): date_created = registry[uid]['date_created'] date_modified = registry[uid]['date_modified'] kwargs.update({'verbose': False}) new_model = super(UidModel, cls).deserialize(value=registry[uid], registry=registry, trusted=trusted, **kwargs) new_model._backend.update({ 'uid': properties.Uuid.from_json(uid), 'date_created': properties.DateTime.from_json(date_created), 'date_modified': properties.DateTime.from_json(date_modified) }) registry.update({uid: new_model}) return registry[uid]
def test_serializer(self): with self.assertRaises(TypeError): properties.GettableProperty('bad serial', serializer=5) with self.assertRaises(TypeError): properties.GettableProperty('bad deserial', deserializer=5) def reverse(value): return ''.join(v for v in value[::-1]) def to_string(value): return ', '.join(v for v in value.astype(str)) def from_string(value): return np.array(value.split(', ')).astype(int) def serialize_a_only(value): return value.a def deserialize_from_a(value): return HP1(a=value) def sum_of_a(value): return sum(inst.a for inst in value) def from_sum(value): return [HP1(a=value)] def just_the_classname(value): return value.__class__.__name__ class ManyProperties(properties.HasProperties): mystr = properties.String( 'my string', serializer=reverse, deserializer=reverse, ) myarr = properties.Array( 'my array', serializer=to_string, deserializer=from_string, ) myinst = properties.Instance( 'my HP1', instance_class=HP1, serializer=serialize_a_only, deserializer=deserialize_from_a, ) mylist = properties.List( 'my list of HP1', prop=HP1, serializer=sum_of_a, deserializer=from_sum, ) myunion = properties.Union( 'string or HP1', props=(HP1, properties.String('')), serializer=just_the_classname, deserializer=reverse, ) many = ManyProperties(mystr='abcd', myarr=[1, 2, 3], myinst=HP1(a=10), mylist=[HP1(a=1), HP1(a=2), HP1(a=3)], myunion=HP1(a=10)) many_serialized = { 'mystr': 'dcba', 'myarr': '1, 2, 3', 'myinst': 10, 'mylist': 6, 'myunion': 'HP1' } assert many.serialize(include_class=False) == many_serialized many = ManyProperties.deserialize(many_serialized) assert many.mystr == 'abcd' assert isinstance(many.myarr, np.ndarray) assert np.all(many.myarr == [1, 2, 3]) assert isinstance(many.myinst, HP1) assert many.myinst.a == 10 assert isinstance(many.mylist, list) assert len(many.mylist) == 1 assert isinstance(many.mylist[0], HP1) assert many.mylist[0].a == 6 assert many.myunion == '1PH' assert isinstance(ManyProperties.deserialize({'mystr': 'hi'}), ManyProperties) def kwarg_multiplier(value, **kwargs): mult = kwargs.get('mult', 1) return value * mult def kwarg_divider(value, **kwargs): mult = kwargs.get('mult', 1) return value / mult class HasInt(properties.HasProperties): my_int = properties.Integer( 'Integer serialized as mult', serializer=kwarg_multiplier, deserializer=kwarg_divider, ) hi = HasInt(my_int=5) hi_ser = hi.serialize() assert hi_ser['my_int'] == 5 hi_copy = HasInt.deserialize(hi_ser) assert hi_copy.my_int == 5 hi_ser = hi.serialize(mult=2) assert hi_ser['my_int'] == 10 hi_copy = HasInt.deserialize(hi_ser, mult=2) assert hi_copy.my_int == 5