diff --git a/.ci/travis/run.sh b/.ci/travis/run.sh index 9a4afa62f..879e78a60 100755 --- a/.ci/travis/run.sh +++ b/.ci/travis/run.sh @@ -30,7 +30,7 @@ if [ "$PYVER" == "2.7" ] || [ "$PYVER" == "3.6" ]; then PSUTIL_TESTING=1 python -Wa psutil/tests/test_memory_leaks.py # run linter (on Linux only) if [[ "$(uname -s)" != 'Darwin' ]]; then - python -m flake8 + make lint PYTHON=python fi fi diff --git a/HISTORY.rst b/HISTORY.rst index 1634e4339..9b39fa051 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -1,13 +1,13 @@ *Bug tracker at https://github.com/giampaolo/psutil/issues* -5.7.0 (unreleased) -================== +5.7.0 +===== -XXXX-XX-XX +2020-12-18 **Enhancements** -- 1637_: [SunOS] Add partial support for old SunOS 5.10 Update 0 to 3. +- 1637_: [SunOS] add partial support for old SunOS 5.10 Update 0 to 3. - 1648_: [Linux] sensors_temperatures() looks into an additional /sys/device/ directory for additional data. (patch by Javad Karabi) - 1652_: [Windows] dropped support for Windows XP and Windows Server 2003. @@ -16,6 +16,7 @@ XXXX-XX-XX - 1677_: [Windows] process exe() will succeed for all process PIDs (instead of raising AccessDenied). - 1679_: [Windows] net_connections() and Process.connections() are 10% faster. +- 1682_: [PyPy] added CI / test integration for PyPy via Travis. - 1686_: [Windows] added support for PyPy on Windows. - 1693_: [Windows] boot_time(), Process.create_time() and users()'s login time now have 1 micro second precision (before the precision was of 1 second). diff --git a/MANIFEST.in b/MANIFEST.in index 3b4232e9f..801139b2c 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -115,6 +115,7 @@ include scripts/internal/README include scripts/internal/bench_oneshot.py include scripts/internal/bench_oneshot_2.py include scripts/internal/check_broken_links.py +include scripts/internal/clinter.py include scripts/internal/fix_flake8.py include scripts/internal/generate_manifest.py include scripts/internal/print_access_denied.py diff --git a/Makefile b/Makefile index 4f4d1238c..b15aa5d95 100644 --- a/Makefile +++ b/Makefile @@ -169,10 +169,17 @@ test-coverage: ## Run test coverage. # Linters # =================================================================== -flake8: ## flake8 linter. - @git ls-files | grep \\.py$ | xargs $(PYTHON) -m flake8 +lint-py: ## Run Python (flake8) linter. + @git ls-files '*.py' | xargs $(PYTHON) -m flake8 -fix-flake8: ## Attempt to automaticall fix some flake8 issues. +lint-c: ## Run C linter. + @git ls-files '*.c' '*.h' | xargs $(PYTHON) scripts/internal/clinter.py + +lint: ## Run Python (flake8) and C linters. + ${MAKE} lint-py + ${MAKE} lint-c + +fix-lint: ## Attempt to automatically fix some Python lint issues. @git ls-files | grep \\.py$ | xargs $(PYTHON) -m flake8 --exit-zero | $(PYTHON) scripts/internal/fix_flake8.py # =================================================================== diff --git a/appveyor.yml b/appveyor.yml index b38cbf1ba..d22c1cb4f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -# Build: 2 (bump this up by 1 to force an appveyor run) +# Build: 3 (bump this up by 1 to force an appveyor run) os: Visual Studio 2015 diff --git a/docs/DEVGUIDE.rst b/docs/DEVGUIDE.rst index 0ec64c3ce..170a40a9d 100644 --- a/docs/DEVGUIDE.rst +++ b/docs/DEVGUIDE.rst @@ -36,7 +36,7 @@ Some useful make commands: make test # run unit tests make test-memleaks # run memory leak tests make test-coverage # run test coverage - make flake8 # run PEP8 linter + make lint # run Python (PEP8) and C linters There are some differences between ``make`` on UNIX and Windows. For instance, to run a specific Python version. On UNIX: diff --git a/docs/index.rst b/docs/index.rst index c5de1802c..c6b9a8cca 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -2512,6 +2512,10 @@ Supported Python versions are 2.6, 2.7, 3.4+ and PyPy3. Timeline ======== +- 2020-02-18: + `5.7.0 `__ - + `what's new `__ - + `diff `__ - 2019-11-26: `5.6.7 `__ - `what's new `__ - diff --git a/psutil/_psutil_aix.c b/psutil/_psutil_aix.c index b8584f26d..cf79d307d 100644 --- a/psutil/_psutil_aix.c +++ b/psutil/_psutil_aix.c @@ -15,7 +15,7 @@ * - psutil.Process.io_counters read count is always 0 * - psutil.Process.io_counters may not be available on older AIX versions * - psutil.Process.threads may not be available on older AIX versions - # - psutil.net_io_counters may not be available on older AIX versions + * - psutil.net_io_counters may not be available on older AIX versions * - reading basic process info may fail or return incorrect values when * process is starting (see IBM APAR IV58499 - fixed in newer AIX versions) * - sockets and pipes may not be counted in num_fds (fixed in newer AIX diff --git a/psutil/_psutil_posix.c b/psutil/_psutil_posix.c index fa554be9f..38483b3b0 100644 --- a/psutil/_psutil_posix.c +++ b/psutil/_psutil_posix.c @@ -192,8 +192,8 @@ psutil_convert_ipaddr(struct sockaddr *addr, int family) { // XXX we get here on FreeBSD when processing 'lo' / AF_INET6 // broadcast. Not sure what to do other than returning None. // ifconfig does not show anything BTW. - //PyErr_Format(PyExc_RuntimeError, gai_strerror(err)); - //return NULL; + // PyErr_Format(PyExc_RuntimeError, gai_strerror(err)); + // return NULL; Py_INCREF(Py_None); return Py_None; } diff --git a/psutil/_psutil_sunos.c b/psutil/_psutil_sunos.c index 8aa7eadd3..6548640b7 100644 --- a/psutil/_psutil_sunos.c +++ b/psutil/_psutil_sunos.c @@ -496,7 +496,7 @@ proc_io_counters(PyObject* self, PyObject* args) { info.pr_inblk, info.pr_oublk); } - */ +*/ /* diff --git a/psutil/arch/aix/common.c b/psutil/arch/aix/common.c index 6115a15db..945cbd978 100644 --- a/psutil/arch/aix/common.c +++ b/psutil/arch/aix/common.c @@ -76,4 +76,4 @@ psutil_read_process_table(int * num) { *num = np; return processes; -} \ No newline at end of file +} diff --git a/psutil/arch/aix/ifaddrs.c b/psutil/arch/aix/ifaddrs.c index 1a819365a..1480b60fa 100644 --- a/psutil/arch/aix/ifaddrs.c +++ b/psutil/arch/aix/ifaddrs.c @@ -146,4 +146,4 @@ int getifaddrs(struct ifaddrs **ifap) close(sd); freeifaddrs(*ifap); return (-1); -} \ No newline at end of file +} diff --git a/psutil/arch/aix/ifaddrs.h b/psutil/arch/aix/ifaddrs.h index 3920c1ccc..e15802bf7 100644 --- a/psutil/arch/aix/ifaddrs.h +++ b/psutil/arch/aix/ifaddrs.h @@ -31,5 +31,4 @@ struct ifaddrs { extern int getifaddrs(struct ifaddrs **); extern void freeifaddrs(struct ifaddrs *); - -#endif \ No newline at end of file +#endif diff --git a/psutil/arch/aix/net_connections.h b/psutil/arch/aix/net_connections.h index 222bcaf35..d57ee4284 100644 --- a/psutil/arch/aix/net_connections.h +++ b/psutil/arch/aix/net_connections.h @@ -12,4 +12,4 @@ PyObject* psutil_net_connections(PyObject *self, PyObject *args); -#endif /* __NET_CONNECTIONS_H__ */ \ No newline at end of file +#endif /* __NET_CONNECTIONS_H__ */ diff --git a/psutil/arch/aix/net_kernel_structs.h b/psutil/arch/aix/net_kernel_structs.h index 4e7a088c1..7e22a1639 100644 --- a/psutil/arch/aix/net_kernel_structs.h +++ b/psutil/arch/aix/net_kernel_structs.h @@ -108,4 +108,4 @@ struct mbuf64 #define m_len m_hdr.mh_len -#endif /* __64BIT__ */ \ No newline at end of file +#endif /* __64BIT__ */ diff --git a/psutil/arch/freebsd/specific.c b/psutil/arch/freebsd/specific.c index 3d54b47e5..3f37a08e2 100644 --- a/psutil/arch/freebsd/specific.c +++ b/psutil/arch/freebsd/specific.c @@ -729,7 +729,7 @@ psutil_disk_io_counters(PyObject *self, PyObject *args) { PyObject * psutil_proc_memory_maps(PyObject *self, PyObject *args) { // Return a list of tuples for every process memory maps. - //'procstat' cmdline utility has been used as an example. + // 'procstat' cmdline utility has been used as an example. pid_t pid; int ptrwidth; int i, cnt; diff --git a/psutil/arch/solaris/environ.c b/psutil/arch/solaris/environ.c index eb0fa2abd..482fe1fc1 100644 --- a/psutil/arch/solaris/environ.c +++ b/psutil/arch/solaris/environ.c @@ -11,8 +11,8 @@ #include #if !defined(_LP64) && _FILE_OFFSET_BITS == 64 -# undef _FILE_OFFSET_BITS -# undef _LARGEFILE64_SOURCE + #undef _FILE_OFFSET_BITS + #undef _LARGEFILE64_SOURCE #endif #include diff --git a/psutil/arch/windows/net.c b/psutil/arch/windows/net.c index f0572d529..56c6b6f1f 100644 --- a/psutil/arch/windows/net.c +++ b/psutil/arch/windows/net.c @@ -401,7 +401,7 @@ psutil_net_if_stats(PyObject *self, PyObject *args) { } // is up? - if((pIfRow->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || + if ((pIfRow->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || pIfRow->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL) && pIfRow->dwAdminStatus == 1 ) { py_is_up = Py_True; diff --git a/scripts/internal/.git-pre-commit b/scripts/internal/.git-pre-commit index 621879dfb..e60092538 100755 --- a/scripts/internal/.git-pre-commit +++ b/scripts/internal/.git-pre-commit @@ -77,6 +77,8 @@ def main(): out = sh("git diff --cached --name-only") py_files = [x for x in out.split('\n') if x.endswith('.py') and os.path.exists(x)] + c_files = [x for x in out.split('\n') if x.endswith(('.c', '.h')) and + os.path.exists(x)] lineno = 0 kw = {'encoding': 'utf8'} if sys.version_info[0] == 3 else {} @@ -100,7 +102,7 @@ def main(): print("%s:%s %s" % (path, lineno, line)) return exit("commit aborted: bare except clause") - # flake8 + # Python linter if py_files: try: import flake8 # NOQA @@ -108,12 +110,22 @@ def main(): return exit("commit aborted: flake8 is not installed; " "run 'make setup-dev-env'") - # XXX: we should scape spaces and possibly other amenities here + # XXX: we should escape spaces and possibly other amenities here ret = subprocess.call( "%s -m flake8 %s" % (sys.executable, " ".join(py_files)), shell=True) if ret != 0: return exit("commit aborted: python code is not flake8 compliant") + # C linter + if c_files: + # XXX: we should escape spaces and possibly other amenities here + cmd = "%s scripts/internal/clinter.py %s" % ( + sys.executable, " ".join(c_files)) + print(cmd) + ret = subprocess.call(cmd, shell=True) + if ret != 0: + return exit("commit aborted: C code didn't pass style check") + main() diff --git a/scripts/internal/clinter.py b/scripts/internal/clinter.py new file mode 100755 index 000000000..1d4ba9b14 --- /dev/null +++ b/scripts/internal/clinter.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2009 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. + +"""A super simple linter to check C syntax.""" + +from __future__ import print_function +import argparse +import sys + + +warned = False + + +def warn(path, line, lineno, msg): + global warned + warned = True + print("%s:%s: %s" % (path, lineno, msg), file=sys.stderr) + + +def check_line(path, line, idx, lines): + s = line + lineno = idx + 1 + eof = lineno == len(lines) + if s.endswith(' \n'): + warn(path, line, lineno, "extra space at EOL") + elif '\t' in line: + warn(path, line, lineno, "line has a tab") + elif s.endswith('\r\n'): + warn(path, line, lineno, "Windows line ending") + # end of global block, e.g. "}newfunction...": + elif s == "}\n": + if not eof: + nextline = lines[idx + 1] + # "#" is a pre-processor line + if nextline != '\n' and \ + nextline.strip()[0] != '#' and \ + nextline.strip()[:2] != '*/': + warn(path, line, lineno, "expected 1 blank line") + + sls = s.lstrip() + if sls.startswith('//') and sls[2] != ' ' and line.strip() != '//': + warn(path, line, lineno, "no space after // comment") + + # e.g. "if(..." after keywords + keywords = ("if", "else", "while", "do", "enum", "for") + for kw in keywords: + if sls.startswith(kw + '('): + warn(path, line, lineno, "missing space between %r and '('" % kw) + # eof + if eof: + if not line.endswith('\n'): + warn(path, line, lineno, "no blank line at EOF") + + +def process(path): + with open(path, 'rt') as f: + lines = f.readlines() + for idx, line in enumerate(lines): + check_line(path, line, idx, lines) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument('paths', nargs='+', help='path(s) to a file(s)') + args = parser.parse_args() + for path in args.paths: + process(path) + if warned: + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/scripts/internal/winmake.py b/scripts/internal/winmake.py index f54211d93..4d3fa3184 100755 --- a/scripts/internal/winmake.py +++ b/scripts/internal/winmake.py @@ -386,7 +386,7 @@ def setup_dev_env(): sh("%s -m pip install -U %s" % (PYTHON, " ".join(DEPS))) -def flake8(): +def lint(): """Run flake8 against all py files""" py_files = subprocess.check_output("git ls-files") if PY3: @@ -551,11 +551,11 @@ def main(): sp.add_parser('build', help="build") sp.add_parser('clean', help="deletes dev files") sp.add_parser('coverage', help="run coverage tests.") - sp.add_parser('flake8', help="run flake8 against all py files") sp.add_parser('help', help="print this help") sp.add_parser('install', help="build + install in develop/edit mode") sp.add_parser('install-git-hooks', help="install GIT pre-commit hook") sp.add_parser('install-pip', help="install pip") + sp.add_parser('lint', help="run flake8 against all py files") sp.add_parser('print-access-denied', help="print AD exceptions") sp.add_parser('print-api-speed', help="benchmark all API calls") sp.add_parser('setup-dev-env', help="install deps") diff --git a/setup.py b/setup.py index 7ead39f4f..2402a143c 100755 --- a/setup.py +++ b/setup.py @@ -378,7 +378,6 @@ def main(): 'Topic :: System :: Networking :: Monitoring', 'Topic :: System :: Networking', 'Topic :: System :: Operating System', - 'Topic :: System :: Power (UPS)' 'Topic :: System :: Systems Administration', 'Topic :: Utilities', ],