From 3460db4ee7c7ce6c9a639a644a39c4df09ce31ac Mon Sep 17 00:00:00 2001 From: Stanislav Levin Date: Feb 13 2020 18:39:34 +0000 Subject: pylint: Synchronize pylint plugin to ipatests code Pylint is a static analysis tool and therefore, couldn't always analyze dynamic stuff properly. Transformation plugins is a way to teach Pylint how to handle such cases. Particularly, with the help of FreeIPA own plugin, it is possible to tell Pylint about instance fields having a duck-typing nature. A drawback exposed here is that a static view (Pylint's) of code should be consistent with an actual one, otherwise, codebase will be polluted with various skips of pylint checks. * added missing fields to ipatests.test_integration.base.IntegrationTest * an attempt is made to clear `no-member` skips for ipatests * removed no longer needed `pytest` module transformation Related: https://pagure.io/freeipa/issue/8116 Signed-off-by: Stanislav Levin Reviewed-By: Christian Heimes --- diff --git a/ipatests/pytest_ipa/integration/tasks.py b/ipatests/pytest_ipa/integration/tasks.py index e5ca564..0c75f4e 100755 --- a/ipatests/pytest_ipa/integration/tasks.py +++ b/ipatests/pytest_ipa/integration/tasks.py @@ -1851,7 +1851,7 @@ def ldapmodify_dm(host, ldif_text, **kwargs): args = [ 'ldapmodify', '-x', - '-D', str(host.config.dirman_dn), # pylint: disable=no-member + '-D', str(host.config.dirman_dn), '-w', host.config.dirman_password ] return host.run_command(args, stdin_text=ldif_text, **kwargs) @@ -1872,7 +1872,7 @@ def ldapsearch_dm(host, base, ldap_args, scope='sub', **kwargs): '-x', '-ZZ', '-h', host.hostname, '-p', '389', - '-D', str(host.config.dirman_dn), # pylint: disable=no-member + '-D', str(host.config.dirman_dn), '-w', host.config.dirman_password, '-s', scope, '-b', base, diff --git a/ipatests/pytest_ipa/nose_compat.py b/ipatests/pytest_ipa/nose_compat.py index 6b47804..2736ad5 100644 --- a/ipatests/pytest_ipa/nose_compat.py +++ b/ipatests/pytest_ipa/nose_compat.py @@ -54,23 +54,19 @@ def pytest_configure(config): capture = config.pluginmanager.getplugin('capturemanager') orig_stdout, orig_stderr = sys.stdout, sys.stderr if capture: - # pylint: disable=no-member if hasattr(capture, 'suspend_global_capture'): # pytest >= 3.3 capture.suspend_global_capture() else: # legacy support for pytest <= 3.2 (Fedora 27) capture._capturing.suspend_capturing() - # pylint: enable=no-member sys.stderr.write(self.format(record)) sys.stderr.write('\n') if capture: - # pylint: disable=no-member if hasattr(capture, 'resume_global_capture'): capture.resume_global_capture() else: capture._capturing.resume_capturing() - # pylint: enable=no-member sys.stdout, sys.stderr = orig_stdout, orig_stderr level = convert_log_level(config.getoption('logging_level')) diff --git a/ipatests/test_integration/test_advise.py b/ipatests/test_integration/test_advise.py index b548614..fbd6aad 100644 --- a/ipatests/test_integration/test_advise.py +++ b/ipatests/test_integration/test_advise.py @@ -17,9 +17,6 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . -# FIXME: Pylint errors -# pylint: disable=no-member - import re from ipalib.constants import IPAAPI_USER diff --git a/ipatests/test_integration/test_commands.py b/ipatests/test_integration/test_commands.py index bf4a2d3..6cccc35 100644 --- a/ipatests/test_integration/test_commands.py +++ b/ipatests/test_integration/test_commands.py @@ -183,7 +183,7 @@ class TestIPACommand(IntegrationTest): raiseonerr=False ) assert result.returncode == 2 - err = result.stderr_text.strip() # pylint: disable=no-member + err = result.stderr_text.strip() assert err == "ipa: ERROR: loc: privilege not found" # add privilege result = self.master.run_command( @@ -206,7 +206,7 @@ class TestIPACommand(IntegrationTest): master = self.master - base_dn = str(master.domain.basedn) # pylint: disable=no-member + base_dn = str(master.domain.basedn) entry_ldif = textwrap.dedent(""" dn: uid=system,cn=sysaccounts,cn=etc,{base_dn} changetype: add @@ -225,7 +225,7 @@ class TestIPACommand(IntegrationTest): new_passwd, master) def get_krbinfo(self, user): - base_dn = str(self.master.domain.basedn) # pylint: disable=no-member + base_dn = str(self.master.domain.basedn) result = tasks.ldapsearch_dm( self.master, 'uid={user},cn=users,cn=accounts,{base_dn}'.format( @@ -248,7 +248,7 @@ class TestIPACommand(IntegrationTest): new_passwd = 'userPasswd123' new_passwd2 = 'mynewPwd123' master = self.master - base_dn = str(master.domain.basedn) # pylint: disable=no-member + base_dn = str(master.domain.basedn) # Create a user with a password tasks.kinit_admin(master) @@ -293,7 +293,7 @@ class TestIPACommand(IntegrationTest): time.sleep(1) master.run_command([ paths.LDAPPASSWD, - '-D', str(master.config.dirman_dn), # pylint: disable=no-member + '-D', str(master.config.dirman_dn), '-w', master.config.dirman_password, '-a', new_passwd, '-s', new_passwd2, @@ -376,7 +376,7 @@ class TestIPACommand(IntegrationTest): test_user = 'test-ssh' external_master_hostname = \ - self.master.external_hostname # pylint: disable=no-member + self.master.external_hostname pub_keys = [] @@ -628,7 +628,7 @@ class TestIPACommand(IntegrationTest): dn = DN( ('cn', 'HTTP'), ('cn', self.master.hostname), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), - self.master.domain.basedn # pylint: disable=no-member + self.master.domain.basedn ) conn = self.master.ldap_connect() diff --git a/ipatests/test_integration/test_installation.py b/ipatests/test_integration/test_installation.py index 43dee0e..9084d0e 100644 --- a/ipatests/test_integration/test_installation.py +++ b/ipatests/test_integration/test_installation.py @@ -188,7 +188,7 @@ class TestInstallWithCA1(InstallTestBase1): https://pagure.io/freeipa/issue/7418 """ ldap_conf = paths.OPENLDAP_LDAP_CONF - base_dn = self.master.domain.basedn # pylint: disable=no-member + base_dn = self.master.domain.basedn client = self.replicas[0] tasks.uninstall_master(client) expected_msg1 = "contains deprecated and unsupported " \ diff --git a/ipatests/test_integration/test_smb.py b/ipatests/test_integration/test_smb.py index d857ad4..2cc9c4f 100644 --- a/ipatests/test_integration/test_smb.py +++ b/ipatests/test_integration/test_smb.py @@ -54,7 +54,7 @@ class TestSMB(IntegrationTest): cls.clients, domain_level, clients_extra_args=('--mkhomedir',)) - cls.ad = cls.ads[0] # pylint: disable=no-member + cls.ad = cls.ads[0] cls.smbserver = cls.clients[0] cls.smbclient = cls.clients[1] cls.ad_user = '{}@{}'.format(cls.ad_user_login, cls.ad.domain.name) diff --git a/ipatests/test_integration/test_sssd.py b/ipatests/test_integration/test_sssd.py index 4cfec0b..57d5de6 100644 --- a/ipatests/test_integration/test_sssd.py +++ b/ipatests/test_integration/test_sssd.py @@ -45,7 +45,7 @@ class TestSSSDWithAdTrust(IntegrationTest): def install(cls, mh): super(TestSSSDWithAdTrust, cls).install(mh) - cls.ad = cls.ads[0] # pylint: disable=no-member + cls.ad = cls.ads[0] tasks.install_adtrust(cls.master) tasks.configure_dns_for_trust(cls.master, cls.ad) diff --git a/ipatests/test_integration/test_sudo.py b/ipatests/test_integration/test_sudo.py index eb651ad..faa427d 100644 --- a/ipatests/test_integration/test_sudo.py +++ b/ipatests/test_integration/test_sudo.py @@ -724,7 +724,7 @@ class TestSudo(IntegrationTest): """ self.master.run_command( ['ipa', 'config-mod', '--domain-resolution-order', - self.domain.name]) # pylint: disable=no-member + self.domain.name]) try: # prepare the sudo rule: set only one user for ipasudorunas self.reset_rule_categories() @@ -741,7 +741,7 @@ class TestSudo(IntegrationTest): # according to listing of allowed commands result = self.list_sudo_commands('testuser1') expected_rule = ('(testuser2@%s) NOPASSWD: ALL' - % self.domain.name) # pylint: disable=no-member + % self.domain.name) assert expected_rule in result.stdout_text # check that testuser1 can actually run commands as testuser2 diff --git a/ipatests/test_integration/test_trust.py b/ipatests/test_integration/test_trust.py index 97fde43..e595224 100644 --- a/ipatests/test_integration/test_trust.py +++ b/ipatests/test_integration/test_trust.py @@ -37,15 +37,15 @@ class BaseTestTrust(IntegrationTest): raise pytest.skip("Package samba-client not available " "on {}".format(cls.master.hostname)) super(BaseTestTrust, cls).install(mh) - cls.ad = cls.ads[0] # pylint: disable=no-member + cls.ad = cls.ads[0] cls.ad_domain = cls.ad.domain.name tasks.install_adtrust(cls.master) cls.check_sid_generation() tasks.sync_time(cls.master, cls.ad) - cls.child_ad = cls.ad_subdomains[0] # pylint: disable=no-member + cls.child_ad = cls.ad_subdomains[0] cls.ad_subdomain = cls.child_ad.domain.name - cls.tree_ad = cls.ad_treedomains[0] # pylint: disable=no-member + cls.tree_ad = cls.ad_treedomains[0] cls.ad_treedomain = cls.tree_ad.domain.name # values used in workaround for diff --git a/ipatests/test_integration/test_upgrade.py b/ipatests/test_integration/test_upgrade.py index 84f2dca..cd7341d 100644 --- a/ipatests/test_integration/test_upgrade.py +++ b/ipatests/test_integration/test_upgrade.py @@ -42,7 +42,7 @@ class TestUpgrade(IntegrationTest): """ # Read the current entry from LDAP ldap = self.master.ldap_connect() - basedn = self.master.domain.basedn # pylint: disable=no-member + basedn = self.master.domain.basedn dn = DN(('cn', 'CAcert'), ('cn', 'ipa'), ('cn', 'etc'), basedn) entry = ldap.get_entry(dn) # pylint: disable=no-member # Extract the certificate as DER then double-encode diff --git a/ipatests/test_integration/test_winsyncmigrate.py b/ipatests/test_integration/test_winsyncmigrate.py index be9f440..87fb9a5 100644 --- a/ipatests/test_integration/test_winsyncmigrate.py +++ b/ipatests/test_integration/test_winsyncmigrate.py @@ -74,7 +74,7 @@ class TestWinsyncMigrate(IntegrationTest): def install(cls, mh): super(TestWinsyncMigrate, cls).install(mh) - cls.ad = cls.ads[0] # pylint: disable=no-member + cls.ad = cls.ads[0] cls.trust_test_user = '%s@%s' % (cls.ad_user, cls.ad.domain.name) tasks.configure_dns_for_trust(cls.master, cls.ad) tasks.install_adtrust(cls.master) diff --git a/ipatests/test_ipalib/test_backend.py b/ipatests/test_ipalib/test_backend.py index 6cc6118..0bac1a5 100644 --- a/ipatests/test_ipalib/test_backend.py +++ b/ipatests/test_ipalib/test_backend.py @@ -22,10 +22,6 @@ Test the `ipalib.backend` module. """ from __future__ import print_function -# FIXME: Pylint errors -# pylint: disable=no-member -# pylint: disable=maybe-no-member - import threading from ipatests.util import ClassChecker, raises, create_test_api from ipatests.data import unicode_str diff --git a/ipatests/test_ipalib/test_frontend.py b/ipatests/test_ipalib/test_frontend.py index 7a51006..1dd0541 100644 --- a/ipatests/test_ipalib/test_frontend.py +++ b/ipatests/test_ipalib/test_frontend.py @@ -21,8 +21,6 @@ Test the `ipalib.frontend` module. """ -# FIXME: Pylint errors -# pylint: disable=no-member import pytest import six diff --git a/ipatests/test_ipalib/test_rpc.py b/ipatests/test_ipalib/test_rpc.py index cf1aea4..424967e 100644 --- a/ipatests/test_ipalib/test_rpc.py +++ b/ipatests/test_ipalib/test_rpc.py @@ -73,7 +73,6 @@ def test_round_trip(): if six.PY2: assert_equal(dump_n_load(utf8_bytes), unicode_str) assert_equal(dump_n_load(unicode_str), unicode_str) - # "Binary" is not "str". pylint: disable=no-member assert_equal(dump_n_load(Binary(binary_bytes)).data, binary_bytes) assert isinstance(dump_n_load(Binary(binary_bytes)), Binary) assert type(dump_n_load(b'hello')) is output_binary_type @@ -110,7 +109,6 @@ def test_xml_wrap(): assert f({}, API_VERSION) == dict() b = f(b'hello', API_VERSION) assert isinstance(b, Binary) - # "Binary" is not "dict" or "tuple". pylint: disable=no-member assert b.data == b'hello' u = f(u'hello', API_VERSION) assert type(u) is unicode diff --git a/ipatests/test_ipapython/test_ipautil.py b/ipatests/test_ipapython/test_ipautil.py index 860718e..884d7d5 100644 --- a/ipatests/test_ipapython/test_ipautil.py +++ b/ipatests/test_ipapython/test_ipautil.py @@ -395,8 +395,6 @@ class TestTimeParser: assert_equal(800000, time.microsecond) def test_time_zones(self): - # pylint: disable=no-member - timestr = "20051213141205Z" time = ipautil.parse_generalized_time(timestr) diff --git a/ipatests/test_util.py b/ipatests/test_util.py index f8772d6..2d93df6 100644 --- a/ipatests/test_util.py +++ b/ipatests/test_util.py @@ -154,7 +154,7 @@ class test_Fuzzy: def test_assert_deepequal(pytestconfig): f = util.assert_deepequal - try: # pylint: disable=no-member + try: pretty = pytestconfig.getoption("pretty_print") except (AttributeError, ValueError): pretty = False diff --git a/pylint_plugins.py b/pylint_plugins.py index 7f3cf01..8f50bcd 100644 --- a/pylint_plugins.py +++ b/pylint_plugins.py @@ -183,9 +183,12 @@ ipa_class_members = { 'normalizedns', ], 'ipatests.test_integration.base.IntegrationTest': [ - 'domain', + {'domain': [ + {'name': dir(str)}, + ]}, {'master': [ {'config': [ + {'dirman_dn': dir(str)}, {'dirman_password': dir(str)}, {'admin_password': dir(str)}, {'admin_name': dir(str)}, @@ -197,15 +200,17 @@ ipa_class_members = { {'fips_mode': dir(bool)}, ]}, {'domain': [ + {'basedn': dir(str)}, {'realm': dir(str)}, {'name': dir(str)}, ]}, - 'hostname', + {'external_hostname': dir(str)}, + {'hostname': dir(str)}, 'ip', 'collect_log', {'run_command': [ {'stdout_text': dir(str)}, - 'stderr_text', + {'stderr_text': dir(str)}, 'returncode', ]}, {'transport': ['put_file', 'file_exists']}, @@ -216,6 +221,9 @@ ipa_class_members = { 'replicas', 'clients', 'ad_domains', + {'ads': dir(list)}, + {'ad_subdomains': dir(list)}, + {'ad_treedomains': dir(list)}, ] } @@ -229,18 +237,6 @@ def fix_ipa_classes(cls): MANAGER.register_transform(scoped_nodes.ClassDef, fix_ipa_classes) -def pytest_config_transform(): - """pylint.config attribute - """ - return AstroidBuilder(MANAGER).string_build(textwrap.dedent(''' - from _pytest.config import get_config - config = get_config() - ''')) - - -register_module_extender(MANAGER, 'pytest', pytest_config_transform) - - def ipaplatform_constants_transform(): return AstroidBuilder(MANAGER).string_build(textwrap.dedent(''' from ipaplatform.base.constants import constants