def __new__(mcs, name, bases, clsdict): mcs_args = McsArgs(mcs, name, bases, clsdict) if mcs_args.is_abstract: return super().__new__(*mcs_args) cls = super().__new__(*mcs_args) routes = {} include_methods = set(cls.Meta.include_methods) exclude_methods = set(cls.Meta.exclude_methods) for method_name in ALL_METHODS: if (method_name in exclude_methods or method_name not in include_methods): continue route = getattr(clsdict.get(method_name), FN_ROUTES_ATTR, [None])[0] if not route: route = Route(None, mcs_args.getattr(method_name)) if method_name in INDEX_METHODS: rule = '/' else: rule = cls.Meta.member_param route.rule = rule routes[method_name] = [route] setattr(cls, CONTROLLER_ROUTES_ATTR, routes) return cls
def __new__(mcs, name, bases, clsdict): mcs_args = McsArgs(mcs, name, bases, clsdict) _set_up_class_dependency_injection(mcs_args) if mcs_args.is_abstract: return super().__new__(*mcs_args) meta = mcs_args.getattr('Meta', None) model_missing = False try: if meta.model is None: model_missing = True except AttributeError: model_missing = True if model_missing: raise AttributeError(f'{name} is missing the ``class Meta`` model attribute') model = None try: model = unchained.sqlalchemy_bundle.models[meta.model.__name__] except AttributeError: # this happens when attempting to generate documentation and the # sqlalchemy bundle hasn't been loaded pass except KeyError: pass meta_dict = dict(meta.__dict__) meta_dict.pop('model', None) clsdict['Meta'] = type('Meta', (_ModelSerializerMeta,), meta_dict) clsdict['Meta'].model = model return super().__new__(*mcs_args)
def __new__(mcs, name, bases, clsdict): mcs_args = McsArgs(mcs, name, bases, clsdict) set_up_class_dependency_injection(mcs_args) if clsdict.get('__abstract__', getattr(clsdict.get('Meta'), 'abstract', False)): mcs_args.clsdict[REMOVE_SUFFIXES_ATTR] = _get_remove_suffixes( name, bases, CONTROLLER_REMOVE_EXTRA_SUFFIXES) mcs_args.clsdict[NOT_VIEWS_ATTR] = _get_not_views(clsdict, bases) apply_factory_meta_options( mcs_args, default_factory_class=ControllerMetaOptionsFactory) cls = super().__new__(*mcs_args) if mcs_args.Meta.abstract: return cls controller_routes = getattr(cls, CONTROLLER_ROUTES_ATTR, {}).copy() not_views = deep_getattr({}, bases, NOT_VIEWS_ATTR) for method_name, method in clsdict.items(): if (method_name in not_views or not _is_view_func(method_name, method)): controller_routes.pop(method_name, None) continue controller_routes[method_name] = getattr(method, FN_ROUTES_ATTR, [Route(None, method)]) setattr(cls, CONTROLLER_ROUTES_ATTR, controller_routes) return cls
def set_up_class_dependency_injection(mcs_args: McsArgs): if '__init__' in mcs_args.clsdict: from .unchained import unchained init = unchained.inject()(mcs_args.clsdict['__init__']) mcs_args.clsdict['__init__'] = init mcs_args.clsdict['__signature__'] = init.__signature__ for attr, fn in mcs_args.clsdict.items(): if isinstance(fn, FunctionType) and hasattr(fn, '__signature__'): fn.__di_name__ = (mcs_args.name if fn.__name__ == '__init__' else f'{mcs_args.name}.{fn.__name__}')
def get_value(self, meta, base_classes_meta, mcs_args: McsArgs): value = super().get_value(meta, base_classes_meta, mcs_args) if value is not _missing: return value return controller_name(mcs_args.name, mcs_args.getattr(REMOVE_SUFFIXES_ATTR))
def __new__(mcs, name, bases, clsdict): mcs_args = McsArgs(mcs, name, bases, clsdict) set_up_class_dependency_injection(mcs_args) if ABSTRACT_ATTR in clsdict: return super().__new__(mcs, name, bases, clsdict) meta = deep_getattr(clsdict, bases, 'Meta', None) model_missing = False try: if meta.model is None: model_missing = True except AttributeError: model_missing = True if model_missing: raise AttributeError(f'{name} is missing the class ' f'Meta model attribute') else: try: meta.model = unchained.sqlalchemy_bundle.models[ meta.model.__name__] except AttributeError: # this happens when attempting to generate documentation and the # sqlalchemy bundle hasn't been loaded pass except KeyError: pass clsdict['Meta'] = meta return super().__new__(mcs, name, bases, clsdict)
def get_value(self, meta, base_classes_meta, mcs_args: McsArgs): value = super().get_value(meta, base_classes_meta, mcs_args) if value is not _missing: return value ctrl_name = controller_name(mcs_args.name, mcs_args.getattr(REMOVE_SUFFIXES_ATTR)) return '/' + pluralize(ctrl_name.replace('_', '-'))
def __new__(mcs, name, bases, clsdict): mcs_args = McsArgs(mcs, name, bases, clsdict) _set_up_class_dependency_injection(mcs_args) if mcs_args.is_abstract: return super().__new__(*mcs_args) meta = mcs_args.getattr('Meta', None) model_missing = False try: if meta.model is None: model_missing = True except AttributeError: model_missing = True if model_missing: raise AttributeError( f'{name} is missing the ``class Meta`` model attribute') model = meta.model try: model = unchained.sqlalchemy_bundle.models[meta.model.__name__] except AttributeError as e: # this happens when attempting to generate documentation and the # sqlalchemy bundle hasn't been loaded safe_error = "'DeferredBundleFunctions' object has no attribute 'models'" if safe_error not in str(e): raise e except KeyError: pass meta_dict = dict(meta.__dict__) additional_fields = meta_dict.pop('additional', None) if additional_fields: fields = [ name for name, field in clsdict.items() if isinstance(field, Field) ] meta_dict['fields'] = fields + list(additional_fields) meta_dict.pop('model', None) clsdict['Meta'] = type('Meta', (_ModelSerializerMeta, ), meta_dict) clsdict['Meta'].model = model return super().__new__(*mcs_args)
def __new__(mcs, name, bases, clsdict): mcs_args = McsArgs(mcs, name, bases, clsdict) _set_up_class_dependency_injection(mcs_args) process_factory_meta_options( mcs_args, default_factory_class=_ServiceMetaOptionsFactory) # extended concrete services should not inherit their super's di name if deep_getattr({}, bases, '__di_name__', None): clsdict['__di_name__'] = None return super().__new__(*mcs_args)
def __new__(mcs, name, bases, clsdict): mcs_args = McsArgs(mcs, name, bases, clsdict) Meta = process_factory_meta_options(mcs_args, ModelFormMetaOptionsFactory) mcs_args.clsdict['Meta'] = type('Meta', (), Meta._to_clsdict()) if not Meta.abstract and unchained._models_initialized: try: Meta.model = unchained.sqlalchemy_bundle.models[ Meta.model.__name__] except KeyError: pass new_clsdict = model_fields(Meta.model, only=Meta.only, exclude=Meta.exclude, exclude_fk=Meta.exclude_fk, exclude_pk=Meta.exclude_pk, field_args=Meta.field_args, db_session=db.session, converter=_ModelConverter()) new_clsdict.update(mcs_args.clsdict) mcs_args.clsdict = new_clsdict return super().__new__(*mcs_args)
def check_value(self, value, mcs_args: McsArgs): if not value: return if isinstance(value, (list, tuple)): assert all(callable(x) for x in value), \ f'The {self.name} meta option requires a list or tuple of callables' else: for method_name, decorators in value.items(): assert mcs_args.getattr(method_name), \ f'The {method_name} was not found on {mcs_args.name}' assert all(callable(x) for x in decorators), \ f'Invalid decorator detected in the {self.name} meta option for ' \ f'the {method_name} key'
def _set_up_class_dependency_injection(mcs_args: McsArgs): mcs_args.clsdict[_DI_AUTOMATICALLY_HANDLED] = True cls_attrs_to_inject = [ k for k, v in mcs_args.clsdict.items() if v == injectable ] try: mcs_args.clsdict[_INJECT_CLS_ATTRS] = \ cls_attrs_to_inject + mcs_args.getattr(_INJECT_CLS_ATTRS, []) except TypeError as e: if 'can only concatenate list (not "OptionalMetaclass") to list' not in str( e): raise e mcs_args.clsdict[_INJECT_CLS_ATTRS] = cls_attrs_to_inject if '__init__' not in mcs_args.clsdict and cls_attrs_to_inject: init = _inject_cls_attrs( _call_super_for_cls=f'{mcs_args.module}:{mcs_args.name}') init.__di_name__ = mcs_args.name init.__signature__ = inspect.signature(object) mcs_args.clsdict['__init__'] = init mcs_args.clsdict['__signature__'] = init.__signature__ elif '__init__' in mcs_args.clsdict: from .unchained import unchained init = unchained.inject()(mcs_args.clsdict['__init__']) init.__di_name__ = mcs_args.name mcs_args.clsdict['__init__'] = (init if not cls_attrs_to_inject else _inject_cls_attrs(_wrapped_fn=init)) mcs_args.clsdict['__signature__'] = init.__signature__ for attr, value in mcs_args.clsdict.items(): if isinstance(value, FunctionType): if not attr.startswith('__') and not hasattr( value, '__signature__'): from .unchained import unchained mcs_args.clsdict[attr] = unchained.inject()(value) value.__di_name__ = (mcs_args.name if value.__name__ == '__init__' else f'{mcs_args.name}.{value.__name__}')