bee_python 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +202 -0
- data/build/README +23 -0
- data/egg/egg/build.yml +70 -0
- data/egg/egg/ez_setup.py +280 -0
- data/egg/egg/script.py +12 -0
- data/egg/egg/setup.erb +11 -0
- data/egg/egg/suite.py +37 -0
- data/egg/egg/test.py +31 -0
- data/egg/egg.yml +69 -0
- data/egg/http/build.erb +53 -0
- data/egg/http/server.py +34 -0
- data/egg/http.yml +50 -0
- data/egg/mysql/mysql.py +43 -0
- data/egg/mysql.yml +44 -0
- data/egg/project/build.erb +77 -0
- data/egg/project/script.py +42 -0
- data/egg/project/test.py +31 -0
- data/egg/project.yml +59 -0
- data/egg/script/build.erb +35 -0
- data/egg/script/script.py +42 -0
- data/egg/script.yml +50 -0
- data/egg/soap/build.erb +52 -0
- data/egg/soap/client.py +18 -0
- data/egg/soap/server.py +30 -0
- data/egg/soap.yml +58 -0
- data/egg/source/source.py +42 -0
- data/egg/source.yml +47 -0
- data/egg/test/test.py +28 -0
- data/egg/test.yml +44 -0
- data/egg/xmlrpc/build.erb +52 -0
- data/egg/xmlrpc/client.py +22 -0
- data/egg/xmlrpc/server.py +24 -0
- data/egg/xmlrpc.yml +51 -0
- data/lib/bee_task_python.rb +390 -0
- data/test/build.yml +16 -0
- data/test/tc_bee_task_python.rb +27 -0
- data/test/test_build.rb +26 -0
- data/test/test_build_listener.rb +62 -0
- data/test/ts_bee_python.rb +26 -0
- data/tools/common/__init__.py +5 -0
- data/tools/common/common/__init__.py +140 -0
- data/tools/common/common/__pkginfo__.py +43 -0
- data/tools/common/common/adbh.py +35 -0
- data/tools/common/common/cache.py +114 -0
- data/tools/common/common/changelog.py +234 -0
- data/tools/common/common/clcommands.py +181 -0
- data/tools/common/common/cli.py +212 -0
- data/tools/common/common/compat.py +328 -0
- data/tools/common/common/configuration.py +1087 -0
- data/tools/common/common/contexts.py +58 -0
- data/tools/common/common/corbautils.py +117 -0
- data/tools/common/common/daemon.py +171 -0
- data/tools/common/common/date.py +279 -0
- data/tools/common/common/db.py +49 -0
- data/tools/common/common/dbf.py +229 -0
- data/tools/common/common/debugger.py +208 -0
- data/tools/common/common/decorators.py +190 -0
- data/tools/common/common/deprecation.py +118 -0
- data/tools/common/common/fileutils.py +409 -0
- data/tools/common/common/graph.py +259 -0
- data/tools/common/common/html.py +142 -0
- data/tools/common/common/interface.py +76 -0
- data/tools/common/common/logging_ext.py +166 -0
- data/tools/common/common/modutils.py +670 -0
- data/tools/common/common/optik_ext.py +383 -0
- data/tools/common/common/optparser.py +92 -0
- data/tools/common/common/pdf_ext.py +111 -0
- data/tools/common/common/proc.py +276 -0
- data/tools/common/common/pyro_ext.py +146 -0
- data/tools/common/common/pytest.py +754 -0
- data/tools/common/common/shellutils.py +383 -0
- data/tools/common/common/sphinx_ext.py +87 -0
- data/tools/common/common/sphinxutils.py +122 -0
- data/tools/common/common/sqlgen.py +31 -0
- data/tools/common/common/table.py +930 -0
- data/tools/common/common/tasksqueue.py +97 -0
- data/tools/common/common/test/__init__.py +1 -0
- data/tools/common/common/test/data/ChangeLog +184 -0
- data/tools/common/common/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
- data/tools/common/common/test/data/__init__.py +1 -0
- data/tools/common/common/test/data/content_differ_dir/NOTHING +0 -0
- data/tools/common/common/test/data/content_differ_dir/README +1 -0
- data/tools/common/common/test/data/content_differ_dir/subdir/coin +1 -0
- data/tools/common/common/test/data/content_differ_dir/subdir/toto.txt +53 -0
- data/tools/common/common/test/data/file_differ_dir/NOTHING +0 -0
- data/tools/common/common/test/data/file_differ_dir/README +1 -0
- data/tools/common/common/test/data/file_differ_dir/subdir/toto.txt +53 -0
- data/tools/common/common/test/data/file_differ_dir/subdirtwo/Hello +0 -0
- data/tools/common/common/test/data/find_test/__init__.py +0 -0
- data/tools/common/common/test/data/find_test/foo.txt +0 -0
- data/tools/common/common/test/data/find_test/module.py +0 -0
- data/tools/common/common/test/data/find_test/module2.py +0 -0
- data/tools/common/common/test/data/find_test/newlines.txt +0 -0
- data/tools/common/common/test/data/find_test/noendingnewline.py +0 -0
- data/tools/common/common/test/data/find_test/nonregr.py +0 -0
- data/tools/common/common/test/data/find_test/normal_file.txt +0 -0
- data/tools/common/common/test/data/find_test/spam.txt +0 -0
- data/tools/common/common/test/data/find_test/sub/doc.txt +0 -0
- data/tools/common/common/test/data/find_test/sub/momo.py +0 -0
- data/tools/common/common/test/data/find_test/test.ini +0 -0
- data/tools/common/common/test/data/find_test/test1.msg +0 -0
- data/tools/common/common/test/data/find_test/test2.msg +0 -0
- data/tools/common/common/test/data/find_test/write_protected_file.txt +0 -0
- data/tools/common/common/test/data/foo.txt +9 -0
- data/tools/common/common/test/data/module.py +88 -0
- data/tools/common/common/test/data/module2.py +77 -0
- data/tools/common/common/test/data/newlines.txt +3 -0
- data/tools/common/common/test/data/noendingnewline.py +36 -0
- data/tools/common/common/test/data/nonregr.py +14 -0
- data/tools/common/common/test/data/normal_file.txt +0 -0
- data/tools/common/common/test/data/reference_dir/NOTHING +0 -0
- data/tools/common/common/test/data/reference_dir/README +1 -0
- data/tools/common/common/test/data/reference_dir/subdir/coin +1 -0
- data/tools/common/common/test/data/reference_dir/subdir/toto.txt +53 -0
- data/tools/common/common/test/data/same_dir/NOTHING +0 -0
- data/tools/common/common/test/data/same_dir/README +1 -0
- data/tools/common/common/test/data/same_dir/subdir/coin +1 -0
- data/tools/common/common/test/data/same_dir/subdir/toto.txt +53 -0
- data/tools/common/common/test/data/spam.txt +9 -0
- data/tools/common/common/test/data/sub/doc.txt +1 -0
- data/tools/common/common/test/data/sub/momo.py +1 -0
- data/tools/common/common/test/data/subdir_differ_dir/NOTHING +0 -0
- data/tools/common/common/test/data/subdir_differ_dir/README +1 -0
- data/tools/common/common/test/data/subdir_differ_dir/subdir/coin +1 -0
- data/tools/common/common/test/data/subdir_differ_dir/subdir/toto.txt +53 -0
- data/tools/common/common/test/data/test.ini +20 -0
- data/tools/common/common/test/data/test1.msg +30 -0
- data/tools/common/common/test/data/test2.msg +42 -0
- data/tools/common/common/test/data/write_protected_file.txt +0 -0
- data/tools/common/common/test/foomod.py +17 -0
- data/tools/common/common/test/unittest_cache.py +129 -0
- data/tools/common/common/test/unittest_changelog.py +37 -0
- data/tools/common/common/test/unittest_compat.py +239 -0
- data/tools/common/common/test/unittest_configuration.py +348 -0
- data/tools/common/common/test/unittest_date.py +154 -0
- data/tools/common/common/test/unittest_decorators.py +62 -0
- data/tools/common/common/test/unittest_deprecation.py +76 -0
- data/tools/common/common/test/unittest_fileutils.py +133 -0
- data/tools/common/common/test/unittest_graph.py +50 -0
- data/tools/common/common/test/unittest_html.py +76 -0
- data/tools/common/common/test/unittest_interface.py +87 -0
- data/tools/common/common/test/unittest_modutils.py +244 -0
- data/tools/common/common/test/unittest_pytest.py +50 -0
- data/tools/common/common/test/unittest_shellutils.py +248 -0
- data/tools/common/common/test/unittest_table.py +448 -0
- data/tools/common/common/test/unittest_taskqueue.py +71 -0
- data/tools/common/common/test/unittest_testlib.py +956 -0
- data/tools/common/common/test/unittest_textutils.py +247 -0
- data/tools/common/common/test/unittest_tree.py +248 -0
- data/tools/common/common/test/unittest_umessage.py +55 -0
- data/tools/common/common/test/unittest_ureports_html.py +64 -0
- data/tools/common/common/test/unittest_ureports_text.py +105 -0
- data/tools/common/common/test/unittest_xmlutils.py +75 -0
- data/tools/common/common/test/utils.py +87 -0
- data/tools/common/common/testlib.py +1927 -0
- data/tools/common/common/textutils.py +476 -0
- data/tools/common/common/tree.py +372 -0
- data/tools/common/common/umessage.py +161 -0
- data/tools/common/common/ureports/__init__.py +174 -0
- data/tools/common/common/ureports/docbook_writer.py +139 -0
- data/tools/common/common/ureports/html_writer.py +131 -0
- data/tools/common/common/ureports/nodes.py +201 -0
- data/tools/common/common/ureports/text_writer.py +140 -0
- data/tools/common/common/vcgutils.py +216 -0
- data/tools/common/common/visitor.py +107 -0
- data/tools/common/common/xmlrpcutils.py +136 -0
- data/tools/common/common/xmlutils.py +61 -0
- data/tools/compile/compile.py +16 -0
- data/tools/coverage/coverage.py +602 -0
- data/tools/epydoc/__init__.py +227 -0
- data/tools/epydoc/__init__.pyc +0 -0
- data/tools/epydoc/apidoc.py +2203 -0
- data/tools/epydoc/apidoc.pyc +0 -0
- data/tools/epydoc/checker.py +349 -0
- data/tools/epydoc/checker.pyc +0 -0
- data/tools/epydoc/cli.py +1470 -0
- data/tools/epydoc/cli.pyc +0 -0
- data/tools/epydoc/compat.py +250 -0
- data/tools/epydoc/compat.pyc +0 -0
- data/tools/epydoc/docbuilder.py +1358 -0
- data/tools/epydoc/docbuilder.pyc +0 -0
- data/tools/epydoc/docintrospecter.py +1056 -0
- data/tools/epydoc/docintrospecter.pyc +0 -0
- data/tools/epydoc/docparser.py +2113 -0
- data/tools/epydoc/docparser.pyc +0 -0
- data/tools/epydoc/docstringparser.py +1111 -0
- data/tools/epydoc/docstringparser.pyc +0 -0
- data/tools/epydoc/docwriter/__init__.py +12 -0
- data/tools/epydoc/docwriter/__init__.pyc +0 -0
- data/tools/epydoc/docwriter/dotgraph.py +1351 -0
- data/tools/epydoc/docwriter/dotgraph.pyc +0 -0
- data/tools/epydoc/docwriter/html.py +3491 -0
- data/tools/epydoc/docwriter/html.pyc +0 -0
- data/tools/epydoc/docwriter/html_colorize.py +909 -0
- data/tools/epydoc/docwriter/html_colorize.pyc +0 -0
- data/tools/epydoc/docwriter/html_css.py +550 -0
- data/tools/epydoc/docwriter/html_css.pyc +0 -0
- data/tools/epydoc/docwriter/html_help.py +190 -0
- data/tools/epydoc/docwriter/html_help.pyc +0 -0
- data/tools/epydoc/docwriter/latex.py +1187 -0
- data/tools/epydoc/docwriter/latex.pyc +0 -0
- data/tools/epydoc/docwriter/plaintext.py +276 -0
- data/tools/epydoc/docwriter/plaintext.pyc +0 -0
- data/tools/epydoc/docwriter/xlink.py +505 -0
- data/tools/epydoc/docwriter/xlink.pyc +0 -0
- data/tools/epydoc/gui.py +1148 -0
- data/tools/epydoc/gui.pyc +0 -0
- data/tools/epydoc/log.py +204 -0
- data/tools/epydoc/log.pyc +0 -0
- data/tools/epydoc/markup/__init__.py +623 -0
- data/tools/epydoc/markup/__init__.pyc +0 -0
- data/tools/epydoc/markup/doctest.py +311 -0
- data/tools/epydoc/markup/doctest.pyc +0 -0
- data/tools/epydoc/markup/epytext.py +2116 -0
- data/tools/epydoc/markup/epytext.pyc +0 -0
- data/tools/epydoc/markup/javadoc.py +250 -0
- data/tools/epydoc/markup/javadoc.pyc +0 -0
- data/tools/epydoc/markup/plaintext.py +78 -0
- data/tools/epydoc/markup/plaintext.pyc +0 -0
- data/tools/epydoc/markup/pyval_repr.py +532 -0
- data/tools/epydoc/markup/pyval_repr.pyc +0 -0
- data/tools/epydoc/markup/restructuredtext.py +906 -0
- data/tools/epydoc/markup/restructuredtext.pyc +0 -0
- data/tools/epydoc/test/__init__.py +97 -0
- data/tools/epydoc/test/__init__.pyc +0 -0
- data/tools/epydoc/test/util.py +226 -0
- data/tools/epydoc/test/util.pyc +0 -0
- data/tools/epydoc/util.py +289 -0
- data/tools/epydoc/util.pyc +0 -0
- data/tools/logilab/logilab/__init__.py +5 -0
- data/tools/logilab/logilab/astng/__init__.py +82 -0
- data/tools/logilab/logilab/astng/__pkginfo__.py +76 -0
- data/tools/logilab/logilab/astng/_exceptions.py +64 -0
- data/tools/logilab/logilab/astng/_nodes_ast.py +667 -0
- data/tools/logilab/logilab/astng/_nodes_compiler.py +758 -0
- data/tools/logilab/logilab/astng/bases.py +608 -0
- data/tools/logilab/logilab/astng/builder.py +239 -0
- data/tools/logilab/logilab/astng/inference.py +426 -0
- data/tools/logilab/logilab/astng/inspector.py +289 -0
- data/tools/logilab/logilab/astng/manager.py +421 -0
- data/tools/logilab/logilab/astng/mixins.py +165 -0
- data/tools/logilab/logilab/astng/node_classes.py +848 -0
- data/tools/logilab/logilab/astng/nodes.py +85 -0
- data/tools/logilab/logilab/astng/nodes_as_string.py +389 -0
- data/tools/logilab/logilab/astng/patchcomptransformer.py +159 -0
- data/tools/logilab/logilab/astng/protocols.py +333 -0
- data/tools/logilab/logilab/astng/raw_building.py +212 -0
- data/tools/logilab/logilab/astng/rebuilder.py +307 -0
- data/tools/logilab/logilab/astng/scoped_nodes.py +951 -0
- data/tools/logilab/logilab/astng/test/__init__.py +19 -0
- data/tools/logilab/logilab/astng/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
- data/tools/logilab/logilab/astng/test/data/MyPyPa-0.1.0-py2.5.zip +0 -0
- data/tools/logilab/logilab/astng/test/data/SSL1/Connection1.py +33 -0
- data/tools/logilab/logilab/astng/test/data/SSL1/__init__.py +20 -0
- data/tools/logilab/logilab/astng/test/data/__init__.py +20 -0
- data/tools/logilab/logilab/astng/test/data/all.py +29 -0
- data/tools/logilab/logilab/astng/test/data/appl/__init__.py +23 -0
- data/tools/logilab/logilab/astng/test/data/appl/myConnection.py +30 -0
- data/tools/logilab/logilab/astng/test/data/format.py +34 -0
- data/tools/logilab/logilab/astng/test/data/module.py +90 -0
- data/tools/logilab/logilab/astng/test/data/module2.py +112 -0
- data/tools/logilab/logilab/astng/test/data/noendingnewline.py +57 -0
- data/tools/logilab/logilab/astng/test/data/nonregr.py +76 -0
- data/tools/logilab/logilab/astng/test/data/notall.py +28 -0
- data/tools/logilab/logilab/astng/test/data2/__init__.py +20 -0
- data/tools/logilab/logilab/astng/test/data2/clientmodule_test.py +51 -0
- data/tools/logilab/logilab/astng/test/data2/suppliermodule_test.py +32 -0
- data/tools/logilab/logilab/astng/test/regrtest.py +135 -0
- data/tools/logilab/logilab/astng/test/regrtest_data/absimport.py +22 -0
- data/tools/logilab/logilab/astng/test/regrtest_data/descriptor_crash.py +31 -0
- data/tools/logilab/logilab/astng/test/regrtest_data/import_package_subpackage_module.py +68 -0
- data/tools/logilab/logilab/astng/test/regrtest_data/package/__init__.py +24 -0
- data/tools/logilab/logilab/astng/test/regrtest_data/package/subpackage/__init__.py +20 -0
- data/tools/logilab/logilab/astng/test/regrtest_data/package/subpackage/module.py +20 -0
- data/tools/logilab/logilab/astng/test/unittest_builder.py +684 -0
- data/tools/logilab/logilab/astng/test/unittest_inference.py +1112 -0
- data/tools/logilab/logilab/astng/test/unittest_inspector.py +105 -0
- data/tools/logilab/logilab/astng/test/unittest_lookup.py +302 -0
- data/tools/logilab/logilab/astng/test/unittest_manager.py +98 -0
- data/tools/logilab/logilab/astng/test/unittest_nodes.py +302 -0
- data/tools/logilab/logilab/astng/test/unittest_scoped_nodes.py +501 -0
- data/tools/logilab/logilab/astng/test/unittest_utils.py +104 -0
- data/tools/logilab/logilab/astng/utils.py +342 -0
- data/tools/logilab/logilab/common/__init__.py +140 -0
- data/tools/logilab/logilab/common/__pkginfo__.py +43 -0
- data/tools/logilab/logilab/common/adbh.py +35 -0
- data/tools/logilab/logilab/common/cache.py +114 -0
- data/tools/logilab/logilab/common/changelog.py +234 -0
- data/tools/logilab/logilab/common/clcommands.py +181 -0
- data/tools/logilab/logilab/common/cli.py +212 -0
- data/tools/logilab/logilab/common/compat.py +328 -0
- data/tools/logilab/logilab/common/configuration.py +1087 -0
- data/tools/logilab/logilab/common/contexts.py +58 -0
- data/tools/logilab/logilab/common/corbautils.py +117 -0
- data/tools/logilab/logilab/common/daemon.py +171 -0
- data/tools/logilab/logilab/common/date.py +279 -0
- data/tools/logilab/logilab/common/db.py +49 -0
- data/tools/logilab/logilab/common/dbf.py +229 -0
- data/tools/logilab/logilab/common/debugger.py +208 -0
- data/tools/logilab/logilab/common/decorators.py +190 -0
- data/tools/logilab/logilab/common/deprecation.py +118 -0
- data/tools/logilab/logilab/common/fileutils.py +409 -0
- data/tools/logilab/logilab/common/graph.py +259 -0
- data/tools/logilab/logilab/common/html.py +142 -0
- data/tools/logilab/logilab/common/interface.py +76 -0
- data/tools/logilab/logilab/common/logging_ext.py +166 -0
- data/tools/logilab/logilab/common/modutils.py +670 -0
- data/tools/logilab/logilab/common/optik_ext.py +383 -0
- data/tools/logilab/logilab/common/optparser.py +92 -0
- data/tools/logilab/logilab/common/pdf_ext.py +111 -0
- data/tools/logilab/logilab/common/proc.py +276 -0
- data/tools/logilab/logilab/common/pyro_ext.py +146 -0
- data/tools/logilab/logilab/common/pytest.py +754 -0
- data/tools/logilab/logilab/common/shellutils.py +383 -0
- data/tools/logilab/logilab/common/sphinx_ext.py +87 -0
- data/tools/logilab/logilab/common/sphinxutils.py +122 -0
- data/tools/logilab/logilab/common/sqlgen.py +31 -0
- data/tools/logilab/logilab/common/table.py +930 -0
- data/tools/logilab/logilab/common/tasksqueue.py +97 -0
- data/tools/logilab/logilab/common/test/__init__.py +1 -0
- data/tools/logilab/logilab/common/test/data/ChangeLog +184 -0
- data/tools/logilab/logilab/common/test/data/MyPyPa-0.1.0-py2.5.egg +0 -0
- data/tools/logilab/logilab/common/test/data/__init__.py +1 -0
- data/tools/logilab/logilab/common/test/data/content_differ_dir/NOTHING +0 -0
- data/tools/logilab/logilab/common/test/data/content_differ_dir/README +1 -0
- data/tools/logilab/logilab/common/test/data/content_differ_dir/subdir/coin +1 -0
- data/tools/logilab/logilab/common/test/data/content_differ_dir/subdir/toto.txt +53 -0
- data/tools/logilab/logilab/common/test/data/file_differ_dir/NOTHING +0 -0
- data/tools/logilab/logilab/common/test/data/file_differ_dir/README +1 -0
- data/tools/logilab/logilab/common/test/data/file_differ_dir/subdir/toto.txt +53 -0
- data/tools/logilab/logilab/common/test/data/file_differ_dir/subdirtwo/Hello +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/__init__.py +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/foo.txt +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/module.py +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/module2.py +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/newlines.txt +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/noendingnewline.py +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/nonregr.py +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/normal_file.txt +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/spam.txt +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/sub/doc.txt +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/sub/momo.py +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/test.ini +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/test1.msg +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/test2.msg +0 -0
- data/tools/logilab/logilab/common/test/data/find_test/write_protected_file.txt +0 -0
- data/tools/logilab/logilab/common/test/data/foo.txt +9 -0
- data/tools/logilab/logilab/common/test/data/module.py +88 -0
- data/tools/logilab/logilab/common/test/data/module2.py +77 -0
- data/tools/logilab/logilab/common/test/data/newlines.txt +3 -0
- data/tools/logilab/logilab/common/test/data/noendingnewline.py +36 -0
- data/tools/logilab/logilab/common/test/data/nonregr.py +14 -0
- data/tools/logilab/logilab/common/test/data/normal_file.txt +0 -0
- data/tools/logilab/logilab/common/test/data/reference_dir/NOTHING +0 -0
- data/tools/logilab/logilab/common/test/data/reference_dir/README +1 -0
- data/tools/logilab/logilab/common/test/data/reference_dir/subdir/coin +1 -0
- data/tools/logilab/logilab/common/test/data/reference_dir/subdir/toto.txt +53 -0
- data/tools/logilab/logilab/common/test/data/same_dir/NOTHING +0 -0
- data/tools/logilab/logilab/common/test/data/same_dir/README +1 -0
- data/tools/logilab/logilab/common/test/data/same_dir/subdir/coin +1 -0
- data/tools/logilab/logilab/common/test/data/same_dir/subdir/toto.txt +53 -0
- data/tools/logilab/logilab/common/test/data/spam.txt +9 -0
- data/tools/logilab/logilab/common/test/data/sub/doc.txt +1 -0
- data/tools/logilab/logilab/common/test/data/sub/momo.py +1 -0
- data/tools/logilab/logilab/common/test/data/subdir_differ_dir/NOTHING +0 -0
- data/tools/logilab/logilab/common/test/data/subdir_differ_dir/README +1 -0
- data/tools/logilab/logilab/common/test/data/subdir_differ_dir/subdir/coin +1 -0
- data/tools/logilab/logilab/common/test/data/subdir_differ_dir/subdir/toto.txt +53 -0
- data/tools/logilab/logilab/common/test/data/test.ini +20 -0
- data/tools/logilab/logilab/common/test/data/test1.msg +30 -0
- data/tools/logilab/logilab/common/test/data/test2.msg +42 -0
- data/tools/logilab/logilab/common/test/data/write_protected_file.txt +0 -0
- data/tools/logilab/logilab/common/test/foomod.py +17 -0
- data/tools/logilab/logilab/common/test/unittest_cache.py +129 -0
- data/tools/logilab/logilab/common/test/unittest_changelog.py +37 -0
- data/tools/logilab/logilab/common/test/unittest_compat.py +239 -0
- data/tools/logilab/logilab/common/test/unittest_configuration.py +348 -0
- data/tools/logilab/logilab/common/test/unittest_date.py +154 -0
- data/tools/logilab/logilab/common/test/unittest_decorators.py +62 -0
- data/tools/logilab/logilab/common/test/unittest_deprecation.py +76 -0
- data/tools/logilab/logilab/common/test/unittest_fileutils.py +133 -0
- data/tools/logilab/logilab/common/test/unittest_graph.py +50 -0
- data/tools/logilab/logilab/common/test/unittest_html.py +76 -0
- data/tools/logilab/logilab/common/test/unittest_interface.py +87 -0
- data/tools/logilab/logilab/common/test/unittest_modutils.py +244 -0
- data/tools/logilab/logilab/common/test/unittest_pytest.py +50 -0
- data/tools/logilab/logilab/common/test/unittest_shellutils.py +248 -0
- data/tools/logilab/logilab/common/test/unittest_table.py +448 -0
- data/tools/logilab/logilab/common/test/unittest_taskqueue.py +71 -0
- data/tools/logilab/logilab/common/test/unittest_testlib.py +956 -0
- data/tools/logilab/logilab/common/test/unittest_textutils.py +247 -0
- data/tools/logilab/logilab/common/test/unittest_tree.py +248 -0
- data/tools/logilab/logilab/common/test/unittest_umessage.py +55 -0
- data/tools/logilab/logilab/common/test/unittest_ureports_html.py +64 -0
- data/tools/logilab/logilab/common/test/unittest_ureports_text.py +105 -0
- data/tools/logilab/logilab/common/test/unittest_xmlutils.py +75 -0
- data/tools/logilab/logilab/common/test/utils.py +87 -0
- data/tools/logilab/logilab/common/testlib.py +1927 -0
- data/tools/logilab/logilab/common/textutils.py +476 -0
- data/tools/logilab/logilab/common/tree.py +372 -0
- data/tools/logilab/logilab/common/umessage.py +161 -0
- data/tools/logilab/logilab/common/ureports/__init__.py +174 -0
- data/tools/logilab/logilab/common/ureports/docbook_writer.py +139 -0
- data/tools/logilab/logilab/common/ureports/html_writer.py +131 -0
- data/tools/logilab/logilab/common/ureports/nodes.py +201 -0
- data/tools/logilab/logilab/common/ureports/text_writer.py +140 -0
- data/tools/logilab/logilab/common/vcgutils.py +216 -0
- data/tools/logilab/logilab/common/visitor.py +107 -0
- data/tools/logilab/logilab/common/xmlrpcutils.py +136 -0
- data/tools/logilab/logilab/common/xmlutils.py +61 -0
- data/tools/pychecker/COPYRIGHT +31 -0
- data/tools/pychecker/ChangeLog +349 -0
- data/tools/pychecker/CodeChecks.py +1969 -0
- data/tools/pychecker/CodeChecks.pyc +0 -0
- data/tools/pychecker/CodeChecks.pyo +0 -0
- data/tools/pychecker/Config.py +475 -0
- data/tools/pychecker/Config.pyc +0 -0
- data/tools/pychecker/Config.pyo +0 -0
- data/tools/pychecker/KNOWN_BUGS +100 -0
- data/tools/pychecker/MAINTAINERS +81 -0
- data/tools/pychecker/NEWS +406 -0
- data/tools/pychecker/OP.py +131 -0
- data/tools/pychecker/OP.pyc +0 -0
- data/tools/pychecker/OP.pyo +0 -0
- data/tools/pychecker/OptionTypes.py +117 -0
- data/tools/pychecker/OptionTypes.pyc +0 -0
- data/tools/pychecker/OptionTypes.pyo +0 -0
- data/tools/pychecker/README +152 -0
- data/tools/pychecker/Stack.py +115 -0
- data/tools/pychecker/Stack.pyc +0 -0
- data/tools/pychecker/Stack.pyo +0 -0
- data/tools/pychecker/TODO +101 -0
- data/tools/pychecker/VERSION +1 -0
- data/tools/pychecker/Warning.py +50 -0
- data/tools/pychecker/Warning.pyc +0 -0
- data/tools/pychecker/Warning.pyo +0 -0
- data/tools/pychecker/__init__.py +17 -0
- data/tools/pychecker/__init__.pyc +0 -0
- data/tools/pychecker/__init__.pyo +0 -0
- data/tools/pychecker/checker.py +961 -0
- data/tools/pychecker/checker.pyc +0 -0
- data/tools/pychecker/checker.pyo +0 -0
- data/tools/pychecker/function.py +159 -0
- data/tools/pychecker/function.pyc +0 -0
- data/tools/pychecker/function.pyo +0 -0
- data/tools/pychecker/msgs.py +175 -0
- data/tools/pychecker/msgs.pyc +0 -0
- data/tools/pychecker/msgs.pyo +0 -0
- data/tools/pychecker/options.py +275 -0
- data/tools/pychecker/options.pyc +0 -0
- data/tools/pychecker/options.pyo +0 -0
- data/tools/pychecker/pcmodules.py +19 -0
- data/tools/pychecker/pcmodules.pyc +0 -0
- data/tools/pychecker/pcmodules.pyo +0 -0
- data/tools/pychecker/printer.py +47 -0
- data/tools/pychecker/printer.pyc +0 -0
- data/tools/pychecker/printer.pyo +0 -0
- data/tools/pychecker/python.py +427 -0
- data/tools/pychecker/python.pyc +0 -0
- data/tools/pychecker/python.pyo +0 -0
- data/tools/pychecker/utils.py +102 -0
- data/tools/pychecker/utils.pyc +0 -0
- data/tools/pychecker/utils.pyo +0 -0
- data/tools/pychecker/warn.py +778 -0
- data/tools/pychecker/warn.pyc +0 -0
- data/tools/pychecker/warn.pyo +0 -0
- data/tools/pylint2/pylint/__init__.py +16 -0
- data/tools/pylint2/pylint/__pkginfo__.py +67 -0
- data/tools/pylint2/pylint/checkers/__init__.py +155 -0
- data/tools/pylint2/pylint/checkers/base.py +749 -0
- data/tools/pylint2/pylint/checkers/classes.py +527 -0
- data/tools/pylint2/pylint/checkers/design_analysis.py +344 -0
- data/tools/pylint2/pylint/checkers/exceptions.py +183 -0
- data/tools/pylint2/pylint/checkers/format.py +367 -0
- data/tools/pylint2/pylint/checkers/imports.py +379 -0
- data/tools/pylint2/pylint/checkers/logging.py +98 -0
- data/tools/pylint2/pylint/checkers/misc.py +128 -0
- data/tools/pylint2/pylint/checkers/newstyle.py +107 -0
- data/tools/pylint2/pylint/checkers/raw_metrics.py +125 -0
- data/tools/pylint2/pylint/checkers/similar.py +333 -0
- data/tools/pylint2/pylint/checkers/string_format.py +239 -0
- data/tools/pylint2/pylint/checkers/typecheck.py +364 -0
- data/tools/pylint2/pylint/checkers/utils.py +208 -0
- data/tools/pylint2/pylint/checkers/variables.py +498 -0
- data/tools/pylint2/pylint/config.py +149 -0
- data/tools/pylint2/pylint/epylint.py +149 -0
- data/tools/pylint2/pylint/gui.py +433 -0
- data/tools/pylint2/pylint/interfaces.py +98 -0
- data/tools/pylint2/pylint/lint.py +914 -0
- data/tools/pylint2/pylint/pyreverse/__init__.py +5 -0
- data/tools/pylint2/pylint/pyreverse/diadefslib.py +229 -0
- data/tools/pylint2/pylint/pyreverse/diagrams.py +247 -0
- data/tools/pylint2/pylint/pyreverse/main.py +123 -0
- data/tools/pylint2/pylint/pyreverse/utils.py +131 -0
- data/tools/pylint2/pylint/pyreverse/writer.py +196 -0
- data/tools/pylint2/pylint/reporters/__init__.py +67 -0
- data/tools/pylint2/pylint/reporters/guireporter.py +36 -0
- data/tools/pylint2/pylint/reporters/html.py +69 -0
- data/tools/pylint2/pylint/reporters/text.py +156 -0
- data/tools/pylint2/pylint/utils.py +518 -0
- data/tools/pylint2/pylint.py +16 -0
- data/tools/test/suite.py +35 -0
- metadata +566 -0
@@ -0,0 +1,527 @@
|
|
1
|
+
# Copyright (c) 2003-2010 LOGILAB S.A. (Paris, FRANCE).
|
2
|
+
# http://www.logilab.fr/ -- mailto:contact@logilab.fr
|
3
|
+
#
|
4
|
+
# This program is free software; you can redistribute it and/or modify it under
|
5
|
+
# the terms of the GNU General Public License as published by the Free Software
|
6
|
+
# Foundation; either version 2 of the License, or (at your option) any later
|
7
|
+
# version.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
10
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
11
|
+
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
12
|
+
#
|
13
|
+
# You should have received a copy of the GNU General Public License along with
|
14
|
+
# this program; if not, write to the Free Software Foundation, Inc.,
|
15
|
+
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
16
|
+
"""classes checker for Python code
|
17
|
+
"""
|
18
|
+
from __future__ import generators
|
19
|
+
|
20
|
+
from logilab import astng
|
21
|
+
from logilab.astng import YES, Instance, are_exclusive
|
22
|
+
|
23
|
+
from pylint.interfaces import IASTNGChecker
|
24
|
+
from pylint.checkers import BaseChecker
|
25
|
+
from pylint.checkers.utils import PYMETHODS, overrides_a_method
|
26
|
+
|
27
|
+
def class_is_abstract(node):
|
28
|
+
"""return true if the given class node should be considered as an abstract
|
29
|
+
class
|
30
|
+
"""
|
31
|
+
for method in node.methods():
|
32
|
+
if method.parent.frame() is node:
|
33
|
+
if method.is_abstract(pass_is_abstract=False):
|
34
|
+
return True
|
35
|
+
return False
|
36
|
+
|
37
|
+
|
38
|
+
MSGS = {
|
39
|
+
'F0202': ('Unable to check methods signature (%s / %s)',
|
40
|
+
'Used when PyLint has been unable to check methods signature \
|
41
|
+
compatibility for an unexpected reason. Please report this kind \
|
42
|
+
if you don\'t make sense of it.'),
|
43
|
+
|
44
|
+
'E0202': ('An attribute inherited from %s hide this method',
|
45
|
+
'Used when a class defines a method which is hidden by an \
|
46
|
+
instance attribute from an ancestor class.'),
|
47
|
+
'E0203': ('Access to member %r before its definition line %s',
|
48
|
+
'Used when an instance member is accessed before it\'s actually\
|
49
|
+
assigned.'),
|
50
|
+
'W0201': ('Attribute %r defined outside __init__',
|
51
|
+
'Used when an instance attribute is defined outside the __init__\
|
52
|
+
method.'),
|
53
|
+
|
54
|
+
'W0212': ('Access to a protected member %s of a client class', # E0214
|
55
|
+
'Used when a protected member (i.e. class member with a name \
|
56
|
+
beginning with an underscore) is access outside the class or a \
|
57
|
+
descendant of the class where it\'s defined.'),
|
58
|
+
|
59
|
+
'E0211': ('Method has no argument',
|
60
|
+
'Used when a method which should have the bound instance as \
|
61
|
+
first argument has no argument defined.'),
|
62
|
+
'E0213': ('Method should have "self" as first argument',
|
63
|
+
'Used when a method has an attribute different the "self" as\
|
64
|
+
first argument. This is considered as an error since this is\
|
65
|
+
a so common convention that you shouldn\'t break it!'),
|
66
|
+
'C0202': ('Class method should have "cls" as first argument', # E0212
|
67
|
+
'Used when a class method has an attribute different than "cls"\
|
68
|
+
as first argument, to easily differentiate them from regular \
|
69
|
+
instance methods.'),
|
70
|
+
'C0203': ('Metaclass method should have "mcs" as first argument', # E0214
|
71
|
+
'Used when a metaclass method has an attribute different the \
|
72
|
+
"mcs" as first argument.'),
|
73
|
+
|
74
|
+
'W0211': ('Static method with %r as first argument',
|
75
|
+
'Used when a static method has "self" or "cls" as first argument.'
|
76
|
+
),
|
77
|
+
'R0201': ('Method could be a function',
|
78
|
+
'Used when a method doesn\'t use its bound instance, and so could\
|
79
|
+
be written as a function.'
|
80
|
+
),
|
81
|
+
|
82
|
+
'E0221': ('Interface resolved to %s is not a class',
|
83
|
+
'Used when a class claims to implement an interface which is not \
|
84
|
+
a class.'),
|
85
|
+
'E0222': ('Missing method %r from %s interface' ,
|
86
|
+
'Used when a method declared in an interface is missing from a \
|
87
|
+
class implementing this interface'),
|
88
|
+
'W0221': ('Arguments number differs from %s method',
|
89
|
+
'Used when a method has a different number of arguments than in \
|
90
|
+
the implemented interface or in an overridden method.'),
|
91
|
+
'W0222': ('Signature differs from %s method',
|
92
|
+
'Used when a method signature is different than in the \
|
93
|
+
implemented interface or in an overridden method.'),
|
94
|
+
'W0223': ('Method %r is abstract in class %r but is not overridden',
|
95
|
+
'Used when an abstract method (i.e. raise NotImplementedError) is \
|
96
|
+
not overridden in concrete class.'
|
97
|
+
),
|
98
|
+
'F0220': ('failed to resolve interfaces implemented by %s (%s)', # W0224
|
99
|
+
'Used when a PyLint as failed to find interfaces implemented by \
|
100
|
+
a class'),
|
101
|
+
|
102
|
+
|
103
|
+
'W0231': ('__init__ method from base class %r is not called',
|
104
|
+
'Used when an ancestor class method has an __init__ method \
|
105
|
+
which is not called by a derived class.'),
|
106
|
+
'W0232': ('Class has no __init__ method',
|
107
|
+
'Used when a class has no __init__ method, neither its parent \
|
108
|
+
classes.'),
|
109
|
+
'W0233': ('__init__ method from a non direct base class %r is called',
|
110
|
+
'Used when an __init__ method is called on a class which is not \
|
111
|
+
in the direct ancestors for the analysed class.'),
|
112
|
+
|
113
|
+
}
|
114
|
+
|
115
|
+
|
116
|
+
class ClassChecker(BaseChecker):
|
117
|
+
"""checks for :
|
118
|
+
* methods without self as first argument
|
119
|
+
* overridden methods signature
|
120
|
+
* access only to existent members via self
|
121
|
+
* attributes not defined in the __init__ method
|
122
|
+
* supported interfaces implementation
|
123
|
+
* unreachable code
|
124
|
+
"""
|
125
|
+
|
126
|
+
__implements__ = (IASTNGChecker,)
|
127
|
+
|
128
|
+
# configuration section name
|
129
|
+
name = 'classes'
|
130
|
+
# messages
|
131
|
+
msgs = MSGS
|
132
|
+
priority = -2
|
133
|
+
# configuration options
|
134
|
+
options = (('ignore-iface-methods',
|
135
|
+
{'default' : (#zope interface
|
136
|
+
'isImplementedBy', 'deferred', 'extends', 'names',
|
137
|
+
'namesAndDescriptions', 'queryDescriptionFor', 'getBases',
|
138
|
+
'getDescriptionFor', 'getDoc', 'getName', 'getTaggedValue',
|
139
|
+
'getTaggedValueTags', 'isEqualOrExtendedBy', 'setTaggedValue',
|
140
|
+
'isImplementedByInstancesOf',
|
141
|
+
# twisted
|
142
|
+
'adaptWith',
|
143
|
+
# logilab.common interface
|
144
|
+
'is_implemented_by'),
|
145
|
+
'type' : 'csv',
|
146
|
+
'metavar' : '<method names>',
|
147
|
+
'help' : 'List of interface methods to ignore, \
|
148
|
+
separated by a comma. This is used for instance to not check methods defines \
|
149
|
+
in Zope\'s Interface base class.'}
|
150
|
+
),
|
151
|
+
|
152
|
+
('defining-attr-methods',
|
153
|
+
{'default' : ('__init__', '__new__', 'setUp'),
|
154
|
+
'type' : 'csv',
|
155
|
+
'metavar' : '<method names>',
|
156
|
+
'help' : 'List of method names used to declare (i.e. assign) \
|
157
|
+
instance attributes.'}
|
158
|
+
),
|
159
|
+
|
160
|
+
)
|
161
|
+
|
162
|
+
def __init__(self, linter=None):
|
163
|
+
BaseChecker.__init__(self, linter)
|
164
|
+
self._accessed = []
|
165
|
+
self._first_attrs = []
|
166
|
+
self._meth_could_be_func = None
|
167
|
+
|
168
|
+
def visit_class(self, node):
|
169
|
+
"""init visit variable _accessed and check interfaces
|
170
|
+
"""
|
171
|
+
self._accessed.append({})
|
172
|
+
self._check_bases_classes(node)
|
173
|
+
self._check_interfaces(node)
|
174
|
+
# if not an interface, exception, metaclass
|
175
|
+
if node.type == 'class':
|
176
|
+
try:
|
177
|
+
node.local_attr('__init__')
|
178
|
+
except astng.NotFoundError:
|
179
|
+
self.add_message('W0232', args=node, node=node)
|
180
|
+
|
181
|
+
def leave_class(self, cnode):
|
182
|
+
"""close a class node:
|
183
|
+
check that instance attributes are defined in __init__ and check
|
184
|
+
access to existent members
|
185
|
+
"""
|
186
|
+
# checks attributes are defined in an allowed method such as __init__
|
187
|
+
defining_methods = self.config.defining_attr_methods
|
188
|
+
for attr, nodes in cnode.instance_attrs.items():
|
189
|
+
nodes = [n for n in nodes if not
|
190
|
+
isinstance(n.statement(), (astng.Delete, astng.AugAssign))]
|
191
|
+
if not nodes:
|
192
|
+
continue # error detected by typechecking
|
193
|
+
attr_defined = False
|
194
|
+
# check if any method attr is defined in is a defining method
|
195
|
+
for node in nodes:
|
196
|
+
if node.frame().name in defining_methods:
|
197
|
+
attr_defined = True
|
198
|
+
if not attr_defined:
|
199
|
+
# check attribute is defined in a parent's __init__
|
200
|
+
for parent in cnode.instance_attr_ancestors(attr):
|
201
|
+
attr_defined = False
|
202
|
+
# check if any parent method attr is defined in is a defining method
|
203
|
+
for node in parent.instance_attrs[attr]:
|
204
|
+
if node.frame().name in defining_methods:
|
205
|
+
attr_defined = True
|
206
|
+
if attr_defined:
|
207
|
+
# we're done :)
|
208
|
+
break
|
209
|
+
else:
|
210
|
+
# check attribute is defined as a class attribute
|
211
|
+
try:
|
212
|
+
cnode.local_attr(attr)
|
213
|
+
except astng.NotFoundError:
|
214
|
+
self.add_message('W0201', args=attr, node=node)
|
215
|
+
# check access to existent members on non metaclass classes
|
216
|
+
accessed = self._accessed.pop()
|
217
|
+
if cnode.type != 'metaclass':
|
218
|
+
self._check_accessed_members(cnode, accessed)
|
219
|
+
|
220
|
+
def visit_function(self, node):
|
221
|
+
"""check method arguments, overriding"""
|
222
|
+
# ignore actual functions
|
223
|
+
if not node.is_method():
|
224
|
+
return
|
225
|
+
klass = node.parent.frame()
|
226
|
+
self._meth_could_be_func = True
|
227
|
+
# check first argument is self if this is actually a method
|
228
|
+
self._check_first_arg_for_type(node, klass.type == 'metaclass')
|
229
|
+
if node.name == '__init__':
|
230
|
+
self._check_init(node)
|
231
|
+
return
|
232
|
+
# check signature if the method overloads inherited method
|
233
|
+
for overridden in klass.local_attr_ancestors(node.name):
|
234
|
+
# get astng for the searched method
|
235
|
+
try:
|
236
|
+
meth_node = overridden[node.name]
|
237
|
+
except KeyError:
|
238
|
+
# we have found the method but it's not in the local
|
239
|
+
# dictionary.
|
240
|
+
# This may happen with astng build from living objects
|
241
|
+
continue
|
242
|
+
if not isinstance(meth_node, astng.Function):
|
243
|
+
continue
|
244
|
+
self._check_signature(node, meth_node, 'overridden')
|
245
|
+
break
|
246
|
+
# check if the method overload an attribute
|
247
|
+
try:
|
248
|
+
overridden = klass.instance_attr(node.name)[0] # XXX
|
249
|
+
# we may be unable to get owner class if this is a monkey
|
250
|
+
# patched method
|
251
|
+
while overridden.parent and not isinstance(overridden, astng.Class):
|
252
|
+
overridden = overridden.parent.frame()
|
253
|
+
self.add_message('E0202', args=overridden.name, node=node)
|
254
|
+
except astng.NotFoundError:
|
255
|
+
pass
|
256
|
+
|
257
|
+
def leave_function(self, node):
|
258
|
+
"""on method node, check if this method couldn't be a function
|
259
|
+
|
260
|
+
ignore class, static and abstract methods, initializer,
|
261
|
+
methods overridden from a parent class and any
|
262
|
+
kind of method defined in an interface for this warning
|
263
|
+
"""
|
264
|
+
if node.is_method():
|
265
|
+
if node.args.args is not None:
|
266
|
+
self._first_attrs.pop()
|
267
|
+
class_node = node.parent.frame()
|
268
|
+
if (self._meth_could_be_func and node.type == 'method'
|
269
|
+
and not node.name in PYMETHODS
|
270
|
+
and not (node.is_abstract() or
|
271
|
+
overrides_a_method(class_node, node.name))
|
272
|
+
and class_node.type != 'interface'):
|
273
|
+
self.add_message('R0201', node=node)
|
274
|
+
|
275
|
+
def visit_getattr(self, node):
|
276
|
+
"""check if the getattr is an access to a class member
|
277
|
+
if so, register it. Also check for access to protected
|
278
|
+
class member from outside its class (but ignore __special__
|
279
|
+
methods)
|
280
|
+
"""
|
281
|
+
attrname = node.attrname
|
282
|
+
if self._first_attrs and isinstance(node.expr, astng.Name) and \
|
283
|
+
node.expr.name == self._first_attrs[-1]:
|
284
|
+
self._accessed[-1].setdefault(attrname, []).append(node)
|
285
|
+
elif attrname[0] == '_' and not attrname == '_' and not (
|
286
|
+
attrname.startswith('__') and attrname.endswith('__')):
|
287
|
+
# XXX move this in a reusable function
|
288
|
+
klass = node.frame()
|
289
|
+
while klass is not None and not isinstance(klass, astng.Class):
|
290
|
+
if klass.parent is None:
|
291
|
+
klass = None
|
292
|
+
else:
|
293
|
+
klass = klass.parent.frame()
|
294
|
+
# XXX infer to be more safe and less dirty ??
|
295
|
+
# in classes, check we are not getting a parent method
|
296
|
+
# through the class object or through super
|
297
|
+
callee = node.expr.as_string()
|
298
|
+
if klass is None or not (callee == klass.name or
|
299
|
+
callee in klass.basenames
|
300
|
+
or (isinstance(node.expr, astng.CallFunc)
|
301
|
+
and isinstance(node.expr.func, astng.Name)
|
302
|
+
and node.expr.func.name == 'super')):
|
303
|
+
self.add_message('W0212', node=node, args=attrname)
|
304
|
+
|
305
|
+
|
306
|
+
def visit_name(self, node):
|
307
|
+
"""check if the name handle an access to a class member
|
308
|
+
if so, register it
|
309
|
+
"""
|
310
|
+
if self._first_attrs and (node.name == self._first_attrs[-1] or
|
311
|
+
not self._first_attrs[-1]):
|
312
|
+
self._meth_could_be_func = False
|
313
|
+
|
314
|
+
def _check_accessed_members(self, node, accessed):
|
315
|
+
"""check that accessed members are defined"""
|
316
|
+
# XXX refactor, probably much simpler now that E0201 is in type checker
|
317
|
+
for attr, nodes in accessed.items():
|
318
|
+
# deactivate "except doesn't do anything", that's expected
|
319
|
+
# pylint: disable=W0704
|
320
|
+
# is it a class attribute ?
|
321
|
+
try:
|
322
|
+
node.local_attr(attr)
|
323
|
+
# yes, stop here
|
324
|
+
continue
|
325
|
+
except astng.NotFoundError:
|
326
|
+
pass
|
327
|
+
# is it an instance attribute of a parent class ?
|
328
|
+
try:
|
329
|
+
node.instance_attr_ancestors(attr).next()
|
330
|
+
# yes, stop here
|
331
|
+
continue
|
332
|
+
except StopIteration:
|
333
|
+
pass
|
334
|
+
# is it an instance attribute ?
|
335
|
+
try:
|
336
|
+
defstmts = node.instance_attr(attr)
|
337
|
+
except astng.NotFoundError:
|
338
|
+
pass
|
339
|
+
else:
|
340
|
+
if len(defstmts) == 1:
|
341
|
+
defstmt = defstmts[0]
|
342
|
+
# check that if the node is accessed in the same method as
|
343
|
+
# it's defined, it's accessed after the initial assignment
|
344
|
+
frame = defstmt.frame()
|
345
|
+
lno = defstmt.fromlineno
|
346
|
+
for _node in nodes:
|
347
|
+
if _node.frame() is frame and _node.fromlineno < lno \
|
348
|
+
and not are_exclusive(_node.statement(), defstmt, ('AttributeError', 'Exception', 'BaseException')):
|
349
|
+
self.add_message('E0203', node=_node,
|
350
|
+
args=(attr, lno))
|
351
|
+
|
352
|
+
def _check_first_arg_for_type(self, node, metaclass=0):
|
353
|
+
"""check the name of first argument, expect:
|
354
|
+
|
355
|
+
* 'self' for a regular method
|
356
|
+
* 'cls' for a class method
|
357
|
+
* 'mcs' for a metaclass
|
358
|
+
* not one of the above for a static method
|
359
|
+
"""
|
360
|
+
# don't care about functions with unknown argument (builtins)
|
361
|
+
if node.args.args is None:
|
362
|
+
return
|
363
|
+
first_arg = node.args.args and node.argnames()[0]
|
364
|
+
self._first_attrs.append(first_arg)
|
365
|
+
first = self._first_attrs[-1]
|
366
|
+
# static method
|
367
|
+
if node.type == 'staticmethod':
|
368
|
+
if first_arg in ('self', 'cls', 'mcs'):
|
369
|
+
self.add_message('W0211', args=first, node=node)
|
370
|
+
self._first_attrs[-1] = None
|
371
|
+
# class / regular method with no args
|
372
|
+
elif not node.args.args:
|
373
|
+
self.add_message('E0211', node=node)
|
374
|
+
# metaclass method
|
375
|
+
elif metaclass:
|
376
|
+
if first != 'mcs':
|
377
|
+
self.add_message('C0203', node=node)
|
378
|
+
# class method
|
379
|
+
elif node.type == 'classmethod':
|
380
|
+
if first != 'cls':
|
381
|
+
self.add_message('C0202', node=node)
|
382
|
+
# regular method without self as argument
|
383
|
+
elif first != 'self':
|
384
|
+
self.add_message('E0213', node=node)
|
385
|
+
|
386
|
+
def _check_bases_classes(self, node):
|
387
|
+
"""check that the given class node implements abstract methods from
|
388
|
+
base classes
|
389
|
+
"""
|
390
|
+
# check if this class abstract
|
391
|
+
if class_is_abstract(node):
|
392
|
+
return
|
393
|
+
for method in node.methods():
|
394
|
+
owner = method.parent.frame()
|
395
|
+
if owner is node:
|
396
|
+
continue
|
397
|
+
# owner is not this class, it must be a parent class
|
398
|
+
# check that the ancestor's method is not abstract
|
399
|
+
if method.is_abstract(pass_is_abstract=False):
|
400
|
+
self.add_message('W0223', node=node,
|
401
|
+
args=(method.name, owner.name))
|
402
|
+
|
403
|
+
def _check_interfaces(self, node):
|
404
|
+
"""check that the given class node really implements declared
|
405
|
+
interfaces
|
406
|
+
"""
|
407
|
+
e0221_hack = [False]
|
408
|
+
def iface_handler(obj):
|
409
|
+
"""filter interface objects, it should be classes"""
|
410
|
+
if not isinstance(obj, astng.Class):
|
411
|
+
e0221_hack[0] = True
|
412
|
+
self.add_message('E0221', node=node,
|
413
|
+
args=(obj.as_string(),))
|
414
|
+
return False
|
415
|
+
return True
|
416
|
+
ignore_iface_methods = self.config.ignore_iface_methods
|
417
|
+
try:
|
418
|
+
for iface in node.interfaces(handler_func=iface_handler):
|
419
|
+
for imethod in iface.methods():
|
420
|
+
name = imethod.name
|
421
|
+
if name.startswith('_') or name in ignore_iface_methods:
|
422
|
+
# don't check method beginning with an underscore,
|
423
|
+
# usually belonging to the interface implementation
|
424
|
+
continue
|
425
|
+
# get class method astng
|
426
|
+
try:
|
427
|
+
method = node_method(node, name)
|
428
|
+
except astng.NotFoundError:
|
429
|
+
self.add_message('E0222', args=(name, iface.name),
|
430
|
+
node=node)
|
431
|
+
continue
|
432
|
+
# ignore inherited methods
|
433
|
+
if method.parent.frame() is not node:
|
434
|
+
continue
|
435
|
+
# check signature
|
436
|
+
self._check_signature(method, imethod,
|
437
|
+
'%s interface' % iface.name)
|
438
|
+
except astng.InferenceError:
|
439
|
+
if e0221_hack[0]:
|
440
|
+
return
|
441
|
+
implements = Instance(node).getattr('__implements__')[0]
|
442
|
+
assignment = implements.parent
|
443
|
+
assert isinstance(assignment, astng.Assign)
|
444
|
+
# assignment.expr can be a Name or a Tuple or whatever.
|
445
|
+
# Use as_string() for the message
|
446
|
+
# FIXME: in case of multiple interfaces, find which one could not
|
447
|
+
# be resolved
|
448
|
+
self.add_message('F0220', node=implements,
|
449
|
+
args=(node.name, assignment.value.as_string()))
|
450
|
+
|
451
|
+
def _check_init(self, node):
|
452
|
+
"""check that the __init__ method call super or ancestors'__init__
|
453
|
+
method
|
454
|
+
"""
|
455
|
+
klass_node = node.parent.frame()
|
456
|
+
to_call = _ancestors_to_call(klass_node)
|
457
|
+
not_called_yet = dict(to_call)
|
458
|
+
for stmt in node.nodes_of_class(astng.CallFunc):
|
459
|
+
expr = stmt.func
|
460
|
+
if not isinstance(expr, astng.Getattr) \
|
461
|
+
or expr.attrname != '__init__':
|
462
|
+
continue
|
463
|
+
# skip the test if using super
|
464
|
+
if isinstance(expr.expr, astng.CallFunc) and \
|
465
|
+
isinstance(expr.expr.func, astng.Name) and \
|
466
|
+
expr.expr.func.name == 'super':
|
467
|
+
return
|
468
|
+
try:
|
469
|
+
klass = expr.expr.infer().next()
|
470
|
+
if klass is YES:
|
471
|
+
continue
|
472
|
+
try:
|
473
|
+
del not_called_yet[klass]
|
474
|
+
except KeyError:
|
475
|
+
if klass not in to_call:
|
476
|
+
self.add_message('W0233', node=expr, args=klass.name)
|
477
|
+
except astng.InferenceError:
|
478
|
+
continue
|
479
|
+
for klass in not_called_yet.keys():
|
480
|
+
if klass.name == 'object':
|
481
|
+
continue
|
482
|
+
self.add_message('W0231', args=klass.name, node=node)
|
483
|
+
|
484
|
+
def _check_signature(self, method1, refmethod, class_type):
|
485
|
+
"""check that the signature of the two given methods match
|
486
|
+
|
487
|
+
class_type is in 'class', 'interface'
|
488
|
+
"""
|
489
|
+
if not (isinstance(method1, astng.Function)
|
490
|
+
and isinstance(refmethod, astng.Function)):
|
491
|
+
self.add_message('F0202', args=(method1, refmethod), node=method1)
|
492
|
+
return
|
493
|
+
# don't care about functions with unknown argument (builtins)
|
494
|
+
if method1.args.args is None or refmethod.args.args is None:
|
495
|
+
return
|
496
|
+
if len(method1.args.args) != len(refmethod.args.args):
|
497
|
+
self.add_message('W0221', args=class_type, node=method1)
|
498
|
+
elif len(method1.args.defaults) < len(refmethod.args.defaults):
|
499
|
+
self.add_message('W0222', args=class_type, node=method1)
|
500
|
+
|
501
|
+
|
502
|
+
def _ancestors_to_call(klass_node, method='__init__'):
|
503
|
+
"""return a dictionary where keys are the list of base classes providing
|
504
|
+
the queried method, and so that should/may be called from the method node
|
505
|
+
"""
|
506
|
+
to_call = {}
|
507
|
+
for base_node in klass_node.ancestors(recurs=False):
|
508
|
+
try:
|
509
|
+
base_node.local_attr(method)
|
510
|
+
to_call[base_node] = 1
|
511
|
+
except astng.NotFoundError:
|
512
|
+
continue
|
513
|
+
return to_call
|
514
|
+
|
515
|
+
|
516
|
+
def node_method(node, method_name):
|
517
|
+
"""get astng for <method_name> on the given class node, ensuring it
|
518
|
+
is a Function node
|
519
|
+
"""
|
520
|
+
for n in node.local_attr(method_name):
|
521
|
+
if isinstance(n, astng.Function):
|
522
|
+
return n
|
523
|
+
raise astng.NotFoundError(method_name)
|
524
|
+
|
525
|
+
def register(linter):
|
526
|
+
"""required method to auto register this checker """
|
527
|
+
linter.register_checker(ClassChecker(linter))
|