diff options
author | Martin Basti <mbasti@redhat.com> | 2016-01-15 16:58:38 +0100 |
---|---|---|
committer | Martin Basti <mbasti@redhat.com> | 2016-02-11 11:06:39 +0100 |
commit | 2ce8921fe69ed58871f8e33e3899ad80dcc28c0e (patch) | |
tree | c91786320fca02c4ce473ef9e6197aa610cde0fc /pylint_plugins.py | |
parent | 5ac3a3cee534a16db86c541b9beff4939f03410e (diff) | |
download | freeipa-2ce8921fe69ed58871f8e33e3899ad80dcc28c0e.tar.gz freeipa-2ce8921fe69ed58871f8e33e3899ad80dcc28c0e.tar.xz freeipa-2ce8921fe69ed58871f8e33e3899ad80dcc28c0e.zip |
make lint: use config file and plugin for pylint
Our custom implementation of pylint checker is often broken by
incompatible change on pylint side. Using supported solutions (config
file, pylint plugins) should avoid this issue.
The plugin adds missing (dynamic) member to classes in abstract syntax
tree generated for pylint, instead of just ignoring missing members and
all sub-members. This should improve pylint detection of typos and
missing members in api. env and test config.
make-lint python script has been removed, to run pylint execute 'make
lint'
https://fedorahosted.org/freeipa/ticket/5615
Reviewed-By: David Kupka <dkupka@redhat.com>
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
Diffstat (limited to 'pylint_plugins.py')
-rw-r--r-- | pylint_plugins.py | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/pylint_plugins.py b/pylint_plugins.py new file mode 100644 index 000000000..f64c426fd --- /dev/null +++ b/pylint_plugins.py @@ -0,0 +1,210 @@ +# +# Copyright (C) 2015 FreeIPA Contributors see COPYING for license +# + +from __future__ import print_function + +import copy +import sys + +from astroid import MANAGER +from astroid import scoped_nodes + + +def register(linter): + pass + + +def _warning_already_exists(cls, member): + print( + "WARNING: member '{member}' in '{cls}' already exists".format( + cls="{}.{}".format(cls.root().name, cls.name), member=member), + file=sys.stderr + ) + + +def fake_class(name_or_class_obj, members=()): + if isinstance(name_or_class_obj, scoped_nodes.Class): + cl = name_or_class_obj + else: + cl = scoped_nodes.Class(name_or_class_obj, None) + + for m in members: + if isinstance(m, str): + if m in cl.locals: + _warning_already_exists(cl, m) + else: + cl.locals[m] = [scoped_nodes.Class(m, None)] + elif isinstance(m, dict): + for key, val in m.items(): + assert isinstance(key, str), "key must be string" + if key in cl.locals: + _warning_already_exists(cl, key) + fake_class(cl.locals[key], val) + else: + cl.locals[key] = [fake_class(key, val)] + else: + # here can be used any astroid type + if m.name in cl.locals: + _warning_already_exists(cl, m.name) + else: + cl.locals[m.name] = [copy.copy(m)] + return cl + + +fake_backend = {'Backend': [ + {'wsgi_dispatch': ['mount']}, +]} + +NAMESPACE_ATTRS = ['Command', 'Object', 'Method', fake_backend, 'Updater', + 'Advice'] +fake_api_env = {'env': [ + 'host', + 'realm', + 'session_auth_duration', + 'session_duration_type', +]} + +# this is due ipaserver.rpcserver.KerberosSession where api is undefined +fake_api = {'api': [fake_api_env] + NAMESPACE_ATTRS} + +_LOGGING_ATTRS = ['debug', 'info', 'warning', 'error', 'exception', + 'critical'] +LOGGING_ATTRS = [ + {'log': _LOGGING_ATTRS}, +] + _LOGGING_ATTRS + +# 'class': ['generated', 'properties'] +ipa_class_members = { + # Python standard library & 3rd party classes + 'socket._socketobject': ['sendall'], + + # IPA classes + 'ipalib.base.NameSpace': [ + 'add', + 'mod', + 'del', + 'show', + 'find' + ], + 'ipalib.cli.Collector': ['__options'], + 'ipalib.config.Env': [ + {'__d': ['get']}, + {'__done': ['add']}, + 'xmlrpc_uri', + 'validate_api', + 'startup_traceback', + 'verbose' + ] + LOGGING_ATTRS, + 'ipalib.parameters.Param': [ + 'cli_name', + 'cli_short_name', + 'label', + 'default', + 'doc', + 'required', + 'multivalue', + 'primary_key', + 'normalizer', + 'default_from', + 'autofill', + 'query', + 'attribute', + 'include', + 'exclude', + 'flags', + 'hint', + 'alwaysask', + 'sortorder', + 'csv', + 'option_group', + ], + 'ipalib.parameters.Bool': [ + 'truths', + 'falsehoods'], + 'ipalib.parameters.Data': [ + 'minlength', + 'maxlength', + 'length', + 'pattern', + 'pattern_errmsg', + ], + 'ipalib.parameters.Str': ['noextrawhitespace'], + 'ipalib.parameters.Password': ['confirm'], + 'ipalib.parameters.File': ['stdin_if_missing'], + 'ipalib.plugins.dns.DNSRecord': [ + 'validatedns', + 'normalizedns', + ], + 'ipalib.parameters.Enum': ['values'], + 'ipalib.parameters.Number': [ + 'minvalue', + 'maxvalue', + ], + 'ipalib.parameters.Decimal': [ + 'precision', + 'exponential', + 'numberclass', + ], + 'ipalib.parameters.DNSNameParam': [ + 'only_absolute', + 'only_relative', + ], + 'ipalib.plugable.API': [ + fake_api_env, + ] + NAMESPACE_ATTRS + LOGGING_ATTRS, + 'ipalib.plugable.Plugin': [ + 'Object', + 'Method', + 'Updater', + 'Advice', + ] + LOGGING_ATTRS, + 'ipalib.session.AuthManager': LOGGING_ATTRS, + 'ipalib.session.SessionAuthManager': LOGGING_ATTRS, + 'ipalib.session.SessionManager': LOGGING_ATTRS, + 'ipaserver.install.ldapupdate.LDAPUpdate': LOGGING_ATTRS, + 'ipaserver.rpcserver.KerberosSession': [ + fake_api, + ] + LOGGING_ATTRS, + 'ipatests.test_integration.base.IntegrationTest': [ + 'domain', + {'master': [ + {'config': [ + {'dirman_password': dir(str)}, + {'admin_password': dir(str)}, + {'admin_name': dir(str)}, + {'dns_forwarder': dir(str)}, + {'test_dir': dir(str)}, + {'ad_admin_name': dir(str)}, + {'ad_admin_password': dir(str)}, + {'domain_level': dir(str)}, + ]}, + {'domain': [ + {'realm': dir(str)}, + {'name': dir(str)}, + ]}, + 'hostname', + 'ip', + 'collect_log', + {'run_command': [ + {'stdout_text': dir(str)}, + 'stderr_text', + 'returncode', + ]}, + {'transport': ['put_file']}, + 'put_file_contents', + 'get_file_contents', + ]}, + 'replicas', + 'clients', + 'ad_domains', + ] +} + + +def fix_ipa_classes(cls): + class_name_with_module = "{}.{}".format(cls.root().name, cls.name) + if class_name_with_module in ipa_class_members: + fake_class(cls, ipa_class_members[class_name_with_module]) + +MANAGER.register_transform(scoped_nodes.Class, fix_ipa_classes) |