From 7eadee31db2f038763a3a6f978db1ea76bbc4674 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Sat, 1 Apr 2023 12:24:59 +0200 Subject: Fix pylint warnings / cleanup (#2218) --- .github/workflows/issues.py | 4 +-- Makefile | 15 +++++++---- psutil/__init__.py | 2 +- psutil/_common.py | 4 +-- psutil/_compat.py | 4 +-- psutil/_psaix.py | 4 +-- psutil/_pslinux.py | 6 ++--- psutil/_pssunos.py | 2 +- psutil/_pswindows.py | 2 +- psutil/tests/__init__.py | 23 +++++++---------- psutil/tests/test_bsd.py | 2 +- psutil/tests/test_connections.py | 2 +- psutil/tests/test_contracts.py | 2 +- psutil/tests/test_linux.py | 18 ++++++------- psutil/tests/test_misc.py | 20 +++++++-------- psutil/tests/test_osx.py | 37 --------------------------- psutil/tests/test_posix.py | 5 ++-- psutil/tests/test_process.py | 9 +++---- psutil/tests/test_system.py | 18 ++++++------- psutil/tests/test_testutils.py | 10 ++++---- psutil/tests/test_unicode.py | 3 +-- pyproject.toml | 38 ++++++++++++++++++++++++++++ scripts/internal/download_wheels_appveyor.py | 4 +-- scripts/internal/git_pre_commit.py | 20 +++++++-------- scripts/internal/print_announce.py | 2 +- scripts/internal/print_dist.py | 2 +- scripts/internal/winmake.py | 22 ++++++++++------ scripts/iotop.py | 2 +- scripts/procinfo.py | 2 +- setup.py | 5 +--- 30 files changed, 146 insertions(+), 143 deletions(-) diff --git a/.github/workflows/issues.py b/.github/workflows/issues.py index 2aea40be..06438b97 100644 --- a/.github/workflows/issues.py +++ b/.github/workflows/issues.py @@ -222,7 +222,7 @@ def add_label(issue, label): issue.add_to_labels(label) -def _guess_labels_from_text(issue, text): +def _guess_labels_from_text(text): assert isinstance(text, str), text for label, keywords in LABELS_MAP.items(): for keyword in keywords: @@ -232,7 +232,7 @@ def _guess_labels_from_text(issue, text): def add_labels_from_text(issue, text): assert isinstance(text, str), text - for label, keyword in _guess_labels_from_text(issue, text): + for label, keyword in _guess_labels_from_text(text): add_label(issue, label) diff --git a/Makefile b/Makefile index f5472bf4..27bba266 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,7 @@ PY3_DEPS = \ flake8-quotes \ isort \ pep8-naming \ + pylint \ pyperf \ pypinfo \ requests \ @@ -36,6 +37,7 @@ PY2_DEPS = \ mock PY_DEPS = `$(PYTHON) -c \ "import sys; print('$(PY3_DEPS)' if sys.version_info[0] == 3 else '$(PY2_DEPS)')"` +NUM_WORKERS = `$(PYTHON) -c "import os; print(os.cpu_count() or 1)"` # "python3 setup.py build" can be parallelized on Python >= 3.6. BUILD_OPTS = `$(PYTHON) -c \ "import sys, os; \ @@ -191,10 +193,13 @@ test-coverage: ## Run test coverage. # =================================================================== flake8: ## Run flake8 linter. - @git ls-files '*.py' | xargs $(PYTHON) -m flake8 --config=.flake8 + @git ls-files '*.py' | xargs $(PYTHON) -m flake8 --config=.flake8 --jobs=${NUM_WORKERS} isort: ## Run isort linter. - @git ls-files '*.py' | xargs $(PYTHON) -m isort --check-only + @git ls-files '*.py' | xargs $(PYTHON) -m isort --check-only --jobs=${NUM_WORKERS} + +pylint: ## Python pylint (not mandatory, just run it from time to time) + @git ls-files '*.py' | xargs $(PYTHON) -m pylint --rcfile=pyproject.toml --jobs=${NUM_WORKERS} c-linter: ## Run C linter. @git ls-files '*.c' '*.h' | xargs $(PYTHON) scripts/internal/clinter.py @@ -209,11 +214,11 @@ lint-all: ## Run all linters # =================================================================== fix-flake8: ## Run autopep8, fix some Python flake8 / pep8 issues. - @git ls-files '*.py' | xargs $(PYTHON) -m autopep8 --in-place --jobs 0 --global-config=.flake8 - @git ls-files '*.py' | xargs $(PYTHON) -m autoflake --in-place --jobs 0 --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys + @git ls-files '*.py' | xargs $(PYTHON) -m autopep8 --in-place --jobs=${NUM_WORKERS} --global-config=.flake8 + @git ls-files '*.py' | xargs $(PYTHON) -m autoflake --in-place --jobs=${NUM_WORKERS} --remove-all-unused-imports --remove-unused-variables --remove-duplicate-keys fix-imports: ## Fix imports with isort. - @git ls-files '*.py' | xargs $(PYTHON) -m isort + @git ls-files '*.py' | xargs $(PYTHON) -m isort --jobs=${NUM_WORKERS} fix-all: ## Run all code fixers. ${MAKE} fix-flake8 diff --git a/psutil/__init__.py b/psutil/__init__.py index deaf02ea..6036cbe9 100644 --- a/psutil/__init__.py +++ b/psutil/__init__.py @@ -516,7 +516,7 @@ class Process(object): "s" if len(invalid_names) > 1 else "", ", ".join(map(repr, invalid_names)))) - retdict = dict() + retdict = {} ls = attrs or valid_names with self.oneshot(): for name in ls: diff --git a/psutil/_common.py b/psutil/_common.py index 74ae2557..92286746 100644 --- a/psutil/_common.py +++ b/psutil/_common.py @@ -43,7 +43,7 @@ else: # can't take it from _common.py as this script is imported by setup.py PY3 = sys.version_info[0] == 3 -PSUTIL_DEBUG = bool(os.getenv('PSUTIL_DEBUG', 0)) +PSUTIL_DEBUG = bool(os.getenv('PSUTIL_DEBUG')) _DEFAULT = object() __all__ = [ @@ -924,7 +924,7 @@ def debug(msg): """If PSUTIL_DEBUG env var is set, print a debug message to stderr.""" if PSUTIL_DEBUG: import inspect - fname, lineno, func_name, lines, index = inspect.getframeinfo( + fname, lineno, _, lines, index = inspect.getframeinfo( inspect.currentframe().f_back) if isinstance(msg, Exception): if isinstance(msg, (OSError, IOError, EnvironmentError)): diff --git a/psutil/_compat.py b/psutil/_compat.py index 52e762b1..2531cf4b 100644 --- a/psutil/_compat.py +++ b/psutil/_compat.py @@ -254,7 +254,7 @@ except ImportError: http://docs.python.org/3/library/functools.html#functools.lru_cache """ def decorating_function(user_function): - cache = dict() + cache = {} stats = [0, 0] HITS, MISSES = 0, 1 make_key = _make_key @@ -432,7 +432,7 @@ except ImportError: try: from subprocess import TimeoutExpired as SubprocessTimeoutExpired except ImportError: - class SubprocessTimeoutExpired: + class SubprocessTimeoutExpired(Exception): pass diff --git a/psutil/_psaix.py b/psutil/_psaix.py index 2391478c..5c41069c 100644 --- a/psutil/_psaix.py +++ b/psutil/_psaix.py @@ -465,8 +465,8 @@ class Process(object): @wrap_exceptions def cpu_times(self): - cpu_times = cext.proc_cpu_times(self.pid, self._procfs_path) - return _common.pcputimes(*cpu_times) + t = cext.proc_cpu_times(self.pid, self._procfs_path) + return _common.pcputimes(*t) @wrap_exceptions def terminal(self): diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py index 1bdeabfe..d178fe16 100644 --- a/psutil/_pslinux.py +++ b/psutil/_pslinux.py @@ -327,8 +327,8 @@ except ImportError: pid, resource_, ctypes.byref(new), ctypes.byref(current)) if ret != 0: - errno = ctypes.get_errno() - raise OSError(errno, os.strerror(errno)) + errno_ = ctypes.get_errno() + raise OSError(errno_, os.strerror(errno_)) return (current.rlim_cur, current.rlim_max) @@ -1837,7 +1837,7 @@ class Process(object): ) except KeyError as err: raise ValueError("%r field was not found in %s; found fields " - "are %r" % (err[0], fname, fields)) + "are %r" % (err.args[0], fname, fields)) @wrap_exceptions def cpu_times(self): diff --git a/psutil/_pssunos.py b/psutil/_pssunos.py index 541c1aa4..8663de3c 100644 --- a/psutil/_pssunos.py +++ b/psutil/_pssunos.py @@ -143,7 +143,7 @@ def swap_memory(): p = subprocess.Popen(['/usr/bin/env', 'PATH=/usr/sbin:/sbin:%s' % os.environ['PATH'], 'swap', '-l'], stdout=subprocess.PIPE) - stdout, stderr = p.communicate() + stdout, _ = p.communicate() if PY3: stdout = stdout.decode(sys.stdout.encoding) if p.returncode != 0: diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py index b546f15d..3802f3ed 100644 --- a/psutil/_pswindows.py +++ b/psutil/_pswindows.py @@ -699,7 +699,7 @@ def retry_error_partial_copy(fun): def wrapper(self, *args, **kwargs): delay = 0.0001 times = 33 - for x in range(times): # retries for roughly 1 second + for _ in range(times): # retries for roughly 1 second try: return fun(self, *args, **kwargs) except WindowsError as _: diff --git a/psutil/tests/__init__.py b/psutil/tests/__init__.py index cdc8b671..e82bb38d 100644 --- a/psutil/tests/__init__.py +++ b/psutil/tests/__init__.py @@ -85,22 +85,19 @@ __all__ = [ "HAS_CPU_AFFINITY", "HAS_CPU_FREQ", "HAS_ENVIRON", "HAS_PROC_IO_COUNTERS", "HAS_IONICE", "HAS_MEMORY_MAPS", "HAS_PROC_CPU_NUM", "HAS_RLIMIT", "HAS_SENSORS_BATTERY", "HAS_BATTERY", "HAS_SENSORS_FANS", - "HAS_SENSORS_TEMPERATURES", "HAS_MEMORY_FULL_INFO", "MACOS_11PLUS", + "HAS_SENSORS_TEMPERATURES", "MACOS_11PLUS", "MACOS_12PLUS", "COVERAGE", # subprocesses 'pyrun', 'terminate', 'reap_children', 'spawn_testproc', 'spawn_zombie', 'spawn_children_pair', # threads - 'ThreadTask' + 'ThreadTask', # test utils 'unittest', 'skip_on_access_denied', 'skip_on_not_implemented', 'retry_on_failure', 'TestMemoryLeak', 'PsutilTestCase', 'process_namespace', 'system_namespace', 'print_sysinfo', - # install utils - 'install_pip', 'install_test_deps', # fs utils - 'chdir', 'safe_rmpath', 'create_exe', 'decode_path', 'encode_path', - 'get_testfn', + 'chdir', 'safe_rmpath', 'create_exe', 'get_testfn', # os 'get_winver', 'kernel_version', # sync primitives @@ -458,7 +455,7 @@ def spawn_zombie(): zpid = int(conn.recv(1024)) _pids_started.add(zpid) zombie = psutil.Process(zpid) - call_until(lambda: zombie.status(), "ret == psutil.STATUS_ZOMBIE") + call_until(zombie.status, "ret == psutil.STATUS_ZOMBIE") return (parent, zombie) finally: conn.close() @@ -628,7 +625,7 @@ def reap_children(recursive=False): if children: for p in children: terminate(p, wait_timeout=None) - gone, alive = psutil.wait_procs(children, timeout=GLOBAL_TIMEOUT) + _, alive = psutil.wait_procs(children, timeout=GLOBAL_TIMEOUT) for p in alive: warn("couldn't terminate process %r; attempting kill()" % p) terminate(p, sig=signal.SIGKILL) @@ -999,7 +996,7 @@ class TestMemoryLeak(PsutilTestCase): retries = 10 if CI_TESTING else 5 verbose = True _thisproc = psutil.Process() - _psutil_debug_orig = bool(os.getenv('PSUTIL_DEBUG', 0)) + _psutil_debug_orig = bool(os.getenv('PSUTIL_DEBUG')) @classmethod def setUpClass(cls): @@ -1059,7 +1056,7 @@ class TestMemoryLeak(PsutilTestCase): diff = mem2 - mem1 # can also be negative return diff - def _check_mem(self, fun, times, warmup_times, retries, tolerance): + def _check_mem(self, fun, times, retries, tolerance): messages = [] prev_mem = 0 increase = times @@ -1104,8 +1101,7 @@ class TestMemoryLeak(PsutilTestCase): self._call_ntimes(fun, warmup_times) # warm up self._check_fds(fun) - self._check_mem(fun, times=times, warmup_times=warmup_times, - retries=retries, tolerance=tolerance) + self._check_mem(fun, times=times, retries=retries, tolerance=tolerance) def execute_w_exc(self, exc, fun, **kwargs): """Convenience method to test a callable while making sure it @@ -1122,7 +1118,6 @@ def print_sysinfo(): import datetime import getpass import locale - import platform import pprint try: import pip @@ -1616,7 +1611,7 @@ def check_net_address(addr, family): elif family == psutil.AF_LINK: assert re.match(r'([a-fA-F0-9]{2}[:|\-]?){6}', addr) is not None, addr else: - raise ValueError("unknown family %r", family) + raise ValueError("unknown family %r" % family) def check_connection_ntuple(conn): diff --git a/psutil/tests/test_bsd.py b/psutil/tests/test_bsd.py index e541547d..29ea384d 100755 --- a/psutil/tests/test_bsd.py +++ b/psutil/tests/test_bsd.py @@ -36,7 +36,7 @@ if BSD: PAGESIZE = getpagesize() # muse requires root privileges - MUSE_AVAILABLE = True if os.getuid() == 0 and which('muse') else False + MUSE_AVAILABLE = os.getuid() == 0 and which('muse') else: PAGESIZE = None MUSE_AVAILABLE = False diff --git a/psutil/tests/test_connections.py b/psutil/tests/test_connections.py index f3b1f837..d47233bc 100755 --- a/psutil/tests/test_connections.py +++ b/psutil/tests/test_connections.py @@ -501,7 +501,7 @@ class TestSystemWideConnections(ConnectionTestCase): pids = [] times = 10 fnames = [] - for i in range(times): + for _ in range(times): fname = self.get_testfn() fnames.append(fname) src = textwrap.dedent("""\ diff --git a/psutil/tests/test_contracts.py b/psutil/tests/test_contracts.py index 3b806ee3..b767e3eb 100755 --- a/psutil/tests/test_contracts.py +++ b/psutil/tests/test_contracts.py @@ -176,7 +176,7 @@ class TestAvailProcessAPIs(PsutilTestCase): def test_io_counters(self): hasit = hasattr(psutil.Process, "io_counters") - self.assertEqual(hasit, False if MACOS or SUNOS else True) + self.assertEqual(hasit, not (MACOS or SUNOS)) def test_num_fds(self): self.assertEqual(hasattr(psutil.Process, "num_fds"), POSIX) diff --git a/psutil/tests/test_linux.py b/psutil/tests/test_linux.py index 964416b3..e1de6706 100755 --- a/psutil/tests/test_linux.py +++ b/psutil/tests/test_linux.py @@ -749,7 +749,7 @@ class TestSystemCPUCountLogical(PsutilTestCase): # this way we'll fall back on relying on /proc/stat with mock_open_content('/proc/cpuinfo', b"") as m: self.assertEqual(psutil._pslinux.cpu_count_logical(), original) - m.called + assert m.called @unittest.skipIf(not LINUX, "LINUX only") @@ -817,8 +817,8 @@ class TestSystemCPUFrequency(PsutilTestCase): self.assertEqual(ret.max, 0.0) self.assertEqual(ret.min, 0.0) for freq in psutil.cpu_freq(percpu=True): - self.assertEqual(ret.max, 0.0) - self.assertEqual(ret.min, 0.0) + self.assertEqual(freq.max, 0.0) + self.assertEqual(freq.min, 0.0) finally: reload_module(psutil._pslinux) reload_module(psutil) @@ -1057,7 +1057,7 @@ class TestSystemNetIOCounters(PsutilTestCase): def test_against_ifconfig(self): def ifconfig(nic): ret = {} - out = sh("ifconfig %s" % name) + out = sh("ifconfig %s" % nic) ret['packets_recv'] = int( re.findall(r'RX packets[: ](\d+)', out)[0]) ret['packets_sent'] = int( @@ -1150,7 +1150,7 @@ class TestSystemDiskPartitions(PsutilTestCase): for part in psutil.disk_partitions(all=False): usage = psutil.disk_usage(part.mountpoint) - dev, total, used, free = df(part.mountpoint) + _, total, used, free = df(part.mountpoint) self.assertEqual(usage.total, total) self.assertAlmostEqual(usage.free, free, delta=TOLERANCE_DISK_USAGE) @@ -2034,7 +2034,7 @@ class TestProcess(PsutilTestCase): # which no longer exists by the time we open() it (race # condition). threads() is supposed to ignore that instead # of raising NSP. - def open_mock(name, *args, **kwargs): + def open_mock_1(name, *args, **kwargs): if name.startswith('/proc/%s/task' % os.getpid()): raise IOError(errno.ENOENT, "") else: @@ -2042,20 +2042,20 @@ class TestProcess(PsutilTestCase): orig_open = open patch_point = 'builtins.open' if PY3 else '__builtin__.open' - with mock.patch(patch_point, side_effect=open_mock) as m: + with mock.patch(patch_point, side_effect=open_mock_1) as m: ret = psutil.Process().threads() assert m.called self.assertEqual(ret, []) # ...but if it bumps into something != ENOENT we want an # exception. - def open_mock(name, *args, **kwargs): + def open_mock_2(name, *args, **kwargs): if name.startswith('/proc/%s/task' % os.getpid()): raise IOError(errno.EPERM, "") else: return orig_open(name, *args, **kwargs) - with mock.patch(patch_point, side_effect=open_mock): + with mock.patch(patch_point, side_effect=open_mock_2): self.assertRaises(psutil.AccessDenied, psutil.Process().threads) def test_exe_mocked(self): diff --git a/psutil/tests/test_misc.py b/psutil/tests/test_misc.py index afa60b1c..a7b5d02d 100755 --- a/psutil/tests/test_misc.py +++ b/psutil/tests/test_misc.py @@ -299,19 +299,19 @@ class TestMemoizeDecorator(PsutilTestCase): def run_against(self, obj, expected_retval=None): # no args - for x in range(2): + for _ in range(2): ret = obj() self.assertEqual(self.calls, [((), {})]) if expected_retval is not None: self.assertEqual(ret, expected_retval) # with args - for x in range(2): + for _ in range(2): ret = obj(1) self.assertEqual(self.calls, [((), {}), ((1, ), {})]) if expected_retval is not None: self.assertEqual(ret, expected_retval) # with args + kwargs - for x in range(2): + for _ in range(2): ret = obj(1, bar=2) self.assertEqual( self.calls, [((), {}), ((1, ), {}), ((1, ), {'bar': 2})]) @@ -400,19 +400,19 @@ class TestMemoizeDecorator(PsutilTestCase): calls = [] # no args - for x in range(2): + for _ in range(2): ret = foo() expected = ((), {}) self.assertEqual(ret, expected) self.assertEqual(len(calls), 1) # with args - for x in range(2): + for _ in range(2): ret = foo(1) expected = ((1, ), {}) self.assertEqual(ret, expected) self.assertEqual(len(calls), 2) # with args + kwargs - for x in range(2): + for _ in range(2): ret = foo(1, bar=2) expected = ((1, ), {'bar': 2}) self.assertEqual(ret, expected) @@ -732,7 +732,7 @@ class TestWrapNumbers(PsutilTestCase): {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 100}}) self.assertEqual(cache[2], {'disk_io': {'disk1': set([('disk1', 2)])}}) - def assert_(): + def check_cache_info(): cache = wrap_numbers.cache_info() self.assertEqual( cache[1], @@ -746,14 +746,14 @@ class TestWrapNumbers(PsutilTestCase): wrap_numbers(input, 'disk_io') cache = wrap_numbers.cache_info() self.assertEqual(cache[0], {'disk_io': input}) - assert_() + check_cache_info() # then it goes up input = {'disk1': nt(100, 100, 90)} wrap_numbers(input, 'disk_io') cache = wrap_numbers.cache_info() self.assertEqual(cache[0], {'disk_io': input}) - assert_() + check_cache_info() # then it wraps again input = {'disk1': nt(100, 100, 20)} @@ -837,7 +837,7 @@ class TestScripts(PsutilTestCase): return out @staticmethod - def assert_syntax(exe, args=None): + def assert_syntax(exe): exe = os.path.join(SCRIPTS_DIR, exe) if PY3: f = open(exe, 'rt', encoding='utf8') diff --git a/psutil/tests/test_osx.py b/psutil/tests/test_osx.py index af126484..dc0dd6ba 100755 --- a/psutil/tests/test_osx.py +++ b/psutil/tests/test_osx.py @@ -51,33 +51,6 @@ def vm_stat(field): return int(re.search(r'\d+', line).group(0)) * getpagesize() -# http://code.activestate.com/recipes/578019/ -def human2bytes(s): - SYMBOLS = { - 'customary': ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'), - } - init = s - num = "" - while s and s[0:1].isdigit() or s[0:1] == '.': - num += s[0] - s = s[1:] - num = float(num) - letter = s.strip() - for name, sset in SYMBOLS.items(): - if letter in sset: - break - else: - if letter == 'k': - sset = SYMBOLS['customary'] - letter = letter.upper() - else: - raise ValueError("can't interpret %r" % init) - prefix = {sset[0]: 1} - for i, s in enumerate(sset[1:]): - prefix[s] = 1 << (i + 1) * 10 - return int(num * prefix[letter]) - - @unittest.skipIf(not MACOS, "MACOS only") class TestProcess(PsutilTestCase): @@ -200,16 +173,6 @@ class TestSystemAPIs(PsutilTestCase): psutil_val = psutil.swap_memory().sout self.assertAlmostEqual(psutil_val, vmstat_val, delta=TOLERANCE_SYS_MEM) - # Not very reliable. - # def test_swapmem_total(self): - # out = sh('sysctl vm.swapusage') - # out = out.replace('vm.swapusage: ', '') - # total, used, free = re.findall('\d+.\d+\w', out) - # psutil_smem = psutil.swap_memory() - # self.assertEqual(psutil_smem.total, human2bytes(total)) - # self.assertEqual(psutil_smem.used, human2bytes(used)) - # self.assertEqual(psutil_smem.free, human2bytes(free)) - # --- network def test_net_if_stats(self): diff --git a/psutil/tests/test_posix.py b/psutil/tests/test_posix.py index d8732230..0dc1dfda 100755 --- a/psutil/tests/test_posix.py +++ b/psutil/tests/test_posix.py @@ -63,6 +63,8 @@ def ps(fmt, pid=None): cmd.append('ax') if SUNOS: + # XXX: set() has not get() method so this cannot work; not sure + # what I meant in here. fmt_map = set(('command', 'comm', 'start', 'stime')) fmt = fmt_map.get(fmt, fmt) @@ -408,8 +410,7 @@ class TestSystemAPIs(PsutilTestCase): "raw devices not supported" in err or \ "permission denied" in err: continue - else: - raise + raise else: self.assertAlmostEqual(usage.total, total, delta=tolerance) self.assertAlmostEqual(usage.used, used, delta=tolerance) diff --git a/psutil/tests/test_process.py b/psutil/tests/test_process.py index df6a84c3..ec15ffda 100755 --- a/psutil/tests/test_process.py +++ b/psutil/tests/test_process.py @@ -231,7 +231,7 @@ class TestProcess(PsutilTestCase): p = psutil.Process() p.cpu_percent(interval=0.001) p.cpu_percent(interval=0.001) - for x in range(100): + for _ in range(100): percent = p.cpu_percent(interval=None) self.assertIsInstance(percent, float) self.assertGreaterEqual(percent, 0.0) @@ -611,8 +611,7 @@ class TestProcess(PsutilTestCase): def test_memory_maps(self): p = psutil.Process() maps = p.memory_maps() - paths = [x for x in maps] - self.assertEqual(len(paths), len(set(paths))) + self.assertEqual(len(maps), len(set(maps))) ext_maps = p.memory_maps(grouped=False) for nt in maps: @@ -1035,7 +1034,7 @@ class TestProcess(PsutilTestCase): def test_num_ctx_switches(self): p = psutil.Process() before = sum(p.num_ctx_switches()) - for x in range(500000): + for _ in range(500000): after = sum(p.num_ctx_switches()) if after > before: return @@ -1147,7 +1146,7 @@ class TestProcess(PsutilTestCase): def test_suspend_resume(self): p = self.spawn_psproc() p.suspend() - for x in range(100): + for _ in range(100): if p.status() == psutil.STATUS_STOPPED: break time.sleep(0.01) diff --git a/psutil/tests/test_system.py b/psutil/tests/test_system.py index 1722b515..c2b1df84 100755 --- a/psutil/tests/test_system.py +++ b/psutil/tests/test_system.py @@ -123,7 +123,7 @@ class TestProcessAPIs(PsutilTestCase): self.assertFalse(hasattr(p, 'returncode')) @retry_on_failure(30) - def test(procs, callback): + def test_1(procs, callback): gone, alive = psutil.wait_procs(procs, timeout=0.03, callback=callback) self.assertEqual(len(gone), 1) @@ -131,7 +131,7 @@ class TestProcessAPIs(PsutilTestCase): return gone, alive sproc3.terminate() - gone, alive = test(procs, callback) + gone, alive = test_1(procs, callback) self.assertIn(sproc3.pid, [x.pid for x in gone]) if POSIX: self.assertEqual(gone.pop().returncode, -signal.SIGTERM) @@ -142,7 +142,7 @@ class TestProcessAPIs(PsutilTestCase): self.assertFalse(hasattr(p, 'returncode')) @retry_on_failure(30) - def test(procs, callback): + def test_2(procs, callback): gone, alive = psutil.wait_procs(procs, timeout=0.03, callback=callback) self.assertEqual(len(gone), 3) @@ -151,7 +151,7 @@ class TestProcessAPIs(PsutilTestCase): sproc1.terminate() sproc2.terminate() - gone, alive = test(procs, callback) + gone, alive = test_2(procs, callback) self.assertEqual(set(pids), set([sproc1.pid, sproc2.pid, sproc3.pid])) for p in gone: self.assertTrue(hasattr(p, 'returncode')) @@ -165,7 +165,7 @@ class TestProcessAPIs(PsutilTestCase): procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)] for p in procs: p.terminate() - gone, alive = psutil.wait_procs(procs) + psutil.wait_procs(procs) def test_pid_exists(self): sproc = self.spawn_testproc() @@ -449,7 +449,7 @@ class TestCpuAPIs(PsutilTestCase): def test_cpu_percent(self): last = psutil.cpu_percent(interval=0.001) - for x in range(100): + for _ in range(100): new = psutil.cpu_percent(interval=None) self._test_cpu_percent(new, last, new) last = new @@ -459,7 +459,7 @@ class TestCpuAPIs(PsutilTestCase): def test_per_cpu_percent(self): last = psutil.cpu_percent(interval=0.001, percpu=True) self.assertEqual(len(last), psutil.cpu_count()) - for x in range(100): + for _ in range(100): new = psutil.cpu_percent(interval=None, percpu=True) for percent in new: self._test_cpu_percent(percent, last, new) @@ -469,7 +469,7 @@ class TestCpuAPIs(PsutilTestCase): def test_cpu_times_percent(self): last = psutil.cpu_times_percent(interval=0.001) - for x in range(100): + for _ in range(100): new = psutil.cpu_times_percent(interval=None) for percent in new: self._test_cpu_percent(percent, last, new) @@ -481,7 +481,7 @@ class TestCpuAPIs(PsutilTestCase): def test_per_cpu_times_percent(self): last = psutil.cpu_times_percent(interval=0.001, percpu=True) self.assertEqual(len(last), psutil.cpu_count()) - for x in range(100): + for _ in range(100): new = psutil.cpu_times_percent(interval=None, percpu=True) for cpu in new: for percent in cpu: diff --git a/psutil/tests/test_testutils.py b/psutil/tests/test_testutils.py index e757e017..77e52b69 100755 --- a/psutil/tests/test_testutils.py +++ b/psutil/tests/test_testutils.py @@ -406,16 +406,16 @@ class TestMemLeakClass(TestMemoryLeak): self.assertEqual(len(ls), times + 1) def test_execute_w_exc(self): - def fun(): + def fun_1(): 1 / 0 - self.execute_w_exc(ZeroDivisionError, fun) + self.execute_w_exc(ZeroDivisionError, fun_1) with self.assertRaises(ZeroDivisionError): - self.execute_w_exc(OSError, fun) + self.execute_w_exc(OSError, fun_1) - def fun(): + def fun_2(): pass with self.assertRaises(AssertionError): - self.execute_w_exc(ZeroDivisionError, fun) + self.execute_w_exc(ZeroDivisionError, fun_2) class TestTestingUtils(PsutilTestCase): diff --git a/psutil/tests/test_unicode.py b/psutil/tests/test_unicode.py index 3fa3f017..43cf2b49 100755 --- a/psutil/tests/test_unicode.py +++ b/psutil/tests/test_unicode.py @@ -316,8 +316,7 @@ class TestFSAPIsWithInvalidPath(TestFSAPIs): """Test FS APIs with a funky, invalid path name.""" funky_suffix = INVALID_UNICODE_SUFFIX - @classmethod - def expect_exact_path_match(cls): + def expect_exact_path_match(self): # Invalid unicode names are supposed to work on Python 2. return True diff --git a/pyproject.toml b/pyproject.toml index c8cb62af..8d68131c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,6 +34,44 @@ exclude_lines = [ "raise NotImplementedError", ] +[tool.pylint.messages_control] +# Important ones: +# undefined-all-variable, invalid-envvar-default, reimported, raising-format-tuple, simplifiable-if-expression, useless-object-inheritance +disable = [ + "broad-except", # except Exception: + "consider-using-dict-comprehension", + "consider-using-f-string", + "consider-using-set-comprehension", + "consider-using-with", + "disallowed-name", + "fixme", + "global-statement", + "import-error", + "import-outside-toplevel", + "inconsistent-return-statements", + "invalid-name", + "missing-class-docstring", + "missing-function-docstring", + "no-else-raise", + "no-else-return", + "protected-access", + "raise-missing-from", + "redefined-builtin", + "super-with-arguments", + "too-few-public-methods", + "too-many-arguments", + "too-many-branches", + "too-many-instance-attributes", + "too-many-lines", + "too-many-locals", + "too-many-public-methods", + "too-many-return-statements", + "too-many-statements", + "ungrouped-imports", + "unspecified-encoding", + "wrong-import-position", +] + [build-system] requires = ["setuptools>=43", "wheel"] build-backend = "setuptools.build_meta" diff --git a/scripts/internal/download_wheels_appveyor.py b/scripts/internal/download_wheels_appveyor.py index d69ace62..dcded559 100755 --- a/scripts/internal/download_wheels_appveyor.py +++ b/scripts/internal/download_wheels_appveyor.py @@ -101,9 +101,9 @@ def run(): # 2 wheels (32 and 64 bit) per supported python version expected = len(PY_VERSIONS) * 2 if expected != completed: - return exit("expected %s files, got %s" % (expected, completed)) + return sys.exit("expected %s files, got %s" % (expected, completed)) if exc: - return exit() + return sys.exit() rename_win27_wheels() diff --git a/scripts/internal/git_pre_commit.py b/scripts/internal/git_pre_commit.py index 87783627..dad0066b 100755 --- a/scripts/internal/git_pre_commit.py +++ b/scripts/internal/git_pre_commit.py @@ -107,16 +107,16 @@ def main(): # space at end of line if line.endswith(' '): print("%s:%s %r" % (path, lineno, line)) - return exit("space at end of line") + return sys.exit("space at end of line") line = line.rstrip() # # pdb (now provided by flake8-debugger plugin) # if "pdb.set_trace" in line: # print("%s:%s %s" % (path, lineno, line)) - # return exit("you forgot a pdb in your python code") + # return sys.exit("you forgot a pdb in your python code") # # bare except clause (now provided by flake8-blind-except plugin) # if "except:" in line and not line.endswith("# NOQA"): # print("%s:%s %s" % (path, lineno, line)) - # return exit("bare except clause") + # return sys.exit("bare except clause") # Python linters if py_files: @@ -125,28 +125,28 @@ def main(): cmd = "%s -m flake8 --config=.flake8 %s" % (PYTHON, " ".join(py_files)) ret = subprocess.call(shlex.split(cmd)) if ret != 0: - return exit("python code didn't pass 'flake8' style check; " - "try running 'make fix-flake8'") + return sys.exit("python code didn't pass 'flake8' style check; " + "try running 'make fix-flake8'") # isort cmd = "%s -m isort --check-only %s" % ( PYTHON, " ".join(py_files)) ret = subprocess.call(shlex.split(cmd)) if ret != 0: - return exit("python code didn't pass 'isort' style check; " - "try running 'make fix-imports'") + return sys.exit("python code didn't pass 'isort' style check; " + "try running 'make fix-imports'") # C linter if c_files: # XXX: we should escape spaces and possibly other amenities here cmd = "%s scripts/internal/clinter.py %s" % (PYTHON, " ".join(c_files)) ret = subprocess.call(cmd, shell=True) if ret != 0: - return exit("C code didn't pass style check") + return sys.exit("C code didn't pass style check") if new_rm_mv: out = sh("%s scripts/internal/generate_manifest.py" % PYTHON) with open_text('MANIFEST.in') as f: if out.strip() != f.read().strip(): - exit("some files were added, deleted or renamed; " - "run 'make generate-manifest' and commit again") + sys.exit("some files were added, deleted or renamed; " + "run 'make generate-manifest' and commit again") main() diff --git a/scripts/internal/print_announce.py b/scripts/internal/print_announce.py index c2113f36..510dc15f 100755 --- a/scripts/internal/print_announce.py +++ b/scripts/internal/print_announce.py @@ -89,7 +89,7 @@ def get_changes(): break lines.pop(0) - for i, line in enumerate(lines): + for line in lines: line = lines.pop(0) line = line.rstrip() if re.match(r"^- \d+_", line): diff --git a/scripts/internal/print_dist.py b/scripts/internal/print_dist.py index 492bed1c..978e50e2 100755 --- a/scripts/internal/print_dist.py +++ b/scripts/internal/print_dist.py @@ -98,7 +98,7 @@ def main(): elif path.endswith(".tar.gz"): pkg = Tarball(path) else: - raise ValueError("invalid package %r", path) + raise ValueError("invalid package %r" % path) groups[pkg.platform()].append(pkg) tot_files = 0 diff --git a/scripts/internal/winmake.py b/scripts/internal/winmake.py index 466887c2..16de3908 100755 --- a/scripts/internal/winmake.py +++ b/scripts/internal/winmake.py @@ -82,7 +82,7 @@ DEFAULT_COLOR = 7 # =================================================================== -def safe_print(text, file=sys.stdout, flush=False): +def safe_print(text, file=sys.stdout): """Prints a (unicode) string to the console, encoded depending on the stdout/file encoding (eg. cp437 on Windows). This is to avoid encoding errors in case of funky path names. @@ -228,7 +228,7 @@ def build(): # order to allow "import psutil" when using the interactive interpreter # from within psutil root directory. cmd = [PYTHON, "setup.py", "build_ext", "-i"] - if sys.version_info[:2] >= (3, 6) and os.cpu_count() or 1 > 1: + if sys.version_info[:2] >= (3, 6) and (os.cpu_count() or 1) > 1: cmd += ['--parallel', str(os.cpu_count())] # Print coloured warnings in real time. p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) @@ -547,8 +547,7 @@ def get_python(path): return pypath -def main(): - global PYTHON +def parse_args(): parser = argparse.ArgumentParser() # option shared by all commands parser.add_argument( @@ -587,8 +586,19 @@ def main(): for p in (test, test_by_name): p.add_argument('arg', type=str, nargs='?', default="", help="arg") + args = parser.parse_args() + if not args.command or args.command == 'help': + parser.print_help(sys.stderr) + sys.exit(1) + + return args + + +def main(): + global PYTHON + args = parse_args() # set python exe PYTHON = get_python(args.python) if not PYTHON: @@ -597,10 +607,6 @@ def main(): os.putenv('PYTHON', PYTHON) win_colorprint("using " + PYTHON) - if not args.command or args.command == 'help': - parser.print_help(sys.stderr) - sys.exit(1) - fname = args.command.replace('-', '_') fun = getattr(sys.modules[__name__], fname) # err if fun not defined funargs = [] diff --git a/scripts/iotop.py b/scripts/iotop.py index f4d62d46..07ae2fa3 100755 --- a/scripts/iotop.py +++ b/scripts/iotop.py @@ -71,7 +71,7 @@ def poll(interval): sorted by IO activity and total disks I/O activity. """ # first get a list of all processes and disk io counters - procs = [p for p in psutil.process_iter()] + procs = list(psutil.process_iter()) for p in procs[:]: try: p._before = p.io_counters() diff --git a/scripts/procinfo.py b/scripts/procinfo.py index 743a1777..fd44c83e 100755 --- a/scripts/procinfo.py +++ b/scripts/procinfo.py @@ -316,7 +316,7 @@ def run(pid, verbose=False): print_("", template % (bytes2human(region.rss), region.path)) -def main(argv=None): +def main(): parser = argparse.ArgumentParser( description="print information about a process") parser.add_argument("pid", type=int, help="process pid", nargs='?') diff --git a/setup.py b/setup.py index 65dad252..4e6f6f17 100755 --- a/setup.py +++ b/setup.py @@ -346,10 +346,7 @@ if POSIX: # for an explanation of Solaris /etc/release with open('/etc/release') as f: update = re.search(r'(?<=s10s_u)[0-9]{1,2}', f.readline()) - if update is None: - return 0 - else: - return int(update.group(0)) + return int(update.group(0)) if update else 0 posix_extension.libraries.append('socket') if platform.release() == '5.10': -- cgit v1.2.1 From 55b7ca0163ac19178d615a067bc35fef177f3e84 Mon Sep 17 00:00:00 2001 From: Mark Asselstine Date: Wed, 5 Apr 2023 13:57:32 -0400 Subject: Fix Linux test: allow '-dirty' or other version postfixes (#2221) It is possible that 'free -V' will return a version that includes a postfix such as '-dirty'. For example procps-ng will explicitly add this when building from git: https://gitlab.com/procps-ng/procps/-/blob/master/local/git-version-gen#L154 Process the version string to drop these string postfixes from the version tuple, failing to do so will result in the test failing File ".../psutil/tests/test_linux.py", line 204, in get_free_version_info return tuple(map(int, out.split()[-1].split('.'))) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ValueError: invalid literal for int() with base 10: '3-dirty' Signed-off-by: Mark Asselstine --- psutil/tests/test_linux.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/psutil/tests/test_linux.py b/psutil/tests/test_linux.py index e1de6706..ac11017a 100755 --- a/psutil/tests/test_linux.py +++ b/psutil/tests/test_linux.py @@ -201,7 +201,7 @@ def get_free_version_info(): out = sh(["free", "-V"]).strip() if 'UNKNOWN' in out: raise unittest.SkipTest("can't determine free version") - return tuple(map(int, out.split()[-1].split('.'))) + return tuple(map(int, re.findall(r'\d+', out.split()[-1]))) @contextlib.contextmanager -- cgit v1.2.1 From 52fe5517f716dedf9c9918e56325e49a49146130 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Sun, 9 Apr 2023 11:32:21 +0200 Subject: update cpu_freq() doc --- docs/index.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/docs/index.rst b/docs/index.rst index dcc25ab0..119102a8 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -268,13 +268,13 @@ CPU .. function:: cpu_freq(percpu=False) Return CPU frequency as a named tuple including *current*, *min* and *max* - frequencies expressed in Mhz. - On Linux *current* frequency reports the real-time value, on all other - platforms this usually represents the nominal "fixed" value (never changing). - If *percpu* is ``True`` and the system supports per-cpu frequency - retrieval (Linux only) a list of frequencies is returned for each CPU, - if not, a list with a single element is returned. - If *min* and *max* cannot be determined they are set to ``0.0``. + frequencies expressed in Mhz. On Linux *current* frequency reports the + real-time value, on all other platforms this usually represents the + nominal "fixed" value (never changing). If *percpu* is ``True`` and the + system supports per-cpu frequency retrieval (Linux and FreeBSD), a list of + frequencies is returned for each CPU, if not, a list with a single element + is returned. If *min* and *max* cannot be determined they are set to + ``0.0``. Example (Linux): @@ -289,7 +289,8 @@ CPU scpufreq(current=1703.609, min=800.0, max=3500.0), scpufreq(current=1754.289, min=800.0, max=3500.0)] - Availability: Linux, macOS, Windows, FreeBSD, OpenBSD + Availability: Linux, macOS, Windows, FreeBSD, OpenBSD. *percpu* only + supported on Linux and FreeBSD. .. versionadded:: 5.1.0 -- cgit v1.2.1 From e6bf2bcafc41319a22945e98f50906149527ff51 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Mon, 10 Apr 2023 13:17:26 -0700 Subject: move psutil_virtual_mem() in a new mem.c file --- psutil/_psutil_windows.c | 30 +----------------------------- psutil/arch/windows/mem.c | 35 +++++++++++++++++++++++++++++++++++ psutil/arch/windows/mem.h | 9 +++++++++ setup.py | 1 + 4 files changed, 46 insertions(+), 29 deletions(-) create mode 100644 psutil/arch/windows/mem.c create mode 100644 psutil/arch/windows/mem.h diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c index 6e51c449..969c5713 100644 --- a/psutil/_psutil_windows.c +++ b/psutil/_psutil_windows.c @@ -33,6 +33,7 @@ #include "arch/windows/process_handles.h" #include "arch/windows/disk.h" #include "arch/windows/cpu.h" +#include "arch/windows/mem.h" #include "arch/windows/net.h" #include "arch/windows/services.h" #include "arch/windows/socks.h" @@ -603,35 +604,6 @@ psutil_proc_memory_uss(PyObject *self, PyObject *args) { return Py_BuildValue("I", wsCounters.NumberOfPrivatePages); } - -/* - * Return a Python integer indicating the total amount of physical memory - * in bytes. - */ -static PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) { - unsigned long long totalPhys, availPhys, totalSys, availSys, pageSize; - PERFORMANCE_INFORMATION perfInfo; - - if (! GetPerformanceInfo(&perfInfo, sizeof(PERFORMANCE_INFORMATION))) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - // values are size_t, widen (if needed) to long long - pageSize = perfInfo.PageSize; - totalPhys = perfInfo.PhysicalTotal * pageSize; - availPhys = perfInfo.PhysicalAvailable * pageSize; - totalSys = perfInfo.CommitLimit * pageSize; - availSys = totalSys - perfInfo.CommitTotal * pageSize; - return Py_BuildValue( - "(LLLL)", - totalPhys, - availPhys, - totalSys, - availSys); -} - - /* * Return process current working directory as a Python string. */ diff --git a/psutil/arch/windows/mem.c b/psutil/arch/windows/mem.c new file mode 100644 index 00000000..8b678254 --- /dev/null +++ b/psutil/arch/windows/mem.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include +#include +#include + +#include "../../_psutil_common.h" + + +PyObject * +psutil_virtual_mem(PyObject *self, PyObject *args) { + unsigned long long totalPhys, availPhys, totalSys, availSys, pageSize; + PERFORMANCE_INFORMATION perfInfo; + + if (! GetPerformanceInfo(&perfInfo, sizeof(PERFORMANCE_INFORMATION))) { + PyErr_SetFromWindowsErr(0); + return NULL; + } + // values are size_t, widen (if needed) to long long + pageSize = perfInfo.PageSize; + totalPhys = perfInfo.PhysicalTotal * pageSize; + availPhys = perfInfo.PhysicalAvailable * pageSize; + totalSys = perfInfo.CommitLimit * pageSize; + availSys = totalSys - perfInfo.CommitTotal * pageSize; + return Py_BuildValue( + "(LLLL)", + totalPhys, + availPhys, + totalSys, + availSys); +} diff --git a/psutil/arch/windows/mem.h b/psutil/arch/windows/mem.h new file mode 100644 index 00000000..871cd64e --- /dev/null +++ b/psutil/arch/windows/mem.h @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include + +PyObject *psutil_virtual_mem(PyObject* self, PyObject* args); diff --git a/setup.py b/setup.py index 4e6f6f17..a4f719b2 100755 --- a/setup.py +++ b/setup.py @@ -214,6 +214,7 @@ if WINDOWS: 'psutil/arch/windows/process_info.c', 'psutil/arch/windows/process_handles.c', 'psutil/arch/windows/disk.c', + 'psutil/arch/windows/mem.c', 'psutil/arch/windows/net.c', 'psutil/arch/windows/cpu.c', 'psutil/arch/windows/security.c', -- cgit v1.2.1 From 4dd1e215f3d49fb3a5074b82430bf6199c14898e Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Mon, 10 Apr 2023 13:20:39 -0700 Subject: move psutil_getpagesize() in a new mem.c file --- psutil/_psutil_windows.c | 11 ----------- psutil/arch/windows/mem.c | 8 ++++++++ psutil/arch/windows/mem.h | 3 ++- 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c index 969c5713..2ed937ee 100644 --- a/psutil/_psutil_windows.c +++ b/psutil/_psutil_windows.c @@ -1515,17 +1515,6 @@ psutil_sensors_battery(PyObject *self, PyObject *args) { } -/* - * System memory page size as an int. - */ -static PyObject * -psutil_getpagesize(PyObject *self, PyObject *args) { - // XXX: we may want to use GetNativeSystemInfo to differentiate - // page size for WoW64 processes (but am not sure). - return Py_BuildValue("I", PSUTIL_SYSTEM_INFO.dwPageSize); -} - - // ------------------------ Python init --------------------------- static PyMethodDef diff --git a/psutil/arch/windows/mem.c b/psutil/arch/windows/mem.c index 8b678254..18b535e6 100644 --- a/psutil/arch/windows/mem.c +++ b/psutil/arch/windows/mem.c @@ -11,6 +11,14 @@ #include "../../_psutil_common.h" +PyObject * +psutil_getpagesize(PyObject *self, PyObject *args) { + // XXX: we may want to use GetNativeSystemInfo to differentiate + // page size for WoW64 processes (but am not sure). + return Py_BuildValue("I", PSUTIL_SYSTEM_INFO.dwPageSize); +} + + PyObject * psutil_virtual_mem(PyObject *self, PyObject *args) { unsigned long long totalPhys, availPhys, totalSys, availSys, pageSize; diff --git a/psutil/arch/windows/mem.h b/psutil/arch/windows/mem.h index 871cd64e..a10781df 100644 --- a/psutil/arch/windows/mem.h +++ b/psutil/arch/windows/mem.h @@ -6,4 +6,5 @@ #include -PyObject *psutil_virtual_mem(PyObject* self, PyObject* args); +PyObject *psutil_getpagesize(PyObject *self, PyObject *args); +PyObject *psutil_virtual_mem(PyObject *self, PyObject *args); -- cgit v1.2.1