Howto tell pylint or astrooid that only one definition of class has to be loaded for specific python major versions (Python2 vs Python3)
Hi I do have a module which at least until next year has to be awave of some users who still use pyhton 2 eventhough not so far from now at end of life. For this i have a central module which deals with all the differences and ensures that base classes and basic classes exported by the module are independent of pyhton verison. All pyhton version specific stuff is handled by a single if sys.verision_info[0] >= 3: else: clause. The question i do have is how do i tell pylint or astroid respective that eiter the if or the else branche is relevant and that i can ignore the other. The cause of this question is that the module also contains a class which has dynamic attricutes, as it represents the DOM of binary data files. For smoe specific requirements this class in addition has a custom metaclass sepcified. As metaclass specification differs in Pyhton 2 and Pyhton 3 i have defined an empty parent class as follows if sys.version_info[0] >= 3: class ParentClass(object,metaclass=NodeMetaClass): pass else: class ParentClass(object): __metaclass__ = NodeMetaClass pass class Node(ParentClass): pass pylint will not report any no-member error on the Node class cause it thinks that the PraentClass object is ambigously defined. The method safe_infer retruns None. Is it possible via transform plugin module to make pylint or astroid ignore one of the two definitions or at least hide them from safe_infer method. So that no-member check is performed properly. Currently i have enabled all checks.
На 4.11.19 г. в 1:04 ч., christoph@out-world.com написа:
Hi I do have a module which at least until next year has to be awave of some users who still use pyhton 2 eventhough not so far from now at end of life. For this i have a central module which deals with all the differences and ensures that base classes and basic classes exported by the module are independent of pyhton verison. All pyhton version specific stuff is handled by a single if sys.verision_info[0] >= 3: else: clause.
The question i do have is how do i tell pylint or astroid respective that eiter the if or the else branche is relevant and that i can ignore the other.
The cause of this question is that the module also contains a class which has dynamic attricutes, as it represents the DOM of binary data files. For smoe specific requirements this class in addition has a custom metaclass sepcified. As metaclass specification differs in Pyhton 2 and Pyhton 3 i have defined an empty parent class as follows
if sys.version_info[0] >= 3: class ParentClass(object,metaclass=NodeMetaClass): pass else: class ParentClass(object): __metaclass__ = NodeMetaClass pass
class Node(ParentClass): pass
pylint will not report any no-member error on the Node class cause it thinks that the PraentClass object is ambigously defined. The method safe_infer retruns None. Is it possible via transform plugin module to make pylint or astroid ignore one of the two definitions or at least hide them from safe_infer method. So that no-member check is performed properly.
You are essentially mixing Python 2 and Python 3 style code in the same file and examining this with latest pylint where runtime is probably Py3 only. I don't think there's machinery in astroid to arbitrary skip an AST node based on another AST node (your if condition) but I'm not a low level expert on astroid. If you'd like to dig deeper into that check: http://pylint.pycqa.org/en/latest/how_tos/transform_plugins.html https://github.com/PyCQA/pylint-django/tree/master/pylint_django/transforms I suggest you put your special class into a separate module and import it from different places based on Python version (e.g. from mymod3 import ParentClass). Then configure your CI (whatever) to execute pylint in multiple stages checking the special module/files separately. In one of my projects we have 3 different invocations of pylint against various directories/with various checks/plugins enabled. All of this is grouped in a `make check` target.
Currently i have enabled all checks. _______________________________________________ code-quality mailing list -- code-quality@python.org To unsubscribe send an email to code-quality-leave@python.org https://mail.python.org/mailman3/lists/code-quality.python.org/
-- Alexander Todorov Co-founder & Open source QA at Mr. Senko http://MrSenko.com
Thank you very much for your answer. I figureed my self how to do it. 1) get the entry from the locals dictionary of the module defining the class 2) check if the list representing the class contains more than one ClassDef astroid node. 3) In my case the parent node of the ClassDef node is an If astroid node which separates between python3 and python2 4) pop either version from the locals entry of module dependent whether checking for python3 or python2 5) remove the ClassDef node from the body or orelse structure of parent node beeing and If node 6) check if next entry on bases structure of node has a lookup method 7) if has lookup method than call clear_cache method on lookup method object to clear functools.cache 8) repeat 6 and 7 with all remaining entries bases structure of node 9) return node With the above i managed to at least handle it properly for Python3 and Pylint 3 not tested yet on python2 and pylint2
participants (3)
-
Alexander Todorov
-
christoph@out-world.com
-
straic009@gmail.com