def transform(cls): """ Mimics Flask-SQLAlchemy's _include_sqlalchemy """ if cls.name == "SQLAlchemy": import sqlalchemy # pylint: disable=import-outside-toplevel import sqlalchemy.orm # pylint: disable=import-outside-toplevel for module in sqlalchemy, sqlalchemy.orm: for key in module.__all__: cls.locals[key] = [ClassDef(key, None)] if cls.name == "scoped_session": from sqlalchemy.orm import Session # pylint: disable=import-outside-toplevel for key in Session.public_methods: cls.locals[key] = [ClassDef(key, None)]
def transform(node: NodeNG) -> None: """Make pylint understand FlaskSQLAlchemy proxies and wrappers. Note : it _looks_ like astroid transforms are run in some kind of try/except mechanism which makes some errors fail silently. For example, if you call: ```python from sqlalchemy.orm import Session Session.foo ``` here, you would think it will raise an: `AttributeError: type object 'Session' has no attribute 'foo'` but... no. Instead it stops the transform and continue to the next node, so pylint does not raise an error, so you think your code (and ours) works, but it's not :-( So we need to write tests that fails to make sure our plugin works. """ if node.name == "SQLAlchemy": import sqlalchemy import sqlalchemy.orm for module in sqlalchemy, sqlalchemy.orm: for key in sorted(module.__all__, key=sort_module_keys): if key not in FLASK_SQLALCHEMY_WRAPS: node.locals[key] = [ClassDef(key, None)] else: node.locals[key] = [ ClassDef(key, None), node.locals["Query"] ] elif node.name == "scoped_session": from sqlalchemy.orm import Session for key in sorted(dir(Session), reverse=True): # `query` is in fact a proxy to `query_property` if key == "query": node.locals[key] = [ ClassDef(key, None), node.locals["query_property"] ] else: node.locals[key] = [ClassDef(key, None)]
def cubicweb_transform(module): # handle objectify_predicate decorator (and its former name until bw compat # is kept). Only look at module level functions, should be enough. for assnodes in module.locals.values(): for node in assnodes: if isinstance(node, FunctionDef) and node.decorators: for decorator in node.decorators.nodes: try: for infered in decorator.infer(): if infered.name in ('objectify_predicate', 'objectify_selector'): turn_function_to_class(node) break else: continue break except InferenceError: continue # add yams base types into 'yams.buildobjs', astng doesn't grasp globals() # magic in there if module.name == 'yams.buildobjs': from yams import BASE_TYPES for etype in BASE_TYPES: module.locals[etype] = [ClassDef(etype, None)] # add data() to uiprops module elif module.name.split('.')[-1] == 'uiprops': fake = AstroidBuilder(MANAGER).string_build(''' def data(string): return u'' ''') module.locals['data'] = fake.locals['data'] # handle lower case with underscores for relation names in schema.py if not module.qname().endswith('.schema'): return schema_locals = module.locals for assnodes in schema_locals.values(): for node in assnodes: if not isinstance(node, ClassDef): continue # XXX can we infer ancestor classes? it would be better to know for sure that # one of the mother classes is yams.buildobjs.RelationDefinition for instance for base in node.basenames: if base in ('RelationDefinition', 'ComputedRelation', 'RelationType'): new_name = node.name.replace('_', '').capitalize() schema_locals[new_name] = schema_locals[node.name] del schema_locals[node.name] node.name = new_name