class AddOperation(Numeric): left = SpecField(0, base_type=Numeric) right = SpecField(1, base_type=Numeric) def apply(self, runner): return runner.execute(self.left) + runner.execute(self.right) def __repr__(self): return '{} + {}'.format(self.left, self.right)
class FileDataStore(BaseDataStore): path = PrimitiveField(0) split_keys = PrimitiveField(default=True) serializer = SpecField(default=None, base_type=Serializer) use_class_name = PrimitiveField( default=False, help='Whether the first level should be the class name') def __init__(self, *args, **kwargs): super(FileDataStore, self).__init__(*args, **kwargs) if not os.path.exists(self.path): os.makedirs(self.path) conf_file = os.path.join(self.path, 'conf.yaml') if os.path.exists(conf_file): with open(conf_file) as f: conf = yaml.load(f) if 'serializer' not in conf: warnings.warn( "Old conf.yaml format. Please update it to the new format") conf_serializer = Spec.dict2spec(conf) conf_use_class_name = False else: conf_serializer = Spec.dict2spec(conf['serializer']) conf_use_class_name = conf.get('use_class_name', False) if conf_use_class_name != self.use_class_name: raise RuntimeError( 'This store was initialized with use_class_name = {} and now was instanced with {}' .format(conf_use_class_name, self.use_class_name)) if self.serializer is not None and self.serializer != conf_serializer: raise RuntimeError( "This store was initialized with this serializer:\n{}\n\n" + "But was now instanced with this one:\n{}".format( json.dumps(conf['serializer'], indent=2), json.dumps(self.serializer.to_dict(), indent=2))) self.serializer = conf_serializer self.use_class_name = conf_use_class_name else: if self.serializer is None: self.serializer = PickleSerializer() with open(conf_file, 'w') as f: yaml.dump( { 'serializer': self.serializer.to_dict(), 'use_class_name': self.use_class_name }, f) def clean(self, cls=None): for op in self.iterkeys(): if cls is None or (cls is not None and isinstance(op, cls)): self.remove(op) def _remove(self, op): subdir = self._get_subdir(op) shutil.rmtree(subdir) def iterkeys(self, raw=False): for subdir, _, _ in os.walk(self.path): key_fname = os.path.join(subdir, 'key') if not os.path.exists(key_fname): continue with open(key_fname) as f: key = f.read() if raw: yield subdir, Spec.key2dict(key) else: try: spec = Spec.key2spec(key) except Exception, e: # there might be a key that is not a valid json if len(e.args) > 0 and isinstance( e.args[0], basestring) and e.args[0].startswith( 'Unknown spec type'): raise e traceback.print_exc() warnings.warn('Unable to load spec key: {}'.format(key)) continue yield spec
class ObjectWithOperations(object): @as_operation(method_type='instance', op=SpecField(base_type=base_case)) def op1(self, op, val=1): return 1 @as_operation(method_type='class', op=SpecField(base_type=base_case)) def op2(cls, op): return 1
class A(Spec): t = SpecField(0, default=None)
class OtherSpec(Spec): spec = SpecField()
class SpecWithDefault(Spec): a = SpecField(default=SpecA(10))
class SpecB(Spec): spec_a = SpecField(base_type=SpecA) def __repr__(self): return "B(spec_a={})".format(self.spec_a)