From 845a4a86e47fefed99d42b5271b2c5ba8a74e65d Mon Sep 17 00:00:00 2001 From: Ivan Maslov Date: Sat, 13 Apr 2019 08:43:34 +0300 Subject: [PATCH] #Python32Add_psutil --- .../Lib/__pycache__/__future__.cpython-37.pyc | Bin 4147 -> 4157 bytes .../__pycache__/_bootlocale.cpython-37.pyc | Bin 1264 -> 1274 bytes .../_collections_abc.cpython-37.pyc | Bin 28957 -> 28967 bytes .../__pycache__/_compat_pickle.cpython-37.pyc | Bin 5823 -> 5833 bytes .../__pycache__/_compression.cpython-37.pyc | Bin 4139 -> 4149 bytes .../__pycache__/_markupbase.cpython-37.pyc | Bin 7800 -> 7810 bytes .../__pycache__/_sitebuiltins.cpython-37.pyc | Bin 3480 -> 3490 bytes .../Lib/__pycache__/_strptime.cpython-37.pyc | Bin 16129 -> 16129 bytes .../__pycache__/_weakrefset.cpython-37.pyc | Bin 7477 -> 7487 bytes .../Lib/__pycache__/abc.cpython-37.pyc | Bin 6466 -> 6476 bytes .../Lib/__pycache__/base64.cpython-37.pyc | Bin 17003 -> 17013 bytes .../Lib/__pycache__/bisect.cpython-37.pyc | Bin 2713 -> 2723 bytes .../Lib/__pycache__/bz2.cpython-37.pyc | Bin 11196 -> 11206 bytes .../Lib/__pycache__/calendar.cpython-37.pyc | Bin 27439 -> 27449 bytes .../Lib/__pycache__/cgi.cpython-37.pyc | Bin 27206 -> 27216 bytes .../Lib/__pycache__/codecs.cpython-37.pyc | Bin 33913 -> 33923 bytes .../Lib/__pycache__/compileall.cpython-37.pyc | Bin 9131 -> 9131 bytes .../__pycache__/configparser.cpython-37.pyc | Bin 45895 -> 45905 bytes .../Lib/__pycache__/contextlib.cpython-37.pyc | Bin 19915 -> 19925 bytes .../Lib/__pycache__/copy.cpython-37.pyc | Bin 7116 -> 7126 bytes .../Lib/__pycache__/copyreg.cpython-37.pyc | Bin 4259 -> 4269 bytes .../Lib/__pycache__/csv.cpython-37.pyc | Bin 11857 -> 11857 bytes .../Lib/__pycache__/datetime.cpython-37.pyc | Bin 57264 -> 57274 bytes .../Lib/__pycache__/decimal.cpython-37.pyc | Bin 398 -> 398 bytes .../Lib/__pycache__/dis.cpython-37.pyc | Bin 15220 -> 15230 bytes .../Lib/__pycache__/enum.cpython-37.pyc | Bin 24277 -> 24287 bytes .../Lib/__pycache__/fnmatch.cpython-37.pyc | Bin 3352 -> 3362 bytes .../Lib/__pycache__/functools.cpython-37.pyc | Bin 23964 -> 23974 bytes .../__pycache__/genericpath.cpython-37.pyc | Bin 3763 -> 3773 bytes .../Lib/__pycache__/getopt.cpython-37.pyc | Bin 6254 -> 6264 bytes .../Lib/__pycache__/getpass.cpython-37.pyc | Bin 4189 -> 4189 bytes .../Lib/__pycache__/gettext.cpython-37.pyc | Bin 14183 -> 14193 bytes .../Lib/__pycache__/glob.cpython-37.pyc | Bin 4284 -> 4284 bytes .../Lib/__pycache__/gzip.cpython-37.pyc | Bin 17210 -> 17210 bytes .../Lib/__pycache__/hashlib.cpython-37.pyc | Bin 6606 -> 6616 bytes .../Lib/__pycache__/heapq.cpython-37.pyc | Bin 14377 -> 14387 bytes .../Lib/__pycache__/hmac.cpython-37.pyc | Bin 6138 -> 6138 bytes .../Lib/__pycache__/inspect.cpython-37.pyc | Bin 80047 -> 80057 bytes .../Lib/__pycache__/io.cpython-37.pyc | Bin 3424 -> 3434 bytes .../Lib/__pycache__/ipaddress.cpython-37.pyc | Bin 63019 -> 63019 bytes .../Lib/__pycache__/keyword.cpython-37.pyc | Bin 1824 -> 1834 bytes .../Lib/__pycache__/linecache.cpython-37.pyc | Bin 3804 -> 3814 bytes .../Lib/__pycache__/locale.cpython-37.pyc | Bin 34570 -> 34580 bytes .../Lib/__pycache__/lzma.cpython-37.pyc | Bin 11954 -> 11964 bytes .../Lib/__pycache__/mimetypes.cpython-37.pyc | Bin 15503 -> 15503 bytes .../Lib/__pycache__/netrc.cpython-37.pyc | Bin 3788 -> 3788 bytes .../Lib/__pycache__/ntpath.cpython-37.pyc | Bin 13019 -> 13029 bytes .../Lib/__pycache__/nturl2path.cpython-37.pyc | Bin 1640 -> 1640 bytes .../Lib/__pycache__/numbers.cpython-37.pyc | Bin 12217 -> 12217 bytes .../Lib/__pycache__/opcode.cpython-37.pyc | Bin 5393 -> 5403 bytes .../Lib/__pycache__/operator.cpython-37.pyc | Bin 13915 -> 13925 bytes .../Lib/__pycache__/optparse.cpython-37.pyc | Bin 47918 -> 47918 bytes .../Lib/__pycache__/os.cpython-37.pyc | Bin 29708 -> 29718 bytes .../Lib/__pycache__/pickle.cpython-37.pyc | Bin 42981 -> 42991 bytes .../Lib/__pycache__/pkgutil.cpython-37.pyc | Bin 16375 -> 16385 bytes .../Lib/__pycache__/platform.cpython-37.pyc | Bin 28235 -> 28245 bytes .../Lib/__pycache__/plistlib.cpython-37.pyc | Bin 25110 -> 25120 bytes .../Lib/__pycache__/posixpath.cpython-37.pyc | Bin 10445 -> 10455 bytes .../Lib/__pycache__/pprint.cpython-37.pyc | Bin 15834 -> 15844 bytes .../Lib/__pycache__/py_compile.cpython-37.pyc | Bin 7216 -> 7216 bytes .../Lib/__pycache__/queue.cpython-37.pyc | Bin 11487 -> 11497 bytes .../Lib/__pycache__/quopri.cpython-37.pyc | Bin 5786 -> 5796 bytes .../Lib/__pycache__/random.cpython-37.pyc | Bin 19409 -> 19419 bytes .../Lib/__pycache__/re.cpython-37.pyc | Bin 13819 -> 13829 bytes .../Lib/__pycache__/reprlib.cpython-37.pyc | Bin 5365 -> 5375 bytes .../Lib/__pycache__/runpy.cpython-37.pyc | Bin 7960 -> 7970 bytes .../Lib/__pycache__/selectors.cpython-37.pyc | Bin 16963 -> 16973 bytes .../Lib/__pycache__/shlex.cpython-37.pyc | Bin 7005 -> 7015 bytes .../Lib/__pycache__/shutil.cpython-37.pyc | Bin 30879 -> 30889 bytes .../Lib/__pycache__/signal.cpython-37.pyc | Bin 2527 -> 2537 bytes .../Lib/__pycache__/site.cpython-37.pyc | Bin 16541 -> 16551 bytes .../Lib/__pycache__/socket.cpython-37.pyc | Bin 22036 -> 22046 bytes .../__pycache__/socketserver.cpython-37.pyc | Bin 24213 -> 24223 bytes .../__pycache__/sre_compile.cpython-37.pyc | Bin 15218 -> 15228 bytes .../__pycache__/sre_constants.cpython-37.pyc | Bin 6306 -> 6316 bytes .../Lib/__pycache__/sre_parse.cpython-37.pyc | Bin 21372 -> 21382 bytes .../Lib/__pycache__/ssl.cpython-37.pyc | Bin 39796 -> 39796 bytes .../Lib/__pycache__/stat.cpython-37.pyc | Bin 3888 -> 3898 bytes .../Lib/__pycache__/string.cpython-37.pyc | Bin 7850 -> 7860 bytes .../Lib/__pycache__/stringprep.cpython-37.pyc | Bin 10057 -> 10057 bytes .../Lib/__pycache__/struct.cpython-37.pyc | Bin 349 -> 359 bytes .../Lib/__pycache__/subprocess.cpython-37.pyc | Bin 38780 -> 38790 bytes .../Lib/__pycache__/sysconfig.cpython-37.pyc | Bin 15289 -> 15299 bytes .../Lib/__pycache__/tarfile.cpython-37.pyc | Bin 61866 -> 61866 bytes .../Lib/__pycache__/tempfile.cpython-37.pyc | Bin 22160 -> 22170 bytes .../Lib/__pycache__/textwrap.cpython-37.pyc | Bin 13627 -> 13637 bytes .../Lib/__pycache__/threading.cpython-37.pyc | Bin 37350 -> 37360 bytes .../Lib/__pycache__/token.cpython-37.pyc | Bin 3614 -> 3624 bytes .../Lib/__pycache__/tokenize.cpython-37.pyc | Bin 17846 -> 17856 bytes .../Lib/__pycache__/traceback.cpython-37.pyc | Bin 19638 -> 19648 bytes .../Lib/__pycache__/types.cpython-37.pyc | Bin 8989 -> 8999 bytes .../Lib/__pycache__/uu.cpython-37.pyc | Bin 3628 -> 3638 bytes .../Lib/__pycache__/warnings.cpython-37.pyc | Bin 13964 -> 13974 bytes .../Lib/__pycache__/weakref.cpython-37.pyc | Bin 19125 -> 19135 bytes .../Lib/__pycache__/zipfile.cpython-37.pyc | Bin 49887 -> 49897 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 46625 -> 46635 bytes .../__pycache__/abc.cpython-37.pyc | Bin 220 -> 230 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 16164 -> 16174 bytes .../ctypes/__pycache__/_endian.cpython-37.pyc | Bin 1971 -> 1981 bytes .../__pycache__/wintypes.cpython-37.pyc | Bin 5132 -> 5142 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 423 -> 423 bytes .../__pycache__/archive_util.cpython-37.pyc | Bin 6557 -> 6557 bytes .../distutils/__pycache__/cmd.cpython-37.pyc | Bin 13933 -> 13933 bytes .../__pycache__/config.cpython-37.pyc | Bin 3510 -> 3510 bytes .../distutils/__pycache__/core.cpython-37.pyc | Bin 6635 -> 6635 bytes .../__pycache__/debug.cpython-37.pyc | Bin 233 -> 233 bytes .../__pycache__/dep_util.cpython-37.pyc | Bin 2749 -> 2749 bytes .../__pycache__/dir_util.cpython-37.pyc | Bin 5843 -> 5843 bytes .../distutils/__pycache__/dist.cpython-37.pyc | Bin 34464 -> 34464 bytes .../__pycache__/errors.cpython-37.pyc | Bin 5519 -> 5519 bytes .../__pycache__/extension.cpython-37.pyc | Bin 6930 -> 6930 bytes .../__pycache__/fancy_getopt.cpython-37.pyc | Bin 10642 -> 10642 bytes .../__pycache__/file_util.cpython-37.pyc | Bin 5928 -> 5928 bytes .../distutils/__pycache__/log.cpython-37.pyc | Bin 2344 -> 2344 bytes .../__pycache__/spawn.cpython-37.pyc | Bin 5034 -> 5034 bytes .../__pycache__/sysconfig.cpython-37.pyc | Bin 11883 -> 11883 bytes .../distutils/__pycache__/util.cpython-37.pyc | Bin 15080 -> 15080 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 580 -> 580 bytes .../command/__pycache__/build.cpython-37.pyc | Bin 3860 -> 3860 bytes .../__pycache__/install.cpython-37.pyc | Bin 13544 -> 13544 bytes .../email/__pycache__/__init__.cpython-37.pyc | Bin 1706 -> 1716 bytes .../__pycache__/_encoded_words.cpython-37.pyc | Bin 5623 -> 5633 bytes .../__pycache__/_parseaddr.cpython-37.pyc | Bin 12363 -> 12373 bytes .../__pycache__/_policybase.cpython-37.pyc | Bin 14865 -> 14875 bytes .../__pycache__/base64mime.cpython-37.pyc | Bin 3250 -> 3260 bytes .../email/__pycache__/charset.cpython-37.pyc | Bin 11544 -> 11554 bytes .../email/__pycache__/encoders.cpython-37.pyc | Bin 1679 -> 1689 bytes .../email/__pycache__/errors.cpython-37.pyc | Bin 6206 -> 6216 bytes .../__pycache__/feedparser.cpython-37.pyc | Bin 10640 -> 10650 bytes .../email/__pycache__/header.cpython-37.pyc | Bin 16395 -> 16405 bytes .../__pycache__/iterators.cpython-37.pyc | Bin 1947 -> 1957 bytes .../email/__pycache__/message.cpython-37.pyc | Bin 37955 -> 37965 bytes .../email/__pycache__/parser.cpython-37.pyc | Bin 5762 -> 5772 bytes .../__pycache__/quoprimime.cpython-37.pyc | Bin 7679 -> 7689 bytes .../email/__pycache__/utils.cpython-37.pyc | Bin 9482 -> 9492 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 3962 -> 3972 bytes .../__pycache__/aliases.cpython-37.pyc | Bin 6311 -> 6321 bytes .../__pycache__/cp1251.cpython-37.pyc | Bin 2468 -> 2478 bytes .../__pycache__/cp437.cpython-37.pyc | Bin 7858 -> 7868 bytes .../encodings/__pycache__/idna.cpython-37.pyc | Bin 5749 -> 5749 bytes .../__pycache__/latin_1.cpython-37.pyc | Bin 1911 -> 1921 bytes .../__pycache__/utf_16_be.cpython-37.pyc | Bin 1659 -> 1659 bytes .../__pycache__/utf_16_le.cpython-37.pyc | Bin 1659 -> 1659 bytes .../__pycache__/utf_8.cpython-37.pyc | Bin 1629 -> 1639 bytes .../html/__pycache__/__init__.cpython-37.pyc | Bin 3412 -> 3422 bytes .../html/__pycache__/entities.cpython-37.pyc | Bin 50484 -> 50494 bytes .../html/__pycache__/parser.cpython-37.pyc | Bin 11122 -> 11132 bytes .../http/__pycache__/__init__.cpython-37.pyc | Bin 5947 -> 5947 bytes .../http/__pycache__/client.cpython-37.pyc | Bin 34073 -> 34073 bytes .../http/__pycache__/cookiejar.cpython-37.pyc | Bin 53432 -> 53432 bytes .../http/__pycache__/cookies.cpython-37.pyc | Bin 15269 -> 15269 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 3747 -> 3757 bytes .../importlib/__pycache__/abc.cpython-37.pyc | Bin 13502 -> 13512 bytes .../__pycache__/machinery.cpython-37.pyc | Bin 987 -> 997 bytes .../importlib/__pycache__/util.cpython-37.pyc | Bin 9371 -> 9381 bytes .../json/__pycache__/__init__.cpython-37.pyc | Bin 12363 -> 12363 bytes .../json/__pycache__/decoder.cpython-37.pyc | Bin 9849 -> 9849 bytes .../json/__pycache__/encoder.cpython-37.pyc | Bin 11331 -> 11331 bytes .../json/__pycache__/scanner.cpython-37.pyc | Bin 2021 -> 2021 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 62573 -> 62583 bytes .../logging/__pycache__/config.cpython-37.pyc | Bin 23040 -> 23040 bytes .../__pycache__/handlers.cpython-37.pyc | Bin 43008 -> 43008 bytes .../pip/__pycache__/__init__.cpython-37.pyc | Bin 200 -> 200 bytes .../pip/__pycache__/__main__.cpython-37.pyc | Bin 452 -> 452 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 1844 -> 1844 bytes .../__pycache__/build_env.cpython-37.pyc | Bin 7457 -> 7457 bytes .../__pycache__/cache.cpython-37.pyc | Bin 7052 -> 7052 bytes .../__pycache__/configuration.cpython-37.pyc | Bin 9837 -> 9837 bytes .../__pycache__/download.cpython-37.pyc | Bin 21173 -> 21173 bytes .../__pycache__/exceptions.cpython-37.pyc | Bin 11744 -> 11744 bytes .../__pycache__/index.cpython-37.pyc | Bin 25254 -> 25254 bytes .../__pycache__/locations.cpython-37.pyc | Bin 4431 -> 4431 bytes .../__pycache__/pep425tags.cpython-37.pyc | Bin 8163 -> 8163 bytes .../__pycache__/pyproject.cpython-37.pyc | Bin 3180 -> 3180 bytes .../__pycache__/resolve.cpython-37.pyc | Bin 9098 -> 9098 bytes .../__pycache__/wheel.cpython-37.pyc | Bin 25931 -> 25931 bytes .../cli/__pycache__/__init__.cpython-37.pyc | Bin 275 -> 275 bytes .../__pycache__/autocompletion.cpython-37.pyc | Bin 5088 -> 5088 bytes .../__pycache__/base_command.cpython-37.pyc | Bin 7816 -> 7816 bytes .../cli/__pycache__/cmdoptions.cpython-37.pyc | Bin 16891 -> 16891 bytes .../__pycache__/main_parser.cpython-37.pyc | Bin 2361 -> 2361 bytes .../cli/__pycache__/parser.cpython-37.pyc | Bin 8939 -> 8939 bytes .../__pycache__/status_codes.cpython-37.pyc | Bin 404 -> 404 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 2503 -> 2503 bytes .../commands/__pycache__/check.cpython-37.pyc | Bin 1328 -> 1328 bytes .../__pycache__/completion.cpython-37.pyc | Bin 3077 -> 3077 bytes .../__pycache__/configuration.cpython-37.pyc | Bin 6429 -> 6429 bytes .../__pycache__/download.cpython-37.pyc | Bin 4716 -> 4716 bytes .../__pycache__/freeze.cpython-37.pyc | Bin 2873 -> 2873 bytes .../commands/__pycache__/hash.cpython-37.pyc | Bin 2067 -> 2067 bytes .../commands/__pycache__/help.cpython-37.pyc | Bin 1243 -> 1243 bytes .../__pycache__/install.cpython-37.pyc | Bin 12460 -> 12460 bytes .../commands/__pycache__/list.cpython-37.pyc | Bin 8709 -> 8709 bytes .../__pycache__/search.cpython-37.pyc | Bin 4309 -> 4309 bytes .../commands/__pycache__/show.cpython-37.pyc | Bin 5890 -> 5890 bytes .../__pycache__/uninstall.cpython-37.pyc | Bin 2699 -> 2699 bytes .../commands/__pycache__/wheel.cpython-37.pyc | Bin 5002 -> 5002 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 263 -> 263 bytes .../__pycache__/candidate.cpython-37.pyc | Bin 1312 -> 1312 bytes .../__pycache__/format_control.cpython-37.pyc | Bin 2266 -> 2266 bytes .../models/__pycache__/index.cpython-37.pyc | Bin 1167 -> 1167 bytes .../models/__pycache__/link.cpython-37.pyc | Bin 5001 -> 5001 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 199 -> 199 bytes .../__pycache__/check.cpython-37.pyc | Bin 3629 -> 3629 bytes .../__pycache__/freeze.cpython-37.pyc | Bin 5614 -> 5614 bytes .../__pycache__/prepare.cpython-37.pyc | Bin 10275 -> 10275 bytes .../req/__pycache__/__init__.cpython-37.pyc | Bin 1696 -> 1696 bytes .../__pycache__/constructors.cpython-37.pyc | Bin 7616 -> 7616 bytes .../req/__pycache__/req_file.cpython-37.pyc | Bin 9194 -> 9194 bytes .../__pycache__/req_install.cpython-37.pyc | Bin 25031 -> 25031 bytes .../req/__pycache__/req_set.cpython-37.pyc | Bin 6031 -> 6031 bytes .../__pycache__/req_tracker.cpython-37.pyc | Bin 3145 -> 3145 bytes .../__pycache__/req_uninstall.cpython-37.pyc | Bin 16988 -> 16988 bytes .../utils/__pycache__/__init__.cpython-37.pyc | Bin 194 -> 194 bytes .../utils/__pycache__/appdirs.cpython-37.pyc | Bin 8041 -> 8041 bytes .../utils/__pycache__/compat.cpython-37.pyc | Bin 6142 -> 6142 bytes .../__pycache__/deprecation.cpython-37.pyc | Bin 2568 -> 2568 bytes .../utils/__pycache__/encoding.cpython-37.pyc | Bin 1271 -> 1271 bytes .../__pycache__/filesystem.cpython-37.pyc | Bin 663 -> 663 bytes .../utils/__pycache__/glibc.cpython-37.pyc | Bin 1682 -> 1682 bytes .../utils/__pycache__/hashes.cpython-37.pyc | Bin 3601 -> 3601 bytes .../utils/__pycache__/logging.cpython-37.pyc | Bin 7828 -> 7828 bytes .../utils/__pycache__/misc.cpython-37.pyc | Bin 25733 -> 25733 bytes .../utils/__pycache__/models.cpython-37.pyc | Bin 1943 -> 1943 bytes .../utils/__pycache__/outdated.cpython-37.pyc | Bin 4079 -> 4079 bytes .../__pycache__/packaging.cpython-37.pyc | Bin 2615 -> 2615 bytes .../setuptools_build.cpython-37.pyc | Bin 389 -> 389 bytes .../utils/__pycache__/temp_dir.cpython-37.pyc | Bin 4916 -> 4916 bytes .../utils/__pycache__/typing.cpython-37.pyc | Bin 1338 -> 1338 bytes .../utils/__pycache__/ui.cpython-37.pyc | Bin 12300 -> 12300 bytes .../vcs/__pycache__/__init__.cpython-37.pyc | Bin 15385 -> 15385 bytes .../vcs/__pycache__/bazaar.cpython-37.pyc | Bin 3802 -> 3802 bytes .../vcs/__pycache__/git.cpython-37.pyc | Bin 9444 -> 9444 bytes .../vcs/__pycache__/mercurial.cpython-37.pyc | Bin 3775 -> 3775 bytes .../vcs/__pycache__/subversion.cpython-37.pyc | Bin 5987 -> 5987 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 2882 -> 2882 bytes .../__pycache__/appdirs.cpython-37.pyc | Bin 20611 -> 20611 bytes .../__pycache__/pyparsing.cpython-37.pyc | Bin 220609 -> 220609 bytes .../__pycache__/retrying.cpython-37.pyc | Bin 8092 -> 8092 bytes .../_vendor/__pycache__/six.cpython-37.pyc | Bin 26416 -> 26416 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 552 -> 552 bytes .../__pycache__/adapter.cpython-37.pyc | Bin 3038 -> 3038 bytes .../__pycache__/cache.cpython-37.pyc | Bin 1768 -> 1768 bytes .../__pycache__/compat.cpython-37.pyc | Bin 759 -> 759 bytes .../__pycache__/controller.cpython-37.pyc | Bin 7638 -> 7638 bytes .../__pycache__/filewrapper.cpython-37.pyc | Bin 2156 -> 2156 bytes .../__pycache__/serialize.cpython-37.pyc | Bin 4240 -> 4240 bytes .../__pycache__/wrapper.cpython-37.pyc | Bin 660 -> 660 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 296 -> 296 bytes .../__pycache__/file_cache.cpython-37.pyc | Bin 3230 -> 3230 bytes .../__pycache__/redis_cache.cpython-37.pyc | Bin 1552 -> 1552 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 259 -> 259 bytes .../certifi/__pycache__/core.cpython-37.pyc | Bin 520 -> 520 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 846 -> 846 bytes .../__pycache__/big5freq.cpython-37.pyc | Bin 27181 -> 27181 bytes .../__pycache__/big5prober.cpython-37.pyc | Bin 1122 -> 1122 bytes .../chardistribution.cpython-37.pyc | Bin 6308 -> 6308 bytes .../charsetgroupprober.cpython-37.pyc | Bin 2229 -> 2229 bytes .../__pycache__/charsetprober.cpython-37.pyc | Bin 3439 -> 3439 bytes .../codingstatemachine.cpython-37.pyc | Bin 2886 -> 2886 bytes .../chardet/__pycache__/compat.cpython-37.pyc | Bin 357 -> 357 bytes .../__pycache__/cp949prober.cpython-37.pyc | Bin 1129 -> 1129 bytes .../chardet/__pycache__/enums.cpython-37.pyc | Bin 2620 -> 2620 bytes .../__pycache__/escprober.cpython-37.pyc | Bin 2607 -> 2607 bytes .../chardet/__pycache__/escsm.cpython-37.pyc | Bin 7068 -> 7068 bytes .../__pycache__/eucjpprober.cpython-37.pyc | Bin 2415 -> 2415 bytes .../__pycache__/euckrfreq.cpython-37.pyc | Bin 12065 -> 12065 bytes .../__pycache__/euckrprober.cpython-37.pyc | Bin 1130 -> 1130 bytes .../__pycache__/euctwfreq.cpython-37.pyc | Bin 27185 -> 27185 bytes .../__pycache__/euctwprober.cpython-37.pyc | Bin 1130 -> 1130 bytes .../__pycache__/gb2312freq.cpython-37.pyc | Bin 19109 -> 19109 bytes .../__pycache__/gb2312prober.cpython-37.pyc | Bin 1138 -> 1138 bytes .../__pycache__/hebrewprober.cpython-37.pyc | Bin 2972 -> 2972 bytes .../__pycache__/jisfreq.cpython-37.pyc | Bin 22137 -> 22137 bytes .../chardet/__pycache__/jpcntx.cpython-37.pyc | Bin 38016 -> 38016 bytes .../langbulgarianmodel.cpython-37.pyc | Bin 23630 -> 23630 bytes .../langcyrillicmodel.cpython-37.pyc | Bin 29086 -> 29086 bytes .../__pycache__/langgreekmodel.cpython-37.pyc | Bin 23588 -> 23588 bytes .../langhebrewmodel.cpython-37.pyc | Bin 22217 -> 22217 bytes .../__pycache__/langthaimodel.cpython-37.pyc | Bin 22196 -> 22196 bytes .../langturkishmodel.cpython-37.pyc | Bin 22219 -> 22219 bytes .../__pycache__/latin1prober.cpython-37.pyc | Bin 2929 -> 2929 bytes .../mbcharsetprober.cpython-37.pyc | Bin 2234 -> 2234 bytes .../mbcsgroupprober.cpython-37.pyc | Bin 1125 -> 1125 bytes .../chardet/__pycache__/mbcssm.cpython-37.pyc | Bin 15680 -> 15680 bytes .../sbcharsetprober.cpython-37.pyc | Bin 2987 -> 2987 bytes .../sbcsgroupprober.cpython-37.pyc | Bin 1615 -> 1615 bytes .../__pycache__/sjisprober.cpython-37.pyc | Bin 2441 -> 2441 bytes .../universaldetector.cpython-37.pyc | Bin 5831 -> 5831 bytes .../__pycache__/utf8prober.cpython-37.pyc | Bin 1972 -> 1972 bytes .../__pycache__/version.cpython-37.pyc | Bin 441 -> 441 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 446 -> 446 bytes .../colorama/__pycache__/ansi.cpython-37.pyc | Bin 3344 -> 3344 bytes .../__pycache__/ansitowin32.cpython-37.pyc | Bin 7600 -> 7600 bytes .../__pycache__/initialise.cpython-37.pyc | Bin 1665 -> 1665 bytes .../colorama/__pycache__/win32.cpython-37.pyc | Bin 3859 -> 3859 bytes .../__pycache__/winterm.cpython-37.pyc | Bin 4607 -> 4607 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 1044 -> 1044 bytes .../distlib/__pycache__/compat.cpython-37.pyc | Bin 32054 -> 32054 bytes .../__pycache__/resources.cpython-37.pyc | Bin 10888 -> 10888 bytes .../__pycache__/scripts.cpython-37.pyc | Bin 11099 -> 11099 bytes .../distlib/__pycache__/util.cpython-37.pyc | Bin 47956 -> 47956 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 1315 -> 1315 bytes .../__pycache__/_ihatexml.cpython-37.pyc | Bin 13762 -> 13762 bytes .../__pycache__/_inputstream.cpython-37.pyc | Bin 22653 -> 22653 bytes .../__pycache__/_tokenizer.cpython-37.pyc | Bin 41554 -> 41554 bytes .../__pycache__/_utils.cpython-37.pyc | Bin 3307 -> 3307 bytes .../__pycache__/constants.cpython-37.pyc | Bin 66219 -> 66219 bytes .../__pycache__/html5parser.cpython-37.pyc | Bin 97816 -> 97816 bytes .../__pycache__/serializer.cpython-37.pyc | Bin 10832 -> 10832 bytes .../_trie/__pycache__/__init__.cpython-37.pyc | Bin 428 -> 428 bytes .../_trie/__pycache__/_base.cpython-37.pyc | Bin 1511 -> 1511 bytes .../_trie/__pycache__/datrie.cpython-37.pyc | Bin 2030 -> 2030 bytes .../_trie/__pycache__/py.cpython-37.pyc | Bin 2233 -> 2233 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 3323 -> 3323 bytes .../__pycache__/base.cpython-37.pyc | Bin 11246 -> 11246 bytes .../__pycache__/etree.cpython-37.pyc | Bin 11855 -> 11855 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 4000 -> 4000 bytes .../idna/__pycache__/__init__.cpython-37.pyc | Bin 260 -> 260 bytes .../idna/__pycache__/core.cpython-37.pyc | Bin 9063 -> 9063 bytes .../idna/__pycache__/idnadata.cpython-37.pyc | Bin 21434 -> 21434 bytes .../idna/__pycache__/intranges.cpython-37.pyc | Bin 1800 -> 1800 bytes .../__pycache__/package_data.cpython-37.pyc | Bin 214 -> 214 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 9910 -> 9910 bytes .../__pycache__/linklockfile.cpython-37.pyc | Bin 2291 -> 2291 bytes .../__pycache__/mkdirlockfile.cpython-37.pyc | Bin 2653 -> 2653 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 2072 -> 2072 bytes .../__pycache__/_version.cpython-37.pyc | Bin 221 -> 221 bytes .../__pycache__/exceptions.cpython-37.pyc | Bin 2177 -> 2177 bytes .../__pycache__/fallback.cpython-37.pyc | Bin 24549 -> 24549 bytes .../__pycache__/__about__.cpython-37.pyc | Bin 734 -> 734 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 572 -> 572 bytes .../__pycache__/_compat.cpython-37.pyc | Bin 1012 -> 1012 bytes .../__pycache__/_structures.cpython-37.pyc | Bin 2864 -> 2864 bytes .../__pycache__/markers.cpython-37.pyc | Bin 8867 -> 8867 bytes .../__pycache__/requirements.cpython-37.pyc | Bin 3985 -> 3985 bytes .../__pycache__/specifiers.cpython-37.pyc | Bin 19762 -> 19762 bytes .../__pycache__/utils.cpython-37.pyc | Bin 1450 -> 1450 bytes .../__pycache__/version.cpython-37.pyc | Bin 11954 -> 11954 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 285 -> 285 bytes .../pep517/__pycache__/compat.cpython-37.pyc | Bin 1021 -> 1021 bytes .../__pycache__/wrappers.cpython-37.pyc | Bin 5486 -> 5486 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 96822 -> 96822 bytes .../__pycache__/py31compat.cpython-37.pyc | Bin 645 -> 645 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 3913 -> 3913 bytes .../progress/__pycache__/bar.cpython-37.pyc | Bin 2735 -> 2735 bytes .../__pycache__/helpers.cpython-37.pyc | Bin 3019 -> 3019 bytes .../__pycache__/spinner.cpython-37.pyc | Bin 1494 -> 1494 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 379 -> 379 bytes .../pytoml/__pycache__/core.cpython-37.pyc | Bin 942 -> 942 bytes .../pytoml/__pycache__/parser.cpython-37.pyc | Bin 10059 -> 10059 bytes .../pytoml/__pycache__/test.cpython-37.pyc | Bin 1242 -> 1242 bytes .../pytoml/__pycache__/utils.cpython-37.pyc | Bin 2141 -> 2141 bytes .../pytoml/__pycache__/writer.cpython-37.pyc | Bin 3576 -> 3576 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 3490 -> 3490 bytes .../__pycache__/__version__.cpython-37.pyc | Bin 553 -> 553 bytes .../_internal_utils.cpython-37.pyc | Bin 1311 -> 1311 bytes .../__pycache__/adapters.cpython-37.pyc | Bin 16888 -> 16888 bytes .../requests/__pycache__/api.cpython-37.pyc | Bin 6494 -> 6494 bytes .../requests/__pycache__/auth.cpython-37.pyc | Bin 8345 -> 8345 bytes .../requests/__pycache__/certs.cpython-37.pyc | Bin 636 -> 636 bytes .../__pycache__/compat.cpython-37.pyc | Bin 1615 -> 1615 bytes .../__pycache__/cookies.cpython-37.pyc | Bin 18790 -> 18790 bytes .../__pycache__/exceptions.cpython-37.pyc | Bin 5508 -> 5508 bytes .../requests/__pycache__/hooks.cpython-37.pyc | Bin 983 -> 983 bytes .../__pycache__/models.cpython-37.pyc | Bin 24111 -> 24111 bytes .../__pycache__/packages.cpython-37.pyc | Bin 513 -> 513 bytes .../__pycache__/sessions.cpython-37.pyc | Bin 19431 -> 19431 bytes .../__pycache__/status_codes.cpython-37.pyc | Bin 4169 -> 4169 bytes .../__pycache__/structures.cpython-37.pyc | Bin 4382 -> 4382 bytes .../requests/__pycache__/utils.cpython-37.pyc | Bin 22042 -> 22042 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 2118 -> 2118 bytes .../__pycache__/_collections.cpython-37.pyc | Bin 10682 -> 10682 bytes .../__pycache__/connection.cpython-37.pyc | Bin 10151 -> 10151 bytes .../__pycache__/connectionpool.cpython-37.pyc | Bin 23656 -> 23656 bytes .../__pycache__/exceptions.cpython-37.pyc | Bin 10403 -> 10403 bytes .../urllib3/__pycache__/fields.cpython-37.pyc | Bin 5871 -> 5871 bytes .../__pycache__/filepost.cpython-37.pyc | Bin 2763 -> 2763 bytes .../__pycache__/poolmanager.cpython-37.pyc | Bin 12723 -> 12723 bytes .../__pycache__/request.cpython-37.pyc | Bin 5585 -> 5585 bytes .../__pycache__/response.cpython-37.pyc | Bin 18750 -> 18750 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 202 -> 202 bytes .../_appengine_environ.cpython-37.pyc | Bin 1098 -> 1098 bytes .../contrib/__pycache__/socks.cpython-37.pyc | Bin 4908 -> 4908 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 316 -> 316 bytes .../packages/__pycache__/six.cpython-37.pyc | Bin 24404 -> 24404 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 557 -> 557 bytes .../util/__pycache__/__init__.cpython-37.pyc | Bin 994 -> 994 bytes .../__pycache__/connection.cpython-37.pyc | Bin 3169 -> 3169 bytes .../util/__pycache__/queue.cpython-37.pyc | Bin 1043 -> 1043 bytes .../util/__pycache__/request.cpython-37.pyc | Bin 3224 -> 3224 bytes .../util/__pycache__/response.cpython-37.pyc | Bin 1972 -> 1972 bytes .../util/__pycache__/retry.cpython-37.pyc | Bin 12658 -> 12658 bytes .../util/__pycache__/ssl_.cpython-37.pyc | Bin 9550 -> 9550 bytes .../util/__pycache__/timeout.cpython-37.pyc | Bin 8773 -> 8773 bytes .../util/__pycache__/url.cpython-37.pyc | Bin 5183 -> 5183 bytes .../util/__pycache__/wait.cpython-37.pyc | Bin 3135 -> 3135 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 9678 -> 9678 bytes .../__pycache__/labels.cpython-37.pyc | Bin 4092 -> 4092 bytes .../psutil-5.6.1.dist-info/INSTALLER | 1 + .../psutil-5.6.1.dist-info/LICENSE | 27 + .../psutil-5.6.1.dist-info/METADATA | 522 ++++ .../psutil-5.6.1.dist-info/RECORD | 59 + .../psutil-5.6.1.dist-info/WHEEL | 5 + .../psutil-5.6.1.dist-info/top_level.txt | 1 + .../Lib/site-packages/psutil/__init__.py | 2489 +++++++++++++++++ .../__pycache__/__init__.cpython-37.pyc | Bin 0 -> 66535 bytes .../psutil/__pycache__/_common.cpython-37.pyc | Bin 0 -> 13882 bytes .../psutil/__pycache__/_compat.cpython-37.pyc | Bin 0 -> 6561 bytes .../psutil/__pycache__/_psaix.cpython-37.pyc | Bin 0 -> 15465 bytes .../psutil/__pycache__/_psbsd.cpython-37.pyc | Bin 0 -> 20716 bytes .../__pycache__/_pslinux.cpython-37.pyc | Bin 0 -> 48476 bytes .../psutil/__pycache__/_psosx.cpython-37.pyc | Bin 0 -> 14397 bytes .../__pycache__/_psposix.cpython-37.pyc | Bin 0 -> 3685 bytes .../__pycache__/_pssunos.cpython-37.pyc | Bin 0 -> 18022 bytes .../__pycache__/_pswindows.cpython-37.pyc | Bin 0 -> 26945 bytes .../Lib/site-packages/psutil/_common.py | 600 ++++ .../Lib/site-packages/psutil/_compat.py | 241 ++ .../Lib/site-packages/psutil/_psaix.py | 581 ++++ .../Lib/site-packages/psutil/_psbsd.py | 926 ++++++ .../Lib/site-packages/psutil/_pslinux.py | 2119 ++++++++++++++ .../Lib/site-packages/psutil/_psosx.py | 578 ++++ .../Lib/site-packages/psutil/_psposix.py | 186 ++ .../Lib/site-packages/psutil/_pssunos.py | 731 +++++ .../psutil/_psutil_windows.cp37-win32.pyd | Bin 0 -> 61952 bytes .../Lib/site-packages/psutil/_pswindows.py | 1066 +++++++ .../site-packages/psutil/tests/__init__.py | 1244 ++++++++ .../site-packages/psutil/tests/__main__.py | 94 + .../tests/__pycache__/__init__.cpython-37.pyc | Bin 0 -> 30549 bytes .../tests/__pycache__/__main__.cpython-37.pyc | Bin 0 -> 2541 bytes .../tests/__pycache__/test_aix.cpython-37.pyc | Bin 0 -> 3326 bytes .../tests/__pycache__/test_bsd.cpython-37.pyc | Bin 0 -> 19852 bytes .../test_connections.cpython-37.pyc | Bin 0 -> 14817 bytes .../__pycache__/test_contracts.cpython-37.pyc | Bin 0 -> 23435 bytes .../__pycache__/test_linux.cpython-37.pyc | Bin 0 -> 69172 bytes .../test_memory_leaks.cpython-37.pyc | Bin 0 -> 22534 bytes .../__pycache__/test_misc.cpython-37.pyc | Bin 0 -> 34343 bytes .../tests/__pycache__/test_osx.cpython-37.pyc | Bin 0 -> 10329 bytes .../__pycache__/test_posix.cpython-37.pyc | Bin 0 -> 13267 bytes .../__pycache__/test_process.cpython-37.pyc | Bin 0 -> 47392 bytes .../__pycache__/test_sunos.cpython-37.pyc | Bin 0 -> 1498 bytes .../__pycache__/test_system.cpython-37.pyc | Bin 0 -> 26785 bytes .../__pycache__/test_unicode.cpython-37.pyc | Bin 0 -> 11337 bytes .../__pycache__/test_windows.cpython-37.pyc | Bin 0 -> 29204 bytes .../site-packages/psutil/tests/test_aix.py | 121 + .../site-packages/psutil/tests/test_bsd.py | 553 ++++ .../psutil/tests/test_connections.py | 526 ++++ .../psutil/tests/test_contracts.py | 657 +++++ .../site-packages/psutil/tests/test_linux.py | 2083 ++++++++++++++ .../psutil/tests/test_memory_leaks.py | 610 ++++ .../site-packages/psutil/tests/test_misc.py | 1057 +++++++ .../site-packages/psutil/tests/test_osx.py | 294 ++ .../site-packages/psutil/tests/test_posix.py | 440 +++ .../psutil/tests/test_process.py | 1611 +++++++++++ .../site-packages/psutil/tests/test_sunos.py | 45 + .../site-packages/psutil/tests/test_system.py | 871 ++++++ .../psutil/tests/test_unicode.py | 370 +++ .../psutil/tests/test_windows.py | 868 ++++++ .../wheel/__pycache__/__init__.cpython-37.pyc | Bin 202 -> 202 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 157 -> 167 bytes .../urllib/__pycache__/error.cpython-37.pyc | Bin 2801 -> 2801 bytes .../urllib/__pycache__/parse.cpython-37.pyc | Bin 30034 -> 30044 bytes .../urllib/__pycache__/request.cpython-37.pyc | Bin 72329 -> 72329 bytes .../__pycache__/response.cpython-37.pyc | Bin 3274 -> 3274 bytes .../xml/__pycache__/__init__.cpython-37.pyc | Bin 721 -> 731 bytes .../__pycache__/ElementPath.cpython-37.pyc | Bin 6374 -> 6374 bytes .../__pycache__/ElementTree.cpython-37.pyc | Bin 44838 -> 44838 bytes .../etree/__pycache__/__init__.cpython-37.pyc | Bin 170 -> 170 bytes .../__pycache__/cElementTree.cpython-37.pyc | Bin 212 -> 212 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 334 -> 344 bytes .../parsers/__pycache__/expat.cpython-37.pyc | Bin 363 -> 373 bytes .../sax/__pycache__/__init__.cpython-37.pyc | Bin 3203 -> 3203 bytes .../__pycache__/_exceptions.cpython-37.pyc | Bin 5512 -> 5512 bytes .../sax/__pycache__/handler.cpython-37.pyc | Bin 12388 -> 12388 bytes .../sax/__pycache__/saxutils.cpython-37.pyc | Bin 12841 -> 12841 bytes .../sax/__pycache__/xmlreader.cpython-37.pyc | Bin 16949 -> 16949 bytes .../__pycache__/__init__.cpython-37.pyc | Bin 167 -> 167 bytes .../xmlrpc/__pycache__/client.cpython-37.pyc | Bin 34573 -> 34573 bytes 478 files changed, 21576 insertions(+) create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/INSTALLER create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/LICENSE create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/METADATA create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/RECORD create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/WHEEL create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/top_level.txt create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__init__.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/__init__.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_common.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_compat.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_psaix.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_psbsd.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_pslinux.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_psosx.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_psposix.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_pssunos.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_pswindows.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_common.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_compat.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psaix.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psbsd.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_pslinux.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psosx.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psposix.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_pssunos.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psutil_windows.cp37-win32.pyd create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_pswindows.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__init__.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__main__.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/__init__.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/__main__.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_aix.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_bsd.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_connections.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_contracts.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_linux.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_memory_leaks.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_misc.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_osx.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_posix.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_process.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_sunos.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_system.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_unicode.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_windows.cpython-37.pyc create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_aix.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_bsd.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_connections.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_contracts.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_linux.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_memory_leaks.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_misc.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_osx.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_posix.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_process.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_sunos.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_system.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_unicode.py create mode 100644 WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_windows.py diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/__future__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/__future__.cpython-37.pyc index cf405b7041e3496e9efaf7d8d0b37d7b31f8da07..8c0f48829b755d8f48a26468bd32026674e36cb3 100644 GIT binary patch delta 60 zcmdn2uvdZGiIV9HnI1}R{I zDByuB04s&6%3$6v3(|j!tthp)G^Yg992XWFaRHDDuHur!qLSkB%#w^EkikX#lc%%D O3Lq?om^=9hiw*z-5i-;O delta 220 zcmeyx`GJ$$iIgt4>NFXPIDu3Vhz%jQK`frhkC^fmc|Z!7APRWl3cyOCs*0HR z%YyXZVk=55F3l;yG{=v{MqCi2f~&YBv8bfDJhLRD2xM@Pz~qH2vH}Q;A?8j#$D#uO Da%M0g diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/_collections_abc.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/_collections_abc.cpython-37.pyc index 0187bcdc65f4729b3ebf9a27921163176ca32809..0aaed5fa4d39f8aab6ff2fd0f437760ef646e621 100644 GIT binary patch delta 62 zcmbRHh;jKNMs6owUM>b8=quZ}k$WDSQlPU{jAK%9Okz=TMrK)ROmT94L27VOa;Q&? Qe?e+qP=Mp+gKRNb0DeUkfdBvi delta 52 zcmZ4fh;i;CMs6owUM>b8c;ZpJk$WDSguAmBp<1VfeL6&1Wiiy{VtTEt{S#AQ3QW4Ala?1F-q`k<%} zYIM9N8lUye^u;%Q)W0zP6MgZVp}?Bhhi|^~o$s8PolC!^f2L!n;_>J@_&uHf@+CGM zCZ;TgyNRkk4xb~FW}{y`!yG!yEQjaKCcl_vrE)ONaEFUbfpd=v%x8G1#NC?TsEzd# z#hjZn4QR$)-;}BPG|Y3Q-Wybrg723dHe)sw{E|ampZNEHP|qn<>oxqFejWcx|JLIsc-?GM)G3PS7AZjTU!I0-x%2b`h-8>|Fpv0_Wi>zD=R2?f> zD}fndv&``+wn3+A?5PQ}mg8YFUEhfH)7X*frKaT8=*E$qP#_S%whK7|@IK@SsgR0H zd)zKkU-awPY?&_2IX){3Zd1==ZeHw`m1vUeksqVU%HHK71NIB{QS8&97=c0T5AXv4 zJ`mss1N=~c9}e)r03QnQBf!(Jcs<$CK;qak-vom=9^fac*JH=SM9EK0lYO@^i|~6q zGcOjqTsHBbMMA7CW{SeCFdo~2@*3VdqA+(uP?Xze6R@@s2y zBRaHg#oY;>%*d$x-nxN2l##?%@<{e3y4&$P#dB;M2kR4zy5zG&C%Lcjg+?hqC%VW3 znQZGIFEzf>_*&x<;=mj15n7Dle?mXJT3DKR`ycI{*2Ec{DP3i4VG>_hmT)V@HM!8< kZD=|v-?tAMH&DGQf3;`HsNCIgwPo%2HLFxVbZjSo0jAwf6951J delta 1369 zcmZux&2JM&6z|$(ZEWl~CKd=4LL;@pN*qEUv<~Id2{BbtBJ2VhMMRt3NwRpoW8RJf z1VSKi0QHm3A5f_WP>+@WfcDxW9QV>od*u&kFMV&EkCn+wm~^2BnOm5rL)Y(@2o@B~y=ga|k= z^jAc)Dg3Q?vnyFoz2W#yXkszp%TN`2O1RFAo}kPUD^j*RcaddRWYgombme`AF9l($ zTA!Vnvw-TF6(JffXM1feDO|QYf&^)6Xx&6G4-!GoFBq{g~_k5 z#EcurVhn~l_jtlzM&~h1 zVSC&)x3#M@tsN!dF1eoMR7OYc`*_Q+WO)G<>sl#)fhuy{>aaSRIyhaT_6RU+gg626 z79t5tx3}b2|HDH`nKcxmXPIZ$^JTE*)7}qLH zp@7p7{%M4N7UAUxpNQ}?5&n6EpN;Ty$V=F~UhI6taiPmUL;)8g{8Hz3`dr*#>X+>G z!F%K-_-CpzF;ABo%wM!Q%ukBDz9%dvP(!^_#=5%Gd*&00E5_kI<*X4rAlNAZ4@q5D zZ+l15dPrifC}x;S=j>C%gU{e@+wl? z-KhFAcW{HH7OenplG4z)iawU9Nt{&+oGAc7P4%*`P~D`o{LR^!Yjc%JVNY|PgC%t@+I0Yp zUGFu1r;Y7bv0+b-F8P5#7kk$?XgpPY`J-dcsAQoseWhBj&;2ipb_HKkRtEE)lQy6p z>M|5C`yqV4ZolMbn?SN&zPP0{n} X@BW%Gt;&U4x!sY{>|y71VbJ&wkpF5a diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/_compression.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/_compression.cpython-37.pyc index 261cc4d3236b0d911ebade4980df9f915ea2f4fd..d6592eda2ba59f29fe4d0c8d2e241bf1ace7820d 100644 GIT binary patch delta 146 zcmZ3juvLNEiIB}Wx6?#kB3oS2gKF@5oRC) aWL=Rth%f~a_LFP)W7w=fOvB0d_`?Br|01CP diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/_markupbase.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/_markupbase.cpython-37.pyc index a030c3392ede43d3e61ecafb14f4b8bd4d6168b9..1cd6077ad1f428c127a9871f6b5c5fb5c178f91c 100644 GIT binary patch delta 832 zcmaiy&rcIU6vv%*yDgStC_)Rnp;o8S^^a;!ejCSCa2X zXK|he;=mk`6`zu&!V=6eU|B(uE-T_~v?*^f6Ml^-ti@nuWSGokVMCuZjvcT0oAx@+ ziUGac53TCBJverN1waoQ`(;?2poc}@pGw5DiBzzZdO}KPz5bPco~a8h>+~<_J|XwS z;rLWZx7U^ar{Qc7tf-5ej&Bn(D^e5JHlh4{g}J}aptre#$X!4S`(ue&@p_^yKBq@Q zEH4HpUlwzSybjC*`rj=exxDM4UBf5)XGa5aAPJKV`zWx$v z`%}%G&EA7CW#isGGuaY zTVw9Moyq#E2I~(@Zpx75^zD}eDuc)C0H?!|G_2>2%V@)|YD=H>Oa`el5Jwl9#ua5@ zd9e^}8AZsFpwT8-^FBulq}zbyj)J^+U^)YvKIywdG{Z{DSTI-+4hdizhyhJt9xzT2 zg35W>OW%FBc9cF0)R)U;MwBcN9oq=N<+6edJ1#f5$t1=5_^kMm40*fBJyO%TwA&eJPBUoF4W#jYr6z>j6IOburrXe& z&Pbv|Pex}Io#ZIpCS+ACXNsgG?q|~Lr)}$_x`E!ifbL=Hs`BDPW|+8+?Wvujm|uKT zy^5VGumvtw3u+6v4fp^< Md`-`Zr%Nk;0YB!kDgXcg diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/_sitebuiltins.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/_sitebuiltins.cpython-37.pyc index 40043f544df1a243fa70a5af0d295fd6a4637f3e..2c6b92c44f9d3d7dd7d3262389476e83faf4971f 100644 GIT binary patch delta 60 zcmbOsy-1qdiIH^zykmZ$P%6a delta 50 zcmZ1^Jwuw?iInTwHvv=*#Q7L!v+Ze diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/_weakrefset.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/_weakrefset.cpython-37.pyc index 261c383d27fd81107938c74a6c7394da293fe485..e6746e9db0eba7077e937f29164cc41829130dc7 100644 GIT binary patch delta 848 zcmaKqO=uHQ5XXI~yNOvgX|hc=A5xQ6r7>VbQf;$swNYbR8nCv0U|CqwxTs*8_=2Tg zlomu!g?7-3ABYOQDPgfEKW^f!M`3S*2QT7D&(3T@F(U5a&wIa_`M>vO_Ko&IlTOI8 zcNczZOO1x)XFa8pnqHW%>t$ZKdTq(n>y>KFoaL4CCH+jzT%4IMSXp*%H?!fMu)w$@<}ecZ#Lqi}$md#4~KqlzFSjd6lO+xQKxF!nPD) zN$Z>Rk+C^=Ek{@aKFKq30;4HcGbsz}LI_5Db7F=}0`N|avMg-*?xW(#Y`~iJ_p)F= zIS#ZHQgjd=cRpo9phsgY4;KQOoNmi`5?Do_bwPn#@IB_yjq)HVMR}wxkGzKAhVpPH zC)rhM-Cz_}yDq8wFyHQ2DA%~Ft&+Tj(8f+(BQ)Kt6UH#_IoytiArme*_52v3f7Cw; zbL^x~js7?5tg5pNyi)tbEZH1!p7ldrXosI~3+`I+9qQXY>P@mJn zVl(ax$gyz~V9jB8aLvczYxJ2kL`#LF(-}h^Uc_>LHJ6_LD|Rt>fYLOSKZmLSk5As& zPoaY(DU!n^5{Yve8abz*hxKfo(~eIlZclWFC(Wp@?nxu w;-X<(HxVBvGFE7zD}-pnPm!D^j1J3Hj+|P;$4MrLql1GdiMZ+Uu(o&eH@hXk1poj5 delta 890 zcmaJ9 zt1g6MFGyE@7TT4941yr2E4PB1Le}mC7w+7s_r9cRM4iRqaqcNX$IxppotM#f;t~AUnJH3<5!(CgAMc}(_0Fn88=7@dS z!sg9q<s`BSpdQT4h768@3W5Uw%B_SmnY#1KN{VWM@AD{tqhgqftkvw-pbT8-R;5ITakKk2Hc!bu827$rW3;d>gNhBvbt#ba?URml z=xLA&*M0X|T9$$RJ;&SYW#LZGIi(-3>Z$SoaCn&IhP|LJ?xd$R4zLCn7(e0&@& zfAKx`^AzpflusB-v$e%mka~p&Nlz312;2l>gJC+w2xNi~0sTJwAi)Si)1hgND;G6Q{3d*qc$!3fxn4n@ zUX`l^S>o-QR@IR{N=$B>x=hqDqNWH62-IQO;K)-Be41c}cIDOB4VozZ1;> delta 50 zcmX?ObjXO?iI E0Bs)-ApigX diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/base64.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/base64.cpython-37.pyc index 08fb3d0acfa0bc349b14e93321df04c89128637f..cac8aaf19a2b339043412abaa337b4c2eb41edc3 100644 GIT binary patch delta 1630 zcmZ8hUrbw780VDR3ls-tlsPE_N@Q?jBpXmD6rpu=jD}j2hRC>vrwvBAge3p!pn2VqDBN6F}Ro+kM-jd!YJ6)E%OOnT-F#rT(@hT^FMUKfk; z`Q`?1tg2vbPiih|#>QW&N&tPsOw+M12Im$Q_# z9o0w`ta-acqVgbbJB5$8_U&5~iJG#Vzf5}0$Y#hYUTS5EiW;dGt%xE&JGfRY9YJ{e z;eDh}m{C!$R6{L$jvm8YgfFxo)l11@thpSOOuLZD6Jfdq;0GXmVmFG`eXljWdkWt#pf@K48fEEElqGi~` za~)AthT6rgj;l(2UbufPU@ioZI+(oh#Q9fI4naw+mRiNnsWh#my`0Xc=q#r8!>7(< zX+h6B9y_m7zBIdn*?B+)AqvE#S75r0jHwf~OWP#M5}_BZ=3gzy!dJ`6JR%&KWAqX~ z*V$XGi@;J7S;$cQp|jHUU$Oo=wDNzkhQRjbF53|OA~t_0o(Kl?OfID-Oi?^WI}D>9 zSE(LLZgl6c+f@&8q&BN7F8|mLP4~M`Nt(18A%|EaX&Ur`h@>|GAWioAfDC#KKFCUq z0B|U&p$o7i8J^PSxSsMxQdU?_dA5+J*I~Kk0VnX`usIp_EE;eQ9e9f90hC0#*`ED$Qu`v7Q1 zZGeLSS*0THyrbsQreWIh>7w_*7jGW;gKcncsEb|WqajNy|9R+_#tmd%1$+!}3)p!# zHux8VUF>@Cx4{?_g^dnMUV6Q;r8Zkm_2~KfI7e! z;27X}9**qqmiO=s#`0LplaJ?vY5=tWDK?H3y#;uOUyS%VC2@GKsT?3_RbX8MpnbXy MxDB|)zmKf{12~_HFaQ7m delta 1596 zcmZ9MdrVtZ9LGK7_5!VRi%>QPbQEQ9V`RW6l*f3jAl)2D%oeRA^>XQ;quzGE+lGhP z(10Q*h{6TvPP=5GgE z_Kv|d3lz)R4ju^$J!fZ3YhGw)(@EPXryc~%11Sknk}+rKHK;b!QmM`)?ODNF8>;v2 zh7}|D>4vWAMHy#k#qb3(Ggdl9+5D#sOw*APbs<@q(^rSqyvooGYfsT?Hu>2wUuYVA zx)6-rTtcUWlS^f338D2sam@Fdsti?FS{l{pJcftPBVt@ac;aR_WX+l6w9_IFGzWVf zm`meB;n2u<#Lx=`qqxH6SxC#k0#Gj@yLDD zXY%L*Z}NM6?d(?m@4gt5iB0x@%P#W3z*yrKh|Eg}EuG0aLNjUBq0g1!OwP6hOH(&r zA2`MC^7{j;Y>OubL+lR!V6aAVYp~-%IkiIZPEYBFVxk<~45dg?C6<+`V delta 57 zcmX>Wz9*d9iIwu%WYPAw{qaZFAvigC#=&&$bAOex-6!7VJ$ Lcx!WymK7ra^JWr1 diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/calendar.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/calendar.cpython-37.pyc index 1bfc128993d353abcde01e1c76d07a69e6f7e9ea..73833bc659bb8d0bd2dace5829734b97e61b9e29 100644 GIT binary patch delta 3236 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 diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/codecs.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/codecs.cpython-37.pyc index 195f3487b32609d87496441d61998bf439be26df..7d568518f28932dabbb7d5327cf06b28fc535354 100644 GIT binary patch delta 62 zcmey_!PMNz#O=h(%f$c$ePtUra_?eSa(A|haZD GP7MH`gAw2W diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/compileall.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/compileall.cpython-37.pyc index 8c40d8e6c72eaa3b704fcccf8843db0016e07563..6adc6aaf455e1211502fb660c696d29b461a0ff4 100644 GIT binary patch delta 20 acmZ4OzS^DJiIPfDc*B(=Xop7= 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 q)W0x7DaZeifOgU=xDObH`H_HPx$4=Dv6T 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 Xlz}HNQy!8#pPXdbTap4ld@}MsrR1w8 diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/contextlib.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/contextlib.cpython-37.pyc index f685e65926c7de894258f7df59cb3d3bad8440eb..166331c3525eb969d7af8f88e6651ba6498a25c2 100644 GIT binary patch delta 68 zcmX>-oAK&wMs6owUM>b8=quZ}k-Lsr$=lf~#xbclCb1|vBeN_urZ_pjAT_usIn*b{ XzaTX)D8O;^LS`#Z#;D16eBJ{9@E#Y% delta 58 zcmcaQoALB)Ms6owUM>b8IO0*ek-Lsr!qM3(CbT%Us5r(kIkhOpCBHl`CqFTzc=Kvz ND^JE-lb`v#2LKia6r}(F diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/copy.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/copy.cpython-37.pyc index 2a6ea9cf105089293acfddbc676b4b0a8781b9bd..583294305cc1d4fee3af09384fc95b0437a3db5b 100644 GIT binary patch delta 60 zcmX?Oe$AZQiIoL`U{T$CK@6XRcy Onimw{xcN8dML_^dA{7w; delta 50 zcmca+e#V^JiIIoL`U{T$CK@6XRcy znimw{xOpp6C@15s$=o~%j5eEdc$P6)H~5aBY}i$9Lhb@EF7W&sIasNT7d{B5aB#Igg=haW%6eJW&vxE P09ca)h~+ZbO&}cr5lq@nK!lCT{Z36 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 I@0rB^0o%tKT|mN+96BF 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 diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/decimal.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/decimal.cpython-37.pyc index 94cd2df6f7011b3c75df7da5b8094c74a060a3c4..574d530ad81f602e50946d717c88cdf50772c2a3 100644 GIT binary patch delta 20 ZcmeBU?qlY5;^pOH0D``8do8t;F`U_x|Bew_P1=iYPg znRD-N*}t;B^L~H+9`RetZfy7lrC`T}wvlr&eMF}CL^7+4=y5HhJWla}M@JsZDCz#* zbLJ)K4T%kz2fXz;?(f9lqCn1#W{Mj+F4i zU^QDdTY}rJx-&wZ$uYD_LS8y65SHi#*!6%aVCBksJed?{4OiFJJ}i_W&xDY)v~JK6 zhIwL`mQxBXBOIeiQdCm;e06i^MQBn?(^T>clQeR z__(eZG;I#oY_T$=rFP%}0kOMI*st@3+Nxe87%EVv4JDmW5>c5hQV+b>0K2xkin$^j z*Tre{LSgJ-5-VjM@mI)7T@s@eeyjG!79JD%>f+NoL-u zdzsb$yV(x79>jzk%Ny6CYFabo7(Fi(D`zH|343VOoN6d^v01)!;>H1NXzUVh?`}t<$ z!f7;P*h_ChwLjf|v<|%u?=9dhfw0S2(^+KYcdpuy3b{(NJN(bAp?Evn9|x3g6BH zvTOI2=b~a{WpzpsAJwjnjPMlqwho@S1oK(oIpAI3J>a&0<%^5Eqo)*OLQBvGkUuo9 zwGObh4R|F|jy-JPl0;{6GPKr_X-zoW5{lSOXlX0~-JjVBd^6vumqnPG;{0Vtq-SVn@xntYK;?%USkb^$ORi z54INg`*{KN$X7}(i4o_QlAnY)A#a!2Otb89XSCe$h#^^6`LY<1vC1*=qP$tzEJo$M z%0Xsh)%POd{93i{6}`@4bqv1u_9oe@Z{JqoB!?cLUg;0DiZk+BSGDs}XvkB10y}EJ zYjUIJa43%9t3Zqq_ES5?3qZp8vnDGWPSp$1h9 zEo)n@FR2@bMd#tM44dE35;`ldL&-w%m^rdAGl1>y=_{`i=j4(7W6aC@R|fLwgTo>a z1X_SP;GvBAD8Z`hGc?Oi(_VNi0p}%$mGcK2(IX>GPwheasUBzoni-s>gtVH5#j^aa z>9>%|o`4Y0nYS)2%Fw0ZO7NlUlsl%qF)EB0Vp>H+!~e7Zr5FUx48z6Kjil<4!e&P9=mYcxs6 zVU>V|ZxyR@E%F5OdgSM)5sCw>!g`URu6J5XSTqESKY!r&VaB~|hjDJVTokSU9^-kK z2C$$2_Z&B}rmZFDEmquu)9G9|Kx@vzlRG_PL9Vx5=|S|C2zGa9YS%1gR}uvUCRFy z27L_cC%`pE*prW$4$qC4w)RpKOS*w)fkSZfxCKeBKy z4aonj{-*QCg%2PE9)0~dbG|%LCgIZj>9MElNtKbo*1G}9C-UL1aJ_o*JxW!3+EmlUir_2<61^K#jrE5%d--Ojm zx|X6!$h!d_gDd81*!($-xaqoHE3LmBpTDt=N+BXkEL?hM({^j9<7je~?ZD z@!6+xy2Yn34MR`bX>LNaDV=D)xFP?Db}bx3#1Q}mMP5K9y_iR?>WwLTCTHlBf++{6 zrjqX`n5v>yPgOM@MG}UQQ9Fs{NEb8=r7y2kvok^$<^5^#xbclCb1|vBeN_urZ_pjAT_usIn*b{ zzaTX)D8O-ZCzC-GW7OtdF%pc5w|L@{^K)`ilS?x5^NNdDfF|AI_RKBFFDh{@D#|aq JHTiSwBLJ2XCaC}b delta 71 zcmcb=m+|UeMs6owUM>b8IOkEjkvok^!rIv?CbT%Us5r(kIkhOpCBHl`CqFTzc=Kc? ZgDA#Zn~%guFfv9>z8fnKB>%=f0su#W8Gir( diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/fnmatch.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/fnmatch.cpython-37.pyc index 52f0c6f05b81c962f8ac7290bb0e3ad0ac8fdd96..f271fbb544e237305de3cbe68d188ef0f39c5507 100644 GIT binary patch delta 67 zcmbOswMdHFiITkY!%~}R2-97l$?=SmKsx>oL`U{T$CK@6XRcy Vnimw{xOpo}1UqBYWInUC249WPMu^)n$Ip<$=oVSGg_R%La7sB9QQg2@ke^D zlhk7&wA)JApc|aQy0NlBTWEg_Q7#*kDnvocJ~T~YohqUG1H=!6#1Dj!_ybkpJm*}; zH`z)H%e>+_isA4|Kv?5&bSpb6G?+6;OC&;r;Eu$qjy8%Qh5xR*C;P*Lh5ZQP)i zeWvt@op+P}d#R88#p7k|9xc$$eQzS7RgaIoR_0}A+#Rg5tbem+&y@K{rx{lR`*Yc` zyT&%N)kpRSi;G(mfv(L(*Hzv?x>>k@#{a@aggi~ZSf!`tiAT1szu*g!*C%-Di=@9n^GXd?G096)5NY- z@2|5^>Hak>KSo`ww&u&#cObBrYG~sf)?kcme=od@)&5T}z3iv8;XY9dQHBF~Yf&r1 z6^+isw3%pBWWXz636gbtTN?IqKHtn@`XSh&7Iu(G`clF~A&R@|Y>b z)nqcCmI#W_M?v!IwN3XZB*FRuO>(b}U|NJRijl=FI}!Njt~8(I=OHqp5x~So*4dUT zqhLt~+c2sGKsbN$tm#KQi40A}vQaHdXVcSGcd&`;U)voZ?m_|l>}qgDHYEkY%ta8; zl*V>;vUNNAQtL+~#d_O1JXx?(9D+r(nPu9V%Pkp+HFmLWHmLF8L%dC@F(o1;^3>kI z)>wagxI+|qP1$hGQ+}n;Y>q<4l7lez>w5bI;#=lRyl|qKY}ti*!;ZeSkp1jL$5^$X zecU(uW5@8|SD_vP41baz%stNGEWfif7azDBcEzrg+Ueu^7duZW4Wd|ze0O+ld>2Gv zB*SF4_o#QHob0~W0~f&(*&?&-TK8c7>=9airu1}?C-t75XKdAVpepn$aB|Y(>1O{} zcY;3~w%K%+9sH7l?L=j=H-@h;XO+KRE;*gIesiqBk zVj-E75!sWO_#8b8mZ+~tdI*oA(i=l!p$9H?i5D%ppoo4Q)b9e2AbkN)5Hee$YTrj~ zCSSz!z4iQpPm{m>Q{fdHxb#WDA_v16jq=F(*;9_GbAXpP1fB8?6?#JigpMhYhMDB9O z7-ZeK&;I)05bwp-P`@Wqtf|Kr)O1|c=n_kX>ed~~&xal$7xWK9?T#vW4NUQy#y%C( z)cn4y9Ld#*^YkY&fXj$b78IlN?DEJ|D<*kxSMXzQ;XBcL4-Wr7^a}?=O_#W=VT+}6 z^c9SXsG7tcte}hgLpDep$-8ARE>Ap0`-=rB#LRW&UqV(UwPfB&Ybua8i{QNK<*# z;?=ke8w?SwQ5KDA3sd4#LdC}fDk2MO*D^FaK@Vd>yh^96%o{MXrD#T^X*d#@h4eA5 zxG)td5>hf*euwEW9R!GCiTvKgBP6Jw)rN=3bv+vPD&gyV#<24z?7{n}utOk4cksh+D-+JVnt^7r>T%T5R!<5HNSJ}n! zA@^?~ExG#N#%~bfW4}4#Eiz~RbYur{U4%~$O|aWvxQBeeyhl4nAZ3OjF5U=l!!-SX z&qkavI*qR){?+gfwBH514}dFPc~J+kgWqS*9lg0LqRcJv7xW%qHC%~>bX$pBzh z$4*C%kT=*LBF%1bObM~~SlL8X5hUr0taYNHPn7b8FaW@wS6+kwX&J|d7_9}vE5AI^ zO`c*un;5Dz-0@5@sm8OjnY2dBIMHCrWY@kHm;?c>fHuIrfDS+>U=N@h&;#fL^aBQ1 zX0paBg2sPzbOknb^Lf&FFPJt^(WuQIP`p*{#V}{|gu? BF!=xg delta 4021 zcmb7Hdu&tJ8PBmD+lk|lN2wt%lAB;+5<4Q<)(oJKJGPc!wwb3+$+M%v$nL3!JJ5BAMo7g{-Hfiem$G+dWH?fmG z$Rg!;&;8Etd!Fx{dwhA3U0h_oKEFRdhyLChJoPi*f88uBJf6LkH6;0{XK&ZY5kup~ zNN-f*BVUZq>#=xb%t+69@*SNOMB$ZyDuR%M=V8n+cJh^z9Of)g#A|uCecA6%=PRsU zbQf$C@8ypNYoYJrbx_z02m-bMvX#QVDi)GTzQQJP&DXJ3#fk!jZ6(Evo9^b~BVsm6 z7ae{h*gz4iA+DQ#MO669gs*UHtt!tJD&n7{^4Gj}G3BopJ*6JezOL%7@$q#EYnJg{ zT{j-wzP9+fimKQSsdT5LNn9%GSgYd4MG9*Xn~LvVH?vq_ZPLZPB}TAyZE^jiL=hhs zmx((iV{27OmMRS$=nJIIu|6EmxZOc`SW-FPn!aA@VEzR>MRQHTehKKglKMw zR|0in|AxNW&nB8~Rn_KH^-q#}YeV1X8AbMgCgNr>ys`K5h^UY$Eq=IhOS`O*EYDtq zwp>HgtE!U`V^URRW>lH1B*d<=EmfVwr!6nV_e0mNpcE+Sua^DJu>rYJiSkr68jBc) zZH(%xRytTEX2U*Ro1fNF^Km|AuZJwQl76JBn3e7%ipfr_Sb*pa_^Ylxnv}!M`koWxD=s9RK(5d7m8%*v(`3!vgS?3>O^;KaK-sFTl;A97z}8D z7-I692Y|(adeP~;#7+V1gZ;N&} z%DI+pemD!|TfJ~hyw%dRbofYHiYRDpW{;(Jx1Mtb$}NXqfs->?o<8U})G|TurgKV9 z@B?5ud4~1G5|x6@NR@P?vzf8e;_00OEvJ_$PCF6^P7sjJmofhO5`!xkl?&e&UYt0+ zB&3d$&3p`kM*&jTYvx8H(MiqBlMi)5OYoC4YkFrQ)0#>!fF1(rIxA*NH`X*RU;??#U({$4{o{YsT&#qWJI?cZYmaK(L zt{bniqN`nt{ky)`EEiOIcJs$UeI9^B__qNWL-x{F@BU+h&6n|z_@l-N)G`nUT!h+8HKWagd9D^>kCuwe@zinR$jb zm(=vAX2@nT~7a{w=wtLo#fYKqx3~_jYjBJ zYS*%IAXR}W{v#`{S24EcFnU?MHZZysLW=nc9`+9YEc%|o{{M&m!{=>dLM>TBWf|5whh8$)t zGBqp{cD^kK=7Mr)8?(xyQ+B_CMT>>e%i`?=C#!!Bdk+2!NN}IVorP?ZQQKbh;Hmo6 z_V}+QlfMD2Y>VCpdKW%He#tWHg;~|0EuW=9Q*SxwWTpQccg|so1gC}R;Tjdl&?suT zG+wNHf+JY7P*siOsJt?0xHO<5R$*O6oF|6)K?vkhdaTO44mIZtkIOW}x#RJqK1LRk zqhYr+WhF}=vtL5B3m}Un^IOC#OmIci4)wF^>8YVI$Ix|>m@Yc93>lUc#wF0?XBe9{ zlq+qSUan0{83~@^*GNit!bl=IX)?PIRyD-?54N%!Y4?}TJBwZb%e!Ao^>d1u-w;=i zbo<^UpsJu~SmbhFz6+X&d7k>+Hw$3zZOwx-EMrIM!As#=GI!xUmeQ-n9PC!23allUj z_{{Tj1k{HKZsv{i_(@F{izB5w<)QDvJdRR%OvrZTXgPiZ-~-4SXFw6|hcEpPq(M+; diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/genericpath.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/genericpath.cpython-37.pyc index cb23b3a667a4d810906f8ce895731d414a4e2ae1..b73c4ff8379a9d3fca6dc7db8cef8ada0b2f871d 100644 GIT binary patch delta 60 zcmdliyH}RmiIoL`U{T$CK@6XRcy znimw{xS5&dt^nh$%@0MUFo~N3wVns!Vh)fYj6#euj3SIh=97EG>ln=^b4w%x09v*j A{{R30 delta 75 zcmexi@XmnSiIIf(1YT delta 20 acmcbsa94rbiIBLy7* diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/gettext.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/gettext.cpython-37.pyc index 66437101b308ff6bcf17262efcb0cece2c96d7a8..56038a749b37d624efa0ecbd034a2b5ec0790526 100644 GIT binary patch delta 2831 zcmbVOUu;uV7~g5vf9s!g%IMh2=${Sgx|I#O$rwXAU=f*YZfuKXc)4wFyUW_!a&9{q z8i4>Y8VTybNaB1lV5WhL6i{DC2#E1X@yXmLA54rfJdhX@|2%lUbJ=>^iW-;Yx9^2q?I?Vf!m%MC#qoajdFf$cAbg39Q0pl#@sVo~Q z)Sy~q(_tU!w#*wL1YSp$EUT@m2x||yZ)rxI@tQy93gKyuR8}o^aA+Q&CzQklMZb9NchRy4UmeWr^ixeP`64z zsbX%G6S*O1K&RBoLOQAFlDRV8LIdZ8PYCF68hmB|G~Wcv0peaQglDO!*!V;O3YCuW z@!3Zyd|z z0sy#DYV$NeSvH@niMwXN0I3GrU~Nq=xWvck&NWTB4nIcsN0aDgx<`j{jPlBYo^1Xe z9U#2>fE!Ar7$lyS6u(kQ`_BDb`(7Z_aa<;wD5M3BQ*0b}q`;@agyXOTHmohPWO!|3 z;3%wFym^q01DF6x-^C;kIk$ERg~;}nSr2Tiob8-|Wicyh_@3fdEw}V7tm+7F2QsQY zm`lDPYai7e*KZ5&!K36?-=wi00*A<$e-xc1ANqZ0jNJ2k8_v*e#XPxtY<$nizHvn_ z=P^D={`7mt;UF+n98UqqB1nadfcd--@M+rnEVECFX#t85HO2WnpU$QfeXNjFj1;Is zF=Y6Z7{{kcu5~vGlAEoaXpa2Q+UjG)S!oLe9n*d)gdQliw>i=CZ-E>E(6luyD;iDh zTnuflm@=X)i&6^D0kKqa4|#3^+SkLJMqV4CKz(Eqj?Y5F9D>;<=`%qBtHk68{tN#S4b9G zMB~d-Z0Q(8=qBMiC;C4JPW=#N?91kdvIQxjp2SsfwggHOACq%Dz0d9Rjo~FZ&FAT0 z$T&hCcDiG1va*yHaNr`?TnD&8A!>}Ld0FOg4tCwNEZNDJL=U4>~W~f zo9ypCKf%0MFf(I`v9D+Tn3wV?#Lz|b5n*XFr!2K9&s#RVJ<2q!(f=VyXv5_)uUr=D ztykrA&E`e1O2Oq0@5FYX}J3X!l zrai#@Jwsdml|`eoiJgbWf`4Ud5Y48WeA^R3R|)EMHNpVlYZMe~jF$y2hlQkg3|}E# zz5YorD189W0K5;d1Ax6_BOt-`k5d5P9_s-N0Ji{E1_85vU_Ek|EcWhjmOh0^9`akS F^cT};TJit@ delta 2795 zcmbVOZERCj7~bjU#y-;NwoX>Yy=w;)=r*vMq>#x9TZF-6n_#Sy(yh0%TR+CR8_+3Y z#3*Wv!4nxVW+!h$xt7}vr z>Kf7L(DwAa3%*&(b6`*m-{)n=L))SSc3L#sHPAENdWcwz({`8lEKAYvHDr zHcsLpb9zGOru0OC#dpG@h21Vwh&NlmENF7H3d8BrW?hj#8en4;n}yFa6>AA+H!74W z1m$Fmu15qP`>UeSp@5X2g6d?x%BM&td#!Sg1Xz33;PMWzr9od#)zD|}R;?xd+3QuW z6Pq8hR(8PAW@`u8&rUf$baaBmwyE1-hN@L}H^?3V+#1y;CZFbHgqu=&!PaK0H)g@6>b()FEFU7(a2bKy2e3V2@VN+!QOU*_qm~sz?Qz z77scB0HdG=tLij=N-%jvBpMCJB8kLsWMtfHk~X|_fl+Ko+2?hm%`l{u0v7b`Nln)y zqguW?>vbM4mzq^jPqJ^F-ddT_B-Tm}ROYOIZWD?i+)0D`KwFGdY)O4I9^Jr==SC_I zE8qBf{X4s)vCS~9hT|k)3Qz+$B*1Gm>Twv1BLKMKmPrwyAe)O1j5x<(Knw!~x)M~@ zy1d_+xQA?J`QuK+y_=o2A?}hgqrmi;oX}TVyCtWBJx27VZr1V&^+E1>X zWHahP@s`J z+(Y8F$J41iGc|j&@iTLyEIXkOLzyf+nR87&ywloU^b7s8V5m9aTB*SibJWa9~xd!0mNdBG>q%-Sp zc8Cgt4g&HT7|WuTGJ2Gvp}9R7*Y$X6lxCo)SMYd+XN2X|9Op(q(b@4*p_5Lh%^@_L4vm2Jj z0WSjH0-OSz2H>>C7{2AL&zsE(m}<6e?I0;bmvFL;zR&2o7Kc2Cw;_%I#@PJ2?f$qR zL-v%Gh@?h!ZowmDGnN$NSImoaES@NsNZB>(gM@s-#(jIqC3eN4 zpKDm&5nL#56}<@IM}Ut7aN9^CqU&L*gA)@FvKt|EdI>B!^go5Bd0fkIGHFcSFCbHL zpt4NM^8+~_;*QxM!?hFxYB3}N&=&w#0ZI~I#LKU@b(ce$D}rO_ ztL$v+0acdooM4Jri~jSq*0c>bLu)}n#?Dg^B8m@#AluO9WHXhO>}K1}E@*jeM*3eu zMF#o`)C@p&p4kW~Cw}op*!~S~?3G^1s5FxfY_OI7q?aiyb2D5{IML2>AJQr8mz0PF zH=f)hC9rbQ{_d)VLJv*};85D{C- zAT#kVG85TsWZ$>9w8{HaCs<;HXLN24hsB3QI7}}H7R`cRJ{-}t@C4Oj@gwvc3v{^m zH9;u9p0yq)p%nzmh2C;KT AZU6uP diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/glob.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/glob.cpython-37.pyc index ca7e6e048114f617668529d4b498599de26954a5..5ff217c6b4ea7e360829262fb97d39df3986eb3d 100644 GIT binary patch delta 20 acmdm^xJQxOiIPQe%pf^9xdgi;_cqV*CqI^MV2#H{0>?ax>nV>?7F(0F+f4QUCw| delta 90 zcmca%e9oBLiIej&V#*EsAl;FVD-#PfRJ^?7_#&%@{Q~OtJ|8idPmp diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/heapq.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/heapq.cpython-37.pyc index 2bf7302c5ebbc464a1e17ca2f1afad491b12c1b0..fe6c72570921d79a01274d62296bdb117b072500 100644 GIT binary patch delta 473 zcmZ2ku(^QSiIoL`U{T$CK@6XRcy znimw{xS3r_MvyUTvx>GdGo$5X550%nRzL%atU-jybnVm zmD&RNNbal$8RgEzz)%dt3~UUVJVkmS6?Q=47ISW5MG-HE>i{AgL4*^Ca0U?)Ac7f0 zuz&~`Afd@uBn4u-f(UR(nSxkuAi^C)cz_5`5CIJnVIUJ6=w2W}u;aWpXPO;g1OST! BUzz{_ delta 496 zcmdm7u(E*LiII8m3|N^ttbk&gOhs0c zzZ!=?Tm-QVq#nc243i3iuKsU=;c7NpplOy&lTYir)q_1`2QnS(F076R%DOW#FcbqZ z0~>=TPmvx-y*-e)#hja1QN#=4I)Vr%5aA3WTtI{bh+qa0EFi)aNNDmENrBjIAVQPD j3`hboLyAi@hopoUbDH%JWZRG-boW(ODn*#ljg diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/hmac.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/hmac.cpython-37.pyc index 54efa757111282eb0306f1fce3330fc05ffde70a..9a5244414b14de33835b50ecb4f7ec450e2fa919 100644 GIT binary patch delta 20 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 delta 8959 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 diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/io.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/io.cpython-37.pyc index 5a8a040d9cc88b47e14c2e206fe9a23cb5db25bb..f13573a6d1ac16db5fb323ed889d38c7ebe3bfed 100644 GIT binary patch delta 60 zcmaDL^-7A{iIb8=r7y2kz3[YlE&u=k delta 22 ccmZ4ehI#cHW^N~5UM>b8xZqK{kz3}jp4FCWD diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/keyword.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/keyword.cpython-37.pyc index 1028951e8fcbd2a1ec35a0f5a69446b0de10b39b..b1cc0a8a4afee365ca80dc2a2eac170938dc8cc3 100644 GIT binary patch delta 161 zcmZ3$w~CM3iIo6w1EURN)MQ;INg(OYq`?@qxqxXW z6Og0D>deLm)KSDgxtLWQC@`BA8>tztrpQ;UjY9FtRvVqEge^K$YNQ;H{l lWX)wXm>kdMCT{>#cZ(xFJ})shH9o!wqz#GCpL~QZ4FI^3Ee-$x diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/linecache.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/linecache.cpython-37.pyc index c3a6a96842da536ca2fda96f87cf30545bb914d8..f8e3915784f8bca26b99dbecf522773d52f925a3 100644 GIT binary patch delta 180 zcmca3`%ISGiIoL`U{T$CK@6XRcy znimw{xY>cJjhXS*=HskOm>Cr(=Wy<2l$)%@rOhS-G^R*)b2OJMGn+h!tuVQc*O*NW z#8jWWo!5cUYVr?WIYy1i;(XdV8bD!9Mn44Ny~Q3MpOT*(A75k((xM9@#6X1MzEx-T( delta 173 zcmaDRdqk?*0g~?@{dl_XXn{a8fNdq+($!t#Ll4WL-1F_{Nckmjsse+hllMnJbC|ClS zQJm?iCGk0#d8x%kydWts!3ScgPgdm9W>lZ-%O@>h0}{{y5n>?1U~&amY6+hc0Bss6 AH2?qr diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/locale.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/locale.cpython-37.pyc index 9e6fb0845a710a03d3ab0676fac35fe74c412ead..ec97f81710bc4ad9b28227695e03f0b8e2e0655c 100644 GIT binary patch delta 1554 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 diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/lzma.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/lzma.cpython-37.pyc index 6681d044a2c2a1e51b2497e866afc13fb17d887e..d0c145a1e58889299d65f458ae8fe3f26c60d708 100644 GIT binary patch delta 1595 zcmaKsyKfUo9LK$W$0kP-=K&}jc@eTi;jM^prv!(rLjp;_b`&WDmbEih7S<2_)(1y) zl669e4k4zy3W@536a-s9feb*ASfM1YK&|NCfCI(*j7oLWof>@|b(8|DqRX6MTl zmZALe`L(4AE2S?ao&P%CE9qfG-w%ucCnZEEZ*k%c+!>)-!Xf+Si#7GuDs( zD&~SS+iNOEwv!N1xL9V1{mN_6`LOq{GK=97F2Q#LA4Nt1IUqIgwf1$RYKYjk)5_Kx z%j$Qw_8I5%kt#F?eY3d>PInHWtK(Aq{)ns?h5}r za9}TPr!+`3{qV`bMc40nFh=PDc~$H5A*>Gz#`z@0e48zjHaE_ zGg_9iP^7f!zjo;C7r9$aod5s; delta 1548 zcmaJ>OKTHd7|uy1lQgxER8ueX^4ZqfQEIi8+G@47O*C3Bm|DcrI!v2W3{E=Xok&rT zBBJ6>JbysY&4(c9EL0E?*W$wE!G&vofw=NKC)!Ae&f+=my!YEVZx>%KHcz#*Btq)@ zoV)d+`DK{Ri+ABCY(7|ud|@maOhjKL5=kYOVOpZpqvW%6tNNqOfGvPDAR*o-eN#)) zVk|W>&Jlc>qh0h*9A7Dg*j4r#LGT05qPCyr+UyD}U>;6^hRYtE9(|Du`|U)%2VO~Fb>MlF9)&4>qE z@9wOrqRIxU!Qi$b)~|ybWfj~C>uROp7jN?VnsdQ}?NPS(B;vz_I^ncxL8ri|Yf@+M zX2)r!cg>2Dwi_17_U+YxQQ}VFz`yKgf(z|Mwtpj_jKjn&uJV6boe92m+-D~-NQwh$ z!?o0}jHqE)kzaKdoQfk8zxRPzSfUUxa+p=yUPp5KR8Qb*1OU zO!u9UTK{WnXH>ZB5;AEp52QOMjGo;cxPM9^)$kCxo`dVhpgf^K#>?cDIaO}ZBzV(+ zEFc3o0muO`FPZ_I0qA`nR+Nm-X0tQ)Z1y7MA(#Wy3euF``lu41692zYNc`yOZf}F8 z&M`*ymo*seT{l>Vc-{YePrXc;sg2mB4jCg}b{*A0IHzIp&`MjQAjbd=3~2#^MZgvD z$=Z>uWvY{m1>dc6>^Pp9>imx@$};IZ7!CYMLyy1COFX!@_akdIVAKRK#o|EU#DT%-!A5GM$HHi-cgX?ITwV5ufL&j{|ab4S{LBzl? zXh6Yy)OK%{9NGj%3t$LPd%dCV) zLY%~dA@SnDqjeKKbI`<#2XF2_;6?ug6W<#Wx?bGFw{PC}y>H%|neFa&H#`@Oh7Q5E z^SIXw>p|kVMsQCWPC<$#5e5ND3f*cu>?p1UXl^L7704pzsZQk~tQS>V^(Y_97C`hZ8&zb;q3R|-}qB} zSJDo&>>QT*`Fe7VkWv0Mm5mECX`}TIFQ52E(&JbqXr*R1s2A95vImYwpmF|7%cvUi zWA3qZQ6dw3MK6#m{HdNG8h@pi2QLEqBvNcPpv(5~O1DLg0XD;rWEPLl0R;;&5c;#L zyqdWTb#F5tNSfar(zP*6FCp~X7Ln$@7-DiFkCdqG^O~C&xg}+nkqRQH0EW~*GoKgO zoSE`#5C2d5JGVy)ecu7p%KN?t*Y7vyKa8F_11h$}ck&m=GXI=E1@ryP?~b3xG@bxc z5X7KSh`{g;{5-P3ZX@BJ>to@07#>G)a)FRl_t~XILgxARsSa3Pn?9*psGs1Ere9Ca zqf?gMz|2jA`v^GzFVbPPnq5BIvKTzL5lpF@c7xF>T#IR*hA!95Txt~yt_v0(U$fO_ v_b_AeH>N(jj-fdA3MyovJ=tQ_QlQ#~8-`zpIu2Vy*(gGP3K41ikNNU1t!1{0 delta 851 zcmaJ<&ubGw6n1u#wfSX@BxyJ8ruEm>O-d~qsci}+rr1)U6^vN6f=TK$MzTqmO=u$s zo<&-5z=IULc<^Xl&~pz8UV7-w{Rh10pCI_&RGRhT9KLz;zW2U)@6GIVceb zts298*H;9b~UvcZZ-c>DU4c@cuoQJA_($g1=F`T`;I{BXJhl8ZCLN(tk${PE12 zsd+FBoh_s1Ho|=b9l#BDSiN4WOti`jKHNEUDVwzhqg8m8Tjdq$SqiIjdq$SqiIiILFC^;juEH$P$Ilmw^xF|W)C&s@Z OH7_W@aWfC=d0hZy-4wzA delta 50 zcmaEwdOMZdiIID+Lk& diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/numbers.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/numbers.cpython-37.pyc index 9ffd250feac8fefdd1c653b21a5de6fae0b9ef29..5e45e78076074d60458a2604cede8cded5851bd9 100644 GIT binary patch delta 20 acmdlPzcZfOiILFC^;juEH$P$Ilmw^xF|W)C&s@Z OH7_W@ar0$%J6-@H1{0b9 delta 50 zcmbQOHBpP(iIILFC^;juEH$P$Ilmw^xF|W)C&s@Z zH7_W@aq}LwS7MA&o0rR;XJknSYMsm|FEe?XyqR7GkW-WiByO?C$EV~c$H(8|jE^tQ z$uB96k1t9E$)_QMx1R|n9gawe$WI__P z28pIlu2rsNOq={&xlA79j3Ti0jv!VRh)4nv*&w1|lByJA&gA7P!E9iKV1DjoX;nQH zxRZuVHngXN*3hH`RDMQNK) zX}B^vfn5NSyv3GUQIeXM0&y5bCCCu4Ke2cK=wonTluu^l5C%FwRcoIq)K-)=`HsAVXc~x_4kB_vL>`E+nC!?dyje!UgxS0h#191$ znk+@hAa)UmCCbuhBGNw;vR4J3s011FCbOf=oK|~UW$N>?B zlX>MOCkJS=PTrytzy?+e7Gf&Oo2;s;rwMT>NM$~VC;$<-o!qaQ&Lmm_QsWIG5FS#T?Kc~2;7AOtVR0|4g#=OZv+GZ-m ecy{v|?MZ9`puq6cWGpfVnUqb8m{7KHBe(Ky09Gsq4*&oF delta 22 ccmZ4YjcMICCT=HQUM>b8xZ+W}kz08;09Eh?@c;k- diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/os.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/os.cpython-37.pyc index 298b6144255858cc1e311195b7cd950a8168a4fa..d954297c1614175a37bd6bd3f9f47fc7f8b62325 100644 GIT binary patch delta 62 zcmeBq!8q*&BexSTFBbz4Oeov9k=u($$=TT|#xbclCb1|vBeN_urZ_pjAT_usIn*b{ QzaTX)D8O-ZF3?+6Dy1jA@&e&@_oRX{FWD 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 delta 7328 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 SJ(4T`W>TJNiJUr8&i)VIvMyEt diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/pkgutil.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/pkgutil.cpython-37.pyc index 579ba184ef6caa27a49d48e6fc481f098538b21c..58cdbf9e1b6a0297c844a7a438a0060d056174fb 100644 GIT binary patch delta 159 zcmexf-`K#&?ZnH=#Q+2o$~JD~zRIlR;cOM-m{c5-Sd^TRS(X}8oSa{f8eEhd>J#H% zkeU}1;JEn*^9Dt(DE5@hqMXd)lBmg>RBIW#HXEo3uyWtxD9BEa&r8frjoR$3?Zd)2 zVe$-pd&bF|Z|I+87o7;Sr^pCI7=s8+5YaPvm-#oKf{hm3tc)u+@3o!9$k;VG!hSvg D#pgAF delta 149 zcmZo{VEkUs?ZnH=#Q+3XJZd*`UuBlCbGC{JElw>ej&V#*EsAl;FVD-#PfRJ^%*3)m zk?R(FN@h_`W^u`_$$M058GANcsR^)hM{yKnr^n|d=BD1-9IEZZ!Z>O2B7J+tshc0^ tpJf-F3^cvS2t*iz2u%>tH~EP9H=u&u7Tm0it2ZCFoyEx5GdanAJ^-MnGEe{j diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/platform.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/platform.cpython-37.pyc index 4f95f5673299661454f81d1475a5cd11f1ed257f..c76fa21f3ad8700fcaddc437ad2a8253e59dbf60 100644 GIT binary patch delta 3109 zcmb7`e{2-T6~{fkA3pAE=L{S+wH-Td3^~B&M}@%&m>Qo626HyJ=Eq{Z-rHO7+UL8= z?46NKjh&b@ji3QKQPrwR8WjXBq#2MiS|03aj#)h#*Za+3 zqsP)yX`_ql-R(UcX(PF*v)OL)zwTj<@C26;R|Y58D*GqFCtcK7J9CtEi*qygvd@dv zp;c^+cr5fbYZ0+o&1|hWI;+|nrK$J|@#d^fZx6&4QC<2q)+}Bv?Fei@M>!A`C1rK2 zSG-jCJy1t*+yf~y>G-&z#S>=I;8;$$m`_;*RAYb+eV5_S=#CqXX#-W2 z^?@|B3?L%> z)sN4f>e(~ZoA^%k917LXI%k9)A@%23UY_M8Ai#PQ}LkaM?njAWB*8J|{=R`5$0^oHmN_15dlrq=?^#U$OU8J!I29gRIF3bph2R9*hSDjXkxA)zcbiFW?BY*h_#kiy zI4suB+dqFFM0p@C-HJP&bY>)NNGJcP&*sl!dqmm%G&^EHIlqntA0}g*jA>;OW{f{A zUSCjKa}*vMff4`{H~~5m%SEJ7I6GJIqQ?kP0QIT*`N0a~$}RR4ZBd z8TNu$uyCyYd(^1}b{UyYPQ`#{M))_So#Vz8a|+_dPA!|raOm-k()h!L53tkrj76vN zr@x5ar-9S33h;g6S4)nv*X)tcear&LGp&HWFfRc@3KoPc8ofyC|+Lf3XVFI#_vs%F4)kfNZ6# zc?qt6DVKV#v6@{H?>1gz3Gv2*Ti9h${gAU-p6CR$768b4#}{ectVX-r+vWaqiI1Bg zv!6doQrP2oQ|S!Fo4+JhtmtA_?L#Y`Wh^D?o8|`Y`n)Xqnrgj>A|DX@o8}Z^J#;&G zO6OO^nWi@Oo+wyV$ueqVLC~qqthz*C_d&t^5p(-$$3brDM&SQSXMX zx=2SC{~dLOr#W6L!?SwE@#$JZx6Dz)@ffmD$^gFyW4W9LND~AnB(ArF#9NWl&>zrr z!$>JWy`vk=i^YYiG7)Ok*$sQ7b+?U55hfPi)pN+03fY$(Iky9`{WU2CsP)qSrDp(^Xzl!mX3E|$L5=f@hl$D#`nT9hk zEQ_8Lq#vbtDsD_kLR=7~I7?3q)kb|Nj*`cpgS&45F9SC4ec*56*!o&_Ok7xhlGwN5 z0r7nMVXxfSq&TdWPM4F^QaG%9($6d4lce>FoW`x3#x3fvzoX&fx1^tm=;Jx9eL1at zq_zBxRsmfy%+}MfKc`g=E#dBbIoCX%Gs0%pO))x7Msw}LjrXyf+RdEWO;YQ+qvq!~ z?Ve48UiON3W9wJLKc_**t?n{2j$fq*SI=@&OUM_5qZISM62c)qE+)4{*%onWTLWFu zY0C2G-!Ym;MVN;mEdq7}IJj`J6QBqqyeMD10t2T2`J$t4DgiB#`KN*+4l3bU=cwE9 z#<-T$`xScIhfNrZi&Y_UO*ts0YxC@9wyTW!#XEgvV&;w-77*vvc|zOqrmux;>Fv%9 zt?w;oh4!xA8EiWGa}T16Z-wj^2h=83WS>`ym=9aLZMB3IOJ^&!_kFkmcbr9H73?0N z#lBwj7uX+|I(DxYDqtLF0OXapA@-Z)jgx32t^O^qISyKJ(KnRhM%<_5^#rsxh_}r} z_sfrxO0;F3{{Ygfzz>0sfIs7NgiiV40W&y39ga^`hcq*(s(iNi=|I?f`@`l>0~Ktq zC>*@6;v~#!2vo-LlY{I%DcS~?(8uK$2g8fyb{4>6J~#L~P{fB7o}l4mHj&^Cx@66m zfMkl_4AzayNOYq;2y6zn5tN{6Wz%@Bjkp@8r__>PfjkZc4UmCE?dM~_V}L9$-+=Ti zAP)fVD1QOK8<&gqSx7jUaV~4sWwfsXvie?!bc5jdQTXDSY?{6-QIq(mK(0tY`d=r- yy|_Crzzq}t4DbU1ppdYX7eOor?g4^82@oRSaAfIK9k<4J4fEL;DYF}fLhK)Ev`2gZ delta 3027 zcmb7`e^8Xi8OPbN}aZof7(o~(@uu8nYT_Y^$+W`F=-m7nsk!xch3Nm z>2#*f_~F@Szx(X&v(N5(?_Ob-t}t73dU{%t_&2|0=Df|Bmecsq0|UL$0FMqd`2&2w z6WJ3EM!Z8&eM{OeQ0DNUrAu5f!%d!(@6P0Fvk2TU;*`2m+a5#ZBa^{q?ep;x=pn;qc=GDKQ z<1(`?^rFkjw$jgB*|r_fRRP^})wQ+^(cG)}vKZ)7fyV@tbFxRN zC9jYT(r8{i8`MwdeaKoGh0x8ofk>;eX%NcpdmB^G@%-)Rd%=>wW6 zv*7VH%cG|(k4P5^irsRCe5fS~V1)!;U`a_)i!hSRR%T~Bq_cZHY^^37Vg<;Sk>ZPM z!6Du!Y{jgFV^M|tg&ww7KT~+pWN8*|zMHy=a_>hxULlA0gAsAGBXG3BVN)jqT#dwI z6Y&^d%I#iyzNnIg>9<7=Rws|+c2P4sKy}3p%%G`a*Y+n6qDeqxOxkjr3A@8>x`Cy0 zu?O^jcbQh&ceT>ycQtgq*k8XqlI;C|BIr+)@Cn(CxTiu7Sw$FDf(SmQQ->+Rtu~KW(5qJ2olvIVJ$oy;iqJ3OUtX+Y5lSC zr&;!CArWN1bA#8|Gx0J&4xMb4F!zU zp}?>=9*lA5c&8X#$Ij|`8(uSg5Wab;-cT&w0{N4u0w1=qj*gro2F-LcCbtI ze$BajOe1ORUrqMeOJj&*&w9aUjM>h>s8Gv#& zte%!f)Q;Y^Ho5miMWe)JS@UlQ%bj9aA`>x@YyK*=Zth|4>Bl!e&)7KCG?dtuV$Rc8 zLy-j;FnXx=%^>(A@jKaiJZL})-=84sm%SWFb#85n+hnY zc&o&P%Mx-qpWDx{5%qk49BLDtJiPfsC<4}N|NsN-|h{JjtSjyIAG*1W^ zse$mM#zl75z;yt46F|Wjsgt3oDsO^lDHc(y(R~_!5B(nsxT$+vt_L+GYBn+ySXNo6 zcx6>Q8c?JAqW;hj9w>es1AhRV16~7O2mVE`Z!2Oa>G#`S5iIEX8ok{1v_)=VKQ*=I zti~KgV&74dFp^UFeknTE{$fIOM~d!f(LG(~6U|d{3^ucM*_cyeOo^Vg{a%((-G(abwovsfs?s>xQ*G4VldT`G%Y_ zp8^hG0}ut|-CkwbM5d8uyi44Lj#mKrIlygKY~En(3xPq;DejzK2)AMJac|f^s#tko zQj>!d<$ARtg+5XaGYd8Ca_gu2RVGZkKZn-tDrBj``LVT0j2EBWgu8dp$*lVB!3>rS zzub~LnfJoBi1&y)M4Gbcf?CK{h|#6=xq8itEiXned2?Bs?0VRH-6}sRUj*;)xtNW{ zeb1)<1M%=xxjU?qt&~H8{$A@ccMf&_xL{Wy}%4`0C)y?4v=St?<_w9oCW0ZT!e+goaOS7n@3x| zSPQWJ2H*&dG`yHYvG|1eO^L^h-vUko|MM6*LoI&>-RFP_&40s^MV^YLRiKKmfSCr^ efR#WxU>Cso$TwRx%w9e+$urTDp+6XMu>SyK))QF( diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/plistlib.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/plistlib.cpython-37.pyc index 2416220c168cf7fd6e943a8f2a9d2faade5131cd..e96e1f6bb22c4dd62011e1d12724760f5dc3d852 100644 GIT binary patch delta 3303 zcmZWrdr*|u73VInEUZwF*Rm0LiMYzEqGG7sxLA2)wjhuAKy-!O4_w^`p8Y_it>7y) z&C7Tat4hk*v=V1~1IHVlz^DmiBsjdm`G3WrkS`dBZ-B)>{=k|*9M(Nu~ z43keI!_@CH_`5c@*urnxyzI)$Orka^r*>}3TWR)4(kochWksLPTPDQL=neb*CJ|;& z{!O8?YyRlmJyOLHPm5tR0{Au}i9x@lm098{_|7j%m;N$Cph z{938ks!Z3zH0JKUh5f1E8Hs&?aF4FI1^oWPjb^18Q`%OxFMR+uidPP5KYvp8K+M~g z*x6ZHz-JaY*AL^U0|o&@fHA;+zyZJ^!2N*3fCm8I13UKCIZ~% zsF8TcF(HCnySO;(aVa$B_(MKfBTqmZ(gJi0HRiF!hYDwFVkGS*zpe#B^n}!Rn5H{I z6=&s=r|OPN?nvUQs?vzlk*IWxG*={|k?s$N*2vH+i@?Ye-AyOAjRM$`eZ~{-yJ1R+! zh>MG0{465HY)Q13Q!I3p$0|p~@uO88nd4GoSl79mJ35=zy1uctT?+fE%B%=Y-v=Dy z<5e%pn4Q(-Vm!L9`X?gGNb-kttzV-NQ>o8LAgw20uxsfeyNZoQF;ZKHG?Lx1JC=!u z`M}a<^9K0y@Ec1@#9kgRoNuCYoKtg9T#|E9Vxo)uO3l@c$m>)(G^+qVln}8QSL81_3wsAZJ?9)KWL8#LErqRMTn22G<+6zjylcge=c((=>MGNjseVzZ zJ;yDzUo+!5betcpoo7etNm*P3bqR0*@SN(~(>z(5FHT4A)UFW1%{6x)5LfwUcMpqx zuCD76zvc()+~RojM%`tRI{-86m6?zQV9<0^Cq!Ra^&=t9^LFQMG0g8c-|9q?DHU)J zz$ZaI?+wszNifnp_027=_D!CK*7k3@I_YglZp5^Z1jDR{cWNOw?SKFan99^-EjHB#DSZ?UdV2ThTEt;8OqJEt%x$h69kY>W3bwQEV`Vgh7X`Q^OuxwxA-WA- z9(X1y1+5r%PzI;f_s=yz{w}7ViuDO@6+KzMBffn0%~Kyk>wO6=^t!}`sbqJ0Af|#L{Ps1dgN6aMzZp99ZQxQuR@FH>@7g`aFGM3d*mD@-)sKcWF5?Vk8Xocz4P{SGiq)2!94U zKHR&5ZsGVI;9b7xE)suIb3Got<<2lQ>;?ZTh@`THMlno&AEkq(_Cy*eduDFimMDNv0u&$immRW{M1crggH=21ON9MV}2E3z{eR zRAIh}vZ7blC5ddb-iXOrPs!41B*7^&MbGoQZM8+Q93Y-*iX17Q8EG>j+*a+}+P*nq zjoKs_;gNV}{VpnkSoxDj=}rn%?I3NU0x1o|OCJ6bl!==P`J?p}_k1WhvPgfE|Dfxm ze@M!IJxRJ#6Z4ro(&vDe0RNOQVj0x?D!#fx{<68ln>MUY&B8rn^B}WwZbPs6U(oeo z!;b!2l8$16POQe+pj11k6_^QCH4U?GrkmiMmta`*aBP3j!{BWIFI5lgJps@3bjGS& z45zBNs5dPFOaRQPoNhk9(bgWTB)D^-u8RLf-BoeVLh1mhpGkB6tNr3(gIO|!-X*_! zeGxfSxtogSp&@8KK<%dKbzp~+OzzzDn;i8{)k`W1>aLlBS7+slIqdGrOPC{#IjuB@ zN4sox>?HNc>y@9ch+bViqI0a>rwy)fi}l>54MnDnO^Q4ln-6Cbcfl~oo$9Hy~-oqe;35NwiHR+XSMM&Tiz?E zKyVWkL!(4Oi)_zInD>J-&J$Y;L`C%a)*7+wWyvv8@vI_WnW3@}rLW4m$j$ulJ zg&nqULeoSVz0E7PZIr+JAKO+r`ZSnH-f(chAJ9mHay0HuR4zynaf zrvjjk0!{<20@UTy1E=KCFv}H!)T!Nk4GL;6sYX$aC|hmebPuV)MtKN%Cpi|=ePaPt J$-bUT{{ea=P3r&v delta 3479 zcmZ`+3s98T73MCx%ff<19`cCDTUmpGpkhdhvP1$%#0NfD46ofET-^tr{ZSzgw6$%F zjj3GCB&DWcr`4pkYS&~kvFS`xXBur|HMObpC$)JrX-GS%Nt!gR)28RUKVqNj%*VOs zb?x#z(fSn5PGZcTs!Xw2w!11B ze|%e(Jmz{#_+{C%aBseb97F{hl#*Cq~t=eEDFE|j<^Ln(rh)(`cUxYTW$mKM*9Fy6Lb8a1nwF{t5 zd;}D3p9^FzXb<2tU;}44!$MEWdlw&@se+zTR<<`L#M7qU3AwTAb~{c@2j$~cGqaH& zQYKGGneao7=Yg_3OBrls;#hqr2>X6l8YUVd)b+oDT;yliEr zDwu>`3I{uT26ZjsvKW^6<7KZV<_(8@kqJm9RzdQN+*9A`xWXiF|E_$!K2y9W|61P^`Zc7l0Dc8fhkFUsMF1{> zeh;{LO!SN=UiSwzpBB)&>1~Kr;%uOP2>2rdzoR>KE#xEQ(}*4N_tO=5>aK;(-$7#z zpk7|Pt4v&xc@58|>tHBf>LTEQ^?7RKoM$q{!fiK=2}hh&IINB=M*{zgrSr0&aeX$f z$R86UVrVAJeg>!koRcGs4I);)+W2j!I@%bxZXc$X;}O|a)9NA&(!91cVbn|E`!KSc2`|2`B@fv$M7_lubJ*h!PST2iN-hV(NALu{uQIo^^g;^osV zSM!o#tAbNuPDN-&H(f|kIZGr)UtSd_(ous$mKrw+HX5?l@CDLI`TpvveDi9shbow9 zEWgpp{{VLauUNEgO}n*D&6Ff~imh>Pqb%&N{PB|Au|TC1(gw<4X&{z)_*s=nGiA!Z zte>~^9p-TE{=|Qv>!S~t@?VN$cc=^c5bzP;8NiD{m_DG_mU zV?ZHBp4`wg{0Yb|=>G2!{3(lE1q4I09+E(*(oqvK751%wsf(aju{_FPIP|bNS!geK zs-=?ju-+Z$G<$bAV%A7DysFYbwNMG*yMQ!66N8bmF677e>T>nfYQAn$H9!e)po(b> z7OIX;gBk~*j?C}E#GAE3*JEO)n;mKh-NUbGZ-iSlzb$_z3WsLErJ7{IG*Uy%DLdNE z&roMqWvFgOh3^#dVpYa1RyI3>Hcn(G4#7|VJV&|1;YcQ{?Ds6lKF4hJvi9&R8PUtj zZ|w2B`trHpxn*tvyKu!CcAuteUfui_wwqrltz2fa5M3@H6isbU7n{@|K#5TyV#c>K zXW7&MZ8xXfOH3P%$!B6Mr9)TEaUDty%H%))>Kx1G<(^HSh>*PZo_xl`_k5OHgy1Yx z0BIq^N{*-)uDsxk$}=6gq6iHaeZM15EPR%^o&=uLI*-YKzeg2;VbwwdK^_WW!my(h z*k54Eu#iTVq`PY)|Bq#~YyR*z!Hn~UgZ=)1M%_>@2b6+ut6f{y*hs6vXalqZ`T&~& z`vG{P=>>oaP#yR!UK(~DWVl}SDq#4M8iuOkTCwDsojqBLYHA>}gxnA}-DI^nKo!eS H_YeLF>2+^t diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/posixpath.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/posixpath.cpython-37.pyc index 5d3a675da109099a88e76c7239c59224d060ea46..af1dfe84f4dd7f7832160c9e418bb3cb5d5e05e8 100644 GIT binary patch delta 60 zcmX>bcs-EYiIoL`U{T$CK@6XRcy Onimw{xOpb4i82614HNeO delta 50 zcmcZ}cs7vRiIVc7+C-*J zxHDV(<5Cs&VL?Q=zEs^6K^FR0W_>6k_#}d`Eczf^e?alYeW)lRBFK8qotn( z=iYO^bG~!V+~FHPZFryZ`RZ%n_twhJj`vm9=uB;emX>veZr9L8*#B$t>D26*d2KdF z^TpDNGOOjw73DI`Uwv-&`HHeUb@2?l=X&TxTj4So56F3^^LHvgL|nYvd9P%NaEJYR96aI0=-Kb?ZG{N z)=Uzp^Lkbs$n`YD9yLch(4D&>@}gd(mypI%MK%%oE+H&jRH;x%E}K_#nwHJdE;JQ2 zbEzem0(6x>B*}(agCGUMT8qJG>#kp@Kml~lLd34M)mu#st*w;| z3fmXZb{YV>17#BFT*N(`6_cdS%%+(;VL)jX_bu9tz4k@Nlf$@s9^op0?4<{ZU<6*T zRn(HMmX;Nb4zSld(`Npl<%iCBTWS}&t`PqrItki)FC6w@dx2X>2iHg87ON|ZM!sqi zan~`VG{2@R+I}sg4dTF(H%mu94Tw#%`fx|A$+af8mDNahcanZFrEXJIbx7zU#G&H| z$RR%g-mk@?klBZ^Q5(mPu?M6XIo2KVFwBgID|iOj=e=E_p(>H+onZ4<*&=;oRyJ1X z`_|u&9vOr*fJl6*-!>1%X8#}=5to>B@DkFqV9x87a;vJcqQG=bB8Rmu-^dR^!Dj<8 zpBRQ`kpABhm~qm=0)6q2i;);SMtV$nH)N=|5Fs>H$IF~7ndRawX6xB|ar;c}#4nS` zQBI=Dq9pq-8=Fk{tOYT$iE%=j*zKVn`3M5;7HXHpG>dla>xnYouq_7`9o{;Ik+`dn z({o3S1N&q6rVmXh!@?XfFzlm||Fh7O)3PXT7>ObX;!=0w%7x%YkPt@L@5v%*V{@Y) zTP`lqFu&1%qT(d&Z0l62OWcAf^e7@=->GnsMk!_>bBKs4qQ4cG-0LZ)=ZOHZw<}?2}BG z#M$?mRx--|%=B)GTLv#zik~Yp>vwR~hVTl)y9m7iTv|}eIi1($%S#niS)~a)5lP?0 hl@Py+t5pOcMAYd3P&W5umdb_esxr}C!)}j{{{sgq!jS*~ delta 2087 zcmah~O>7%Q6wcUQC$Vvo`X_dhCUG3&WNVWjJ5tjm4gy*!m0F2VN=lU0+S-%E(%Nfg zx3ozc#3hFaPRykRluMGXYe#yTXkHWc3SjR3+I7Ik;|JJk4%*)NclHNEvdMuw# z)n$eoJIW*X?bdA)=fyxWo`54u(u`HgTnr%XH|pB9wr2y>ds&LHnMr-wX9I%ZACptW$$C^qF1kKPH}!UOfxayLka$6jnx$6 znbISXb&}xMBLmK>GJl9n5PvTwS>Wxl5t8Mzu`aTopNfqEdn-2A@kA|o{!{E;e*rxX zAj|?-eqCb*tymJ&R?}IA-|OrK_xXIP7nzn{rS%nKmCd7vLy*tKe;g4EAEOOswU$a{ zRnhfQi6xOLTH#Zxx*=TU7M9@O^bEF_Rox}CnK0u*CRDP!P!fsA&A^8woE7s+U0;Ne zD>7%NVf9Eh6>X;VN_kar&6By&-9@s(;SKa!0I<9|HS7#uMH>#0t<)+K%sB&^_j^`6 z;c=uKM>q)}2cg|>^>stL-|w5YJ4Fiox4yG3&r|)clP5hT@Vu2wwq$J?QC}Ln< zENKz%mjqH@%6%@8U*x+`!kq)@P!d%RqY7R-$-1w7GTTOG?V>hh=(9*rbZB>um{7om zS;3m78>O;Vt3g$-{ig{x6MGXjPklJ%&D;qxu$P)>y6ATRk^+H*5YR9PsW}J2td0~3 ziSbWHpSQ2ykr&??P1s{8;xBqxO?CS6+}M>idon7Dq3ksoAB=B?kij@sv)7mS)&DZy z$uG!B)EGcWA&95liz^?3A3;LM^N0CW(!*B@Hyv+Q7>^=mexl)pSMBP-sebX;O`&-e z0q>cKuUI@z8UFXd+YbMT;Baeli$r^`okO>wtDjCC2ai9d(oxG} zq=Xu>{xv diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/queue.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/queue.cpython-37.pyc index 08701f58b254090696800a34fb572460b3cc93f6..290718949be439a899f5a05135f93ac41ad07640 100644 GIT binary patch delta 60 zcmcZ~`7)B*iIoL`U{T$CK@6XRcy Onimw{xVf7tL<;~-oD?ho delta 50 zcmaDEc|VfdiIoL`U{T$CK@6XRcy snimw{xH*}5w;+EMOG#o<@h!&uA{U_UsL8sbjf}CA*NgT5NgJ^^02)mk^Z)<= delta 82 zcmZ3YJ4=__iIi$Nd{E;{dTFqnYatu3u@57t;zkaT%}p@;rZW#uB^yeMk&xuk?PdN+J!w8HpTq(7tlVC z{Sl+H3r3UVD?*E~L5LFKgaN{~cs#ofS|?e?6PbAT{wJKv424a_Pj&wzC9@{p%iM&v z_?h_w(8m3X9_->+HqrN47L$u?1MRFa^M<;rgtrobx?J=tte4L80HzVv2uBG|2z`X- zgnmK|53}*Hmr@3b%h_@AHt7^8SZ=i{f8B9wyihDzEKId3AwpQjL@paalFtaQ30t_5 h8`Rn)cd?aQiJB2+mmTigtWfj|w_J9IH8DNk`VY=luMz+N delta 581 zcmXAl&rcIU6vz9PWh<<;go0oiJ($XF50wfSBe+qascbzMO-M{_EDdaFrR}b>OH33G z>XqAz786scnySPfn7Lp$c+is}1`{P_O+0w>>_6Z5E6lvQf* z5Z_LGf>m5L265%ouU@Bp=rHZI1AN)|Aw!GLOnwCACHd>vj70EQ$~fAfm@5rplh-%e37}+ Y=l3vcq3n7V%NM+S(PoRRAzt422Oh+zEC2ui diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/re.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/re.cpython-37.pyc index 99f64bf0fe25fbf9822519a8f6939108b0a631b3..1bb05bd0455879583672bd4532c14bbb6453ed76 100644 GIT binary patch delta 507 zcmYL`OD_Xa6vul@Mro^FJ4K=kZI$sTQY79Btw$dOW0J|ZE-llUI@2~p*s&v$yB43J zX6u8xu z)tPEjtHKIEcQ@4S3N!QBCC3+j4-nV+jLs1<KmME#0 z>){^$IC}lp+2kQP+qEh>u_lP2H-O0U3wea(_=~(s(xUF>-*OMhJAtt@iR_?b7m-2? zAQlAN7K2@usAWQiUyUCo_OLOG_)nzKM{Gr^6hXI{E9taavP|W5!cW56q8anSK1L1@ zUUWAx^BDH{(BxoLK{1Y^1kA1()ju!VU>apocF7s2{9^KOg%&e6mf+5_F+j>$nY1Og}+vQKm{&v@|X>|s+m`l?X{+8?~3jav1AIxJUh*(5~ w5FH2^v4)5WxUB}%G^*1ggK-pb@sJZxTEy2~0Xu~}-lR&2o*PWebu)GQ3ls5zK>z>% delta 489 zcmYL_OD_Xa6vumzQLTC=9?_7n&{9UV#3Lc-LhDs;Mw3Z%U0TLWbEfr(h=o{6B-cv9 z-csf}_yiU*dn<|9+qfrPxQk!z`9G4Ab8Gw_`)30IpGUs;`Kwp|XGh!k+(c&6=4fYT z7{^S)Ix`I`yKg&9!H-(doUhO%z^K#Pm#cs==RWcTN=nvoLBs|ZU`bpLK9q$;(XOVO z=A;*{#4tr_2`l1K9e}iWQ4^39-)b+cIxRyf=vgOsgD^(uB1}oR)doM$Gt0!3xQXsX zw#euw{5O)616xxHIn3JJRkEy@w@laZ4f`RuEZwjdx2dy3sGxWyH}`Q%L}T5dT@w39 zRFK;xqgc*T3`aVl8gWf@#97d-;%4atd#FSgacd4r zCM#N&VQbs{lr?u^T^>J=Td$) diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/reprlib.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/reprlib.cpython-37.pyc index 2684335cc832b16bc864dcef1cff29fc59902941..89118687f5275b3fa6a443cdb185563a4467b263 100644 GIT binary patch delta 607 zcmeyW`CpUUiILFC^;juEH$P$Ilmw^xF|W)C&s@Z zH7_W@ar0TG-7Ji^Hg~cgXJn6J$w^HsiJBbFsl#YHxrK8Qn+wpeBBjZCJSvkNxDp{; zWiaXs#vO3i)%I6i|j#$=z<7V5CJw*6~uA?5yn75le>r;#MT25W+1{5MA(7| zutsMPiw8(Vv1g}N7Nr&xMX{G9=71PQP7IqB_)QsQK-S!1&P}Y)WJ5R2X>y^!Ww#KJ zA)!D5>_ko0qA-vE6NmsiQ47Qh2NGBe07*rFh{(zIJd%?a3w{zpGmf(;Z1Qp;O>MAI z+Qb?4TgZ#ia_8z+o+42ob&EYdJ~1aJJ|5`I1`!=b|H*4bJOHiI Bfu{ff delta 474 zcmeyb`BjtKiIIThELYT4kWG%B3MBLSeYt_We*~ZfrKV^5jTjf z2O`WsgcFFc0TE!0E|Yorr5T+!Yx0{hGTKc}5RhVYo?I<(*)0^LBn(JYG3)8+X|fiD zg9MmB1lU?F5Gw*mXtJSO;S7?B1QAi2rwDR03Za?BSrk5bqmZUH*c@%5%$dw8?8Rs? zIY3xN4;(h0AYDEn!WTpYf`}jx5eyLFC^;juEH$P$Ilmw^xF|W)C&s@Z OH7_W@aq~B3C20UNnG^p2 delta 49 zcmZ2vH^YwGiIIaB#MY2`x@7DvohXPA!UY$uG~#$xlov-n@aO N-i9%1vw@>5BLEw`6374m diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/shlex.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/shlex.cpython-37.pyc index d32ac6ef1e577796e7f5478009b9e516dbc7e300..63aff159c75c79b9e6bc47b03ffe68cd21b3e091 100644 GIT binary patch delta 184 zcmca>_S}ryiIoL`U{T$CK@6XRcy znimw{xOo-pd|t*|o4tg0vTz3hwH5_~h|tY^5_1?CqbIMHoWyu*vYnKvLLyN77Ds%1 zZenI$e0&iPkgLh$7NRL$6baJdGkLO9uvQ$1$p#`o%8SB)#4YBW)Vy0PiACvUx0urM TiUL7mjA@evB}68xNLvB`0^&51 delta 169 zcmaEEcGryCiI^nJ zW7Osl;hii3fj|vKK_DUoL}*WD>pe&g9H& zTh|yQ8WTU5fcJ|ZNE9^$BZ6hBR!tP5CdLmYhD6(|n5+bi(HJUHBYwbh?ofQ}hhNT~ z^FL?qz31Hf(h_@pi3Qt2q4HJuJ2*8v8|(>$JKJ~0Ta#8?h17&TrNyn3VQK@A8tjhu znOgqg{#M5f{J4_|KGe3jP58(2YEBd0f}R%s0@)EJ0=5czK4V0Da1=|U2#kU${Kj-% z132bn+QV%7ag4wl6jrjv__zk53eyrPBWHqUS-O#jQxvUO@g%evTksEeZD@Rx{9aT; z16tRJ$HNws~Lmkg}aG~cqx7_TY5VC|h!X!cjV!F9o&uW54y4u>`A^*FC z_XzJ3J|KL85EVt;Ok_|@TZE6u-N@$o zaCH4+cnU>aa&tzc|p=^%?zNBpfEpA|llwH-8V>q6`ef zPT-FIe-_vKB~L{-;k_@j;8#?mn=r>qTWi?@FAeSq337ach%oq;{LVvs)v080Lw`@H>POV=FU;Em}kB+j-PI%~ur|~i+Q1OW0 zUCRA56!>i+U$W8HWY}tv&TiFKL=W^XjU=!%<;Z`d1 zDMIl1ktVjx&yTbONd@vy=lCt7Id+vlKl=L)npAiY5i8rPLI;2WGF@&A)Re7ev+x|o zaaf-w?O%jbd_K{+jxlViubF1U*X)kOX^NiZYsU^L?xFFMV|9w0+)MoPv3orp<^vy&VIQN?1)Ln$aZ!T7F6gd+K5Ff+cTG&fk!vDJ1KQ9?Sm1wJ+t2+kSAuJQF5@?3p&dVm>M7|tCl+$~awhJcCGd0WYQWaUURSH=Fd8ewGGcw)A{sxhx B)V2Ts delta 1516 zcmZ8hU2GIp6yCePwcGNOhC-!~7B#w1ii7|WLn2#SwoNITwxZM0Wx6}NUAnuoIWyZf zn-DbmVtkR@2ct2_Pi#c7rH&{{G=xM9RW#8?;`)G^HZ`#{7JX2G#Pi*?qRzvYGv|Eg zoO{oAW=<`L*A_%DTv=J};%6#yXd<{Luxe-1j^1v|Aggy*%%I*!&Eag?)Z>;@2+Zyf zn(PmMyH)cgvwFrTdh)4w(U*rE5?a94DV0r_Auqko1&h8UnfYAN#}y2sQ76~5P8>eP z5qbk*f7(nY4bql!S~O;6a%5Om%FNO@N41JYPt+K(wF;eL1F0b+s@et@-{L8vH&M&O zHK>lQzk90=qPjAnGXy!kP4-sx|C&dqn3-Mwke8N}0o3BVwj0WFnlNu>=< zZi$4O9QfY_ya#w6a1QVhgH};U<)R5D<7o5&T<$`GHo*w+0du-NpviNQXDUBI&W8*k zH=UI&t!rz~!gGwFuq?@C?laib?rY#}UR%&)tr1ukQ7i&MwoP8-kZmrKE;D(HV|h!22ZNRlpcS zXc?)yKg70HMy6>;G4cP6;vYrTP&B8Z>zD|BiW=>J3Hf+=mAEW_?ry96435tkLV~Wq z?{q)WAU0luTgC2$^#$Ndu@P94G_N^5Y^2)wGG3_)wdE8w;4L@px ze5ID(!%uO7T8KAT|#aTG1K#VDDBj<0N`_iPcKk@{|>2RiFml z1Iot?n!LDwy_k{L_iqk@MQV-{GSrt5bMmFW-?n3Y=@C%Nx^!wLGD)RtxC`kqTTiFy zd5-h0J`3(ofN^;-y1V8&n+0zpi^#~m`EXbmx+K>fI8uLSPA{`_F}*Zpuzr+N2Of6M zyPV~EwMTp-ABZg4YxSNpHK}lc&;WV4fvZA{$;iQ$ z3j75$Uo_7@8_jv;V4Jr_3pDL*@7~kVNkYZiTRWONLrcgdZ)aC>)(W%VU(O*4I)}^| zk6&%s4|2ddTw5|Zi&v`(lsdN6cTbn4$KJM0sqW)Q(ZlC02I59S&19B&#Q;pp$k7nq z%5rJlPMDOT3(~Y#*S>>NQHD^kRJ#WbwKYrSsJ&BE$!U93xaAA^?VI01gLFC^;juEH$P$Ilmw^xF|W)C&s@Z zH7_W@aq|~OZYIWClUS@6g*RKXFflTUO}1kVViNI2n$i0|X$<^5^#xbclCb1|vBeN_urZ_pjAT_usIn*b{ QzaTX)D8O;^G2ZJ&08^?J761SM delta 52 zcmZ49$T+u=k=u!vmx}=i9(dGlE diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/socket.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/socket.cpython-37.pyc index 65105816c20a0d752fd78ac2ab2ec402aad7e153..25874589d39da82476150e08e2aa6e1f716339cf 100644 GIT binary patch delta 2529 zcmaJ@UraDS_7?bInI$KZx)N~E2J=+W1R;L*=jzF_a(Gn$ zf`AQx0HBc_D-Q7(my3V2Bbn#dv=Be60&dG0n@ZUp?f1L=R#LgXfh#S?Xw1sglkzzA z!A3w4q^)L6=?QWGp>_=g+>z|4B+E+5ptwcrurnDHapPi}o2URXw&V-^-g-ZdCeeJYBFx3D_cB{6Eq{J%})XkCYZP1EPqP(?y zX?av#)pSGBWW{o-nn63Eb&V$Jgk(G@%>(8i^?y12lZc1w&?6ikWW0~94Nm*2U zCfE}GGN9)5;J8~TI44RuJ3LI2c{3!DCY#0jR7#*qj5=#B^2I{ zafPaeG?Gw6hupjFK@5+Sv-dW+59CvV zFSG3SM#)Xvs3o1@lI2cOKFp{wz0$l^rY21&^kfz+XIZd)y;qb-41h`&ZXY0(>|*=h zc8vA_eZ8HoCahA`;yxo@v3X z-TVt7HO$f390Kiymz6o9YO#nbq3Q;2r%llJ!Y^A+Y8o0{Wy788e1e~z^x$m1b1PXe zzwO-SBo^~@?d0P&+_l9kD$|WPVR3G~`AOGvj=FcCi2>f?5Xqs6e3)~@NYXfz4*{B4 zsHc=Pn0-BW$(Bo8W93KXxFU}~yG$hbQe(vd(z_f2PMZ-sp?HsX)eYan5JjV3gu!yN z9o%lFZM~howYl$l+lm+Z#d7P4G7btqu*0q}|BhFDNLF0z-{cLlpLc{;gO&VyBSH(x zBNuRcp6%`LcVAe}fveb;{dfJsa1asS1mNlI*kGTyh?oZK*T)0<(`XK}Ie?)0`;a~a zd<3`*xB@^1^m)KMAPf*kyZ}jz4gf!=osA8&x$xPL32SXwZJGnuNK?ein>?P>4G=q$ zx3n0U7M~lG(Q@%&%DaHi!g=%T6F)g!Hrv?bV8zU%ID`St0YupaxAG&|h@j}YAVefz zPfk%;i7qS8!~9ji1P9B>EiH#M$}7abea19zyGH19WJ%-1<*8W?U83D^cnx4*jC~i% zG1u%?og<=oK81@*O7VX@VzdNic>po)a_P#E_w`iPXhIs(BW~n|#-Z2XWdc3}d=B^m zB@W_*TaJtj9WgUjWs)+IPjZQytRfV9{F#aUrH;aZZ{R0RQOg{hs delta 2390 zcmaKtU2IfE6vvs}vfb_Wi*467?UwDfrR}n1+tOB>0)=h)Dg-dnMqLY++ud7OyS;ar zdn*>A1rnr$uOjLY|`J( zoH=La+&Ld}{xUgpnRt5&3i1~4zh5@Kbk%z?uY6T+*WiGzP<=3#Q0U-VZJ(Of}(weS>9kkIrRWeFQ4g05bZ$%X>76VN{7+4BK*inBI zx4-89o-~>#AL}6@XoTICGdY&Awc8&y`J-$xHz_KwBCE`0<%h^lm~8D2yW_c%oJc4c zgTmwNWB4?_Xt!b{m0@`-Z5XLhMH@5dYA(0Dx?&8awZuqD-5t)MjWAtyc zR~&cbw{pqvgkvkMWtRd^kr4YUkmPQE48 zP(Sv|-6QL=VNlDXD`_QRXjG>=S!rl#k>#=_bO)5{*_O~^x5S6xBHGCGP^b!DXgL*1 z;|quN)PBYC2#+zOBj(l6dQyf6&bU8{ZB#&Gx4b39Fl%aekutHRm+r#CtXouK=juX{ zG#6UVw4&18d=$>J?;&d=80`fp`?ao`=%#DQIa1sP3BJyb=MwgDy+62u&n?%mMn`4i zQ7-K=AJji^h76d(b$Wo~QOY}5ZDibM=N)vT&?WqCK8n2T789Outi9=o4@qbz=)oBs zTtL*k+ax0!V^Mz@BFwEtUiqM30vu+e(NoLHF+2o_BrV`09Ay7IWD#bK&Er`XBBKlc z&tfV2x_Jvpus}<|E%F@Su%=}{7kxe>!k64_Ipj;gi6g+QCcfkdd!@CfOe{{$E^-@; zkBVSVvOim8Z!H8in6$ikB7pg99a_1Pl++TEWO*b>PiuzG>$(9d%YYW33s?!P0@eb9 z01|`>4@C43I6J3A_D*104+MdOKy(53kD|X=?hMs33N^;(%G1hG= zPc?Xfj%5rbxsFne+BYV$GcWr{#=2ILDf8Q|UMGpO((X;Xi%Q)qTq1-qcA>kRG?+KK zpK)|w!coJ(TO4r@RT3}oCd?bh2!u}n%^X&-G}FK&?t-f6VJC0E+hX?#nP#!x(t6m_ zee;ayJA4W~NH+oRvID)heVrJJihdgk$k3xwcW52cky z7R?nFS%20yjYEV}^OC!X{kDFf6j{q(5V7^VGPYCN4RXQPdAE*#lFHS`(v7Gw2PDK#+FsZ+hw6V$lm|ukJ47NK92$zEF z=l%w%0`r@&^sIXkZ+=Qs?S~`}E22l8#zb8m{zuNBX@?3lCQH>jAK%9Okz=TMrK)ROmT94L27VOa;Q&? ze?e+qP=Mp+ZW&Wc##@^YhWarw&YCO`uEIEd^8OgP$-&{?0@Hv-70mz<#vo$S& L`#$26_2SY2dbvt} delta 239 zcmbQgmvQP|Ms6owUM>b8c;HdHkvl_1!r9p>CbT%Us5r(kIkhOpCBHl`CqFTzc=J>l zQ%lCE&8I{C7#U|ymI_y4oHqGGu-xR>aBqRBKm&@Vg9u{~F>&&a@Giy~o1G(8GcwMd z{62CD+gy-%{Nx9=Qj-@)IdRViahF2G6ywCDie>=W!psZ|#URIUFtadmFasfL(TvH8 z(T_BjfmGT9iCb(1iOJciB}IlHk!c`eCXmo%Dv|}UmrcHCEjWD7-56U)D620%C?6Bg)Qq~Qi}81ad+F^v9i*Z-@R={ ze5gy@Kyg!d7C@G%Q#3wlmS!`NOcRNTiHUC}dY|{;tG?)i$vodvP00H2IluG0zw__+ zr+?=E$$N%sYpY%2x0=6y-}AVvGc-IH4aBUdLGeq;ycxCPnXDP6cq9~^$eQWNvw>oz z(pSTrqQCyJ((;N}O7%bp7zZYSaIt^4>1OBo-KIlqhX35uSkQ&;l*blr({k!{IqG&s zk7p95MTYpOHj>=$tgyB6i^(gwEWHd{$>eN`!m5m4GHBk&(m65v?<81Lz_ftFh^oY> zxha>n9JW9jRCmHC#+!SUkO{{o0abC_v7~L04J8LuNO^~lhl=pfoWLFCa#`?kvFBJF zqdERt>kll&Kl1JoeBjM8i|=pi^5DS#gAi#ODPtzzXiu=~{7L&JTPkjL)Ub*r_+MrE&_;y>e+E>DQo!j)KT&x$ct8s;9I6`WJM(;#2tR^y2@6H+P<$@ z>jmN9xKE9bPV6{&8QZP!=etjOuEXpF-r$AqmV+{3uVH=-cngrpe;bypqlmCH_q<_U zrgQwq?gG2TPxcJ4%Y3EhAY0{IJ*M{-ocjU!`bJm-0;(czcU<+eHJ(@3Sb^8|7T8Ad zX78a&c87o0x83?7ycm648t!2zqff;^oBZxeH&~1x@I}PJtG-6I&ewf2>>d7>kAyvU z`0x7L!cnUXObt(r1jFJ*3rF@JmI0o@4k&cm0Ay{Uv>kUUY1#Av#15bUnEa2%Diz!7NAz0B~x^to-)&=#2`g#g=}%rNl8nm zPq4TYE?8f}ft4;H`(>;6%h4Lv0NqhU$;g(Y+x(CIrafC&@$?3~ZD1dJ#D@pIA6>%x;keKZsp(?^0skujM+dV~$pKU&o+Wpdd>GHyHkv|nW!&-o9q zX@1Y&%(nSA{ucy)_jh=|#a^{IBA!WGwvo0it^7=2?9{MGX4l|}mIv7KArJ(r$S@p8lORWG+)-2vAUsS3S`GRd;b}aiZi!^B9 delta 1433 zcmZXU-%lJ>6vw&DmUUs5A6Ca0g(LkWMKt8{nee=tbhlQbNfA4hMvB;T@%vm%&kbccxOeakzSD}UdB9ZGa zd#F`U$^}#g3XoE2jY>OlWIlCyIYZ}RYw6`Iy#UKQ_i~c3>Vg~{>;Y>Wi1Yc-6Jjbi9|~*3COlOV zy5@T1Rt`DvWPu{(KIB-27w4vw#7Cl_z`>jX@wg}zl;YoO_Nx};_%0%kAyQZ>%0;!H z1^%u!BZ%ATno6dm|KOWA5)9_3E?g)~-mW*rD*GC?#r53%2EQn}j(IkJ|KzEohBWnZ z8i7X@@EZFX>+4a0L#KNl!*ZYknBt+vKC#AE8zW*Zx8JxWgv~Qep+%Lr8B?M_C7=V- zz&v09sEuB7XxF@02>oX(^&t=?5kTb~E1S$@EZdadP|+9UznW}uBWE7_M%3UWuIF6r z%qZ0&Q5~=b+~BU}vlFW@TY(kegoGZ*-s|Sn6I)NGsu4N;(U4 zL4Cuc=0$Of$6BJ|72aq$DK>b\q3r+zxpi0p#EnOoelPdPGN-(F_irf5_zA3J7 zsC7l$$!)c^dBunPbNI)akFiG3C;8W1yb9@_e9>pT^US(Pa%X!ybVWK`-|XvID@~?F za*7vIHu+xrjChwt2Z>Ew30~`XRK_xt@J1&3M+XMSX@%eDJl>%MLW9r@a0gKL^`f*~ z&tl5S(iWTz0JbBOf9dQJ_u1c7XRb?!tIeitdJiEb^84@=PbL?atwEwR=|^cBL7a#_ z2X+7-0R3GpNiPw~o9`wiLk2@!c=~|XyQ;gDBG5)JQrfv5GvyfcDQ4uW0_zJ*5c%y? zS3Su6+T|C|!tZMG5~;={6hcl@{|vO-K~8!g?f<3Z=I&!+mq)sPkP4UgRMy-^veNOf zLF3GDWXKp8jK+tQPPEIBo}fr@yhj&PywdYjQ5+e4P(bYQPdz72?_oPF7K_RKWltCA zCta^$nCUsg$d~wAWDhuG8FOjd$tLZrlQ=RG89LW56??k(bkSEx`8B`V8x&W0wKqJe uL{XaEMCdXSXem3Zekp{%2ekvL5mcww diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/sre_constants.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/sre_constants.cpython-37.pyc index 845d772d1f76a52ba513b616628c044e431d37b4..a19ee6111138f60ecefe657d7bed0cf047523c53 100644 GIT binary patch delta 60 zcmZ2vxWLFC^;juEH$P$Ilmw^xF|W)C&s@Z OH7_W@aWf~|Od$X@O%tF1 delta 50 zcmZ2uxX6&(iII8NvD(&O5qpNq8S(%Xgh(SJSGk83>~^1prN6qC1lF*3&RZTcdlZ| z!OY+pfA{R}IcN7gclECql!w2iRCHHXmM@ZjPfow|QpHx2B67P-Jxcp>ImH08yFEL` z+z0fr2#Zd}r?oLXno4Uy79H`A4W_kZV93p1C|S3(TJn13ziyIHrm$*$z2yChIW^45 z-!zA78|0!(VNLQw+6{2>KFi;&t(a`!ZfoQE6_OMs6I#Y)CSGAqMy5156OV<=DT(uh zAG027BE=pP`4HZjA65TCCHmrw*~GHc#Z$ zvLXL6aMu880nHLbS(-^dvCIskZCzMs2axKGpbE|*%89u;K4x<&b<%lGe%^Mqi9EF# zD_iD^5O;I#f$~O^vV}iw-@UOzGPo)Xe_0aRw3ZO2WFl0iYoE`|q%~cbQfXm|OtYoX zWam|tt&YMGNZ&55R$i>dP74L;Z?o;HZEl@f06zYy!n+_I$`OzoYL?Zbb|zYk3iaImcqCJmpGl(6-?_XX4; z)jiDC@l;jMAQ^}BWNxgN21h&|H5hc+j7XUhDPfw7GZh@Y06W-}gF;CNWwO`{SX{?V z)sOC7AmP|9EZ+z40|o#?fB+x}fQf7!py1m=>UHpUt6P)~O1=7J?^+Qi*2R^YRZ2f^ zt7)vGT%4FMZlochhqTGiRP#H@x76${0ijfkeQgMJ}JSQWp z=x9#<-P#i^By|wH`KnDoL%{$i4=%rd&7EAroSBU4#cYsj+<~A}cAtQ_?6)MkYY$~3NWTdSO+hqX7C;fHZ z(Y40zj9f(31dR)o8>=7w|Cw*q?`jV%`3Qat@oZDL@8HZGioC`z9gKi<%y#B$FybeSsP zW;OzF@DG|+DOKFwtlbOsqTJ&iR=tA(pBiL4!GZmRtxw(8?KS zeo+!nX4p7?v3Y0f1}s=LJsOdHnJWCh;HklGmM$09}4oxocK=U{-mMZR1xv4=TgC?b}0&@)gcMne&k~ z)LALgWHXsb;XwpN`DmX^$Ka6LqcV71R0fAskI(H7d-~jgpy7)n{QQoULsTT^B@bn| zums!#UX@%TDh39J!}+{6`uWq)WjAh{ysEtrrQD&KdxV?rS!3Og$q?UoPfHfnDeQ4Q z9@CPU_;_4n43Dil^NSuqlz5jRV08zBYG7ED8{e=z2_+s|1=&jgH~1{Qez!L$>_)W1 zDyxP*7vLzMT|&t2 z9u9Y_Uf;lgZ@?R}%8@$I!%}j|wXu*T>=_7r6#|y=IMXxiInWOM(1CO$BddZBbX8@a zm2<)zPH4%HIhHBX<#^CAoPA%xBwt@X;Ch`bIhb%%KhlxttQ*IF;^*p*L&)D zb$7EB-Rd@dkgbgATL= z)1=kOd;I=3G&qJ{CX@*Vwd{Kmj@qW;x-P4*xr=>Yj`@q*m-E;CT}v;3;{@QOgkCnn z>-(Q^6qM#Qzt->0lCvoIbhvW5XN)&LwLv=fG*tacf+)LBn=xL3pTiv8dgnkHT$W6Ds{3md~4=A|N$v+zSrgDp47<_r;2`o(j==fwDPUI>RW%6Q7CvfeO-G7#| zA&Z>4{p*jkQn*M-amc?hv|0I>zcu8_z6{krl^|^6EOk_qzhE*(D<_AX!7{nw$Dn== z_yu4;;Fo|a0Nkm@jq(#oiL(5o>C=)E2nvLz^VL>?+CcE zl<~iZj-_)sJ*@T*`Q>HJ{s28x@^6FsBj6qI+SDUaEsZX3R14J--H|cyoCn|zG_Lu} epe_MW(Tu9 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 Onimw{xOp1$EN%cGyc3)N delta 50 zcmdlbw?U5EiI9@h!+JSiO> zx*yxS#-ib5WZg_^pl=u@nl$x%fi8g_pH9vdXl`*nQhsfJQAHB$zVjt%XC4>rY!`a& zQB^&wnWj#&Sycs}$Vn&!ddke@B&45p27E$t=>8$%SG5;OsQkIMpO8WJwf-u*Rkue5 z*t=7g*!Mb5unYAO#0^BNfKmlR7>~%9JGQk#!N_GG#QMDSW>{poQ;lwDMs7wcNCmf< z#dYY%_iemdgN(^-TRSFG$jeS#`e!F^bU$ch44D9XysL*RE=DU zK2Y3pkG!U!fl0Yttd8bVFv`6Cptwsz{^q{FOJkFyK*9@DFM?_0b83nftPN1{=pK9I zj|=G+|5NEoY?kgGyV`HwtXRbY$4R_>tE{ah-nb&NiVd(MuPJHSB83fkIn(T*<%1&E zTn)4Uyhby1!>HWB-&Bytx`xzHc5wEgz2aUb*4RMn9SihKBEGP5)DeKYes{v_@ls;l!H z65prs%{}k7D;OV+rBfyaGd-B4kRCDCi@Kra%*rd*(<;K*Qq40GVF3>n-1HnLU6qHP z8bZ3+gRoz?UV48B`$cUhiB>+>ULd5GeQW4p$@(qQ!`>Y^-N&5;Fv=zFFfD*~(HMph z1Bg}ur3&I`4@;Z7SJhHUD;6NiVm?ax*&|=5qZ?xmUadmGU#T<;WP_S!a5u4Q7Ju-QX>N#i;E~Os+ zu8m!82`u=4X3Jn|MlqA4C2I-pVCXj64yMQ=`x4xhvc!7n#(}Jz(6X%+3miD{?$WF? zoNBr$yoy71CfWT@ADZ+^L#bO|y^gw=5`O-DQyzV2_X9b=lfw z36;fLw@8`2Z;f0v#9!Q9pq6S`pw!q;T>2#m!_K@0ro}}&apx<-v*6au3?{&3Sun@0 zw8bv{xp+V=kV4=<0UJRYQ9$GoDk3L#9QVx$6K_S;b#W_Y_Ps3@lqcfN8oEximYA&x LVN950Gsoyp)1~>2 diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/stringprep.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/stringprep.cpython-37.pyc index cc77b7442edeed7daa3a37e98d19e8d6929c9e0d..88b367119f6f9c29f1da8d58bc7dd56821f696c5 100644 GIT binary patch delta 20 acmX@NX-ih KaGWf`=n4QyCM0_R delta 107 zcmaFPbeD0X%iILjWWgq7|cQmWEtE;Q? zuZ{8lZqA$c#R3?s#$~^AC?>>=wJ1|Rc!W4tG|*# zo-%$`RbnqV3a?|BWTD$U7HW=JhX0#ngiZL19BIXQ|5bGha&G@=pC)yL^ zRz>TkL+o$0e)r8_^eLku5Fq4bHj!OShS(dM8**R5N-ql#tK>i)LPCV`-e7<{%|?Rr z-AABKFWA|TXS^HSLfn&3W&=jpicn$hD?;S+yJP!H>9KQqjwgB#oDcxFEJkA}p;b3KBkRBHsoo(!Hu#$U6;9&2e zYD(cbYiVM;q6O5X;-fS{>Fd&{P^u-G9KLFQgSUoG3Z2Jlo@tM9wz1Ogdt9g}fu6`) z40&?tbI|1iutNI&gv9O9M39vGTZ%2XssQpMqgo_EwgejU@ngB zaiv#ehg#NcT)m2BgzQNox-w*Nm~Yy@XshO4R+<1-RRg=XRd$ z)pdoY)P!bU(n-Xy>M2SOv$x|b7E0zVM3~)xDgY6;Lnk1;2r$_Ej=X*lggXVFRhrP~ zJ~3*_S|@HKr3B2XO^fTzUFAkt6Y z1bi3pJ;1vH?xt@+{663u;0FLy+JDIx`=F!07)x+#N{!u`w=>3oc8U;(QJz%9ANyKo z4S7;t+XZ&LGw%2Z!6yxkx-3iNai$|LClJmNYL{em3r$m&o{A;9Qekm)K~T=Vk;<>j zzF`pMkT#gq29xO{0FZ~fR6QJti~ji;`RJrDh_cLqlWcfXkp99FOFl;~8;iT@$?dXQ z`=OSno3SnwtO>6T`n(&%z6PH^WY*F?<7l^=6gtFScuqi}9jdP1Btix|+q0D98<%@> zEc4{$+LEG_X&Itk1b`|gA^ytd?VRuVpJ^&{c-rXOx!*?q&ZhTko^*V$183*1R$bAe ziI^g4@gGoFV=5K>;7xX{-(MgZ(;(DpKuo+Mwm+?cKF*v2jUjaMotBDuo-%WLR-Dbg ztv99URI*rJ)MnvjcCgxuB1#YrLfM0As139dvTz75%OpfREGq<@(jd{P#Wo_ zk_(5}%0Zvw=dkZ%eS>rJUx$}V6qC4R(Eu-D$R-AhH~$9$|3Cc2N^b++VI{kcJLDd( zvU9t7+;Ra~{b!7t-A@y8mHqLnTghF<#yvJm=`+}fGZO9WQpMKfw7YO#?3Z3*9eclU zBi4z%zg;HDv;ubNxl%~tu>}2^GVzjxTjP;7-85chcze!0^aANeA8&i|3H(m1_ROSi z1edK6%hP)ha5X?)zO&I^Tjlj{FvD1&ms|QGq?>(|%JTn2%;&b0+M#f}9#@p4$9YS8 z<@VT}N?hEFnG*PCP^BZHYO2}x= zu#`N@J~(jqLhhC|6mASwhkQKK9EjSg8ZK|FUyf_4{q)!W^K7g!$Jol6XjslJe@MQm6)x(qzz$@RBscK2lX}VRVNAOOG zE76qTUGY3&<92kPUT)p4^m2#Nt!OD-JfH1d+ID(GR^(-)?4X_8Cd>F)gbX0}*oN?z z)p+CkqBJ;{tY<;k}w}mzI%V%H)dJ5Hx zjjxis8biL|CNbn0Lhaikh*HVjjS%WW-cWrVXGg{g7D$H6%36b9=nvw{XkArxO{G~H z>k0eycmexpY;?KY@oQLJ=G==3GchcOBr|~d)C%~RoqVkH9y~=9-xlIj0_Fgg!P^hG n4h#Y3;$DjKrH}O_{ delta 3066 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 delta 1692 zcmYk7e@t6d6vuZ zJ@?$6bHC^DS>|RYzqgj3%`Njj8{;SQz6&0AWis z!na8{W{vq|OxX1_O$ff?{gRyEL#0|wcTWd_te%m;9bfKW4q9j!n_2Q zuti2i?mUdbjAl|ekws%VWBq)+_HpNF41JB?sjV5lf1g2g`VjKa4YV#Iu0+oL$l`J`b=4G7YrxJ)As(_=0<{INQ} z$tL*Mp^4>wIAST+ZwBRG;GqX9lp=5~z{>*kFC1|rLzz@{R;#u6%Woo7#4&(yCA39T zU!wO#@qiStN~I76LQTcB^sK=Ws=?P=+`Wp^F!9$5`g^STRg-c<#{!1C115GKe z89kk(rYUnPP6$#NWzRqiv-sVXvoI5&7JjbvlJhb;n|OVj&)JM-h>y25+Bd=EKln@D zSZ^cE!aZ^CRT9XPlO^mLJHEiyaKkrS z-ov#*SX-tl&gQ*{4{-4vfRd+DakqCQ7YE=|VF zj1E;up~_43_v0KMl diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/tarfile.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/tarfile.cpython-37.pyc index 3740da5ceef5467440196a4ad2e43ccd69c64e0b..a78480326f146fa6053a4af05a7feb6dd59f7f4a 100644 GIT binary patch delta 22 ccmZ4Wn0eJ>W^N~5UM>b8m{zuNBlrA|08}6cn*aa+ delta 22 ccmZ4Wn0eJ>W^N~5UM>b8c;HdHk$e6}08|bKg8%>k diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/tempfile.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/tempfile.cpython-37.pyc index d9fbb72c062dcadc13f2d2b1ccd07852bf237105..501fa3c5344eaa318e9be80752a98c7d6c952a4b 100644 GIT binary patch delta 4045 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 delta 172 zcmX?_wL6R3iII14;syHiK08m3w;ABN*;mw6w?o7!1i#m>Mj4_i16@@3O8TWF;099%-7sXEAZJaF= v57HJ3A`(D^43GfHf!OhrolN@0{D90`oW7wxA)Y>-ey&A9AgPea&rRY0_T()G diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/threading.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/threading.cpython-37.pyc index 4dd217387f504391ef84ffea060c9aa9689c7ff7..653eeeda47c9a0538b9c06f009ec2613a52fe7c6 100644 GIT binary patch delta 905 zcmYMyO-vI(6ae79+HO}0iV@NxXwYCHO4OUiUkV%$f3PAk)+S9UOQ}c;vnwS2Kmmyr zDyL`zN3gC4|Yf`~?eY5^1Vq?aaoGA1TQP4GmBao<#B4`1HSyq))EX1|PRe~xI4 zB^eoM8ujUKiN%aX`VAGOyX=-4+3qB+dQXdFmtDRlsfxI&57{f5B=51K7FMbMbrNi> z%yC5zL+oAcc3nwSU4dLjdJs1qgC1GJ(KTYBihLxr=F9;W-YxpgrwT zn53Wl>u9;ZHG2{VPau4{E|v4%UkDNU+rM9!!hr}bLQi#k6L_x!^l)eUs%dp5sMBa< zts010GEF~r{#Z)bL>Ic;Fv@B! zTPBg*9$CFzhf{IX`A9<{Bxz>IroW4`)E8=loAi6g40os@+*QDLn>rG#9!9bd6N1-6 u;`Cv7b3p>bbR-Yqz0P5T+awvtYq}WDUCFyJ)H`LTq7d?yAMf64_x}Jr&<$Py delta 891 zcmYL{TS!z<6ozL{b2&IpjF^p$COs%=iS$y@g;EPLMIj=@VPH7uahx1xa?eSL@G@R# zQt{F*a*}jH3VKtwc`3+p^43GqTMSV>L=i+6=rN)FZ@Zj_@BC|>wbowito?n$_;JE$ zE4ABG4B~lT);eV?G-no{IP5tW)@ayMQmawV$xur$5K`;HyvF>qh9r5F_o|tU^4E3y zOu2E9N3R3DfDae}ihw8(V}<^mWQ>*j7sxm_ogXD+gvT3?S;!=N*R+>Ra~o|klW8`* z-^FjXC?+z;UKOWve)$k7y@v{gfCd}{ZUbY$C=dr^3*%6ez!We8OtYfa?fJ8iHw4^P zf4C&zZ`No8u6bYqcnCaVkpr2$yEVn=cno_H$OZCPT4nmRZWDXZ-e!3MkB|K*aj~-< z%^A|HhEFEdLoKqm9R*@&C34*I6pk^JW?JNnB@T0hz3Iwl?VZ(WOTz3o84O{g5Q>p5 zu}_`f{s#?`Ngn9VB4ma|dyd%TbQpxrprA7$aEX<%m`)`zpvfi}eMa zYa-y+-v$gMm24#np=&Ise~zr;82+`t>`z%6imd|jo~*Enfn63kQH(VWmi;o4E$v=DXsnn_U`g zbKOFmT@3_6wW_Xp#jBC-#@TmR+E7>S|4SN!a|qZ5H~}n$CfNMYo~jkdR3ICW?XN>& ma%u;j16cxYhj+7If6#{$)c}?4S{u}`s_T@#l)wAb@crNHVGGaz diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/token.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/token.cpython-37.pyc index bbf209ae6fe1d5fc679c473d882386dfc6c3cf7c..22aba99c6b3dec5059ee18400b96bb21a3f082ad 100644 GIT binary patch delta 60 zcmbOyvqFa3iIoL`U{T$CK@6XRcy Onimw{xOoP18y5f<;uB;5 delta 50 zcmZ1>Gf#%wiI6N53Z9WV6wyPSFki<#q9!}k}y-u&T@7%d_ zD239r0X3+!1+5fSs;UyHFFZh~4)R3R2qX#!Aw}gw9D-LQUU)!#;RSZqNWs$m{J)vm zxxJa$+qg_NFO$GXMTLI{|E(_Gxf6)`8zZBK;=@TZu0rahwn*b<$|%q%q-MwBFBPah zJvnSI`sdsprz{DMy|wdsLLzKu&?Mvb#o!jHoZ`8@=a*T=;oAXI>|tdad$+2)a+(`{ z{GVsq{;BGB(lEzOaFoOG&#Ad04Fee9NErk2ss*$5uaEsj0y7vy5dG|z>LwCn|5VpJ zJCCcRP&gExm~mVMqX65o1{a^&qC;|Q; zGocoE4bxCyAJldd%6_ZO29IIL2?X{5DEp}D@tP=?Kl97CWUn<;NMwesH?NX7JKWMlme{G5-MdY`ND1UL zohD2RG=0Hw<;?|n8?(mP?Ut=$Z=iHzZeKE|>e&QP;g-FyETYimP1B58%vtazny#YB zlhMGm6v?D1gTG}9xA9%QgZ?XsW&69QcvEH&X4W-UjgSYTg$Q0z{$M|fg(_r8Zx(DCo@IB>AD ztGlPSPcGvV^jueKpdVLZT9{$^t`4HGTV2&8$u_!-5ithWxbJTgKkM4_@@r>Z^87jZ zX$WAv==?=gZz0kMocdA)0o5yPp?hyg42zf@oDe4%(bH77R7*2-G32G08Ao4W(xk<- zF@wX%OH)vFSj0qG_Ct59rifBTEO5y6|8;?ddJb3Oa5?2U)wB}WQZU(#o@WTK`#pO) zk8_{Gvl*u1rkr9X6|bgimZs*w!i?CY5?WEM*-gFmgsic_zINXlx5xyR*@e(9cB$_P za@W4y_qwYCPa`knCjWEX^o(Z7Zup$vlv?M@87c9Sj$4HVlPCCsP4&-{D{Q^L!0Y_f zK<}=vaH*uGuomz&E?s5Wfi_8;^K0zpK+kz)=P)c3^Sok{Dwq_MN7QsW!7~b*;xC{T z@6FP1T^GB_X?&*f(3EO~Z&2E&$F$O#4vlE|2GNGV3V~?ZJycDIy@>TkkzXQ2Z!fXr zV0-Jgcz>Tmk;LPn6d{KD5cvh#IkZwHMNp5kbEEH_{}|<`80SqCfM&Eaj?1JL zY@q!U#1TXvB8>PDv4s$Cg`Z^D{+uk~tvF7if}(hL(e?n*j@TX-uGqaQ$!4J@@-Mg{ BsU!dZ delta 1631 zcmYk6U2GIp6vumax6}P#Yg>sekU*q?GPPB{`URGLE@jhp`(1Eb7^b_kb?kO#IWrq- zrBIBD0uSm9#;Eko7=t0=7-ORm;#cB}NfTmpd{7?@zN-)NqW6DS6E~UPp8219&fGcY z%)N7keRPGzdgJkEnfU#DY~@yLB3jqgcW8FXG02(i$rv=-Z=bdDww`so)#!AnJRO*$ zwD)7>-wk%W~$C^_BT0$9qJ62aaCd?ni<%9*ofv^&ehj-DK z_v%(XxE0RQV!12DurhYmP=mDK#kXsWrTOBHPPXFR*b!IQIA7oOnvh0!*B@R%-~k{g z;Kzn+d!blJ5ZRuX za{aW|{pg=cRXVzN-~Iy!TUy)NJJf&}zeGzz>@afSVKmOqw(P6JfZS)1`)t#4us$BW z&+3;0@hF|O#V~riCPDy3K#5w5PM>kzzTBd92c_L&) z%Svc~wdOUqZ)0qYCp((MYeG>Ot@867kFj;{X2-eUK77}rs-KEKKV&SKt{S4x5GlJG z&f6LJf__M+c}E1_<};lq*=4@oSztbIJktK)mk3q#4C+8%A(ZptktRi+7+3i_N7^p< zl|3|HTolzB)k&OQ{w6(})kH?A`OyMY+&iT)yC!#&H^p@0vntgGyD#mt+;Ov}MLQvU z4Kx9$4#{?X0;?Wq1a3S4eh$dKKF9N2%?;n+{tE$Lk&ma+3cNNQ0^|W@^E+KTYw*F* z#{kMJtMErxj@{)m-979Yzuw)n_d2`^&j`@Wg?-n{K~w6l)9 zLS<#eA@;2mHaERr?S8SZI~7lBDVZn}nF3B}N?ye`h%z#mN~$m3q&JYG$?18FCjJ4lqh#l7*z8DjbCIA??_(SkfVg~NNRsnMiFco0y&_c9I<8hUuH5d9oa zx}SiMy`kY3HtcAMe(F!6ep)%O(F4hlRsd*-1h@lO1Uv;CC<2z&KrMl_On(eCMOT=~ zd#ofRHZ3zMmK<6(KUV6dyuz9f?IYJ==*E?iILR)7?Z8P1DHW F{2$F?2rvKu delta 1104 zcmZ{j&rcIk5XXJ}-6Ek#OpBr@AhbaFVM1*n{jn{Ap*2Vh5Stp@ZWkoB-R5oip+Zm* z5J*hSBqne%dh%kTZesL?C!=={ZepS*4@MLI02ALlNQzC|!)M={`Ods~v$H!}DvoSmd);(ipzAlU7KaN|d3nKuURrUnv+zNR%-nF|kK^~K@Ke|&`be2p%6c;>O^ z-&n7S9>-(LtQe4JUiD%9x;;CcmnBiUE+?&1auIhWy>3>Ebh_Zhi1$Jb9BD}%O<=|m z#AU=NVoY0ZxlKx))oqg#m?^KY&;W*N9&Zb&?qg!zUQF*hX-K=)I%u-&_vS^1M8=`I zvy12u?d-1&VCo2l7$jw{DBgF4Cw$#GMtUxy#EB>{cx{xjSJEP~16buM+vw&=D&`K{ zi3(b!ftSb^uj{uYz1$<52GURF4Wx06Wqs8yF4#V%!=6=nchQx142Zk5sP3C zHaETj6;IlAnTR|cFj9Pni z+el{N!}(z{0Iq@UAQnU05vZX_#1+IUVhwTN61e3v^#E7v@O!`$+F(nsofna019P(= zCrxTj$&}ifw5G)jAFXw!O*$lz%0;yxvY&K=_ibv>Xe3K;W2m-+Uv8PnbmxSm1H*YliRs6L2-2W&^epZ?il_ P<1^Te50iNi5=(yp?AHw@ diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/types.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/types.cpython-37.pyc index b2baef2833cfcdf764e0c94b9dab8ee9051559a5..56007d541917c693ea931f68f1935ca8fad7c34d 100644 GIT binary patch delta 74 zcmbR1w%m=|iIoL`U{T$CK@6XRcy dnimw{xVehSNscjU^Iio5M#fv4-zn-d0svR07%>0< delta 64 zcmZ4PHrI{YiI)NbSsXOggSwu%WYPAw{qaZFAvigC#=&&$bAOex;n!sH~! Scx&@<1p`LLsLekV^%((i!W6Lp diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/uu.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/uu.cpython-37.pyc index adf5a0c29ada17f3426f52050b45838a9b4baf35..cd03476e897f970913558433995484aa6554b214 100644 GIT binary patch delta 74 zcmZ1@vrUHEiIFuY*($~{sW>LFC^;juEH$P$Ilmw^xF|W)C&s@Z dH7_W@ar0@$BzDGIoAo&TnHZxs*Kx070svf37!?2j delta 64 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 H@Q=R$j4y%D diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/weakref.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/weakref.cpython-37.pyc index e58ba1552ba8101ce2c1dfeb795b3741d74f256b..94b16c6c6896ce7c49cf5d112a35f51230621fbb 100644 GIT binary patch delta 3230 zcmai1ZETZO6y9ySwou168v~pS2BX``J_Ic6!*#5%jRE6Z$41w!@3unM*4u6j`~qUc zm?-KA`vWnc|MU;o5E3K-gv1zQMD*ADOMhsBiHV7cMq`ZkIk)Y*4HK8_xQbqL*$J{jo$mcqOoqLS`8zZ6w;-u0UB(h_&2 zsHQ8v#iE9K+%ZojAXN}G^tpS3SfBabecSHYtSqKIWu)aMy7R=Eq9z~^(<@{n{rbd3 zClIog-Yr_@Y=r8kADR}^XGQOq^U4lhR>E}eG)@MkOh~U?7Hj00dGD3XM0stwHAHEi zpI%_CH*+YuJOATZp=F0!$wvjMlZ&{#;GA4r$-BK zHRPdkUJhUuM$^Vv%3H_53S`;qh2{dKLdHx!P#?c@UbNIk!XS7RTAc6cd^u z7ESikqop5CYw#@p?AaZm@2g8P_lsBAR{TdQ(>W22jT4l_OeYyso|+ufz1m>yWbOy) z%N3v2Apygt9a#@-V8@Jv&%?@Ro%v#AzYrTK>G4uenRA4j>yb|Zz(k!{is>2+r^4y9 zl;uDGE%Pa4Kz&rKKw+ly_=&I_No6S#i4LWuzE^P3RR=QPlsRq1`3$Bb7EPt~As!9X1F!nvumPeLq7I@Rg0Ey3w4D&$5W67uKnH2gX!ubp%tbrF(^xb^HXg_ zqG26Wl$q;$6b21|RY<-}7GK-xK}CfFo26_1rA?~==WRX>jd2h;M;?Xfe48jJNV%2b zb~|hio4ZipnjV3^Rh76*G|>m^w>QBq9S~rNc6b&V{LQ(c zNK~dzhGIrspKkWvM1W{w?zNNOJEbpLE36h-v)JvhHZpbx*{klmQ3KE2ud703?89Xq z)8=Bpvs-PX?&`B8SkSCMoz`f@ec4HWR`)Mz1>*6=E_$hEd?~wghB3hM?i*N{5327^ZrUTpUhJk26q};cHLEDPVYr;(e0{Qm%^HS#;iEZ! zkQ}vF0*91A5yzUbT!IxrPgZ#te!$BAjP)G-RU6Y~GO4)%)60CGo8C)PbuSemcy3Jj z)zn)?t9%Y>tiP-SaN*hMvIQBrWj=n> zIhZ;7^tZxk0Mx1)yn-e+oh`QxbwDlTZVA5~)7mvazRk&LSSHtF`)uQV2I=AEetisK z0nAAD!JKMgRT@h1H4U$)Mrh2)t0O|1sFF9;R*ETRg{+{S3reG;diQMRYJTB@rn|rJ1Nyq1oiO9S7F1ZO{e&LJFlMAj6A@k5IGyh77IpMh=O*<_!rtX|z6sa2siCVz^iZhl(7(56uVnxL delta 3368 zcmai1TWnNS6y;85rc;JK=#v&K8EBzHDJ_*(ODVKvN*_?5lvjCNrZcx?WI8jPnF19A ztwcoq5O(lG6JJC>h#x{@OwfoV#1D}KQ88YPiAMc1Ci>?G@vMFB%yepvO}caLIcq=8 z-fQoB=hhYNgDaZ5JvVpuEcy3y*HhQsU)$%kb~GQ{9XCY$U|YZt2RBDgM#52lFix7| zj%Lzlj$fVC5-yg|b?1DohVD7}Mx zL>+zUTA_Jwu&0-CSd@=8GStiPBOP;~Xmi$CP`n;7* zQ9)ff{gQuqnt9PJPg9nG?BPJJ6z3EZk%OW zDx&=259`x5Se-BEu+k%S%>mp!(h(GqtK|LlX+1Ygr+p_Yb&NGk?F1KBi3&gm z=&zEiOa4>es@p+8o8^UzC-0Y5+NPvN`J+ek9?WP&mx{>}an`Dtk~+<ZEVxf7Fml=ae$-1PDyXa5$(` zB^M{ZT5w3yR@2JL`VlUqTP(yOlQJ_5GyAAN?oT9y@Bjg{NSPPy@=>w?L7C2DC;eh1 zZc!o_3M8x^f{Kc`ee(NCr>!*Q!L)}%@q{X>&b?6JX|GrTg?fkvh?NjNh%P$rDLT@J zVpKlTnlaHxl^Q<;4sPmkaLl@oplPVo>{xQG~mC`WGTPtSR6 z=j6#n!zG+eTm(LGZm-Va0k7NkeP{rD)e?&5FC^!sW8t>^7G}?3~#zb-Bx9NJ>*X4e+r$QXucosFXTlBv+9;(>Siy!lTMvdrVq6a!5mj=lc?=*n$b^-V z&r52Ev86P3E#wv;TbQ<8l)LPX3sLYS{%)CG$vPb9F|}O^xOLeU+EY7Gh66I#{Mz4YAju@Y8i4-ptjP2UP_8`aiD+*}$i#dgWV3T+47synhEWl}X$ za@4~@KWU9+)W70_he6y$);vqkz3jTIU`ep8{|YEpf?-Na9WacstG2W`LK`LS6)>%ICg8s@Fe4~n;14gC56Zt|cH!WrWXw-%*Tkk^ znN$C|Y6tu2q#xECQkCF#PBA&-<|-{i6j^(%moM#7j0zw;4+M6nv;oruqrvM`uPP>d z5Fqt=fK@+7&`u}U`OeMM%-q8K<-pY23Y}hvZ4jA*OdQ4Deh98?A66U`2AK#!@c4>i zh3sX_FnMh?zb5;e0$J`QIOi8ekUniGEtwV_PnmN5uz1u`sKsgSh8yROOC8fCj1f7Q z4PoZ!#;H(Zcq|eS1+W%};Oxe*n&JU^_K0yRVY>BDBxsz{F>{5$evYmTigDAaMv3+5 zAgZTX;nxtyU=Kxxqv@%a9GU*s-|EMq1Ug8=@uOpjp!|xQ7K&AOQ`5z1u1^iUu<`c> z*5u4`_)MwHJ0uBn8a}EyIX5>wsGX+xKRU&9w=JZNGvWK%FFcmgHtj>vXjtHa$tk76 zJ5J6H-IKzJXW*V;R#S0fB(bk{+?yT|)0Ydp9mXv!>lPT2JLuibHy2qZ!xCd^!=@IR zp5alN@ENYvu%QV-fA|i`7vQ$eRyS0{1jMsQ=)6(6+-;L@9{E4Z36C88z~t@DCan%@ z(>4+q%n8Mfh<_+-1m!1QD2|n4(vvXtJVYlg?P_i~0}ZFb$`QF(J`TEtp*Hl9fVhaA z?3fV=h9Vk@P;uKtS5DBc9*xaf$csvVn zP72c%6VaH|9T!hykGbiTKPy0PG_UC{3xxgg_^6RM8V#x&od8mONW9&>N?S?acCVJd WZgP9P&X;g>iCTJ=Yda~_v*#bqk;s4m diff --git a/WPy32-3720/python-3.7.2/Lib/__pycache__/zipfile.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/__pycache__/zipfile.cpython-37.pyc index 3ee37a5b2e9550a8d4f58218c1a5bda71bae8689..d7478092f3befbdcc67d89206d68443d6f1d6ea5 100644 GIT binary patch delta 4014 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 MQGhF2@V$We7aC{U+yDRo delta 4031 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 diff --git a/WPy32-3720/python-3.7.2/Lib/collections/__pycache__/abc.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/collections/__pycache__/abc.cpython-37.pyc index c5bd3b3f2b95d8a8926cb05236be45b4de60a664..b184d6123c8b4b03c16c51dc148ba25042361ee6 100644 GIT binary patch delta 57 zcmcb^_>7U;iI(2OinF|amg>w%gIknDW15<1pq@J B4{iVe diff --git a/WPy32-3720/python-3.7.2/Lib/ctypes/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/ctypes/__pycache__/__init__.cpython-37.pyc index 092ca8728dadad434303ebef1c8ae8d3c9f44b41..a4e2b46745574a3606ccc37cd027c67e455ac2d8 100644 GIT binary patch delta 2157 zcmZ{ldu&s66vy}Lx~}XY6gJxK0c8VSSz(V3_QWw@1H&B4*d~-g*L8QUv%RgSWpfO+ zxezcQ2s`016cmFz6b554${+F&QABYlBId@JnD~exCK?kGV*;LYH@Ajp(|&q>=X-wV z{_gL0?zzXh2fJgJ#K*@(&}Vo1&`@kjOj`BQqK2}jV1om zkmQ=`vfIEG3>yoSD9sazQ#{HQ@mLf?9%JXoc!gL^WP9 zWnb1?}!52;0@$ZI(Nvhm#$~Ux-_d=M`qAI_c3Jk5}{UA(fRTarxXlNtv zl`y4ERlYYbGI+^*EllyEEvZy1lZTdIi}I5(f+@)*_+3)5AwZ+sVZi}4%`?db1|Y8z zrhux9B89-tOEXf zQJZHLjV-E|!v3b;#G-oD3mPm1hCcE~h>4~2QSl|9Y`H6Xuws@ayO(4~ObhsZ&VUPC zKG;GI;90=;3P}ugMI~%WvU|` z4IavvBlhFvjFn;=##t?7&$F6z>Q-#WmDZH0`*}TlRFo%+?KRkGz4qk9KJs$}M;HSH zCEDkDA?Vp8!7dv8|E|v6qI;F+yoL|w+Wx&>PUg#H>h+8)r7-xYtdZ*3I3~+3pXBrd zeVaY9%L^wtg4Z?*wTzDAgUpJOgY1+T`xp~zc?XPjaj z=L!`4IAEJ2`iC#sG{W*W`*R7(G-pL!)zXT}vgOX|wY4i&Rh3mg1qaod<>$MLOF*qz zE%lVsR32u`&Pv9`^LNCmNfvXa(fC0!w~oh0Qv6_lR&A7v+*Pu7ATTQ+}lC%a9&iBt1lrz$+3XBQXo=e$3~8B`W*6<4XanYPO^NMrCVQeX`T2jLjzlwn0 zHoz|yXk;`o)avEF53P(g1~+ct_6*#W0q}mYrH7mCXaiAO33m}kwA1K;N2J|xe7~EZ82V)OoFG11yo7yCI2>RK>MGai3aF)Tv2wYomp5V~Bo4sD#SCW~j z=sG+y4IDbZSE7GK|C|J};V{UGH!TC-}ZuYoj_=c6ctmxcMj~ps+ RMC;wojch5yI~NUze*jWC7pVXM delta 2088 zcmZWqdu)?c6yI&TwsZ__U~9XTvB7{92HognW9#H0ET|xYOvnf1qqN^^KIPfN_&ILoy!`Q4j?M5k&l}e;7=R#*hfc#E|%p=iCm~Xw&|B?m546&%O7Y zdv1SQUt89k>}*>GeXh-KJ)h;aIqROQURkeeps$=A)L`Y@`1)8R9ti0J&)W<(q2Pj1 zwPG>u9`&23N6493TTi~pY*h_L0=gd5A`w-Ev80pW5wM))aSTfcdg!N{2&}>+UZ9>|xS= zk!A@?%kM6~V;yO)rdfEL6ixVG%oGgg4Hr=vJx1EwX{?y^|23~BGfvvOcq-42Yw|1Y zP3)bzKp+ZRNCE5tydB76 zkn#O2g=nJ={J5w@>>RjPR3}6SP8^pIyYS$+V>IK;;=B=xRo9x;=8Xx>V}Mp{ES_oF zN3OWFJQpt)&k_3vjN>gvs`IRpgLH^}CF2F+jgl9|cFgq@E=1xcEovwdPiQd`UJJxR z5zS+PWgLG8TTRh;NK2Yi7MQ^Li45$Tx)cWRvb+r6@LZiVbdGPa@@<9#1W8LYut5)R z(qJ!*(oc0#tN9?a4&kuLrRG#%teL!bij3f3lbeB)<1xyWDNn@$QB92leM8|`AOi2n z`shV#X`R2D*?bwGi(zOTa<{|h&a0bUzhJ4laM9d(aD*9r=iwMbFPE0+#NN{JqI2MS zsX>V2cymgD=$18ik~o_=x3cC;bmdQCk+%Y0n7TXbIQ!3HNO4b-xa|qoNZiwC^DY&u zQT67FGq~AXGV&~O-h9FlCL5fkI&ux%_U4G3v3@-1cW@;vV|^brgms7$qDB**_c9mB2D8Xjkb?_h72 z@0D!!r-B*I_#gMt!3W2XJ3?!nK3Okj=o&8+sVHRuy#AOrX6yTT?C$W1{AzIg8oE zF9z`Q0Q?dFH+={&$YRx4YGmM64BTabn<{Ysgr+WkVY|+fY!b3vaHmi#LA50w4kdv5 zTB@P6ved@F4JXxKcCxgKf%^mOCrFy(Yu0MPX6R%M*EVp`0zWsYa^pe+PM~56Qf=T- z|KxVXygp1#BBGe%5sm+?>okaI5#KcUi0L0N@G}G#*wGqP`PQq=$}o~rB7Dl`iwyi0 z!RJi0M73x%-l8dH5~!)cB{p4VxWe!i!?lb`!mnAp#qbTobp|d9;G`-ef?WLiR8@oL`U{T$CK@6XRcy znimw{xcLiHB%{M9ZqP)c1)LX1&i8-aIx7gA$Q*%;^Z%s~TSCtjhYIOsRzWxY(Rp8kp&2gKw_GVw>WcCOA?cF5{rQb=&|*?BWVRHC{hIx lY9K-#MDU>!{2;D2kT3^gWW%*5v#^J=fnI&38ulGlz zY7|(TT))kU_A&^=`1b>IEHZ)nTQ0kA@)^T66Ysajw45~9AbJdh&v$ z@{co*@e>@A1M=*HtgG}G_z$SC4Zh!}OidKXa(M6{u@T)mT|n3KBhCUlOuSF7;2!V` zMNc3_Hc~RAIR2t0@+Hm%qUU%!F2FS&NS^aJjIRGp zJ?i!M;2aMG&%t%TzNqxjWKgd~T&DIYVctNFQX{PBk^;#SFuMPV|~a<6jHqN2!C{P|LO z{4V+}l-wxY>a;uuypC!+&?&oz!+p2g^WKYdLXeSd`jsT@n`64=5s8mrKOsc65tS!~3jA3z=ORwpkvJ_aIqCe#4LYtmU=ceH{ z)+=CGqgiDkaaKocVafeTGWYTl78wqT>Nm|WHyz&^iIz&^iIuCjiIuCjiInmx}=i`pY(Mt<8 delta 22 ccmZ3`%e0`EiQ9>nmx}=iPI%OA delta 20 ZcmeCz?$_pa;^pOH0D==9wHvuxL;){a1jqmY diff --git a/WPy32-3720/python-3.7.2/Lib/distutils/__pycache__/extension.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/distutils/__pycache__/extension.cpython-37.pyc index 2af8c71c28cdaad4e1183504dab10a6492329f64..9108e62d5d49b5d81277d14ddcbf07459800e083 100644 GIT binary patch delta 20 acmbPaHpz_JiIv_gp6iIv_gp6iIK diff --git a/WPy32-3720/python-3.7.2/Lib/distutils/__pycache__/sysconfig.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/distutils/__pycache__/sysconfig.cpython-37.pyc index 984f085dba69cd0207ed1048ef276473d726e992..9d4781add984217f872613baea10434d294131cc 100644 GIT binary patch delta 20 acmaDI^E!sxiI zf!l0K+-x8@Fu}f=gT0T5QEKvZP7@gspztl0g2a-HTP#`mnR!LRAa$Z3LTvJLPI+!| z5K{s~NKY2zl46vZtivUvAPW?T;w#8WEQv2JNKMX6%S*NOMEKV-UEGWUH%WAS6uQQ{>V5QC{Q`rh& z0=La2YVkAqx9tIoF+1&K;c^~1&JjYw^*|BGxLf>KR$@ojUS~$h$xXa@ zZt@_98G{IO5Mco#EI|aw=pt(%af_$8G$}qgKQ}iqFQpjCPmmx1DdU`M#^)}^31n(= g-(ruCPsvY?k1tXONvTer%;zNvlETnA`4gWK0D#G9J^%m! diff --git a/WPy32-3720/python-3.7.2/Lib/distutils/command/__pycache__/install.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/distutils/command/__pycache__/install.cpython-37.pyc index 9197a9754caaca35cdb786cc5adf0cfded7a2dbc..67ca9f17e2577bea94364c4752e4638286995203 100644 GIT binary patch delta 20 acmaEn`683siIqAiIt{UZL1!ISTc=rIOO<`b=93j?VNojgIb F5CG%5ApHOU diff --git a/WPy32-3720/python-3.7.2/Lib/email/__pycache__/_parseaddr.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/email/__pycache__/_parseaddr.cpython-37.pyc index 0edb3bbed82fbe37d12f9611661bd27290d4df74..843c59675c31b658ee22dfc751d1f0288449e414 100644 GIT binary patch delta 2006 zcmah}&u<%55az8D$F<`Srx77hpeSvFw@FJYLKT%LYMR9SXnr`2sgUdZSnO?VVtd_L zCut+m|? z&F1%;ksHxy_yzrZzI${Od1#2V_sHlLugA2hwlaGyGxL#~u_&7_?AjSO>s0Jj%6_nr zS+3aSTge&E3w#-T=|%0VL_u}B)t$R{m2j1j%cW&De5Dt0h@lUwsC*KBDxz{d;)rhf zZDe4mN1IK9{18>&)%TZwMV{X5)}NPt4Z%s!AYL7+qgp80Dp=a)cPMKW?Q+f{6~un4 zRF6j2w0CPfFA&X%NDCp4dVVy-8MzR9Q{0e;vGLxU?MI%)2F1C4ZLNv8d5RMF9tW`J zJ6K%+EXd#c&cD2Gh`^IZ=3Tj(Tm~>jd&2CzN%PIf~RaB>`@L6PRQ$qdn=bOz?zB~5wH2YwTY54Foug1J$bUf0BQ zO~vWc-<#40iwvJtI8 zM9;E6RBo<)sNe^h-ji3~3QRUg&~*4TFJ}+qTkO2{f06Uv<8$AMB#P3NK&1AL zayiX5`Tq`krbE#3q;A>X(dZvygIk3XSu``;9{OE;;`lkNST-m|?*pJuT@_k~A=UuC z;nFfshxe|?_ip7l$n!=fBz#YJf1{I!NUR<2VqqWueSh)JSCPAZ;W~%@s2D%Ss>X%XYa45(PUgnamQEXQ8ud!a&z>7e3# z9RJlXChY5jFN>6YI5?Adr`zSb!Dq$fFl!rPN*$mJI9CDE@*<>Zz=|ChI(;(3VlG%W zOGWbtV`p(FAQp}~yWv~9r4VZt@A-q{NH+ZW$ce4v zEU8gifg%e)csIsDt2?Bby5!KJ>h@n-T}q|t8jK>%%w|>JqBUrutRbUj=^#YQtWp)q z*n1=C?$NC|k4OF#2k)^-W|`0#3NbXqLPIQO3H;Qc*Bx1}qy`%90Ou$eWvy7DO;~y5 z<|6t>OvB5b3u=Y#-mxj&V0c6LeC8YrzW#)8QlmeLg9-kiQ2=->(|N}IzT{~$Ng9i4 zyxo}g(6F9Vth#}!QT1lm$F{D*>~7Z#OQ%ct453AqQKqZ>CA&uNBV?bP5%c63PnuRP zQsrssw5#XqyzX_gb7Jt^biN+DBMxMrR$0*y>okEt(Vn{`rzsce3LCkJR?A97W~P-S zIojs4HZfjzZ|}^Wy#sCM{`0Q}=369aiFH{u)G;QxD6PaD!GpX8&m~{!yf$_&`DjY^ z+MkRq^Y#0H!|^|`=&oP47fu~cq4Isd8q5B-@fG`zQ}?EJr19qeMJ_sDO#UoZQ508# zp>=mumeZPFbKj(8PQh$@ZQ8c;&6&SMUbYG)5~!=;?$B@HNXFM8$+2N#^fmzVX-&P(H7fO8Go3;Mt-@zy{zdgBwm=URhc4p6?lGUjUo~;760<06&0}`3SEW P$XEXl*h*y%U diff --git a/WPy32-3720/python-3.7.2/Lib/email/__pycache__/_policybase.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/email/__pycache__/_policybase.cpython-37.pyc index bca0f0ba45601a6613ef220b91a0805e8629f774..0a2b8b3ab0b5c14943d004ccec8be8b4d4bc11ca 100644 GIT binary patch delta 60 zcmbPOGP{J^iIoL`U{T$CK@6XRcy Onimw{xLKV2mk|I?xD=oO delta 50 zcmbPTGO>i)iIIQ3Uk&~KMl3$iubc-=>B}0)YQ0`ZtvsH{^QgKXT zQF2CRS!zsia(+Q-a8YuoPmF&-YFoL`U{T$CK@6XRcy Onimw{xcL&Nn=$}AG88TV delta 50 zcmZ1!H6x1KiIIYlLY_@ZWE6H delta 50 zcmbQq+t17G#LLUY00bvIYBzEhGfKERTg8MHrxq2*I3}kS#kk~`=jG%lrW9{p!1$8| E08}>*=l}o! diff --git a/WPy32-3720/python-3.7.2/Lib/email/__pycache__/errors.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/email/__pycache__/errors.cpython-37.pyc index 12e022853574aec93523f37a4fd27e9b332b63e3..2a7489b870d9272ff7b5cd6c7fbd249b5cd6e180 100644 GIT binary patch delta 60 zcmdmIaKeDwiI$nHVc3cWCGXg?4D% F006aqBF6v# delta 115 zcmbOgJRz9diI87z!ZlW(iWF=lVJQVVBd PteQMYLmwz~NaF?oA~Pjg diff --git a/WPy32-3720/python-3.7.2/Lib/email/__pycache__/header.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/email/__pycache__/header.cpython-37.pyc index 8b7489550d89bfe2defe27e04dedcf14791c86f4..e1f8c3af641ae29d2636e640b9d960ad3a59f323 100644 GIT binary patch delta 2148 zcmaJ>T~8cU7-yIVO@!P@$8xRJnzSO-uImM zv%+px@LvoBN?%~Voz=ZP|Ce6Drr&rY4OgOl3nO>T1(_sL>Z-C}CUirIk;L3<3s((A zo1GcSJ@bAg2tm4A`lC>li~FAzU211xY)>>L6H~EBn0<*J$)8jbdQwToO=X1)FdG>J z41p`8Y{4XMd+U(p45Hum%*94x(aA}I;A9w3&cF`F6S`)pT1K{1U5l@o zqzrpuI$A9@w6LYxgxP(`2Cyi*@U)FLtodWmkO6!NdCv!}XCMy`Mp;3ei&3{T0gYDUIlWivs@ zHD)15ES2dQ>&QM!|E_Di%%yYlOnK#B20d^P#SvL5f9`!CdY+8P5T?oc{csao9u)3` zD`3TP1EJr1Wmg$(oM0G8HEk2ehG($6#K5kI&&%nIGOm+l*|ONdC$KdJ;IhX+DwmVV zxJ6{mRM8VsNB6`g_Zg5{=r3YzycWw6P~D3>l33xWS!x<-)k@$Dd_-(dTGbR&F>Ieh zM9LfRz6H1mH~~Og?GjEVU39)R?5=`&Hn-VYE=)p3avdtb_N6eYC+iHJH!)p6r916!RwHD+p`!_jAoch*oqq4IZ+cQQ-;rY8)T4k$a>cRefdb8`N*ZEuGv5Sa8>Y3Fp9={QDlqkNd z8n#Qtd~GAj!KFJYjCbWcoLq)Xto%|CKbzY;e_NQS#@Ypd*2K#|3_8U@ET>jp^&0zR z(#qOfid~9`>_NzA7Qr1QA==p8@ZzCNPBZQySfOANeY-p24Er|yy!(w_0)G==0r+^P zu;Meih*c7x0PX{_fbD}p9qsv6*r0#)OnBkRn?Bmx!(b>T! zKbMlLxIym^hFD`C4>q5QFoG0RmSr{FzLL=mqAsh;3TdWK2D{D;!~0#pbwCFL$sL;+ riH`LWuFN>h4*;Wp+cY{9t~?EzYcav@l?v-iG&2-II{x^5H#GkbUWnTD delta 2149 zcmaJ?OH3PA6lK5+HpXC397viPyL=*Jeu0)>2owkeQ0hP^NpMIVV-I448Jjm_J|%pb zMWZ%~s`e_a(oL&YT~+Ew-bA8Or7kKpi%Q+jqMI(NNZq8HE~-|2=Z%Xk7uAb1Z|*zy z-goc0^Zf8Yx_=-!M_sP+BK~_ax%;*A6T1|qFYLj(v9W>0d0k=p;z&$kix-odS|S;Z z>zP08pGr~{eN_H~RFhGizZSQ(ac8q^Y$eKc#b7@E7AOll<4P?`sK`1kAx{_FCBiNMzdExl0 zDJzU6na*6;6Ht@+%JW#N4q(?2(UMxsP`3EdXuH-YP11)PtLd=zC8>s<)$Vw!I4@Al zCP6Pv8Y?_reyq3adP+wwgX3bA{EOnLQ8f$qvivD#=-$a`9@;T!zan)k840iMss0y7MToB_81!T( zs3$NkU%_&M-UxV_E@62QPyx8g!K{qN;}L^JHC;8-q{hzBVW4rp9{Xs%X^ZFvGu;to zZApnk&J`sZ=lyvOj8ZV<wszilr>8QxtMj)?H0dP{%q!6OQkgB17{8}&mr4GQ;w~qwN;&+=eBTpBC2y4V9ABd zR}$V==;z?LV-zupLu`~oYl*c*VUA1Q!%i25heTG=86!ycEib*iZY|{ko%c?FTN%P zPau~K0JWH%L%?kv4vn?WDo(vY?w(p1Upn(rTh9wkM-8;Z+k9l2Y`J5O3bSuJLaL@FQqN|yLZx#I2aiU^)*`QrfI8h zq1gv}Nuj<4dflNv`j%ud$L~<2|0KV7H~RM)-bGH#ZB`-vcn>Bkx!9!Ifk%GG$#b}2 z5$%8Lh?PC(PXn{=!q0@d&VL+y6-;qu{GUHaM1P$h@aOpd9eA)7=*D20|A+iISZ8%% zkA54}{P-ha;*LJvZI^Z~%y>n;4>|SNdgYBQyuqJvs)O~Ik>>a=ypaWcaZf0a` uypM@CjKlmUU<`1JUK#dRp9amg9OK`M3Trd%4+lM4Sms2}s`BmdwSNGOfX_Do diff --git a/WPy32-3720/python-3.7.2/Lib/email/__pycache__/iterators.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/email/__pycache__/iterators.cpython-37.pyc index 7b89f00b7e13f69aa003fb2713c78ac6189dcb84..8a787743b23b101cfb472106057e75ab31f7a2e4 100644 GIT binary patch delta 66 zcmbQuzm%WbiIoL`U{T$CK@6XRcy Unimw{xLJm24+~?|Ib8=r7y2k=u_+$b8IOS2hk=u_+!o}GtCbT%Us5r(kIkhOpCBHl`CqFTzcyl$= GrHKHdvJt5O diff --git a/WPy32-3720/python-3.7.2/Lib/email/__pycache__/parser.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/email/__pycache__/parser.cpython-37.pyc index 6b9857399e5c7cb80d63e707e1f19979bf98193f..71db5078825590d2b066d0f3a194c1e548f65271 100644 GIT binary patch delta 429 zcmZqD?a}3S;^pOH0D}IqjT^bAvnu&ITg5mg6~`nNC1+%orN$H|=NF^~7bS=K#P}Da z<^=^fZr;V}&BPeBnT_KHqr3=Et0q&CIFKsh0I`{ic!AU{mXg$pk|L4Ge>scTz><=a z1w!M!g9sTAfiQQo z2+wp@Hd(OXJ&;`zlh2B71pwM}Prd*E delta 490 zcmeCtZPMj-;^pOH0D@BSA2`JrMJKa!6|qSGg^Hvm2Z)JJp2pRs2I6Wm7x98bML+~d zOA#NO;0LiJCcANmsYwBuFr|_pVQfmJCLiL~7nKG{%YX=35P`6Bvn`%0m?L;z-Ukp?&j s3`N?Fpn=2;lOpVx$*)8rP_$`)9RvwQoI#^8xkS_qYtTU4a!qs_0Cl@n7ytkO diff --git a/WPy32-3720/python-3.7.2/Lib/email/__pycache__/quoprimime.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/email/__pycache__/quoprimime.cpython-37.pyc index 3a3c9ac5b1656a4790e143468c07f0854b789212..57b689be86f0fff718cc0c0fd55c0cce6f423750 100644 GIT binary patch delta 187 zcmexw-D$(^#LLUY00jMI8#i*FVp9rqwu*5~Dvn7kO3uhEON}W`&M!y}E=msdiSaK; z%?k=}-29ep8W-cO%`Jl8*cEMnT8s2Rge{2B2N5bjqKb)^%TJT7$YJtqNp%rRkgzL| zxW%55nw+1Kno{Jp`I@8(BV*v^-%@=*YI2uMC}YUv2Qt!(j+6h$WJ%eBv@n4P77)P* NB3MC0;N%9`dI0!pGKK&E delta 142 zcmeCQ`ESkb#LLUY00gHzYBzG9Vv}%pwu%WYPAw{qaZFAvigC#=&&$bAOex;{ooyNy zW7Ot8!Efx`)<6wKdLY7Pa=)Y~qy6NilIkKBAORO35yhU8nw+1Kno{Jt`GKSgBcuOj kR_Q(?^n_T2g%(Onh)cs}y1T{2?d~$WEyzI( zC*#G#;K6wD=EV!y#1l7<-aN_N`~xJ$i<+1?(=vx|-hAJC^S!+HS~`{n9z-JHOYFSq zoSY22gW~f1z4~0kts|^HH9C6TRc%MFVs(AFzT)WC+UlHt3hxJjOn!%^fb6IG&%rE( z60#_Kq&FxmAxz<%!=QwoGoj4{sckZ@y-i_NcPLy@JqpWqhY~5g4Is6i^L41hMf{cF_KMc%dSt9GL-8u-0w_NccWFpV7 zGPyLs4wKS@6gsv;1>~?$1ScDX6$^#jGyYVAq2wzgP)jB}iZyfz{W z4#KGA%3(|2Q!e5wxT)szh1|s(XUW7^Jl$pmazwQ)=H6y4*p@5z>-!!v)ipfA|IBc3 z*#!T9BH2t#f*o>{NP$E0F)=P&h+h*$(DVn#f5P=9ZvkM$tGZ*0_J|t4uJsnS!NuOz zc(lTS>zMBrcUL5|o_R(~#}&>r$c9*-L4?m_?n delta 859 zcmYjP&rcIU6n1vnEdou7AQVc`v}m#cst6i>M1>Y8R9h8_(WNmg-6?F?Uzy$VD;hZ) zP7W9U058T1*?+(j2NN$QCT6bQO+0!qao*O0d-(F^d*6HC%zJxUdQ`MUTwZkXl=pSw@pXWz2F?rMi6IG+X&)8uI(q9QgKPMRlG#DR9x1m zisxMcW$jQTnj%qZnu2R?t9XsLDt=V=Ra|lQR90<2Ky$&D_PuEGp0MV!e`MGVhvvnB z762C5Mq;3EPJ~K?t^l(vfMeU)r}u-C#51XX9tg?txV%k#*U-64HCuNq&i-6dy16Vu z&9LcGSO^d%&HP&5*178>to%Tb&9DvPs2Y;hk zM$*@j&Q8+9=p{Q#56S?WR0#jpJrdEXQs!_w!Jztf4E3{B!rc>8U-{Mi7n7&3|2oc91k+&`1 zX*B2nbO<2@QISQmYybcN diff --git a/WPy32-3720/python-3.7.2/Lib/encodings/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/encodings/__pycache__/__init__.cpython-37.pyc index 73c743dfd666cbd626c9af399d631dc22e8a0c28..f26ee3c4f0f83d73defac19722798329499a7c7b 100644 GIT binary patch delta 60 zcmew**CNmD#LLUY00jMI8#i+2vnmBUTg5mg6~`nNC1+%orN$H|=NF^~7bS=K#P}Da O<^=^fZl1*Yf)fBIBoqJu delta 50 zcmZpX|0T!m#LLUY00d_|YBzG{vr2e6Tg8MHrxq2*I3}kS#kk~`=jG%lrW9|U!}@{~ E0BfNTT>t<8 diff --git a/WPy32-3720/python-3.7.2/Lib/encodings/__pycache__/aliases.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/encodings/__pycache__/aliases.cpython-37.pyc index 7eddab68a8b298ceda2a0c03187ac541d41bd1c8..9905ab5a57aa1ed7d2f413db42971f48e766f23c 100644 GIT binary patch delta 60 zcmZ2(xY3Z?iIoL`U{T$CK@6XRcy Onimw{xcRQ=DJB3m6%>yE delta 50 zcmdmJxZIH2iIIHq)$ diff --git a/WPy32-3720/python-3.7.2/Lib/encodings/__pycache__/cp1251.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/encodings/__pycache__/cp1251.cpython-37.pyc index 36ad7ba8848be5473f08ec335c3f78465da5a5c4..6b1f205fbc15c75f76eb25344ef5cfa6f9ae5de5 100644 GIT binary patch delta 60 zcmZ1?yiSoL`U{T$CK@6XRcy Onimw{xS5q{K05#=W)n{U delta 50 zcmZ1{yhNDWiIIiIoL`U{T$CK@6XRcy Onimw{xcLO@D+vHP85E}g delta 50 zcmdmEyUCW@iIIgAtwu*5~Dvn7kO3uhEON}W`&M!y}E=msdiSaK; O%?k=}-29KRk`(|jF%&ic delta 50 zcmZqV|IWwl#LLUY00d_|YBzGjgsq diff --git a/WPy32-3720/python-3.7.2/Lib/encodings/__pycache__/utf_16_le.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/encodings/__pycache__/utf_16_le.cpython-37.pyc index 285d778384a74a567c6a05303ce2843464c6ec54..014d685d3c44aec4b91252cc87e5091cf53873fc 100644 GIT binary patch delta 20 acmey(^P7j;iIjgsq diff --git a/WPy32-3720/python-3.7.2/Lib/encodings/__pycache__/utf_8.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/encodings/__pycache__/utf_8.cpython-37.pyc index e992f61b05fc36224584cb26c416a1863bdd7260..1acb29a941437bf204a63a0d71df07ee30f88066 100644 GIT binary patch delta 60 zcmcc1^PGpoL`U{T$CK@6XRcy Onimw{xcLlo2PXhIC=@mT delta 50 zcmca7bw!HXiIaGY!wq)oLW>Ih($ diff --git a/WPy32-3720/python-3.7.2/Lib/html/__pycache__/entities.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/html/__pycache__/entities.cpython-37.pyc index 62079164edc9b29f8490424d3900be2d83248faa..ffb1c15e239c5cf71dcc0a923db7b6612a81395a 100644 GIT binary patch delta 492 zcmXw!T}V>_7>4(5JN6@kVznr`h%7MBv4S8R!sf0bab*-SPS9~4akkCV+0LqyMM-IB zP@Qj03!)&?S=yYR^e6pTm=*mh@(AR{~?S#aMwm)M^~SUAEIaIK~UXy3nlFH+a>1v^*Wa1Vz$I zai5N)*Wdw-r#IsvFFsKMJSJZzh$nn3^9y)NZQU_U^3U$mz%w>Z6$yAwC(lgc1vj1b z*cZP1Cr)U}O0W9r|6k=*P3E3b;5ENFKL>bAQ@ugF5GSk!6!t_f6#{_7>4(5J6g%0m@SGfLJJIXtRM)7Fr61gkrWhhI6=L7+e~rmvy6W1*Mzb%=!Z^be|M30b<<6)p!ee8y?WpoOFBl9j*?oJYo4vJ z=j&VZC358g(GgC_Rsnl0XINLFBDGew!7{z8Jfg5qj>l!u8Ld%Ot0*cfyF;=_wO(b8 zB`A?5T@!iKdjJs0>ysdIr!Nu2MKiGwm)Mio0QAx>-Ge@A)~nFZS9RTvELR*{WXAvn zjAgh&vauF})NPbwh;JEbAV*tU4k6EzEd?=i@JOZ@*XaB4Zd|8h?GqTKO&!Z|gZFpL z1#a@;6W{E(%?+I_;0`Z2RSk^M4s#{$Qk!`c_t;6La6Kpl8$wJCHTczsv?3M6BZ{QT zFis~^>+qPyQ`<4YOHY>rPbiSC$5ZY~{{$wfy+^?_{?T&|c){k`A^}r$=KK_1a^nS` zbMdQxVoi^)_N%Y||22N~4Rdb=@Rq0h<^%6&w!a?lx%%=jFio?Wo%lc-vl3<~lWoLD zb`SgpKCydn$brvve>i|IWY2BJSKg9yp)3NMP5p~sb-^lWn-*3zsb)`DmFi;6P0^Sf K(m0tPasL72fxdMB diff --git a/WPy32-3720/python-3.7.2/Lib/html/__pycache__/parser.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/html/__pycache__/parser.cpython-37.pyc index 4fc7ef85cce7cc9d628ce036bfa64ddf7c3655bb..205770c04f6803c1a3df90a4ff544e9665d6fb3b 100644 GIT binary patch delta 273 zcmewq_9u+niIYGKUU9I4vO#OS~I zuKImO#+b=_HC;u6LE20}L==dCm^fKnOP1Ro#Los1Op_I~#V3bp^&9#DxlugH`MJ5N nc_qm?`NgS4As`i@K;jmAm}`)ef3Ry&8b~MuL}X4D(~bcE^_feq delta 296 zcmewp_9=|piI11>4k9upD`>|60M-#mod5s; diff --git a/WPy32-3720/python-3.7.2/Lib/http/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/http/__pycache__/__init__.cpython-37.pyc index b4b30226bce53b0bcc203df4190989cbb4b80321..92fd3e8374d07aa0a562ffcba796ee74910df642 100644 GIT binary patch delta 125 zcmdn3w_A_fiIhi|f?xD)^#v>S2& delta 125 zcmdn3w_A_fiI9$(r4L%YAPH zNr3RxQn4WRS}8(XtX9WqRmjt}V3Dd*ooYV@>rCmhKrYh4@Nwxv+z+GFKF3q_ApnyD~q8uM(k28{KQ<8r}d{ zYrZkbmCDwM-%qX>zY-h;`bO6@dVTfYwpvc>qLxE9csR~iL1H5$(t=t@y`uw6Qn?wF z3s3`CEx}6dQVl)>!*u{Jc$rGDTMhOo!H6bz(*%AaU@M?q94#rHT_;J;Xg&v=5$?*N zm8SQE<5p^Si2I!eSJYULH=37AmNFI)MWt1XXd7L37s9qDl{CTYSj_K;KUdtaYaz!<>kP+2cVZ5aE#kK4 zKdjokU0J}Ewt=$oQXaeOBjUk9`UP@Mc5fGrY+Bjz<*W~Q)8N_V~FTVtwqnPwxb z#cDa%I6sILvjL>fD|S~+VqS8v-+aERoNc|kmVXmsv?W@F9a>`)JuzB0R%?J?KSo|WpPYz~M+^JY7D!PKC* zFt3R1G_84g>|U}6#ZOKlDJlaJ zJ(g6;=i1BAJ&%f;i|>ls3oH~MGJAT z11>;43OEk44%bd*+dP0Lgb?b{ za>ndhPWSc2RlA{1U~&V%&Z?Exp@sT*i+Q8Igt2B(*szAxiBQA7@h?H>7l6}%Gk_t= zr_an@o0qzxS#qq*mPE`5NAGAq2ce$87$g z%7Q}{^@xK;TxlvUP0AmDGIswL&*F2UxS7kV>*40JjJ1e{R{zAL1I1XArmOPsf-n4( z_+@LJ8;0GcJHm`kRaz1u8>V4P6WNXmNv|7Z=-#o#f^_RFB!~FOtWOx(9A0h&2_!(60$$)^3yq&+>5Ff>Jrt1*5FDx843S1{j%A=Sk*pauX#01A)` z0g`RSp9SlL7~}V`x1I?4S&j+DYze~$_Mn+)cd-V1QpWf3lgw-^ohX zrhw#FY-4{)RtA4l(z-*!oUDwj3{N(PLCdM`Fp#oka=_mLkn8V(LS2)eR$AClIlqFj z?T)yrEFVJ;31_f75$nB%$gYP2^A4VyZ$6{s7g}N8(mj1G{dn?q0#ZdR>Zm z<^6Hjx_pDxv??vN%}Q&n*Ju0k4;ZjtO8oDV=GVoA@XO=vjbi*9fKKk~Wa4AL_(&|Umr;_*mea2@8x)MznT21eCdHP&TxlSX-7!#$7N zO7G-azZ#QG#Xo_%=K;yG{0PGhfKvd9&va0qN$|KwrUl#)-pZla8!dN6z_-J5%X}qz zFm(`{^Ni(RD4Ls)%Lb73-+-c4r2__chLtUM5>tc8SB(atCIB8i_QM73Kip++gFE3a z6iLc*i#N6n)=~L=h?!IXtXb)+eZD58sjx?lPn=6sGfUh`6qi}-Yb>#> zx3u{stftGzjfqS^@_=<>NGpaQH(Cz;?(N}7M6tDh`F-sZr+cr}lTWl;>SZ#LBNtol z?K}`ya9qp!LNz`L8y;pNCGcZi-H6VnhD z(bVTL%^gvewMI@1+goE_xT3m$8S{y~dkf5C{cVipi}weLodqycD8}u~m2=Z}J~Vf| zT-l#HO|O_1E}@&h1dqgNx<|HiA%r<>&IjQ3=LO>0&VIIuuAu&1D>BLDi4dG*=koHd zoD?Tr9{J*v!KuV$DR?%k#I)eONIqlC(@JJ-wF)L1=v?*BO zQt%K|6nU*kB@+PDOLU8V0L5rb%heUpIsy^hawg&-oRq%<*R9A8-)K&U%5|yXQ%L6l zj*27uOXvI>B2HaCT7upD2KYY)(DCsHN%>vtR9z2rsk{RG8u6F?#kpD11It|>jceSn R-w_Tm?m!#6M|2$+`Y(vU3&#Ke delta 3999 zcmaJ^eNa@_756UeF0gzFD2f&l6kQZit5zK~TBL#~EU=)i)#tMNfR$x;z3(jwqJWyF z!D?c!sU~VBUybdwY1C(%nkHJCcG{WdqfRHaeMW6E^^ewZrfF)%G)8-W=ZR~QPWO-B zo_p@O=bU>!?!E8HA={HfHrLlPGSWuK-`mwYPPzv2Q%#4*&oz~s;$VI!t2#C2S8QCR zoHx^gYHPebtahtm)2Vc+dPg+Kmy63|TUoWSv>?sKD#e|$d>gM8!SQPytK=HKTD-p? z-}uY;n>JQ2-kC6U)N*kBP?u6!U+1lyz&wUTdUF4JV1 z^-wfY#d(zTZ(~ITfb@C9&hqihLk?~?UM??X8}F~>k3x*LM60kvGgHz0ZK}dme=ro$ zqn2y%#k9Bf=&I&+TB*avO_v_k{b7YB%%raFR_+mBtte)LMoYzvBnM@)PYlhjaO{Ms z0da120o!4iv-8+PWS4?^0COaZ$XXl!j-=d*Gk{{U1(Xhm1G)iy07^MkJ=HqxdOIct0aU|#M~qlFf>W#z z1uNVKK^+1-1$YMVJm3i61;FJu%g4rel~~2e5K#Cbvd|J=|;DswrZuNsO&s$!bKfcGsxaA#@gS3SaYMXrH5)Kq%O|quSgA2a! z=fp3Y@?3D7)7j}4SDOm*kV(^7-(*Fo9kX0QpDd z^)opfK9`C6E+t@#k+NnM(!Frq?grAH>W}MDB^pyB{1Q|+0M!5=U_F59;zyvUOizQN z067sL*;f2zu#SmLpO?M$e89(YehNl~gyF+_z=*GRvY83Z|3lw!s;MntfPY~8_?sO5 zPEgv{1tiC0YkO@OY5Yw|Yjz1UGtx5B+*uq3O^3QoN6Hq<0e=fXu3rPy1Aw1qa!6M> ze;;GZ9dT7zlDQI7jzC8|(y8(98q+o%PRfH74zqkM;2jA*aWU|XY=qZpT#EZEqC8kI z358*1C>^>UQ@XVXa?Sq+LE6gSL2VSB!Lc(FWtK?#9!&oZutb78-70!77|r5zu)Ik2 zq^gIb0bf!i6!xWA1A3HLN(`oc!q}VQ(>6~wIrSmdW&)lT>)VTpHh_Fqf|;sD;$15D z%P<@Ra}!{lIMQBH27ia|nmAFC{0y$UdxvoFkros_&+4guZwe`v!kqyVtfLy+?v6Q=wsu> z%_f^jn=AwS-x7MW{DFWP)63c{5X+58Jd^BLr_0A&4bP}Hh)z(nQH%#u5asDZ?bhI+dZlC^+G0cii>E_)Y@ z(f6T1Ql?A%c1!;XD!+eWCJ6v*W@@$9>rp)Qjb5wr-op%>G1KK0sfPmh-uKk16sL1y zAOA{Y3*>$cpkw>@pe_RF1R)=(`A|%pnh#mG!cFl-EcwTPyMSaS272?2T+PAQX;GkG zmG~cBVQYjh-t6KKNnsLN#H;aT%qMQg3rl>iZk31HdXz5tec(&2tZMWsb@g>sJPnc? zg3s)@bUCdg<;NTeJP;WD1qr{Evg^tlMlP^a0<;uCqeUHsr zD_8dBPS&PQ4i(YOUxWwZWX&zxIUm9rY|a7T_UEI;wZ2}qp01$Y9ZS>6<*^VfuyT2M zM~=-wm&Yh^vwxB_Q!wz5<%r+|Ka|w?!7_;}1{V!tzJRApjx!Ks2tEMX!<+}Bb QND(9VG_!G{eb1@?0>x?&PXGV_ diff --git a/WPy32-3720/python-3.7.2/Lib/http/__pycache__/cookiejar.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/http/__pycache__/cookiejar.cpython-37.pyc index f652719faf1465b02e61466fd31e96303e189062..d8f68ba5568d91b1968c44e6d1015015ba8cb533 100644 GIT binary patch delta 22 ccmdn7ka@>KW^N~5UM>b8=r7y2k$de008APO82|tP delta 22 ccmdn7ka@>KW^N~5UM>b8IOkEjk$de0086_D_5c6? diff --git a/WPy32-3720/python-3.7.2/Lib/http/__pycache__/cookies.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/http/__pycache__/cookies.cpython-37.pyc index d8db9d9e62e363ba2362d143c2cdbcfe603c0692..f9bf7ecdf89dde78d399b59e1008638d5a0e5a92 100644 GIT binary patch delta 20 acmZ2lzO%8?x_(UE^9*Ya{@vqg1yiV z*9wj(3`?EhsFHlNmF;>1#t-)=QB}YN`vj4WYG+gzJ&uzQLKvY9;TZc?7wT?@zh!xJ zfWeej3$&Ok_&*tK-2e|@{MRc;9?46)jZObHv1DK~lu%`s3?zt;{p@It^q0Hr zsBv(-#i$Md$>k7e+;|@d2}&=_RjUG4tJ#`lLsVXq;9lycQ!lL1Y*~`V=b)d24+{eE zX~L*IK1qC)!qGLz?uAZ|UO*Lfv>GiHB|C?6 zd8h}yyuNlCb`b`^`yPglR}hOJNs>pd7D%m2B6NUl`UA#Pc!wNbltB9;NuUBcj)1w- zL4dMGKabY^@*QGtIxbqL72|xK+J0)sAjBUS)=dPpay1=empWhcRa9s{@?{`~36KT& zBZ>4fT;Zf~yX&#gl>`et3t)=5eDVL;S86r9>V48b0m~q-X{201*drgr!$p(E$CEcn z76;8sJ_&!%H7QEVYo)Hbs88nWC7yxIB7T8CcO@W|-2R?P6P2Rz7IvE(4WY-Y`P zZdn`8<>8CLpAH&FHg-D21~MDQHi}wahvya-PVr9*bc50tY2jyyLQ2lW(#aP4(tiOs C2Qiue delta 1913 zcmaJ?&2JM&6wmB#oF)F)7;qd18`~r?Y_K4t0TL5HBq()4fDpcfWGQm(jk1zsM{jMl zmx@adtvJpJ34{ajD9I100(kIIJrE0B#)MfH?HM*(SR-2`kM{GxI*?_ukBV z`^Nms49RommS42YO9XA+N#y+<#oeRHpLFB2kQ&djE|JYRt9poyV^R z7iaoOElw~X3`%deWIcrqc{}QH5y|ipLUOSrjEUQ?|^C1;R^zq(M=WDi}Mw)Mv+kW65i1yv2RF{RE9) zKk*>tQ*ade0kkm=jo;t38UHyh3h}PE*X!i_2Ei=?>P0?BUNB22xI@9v-;3%p5{!f* z-9Y<#MznON3+M*L;|3~UpkIr4caCiQRDqkc3=&X<47we=52sGgg_+sQMzbvbO4#V1 wd{@j;Yjk?&%$hNWJ=Fl9z5~=BfQkX%S7;)^iaa-w9~9S3RKDWQYZIma0D)gVdH?_b diff --git a/WPy32-3720/python-3.7.2/Lib/importlib/__pycache__/machinery.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/importlib/__pycache__/machinery.cpython-37.pyc index 2e12ec504b67b1308daeffd9e69fcf0d2d848cd7..8b850c450f60486ef655bf0588947bd7cae9e273 100644 GIT binary patch delta 60 zcmcc3{*;~DiI6KY!%~}R2-97l$?=SmKsx>oL`U{T$CK@6XRcy Onimw{xcM9tFCzdm;uE6) delta 50 zcmaFLew&@!iII(2OinF|amg>w%gIknDc-Ehyh(xa O*5n7u(LmBhB@+NN!4zfy diff --git a/WPy32-3720/python-3.7.2/Lib/json/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/json/__pycache__/__init__.cpython-37.pyc index 82f80a5dc6c5698f926d4a63b28db8adc21ec027..0b9a8be0a3e9e55e94d620a6c83a4ce2598da63b 100644 GIT binary patch delta 20 acmX?|a5{n8iIG diff --git a/WPy32-3720/python-3.7.2/Lib/json/__pycache__/decoder.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/json/__pycache__/decoder.cpython-37.pyc index a35208a9e60059538ddd9ba3a8129b92ca85c76e..30472fa5ae6be4f916ca7fae506d49548d634eaf 100644 GIT binary patch delta 20 acmezA^V5ghiIcaX5n8iIcaX5n8iIDRRyg8 delta 20 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 delta 6839 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 Np$y2@tN-m5{|AMby-ffB diff --git a/WPy32-3720/python-3.7.2/Lib/logging/__pycache__/config.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/logging/__pycache__/config.cpython-37.pyc index 242c104ed7e63f517a3602978512e1b536fa53c4..abb3e16fd85fd7a964f8ac92c2d6d5ac015d4b8a 100644 GIT binary patch delta 22 ccmZqJ!q~8dk=u!vmx}=iCX{X5$o(}E07cyfod5s; delta 22 ccmZqJ!q~8dk=u!vmx}=iE_u{$nmx}=iCX{X5$o+LW07{exB>(^b delta 22 ccmZp;z|?SoiQ9>nmx}=iE_u{$!G07^;+1poj5 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/__pycache__/__init__.cpython-37.pyc index e5c50fc0f35c22ec9fc9bc3b0b739df290c668c2..ab5bebcd1c53973a460757b393026eb4e1d8dba0 100644 GIT binary patch delta 21 bcmX@Xc!H7FiIAGPRvP-V)Jp1cl7aznk>T-z^FVq kmnEA~e)3HgT}JuM?5xKbrDTCRi{wFsGAf}m`30K~0H2u_s{jB1 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/__pycache__/build_env.cpython-37.pyc index 43d2b09cd0c7fc75e26169636481aa28bc9e3898..f5d5b93c9713ffdfbdc66f10fcd8fb32bfa9f04c 100644 GIT binary patch delta 22 ccmZ2zwa|*!iI delta 22 bcmeA%?=k0f;^pOH00Iur+8CCNy!FxmGfV`4 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/__pycache__/configuration.cpython-37.pyc index 90646a8d6ef394bf0ed66ea6844ef73e1cafef5f..c86742c7ae42df26cb4bac73c4143d1b27465b1e 100644 GIT binary patch delta 48 zcmaFs^VWyYiIb8m{hhgCb)Ye-|`>;VU7pZ delta 25 fcmdnGlyU1)Mm{HAUM>b8;P9-C>1f}`w>$^{S|0}- diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/__pycache__/exceptions.cpython-37.pyc index d71db45830819e9dd01246b3ed872ef6a26ef43a..e1c7f6eaef8fe2b9b7416420614e1f2f39851059 100644 GIT binary patch delta 23 dcmaD5{UDmpiIlyTWnMm{HAUM>b8m{hhgX5I9Se8+jYZ?R;QloS-10!24J;5`-s048w`L;wH) delta 42 vcmZ2>lyTWnMm{HAUM>b8;P9-CxiEPn-*H~b%7 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/__pycache__/pep425tags.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/__pycache__/pep425tags.cpython-37.pyc index 1ed814889499d20508b9f14eaac26ff49483d094..f8502bd53165745d3d0c367a9dd38b881f0a2cee 100644 GIT binary patch delta 35 ocmaEC|Ja_-iIb8m{hhgreMiNKHF3PY=a0Z delta 25 fcmX?oit+R*Mm{HAUM>b8;P9-C(Oj^R&o&hRVk`#r diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/cli/__pycache__/__init__.cpython-37.pyc index 8e90705a113c63022059104452a8b751a416b9e6..ddc17fd244487cf215b686c5eeb04225944dcec1 100644 GIT binary patch delta 22 ccmbQtG?|IliIjmx}=iCY5cBDNESM_tp^rXygb> delta 25 fcmey}%=o*Rkjmx}=iI6P}(d}BBAy>$ctUq%Ns diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/cli/__pycache__/main_parser.cpython-37.pyc index fe261544fda8d2143697ac2a486b116bc7376099..719573c0f24e1790076302eba0116475d10e8a96 100644 GIT binary patch delta 23 dcmdlfv{Q)BiI?M?1y29~ delta 23 dcmdlfv{Q)BiId$5&%~b2Xp`c delta 23 dcmaFu`r4JxiI?q diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/cli/__pycache__/status_codes.cpython-37.pyc index 9e3305c833e1544e45686eea68a5c11b8436659b..08861a9bb70bb0dd72afa3680114f7f6aaecbeae 100644 GIT binary patch delta 22 ccmbQjJcXIpiIud|a5%iIyhz delta 23 dcmX>ud|a5%iI?I(1*ZT2 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/commands/__pycache__/check.cpython-37.pyc index 54aee1c1146c5568d6c0c700a0eeca446294212f..dd84b9ee988b8d84d1c073ff6b50898cd566de91 100644 GIT binary patch delta 22 ccmdnMwSkM*iI*n! delta 23 dcmbPhG}nmFiIiS4FExi1w{Y= delta 23 dcmdlfwo{DHiIz>% diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/commands/__pycache__/help.cpython-37.pyc index 3d4bd4bd309d5020791087bb606cd9d21392237e..07ec41c3c34aaed253542b381416f17dee96dd89 100644 GIT binary patch delta 22 ccmcc3d7G2hiI06NbFH~;_u diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/commands/__pycache__/install.cpython-37.pyc index 353a2aff22966aa84316c61273be0e5f4dd6abf4..a885e3590b20876728775f1177b4fd27cbf0b4ed 100644 GIT binary patch delta 23 dcmZ3JxF(U$iIK0002+`2K4{{ delta 23 dcmZ3JxF(U$iIkg;^pOH0D?(n8)Fkg;^pOH00Iur+8FzZyuSb^Ed+-E diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/models/__pycache__/candidate.cpython-37.pyc index 3d9f6560dbf42b7155afbd4ef37c75f2bcb2324d..f95e44ef88a315bbffd76aefb4e1b8bb91f8fbeb 100644 GIT binary patch delta 22 ccmZ3$wSbG)iIq)tiIq)tiIb8m{hhgMqt54K7LU)CR^KI%(k1AMVI&h0MZ5u$^ZZW delta 37 rcmX?pnDO{wMm{HAUM>b8;P9-C5uUS=k6)CH+1A$f7t>~C(Iq|rz1<1k diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/req/__pycache__/req_set.cpython-37.pyc index 54d9f93e18b1e5f527aaab994b42180548dc1c03..ca49bac0d1b9261f962d193304401a33ce388f22 100644 GIT binary patch delta 23 dcmeCz@7L#Z;^pOH0D?(n8)IA*Hu5!!0{}pM1;PLT delta 23 ccmeCz@7L#Z;^pOH00Iur+L#9UjeL#b069Sg5dZ)H diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/req/__pycache__/req_tracker.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/req/__pycache__/req_tracker.cpython-37.pyc index b28104b5992504f070140bebc13b183a112ef97b..13829e19b9b2c3e3fbe457803ad59cb2a923fe6d 100644 GIT binary patch delta 22 ccmX>paZ-ZUiIpaZ-ZUiIjmx}=iCY5cBQ48D1=jQ|fU=arw delta 25 fcmcc9!g!~Jkjmx}=iI6P}(E(LGo^K$|KTX6=} diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/utils/__pycache__/__init__.cpython-37.pyc index 2a7a61657f004371624a726c44bce1a56612bce0..0283b47472a90ba90efbbf197ce687eaa06ad32e 100644 GIT binary patch delta 19 ZcmX@ac!-hPiI(^b delta 22 ccmey)`JI#3iIjmx}=iCY5cBk#66}SDpd@U0?@f delta 25 fcmZoY$=G_5kjmx}=ixIAlPxSKcfm8SpzRA&Zf diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/utils/__pycache__/models.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/utils/__pycache__/models.cpython-37.pyc index 00c05efe1c5829ba0d74dbcc087515cf5071be1c..a93538f487dead35e45a0dc997f9332199d5d062 100644 GIT binary patch delta 22 ccmbQvKb@b~iI4R075VY!2kdN diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/utils/__pycache__/packaging.cpython-37.pyc index b8f42832646d3342ef4f52d017040d4a46ceaa76..7190632aa10e904072d4436d99468aef7a372ead 100644 GIT binary patch delta 23 dcmdlkvR#DFiIVbc05T2)?f?J) delta 22 bcmZo=Ze`|m;^pOH00J)0+8D8oycLW9DoO+W diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/utils/__pycache__/temp_dir.cpython-37.pyc index d8e447b8e1f778a29706b28f84094bdbdc4cd052..70a0ab87d8d2bd3bbb6b713e31c740f219627772 100644 GIT binary patch delta 23 dcmdm@wndH4iIgV3;;!x1;GFS delta 23 dcmdm@wndH4iI31v~%% diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/utils/__pycache__/typing.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_internal/utils/__pycache__/typing.cpython-37.pyc index 9d379be0430f00b281ff991f9cbbd52e7b1782a7..2f5bbf745f04e18955b69fb22b6988b135282d9a 100644 GIT binary patch delta 22 ccmdnRwTp|_iIdi3IJEX2ciG~ delta 23 dcmaFj`NWgYiIqiIqiIkc1VoRiIkc1VoRiIjmx}=iCY5cBu}|8_R~i5SRsjb2 delta 25 fcmZo($k@D)kjmx}=ixIAlP9>;IwD-8euQAGx^ diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/__pycache__/pyparsing.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/__pycache__/pyparsing.cpython-37.pyc index 934ddc7c39d8aa56614581a09caf453418cff40d..61d18a20803b2e39eaf4d167044410e629b5b5aa 100644 GIT binary patch delta 34 ocmX@OoA=;uUOp#YUM>b8m|V6oM&V*3Un?JDD<9KVKIYA_0JrW68~^|S delta 34 ocmX@OoA=;uUOp#YUM>b8;PR}Ed9%Hdua%Fnm5*sFAM@r|0I{tJFDu diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/__pycache__/six.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/__pycache__/six.cpython-37.pyc index 3a69414704ae8e88d344a122462799075c17a61d..618635984224f0f6fbb0d1c77a1e927dc6f0bfea 100644 GIT binary patch delta 25 fcmdmRj&Z{|Mm{HAUM>b8m|V6orlx5lpHeyiXSN5= delta 25 fcmdmRj&Z{|Mm{HAUM>b8;PR}EIa0TgPbnP$V8aI~ diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/cachecontrol/__pycache__/__init__.cpython-37.pyc index e302c01fe7fb4e40e59df5e4318d2300ed56f9fa..3bce2cbeee0b8e6618810270d8da86b09cf2e046 100644 GIT binary patch delta 22 ccmZ3%vVw)ziI delta 22 ccmZ3%vVw)ziI8vsk}2BiQ1 delta 23 dcmca7eovgwiIYG&ef;^pOH0D?(n8)M8T@_qvVEi46I delta 21 acmZo>YG&ef;^pOH00J)0+8C3Gyx#yOZ3J=v diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/certifi/__pycache__/core.cpython-37.pyc index f47d7505679f79853cd19d03e6cdfe45e0d64a96..4f2640e63416614a6eaeb96d5ecbf1bde0c64d46 100644 GIT binary patch delta 22 ccmeBR>0se?;^pOH0D?(n8)Hm1^8RK705m8Cj{pDw delta 22 bcmeBR>0se?;^pOH00J)0+8Bk6yuTR%EGPt$ diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/__init__.cpython-37.pyc index 68dd4ec0a576b483733e2c0a9f05ffaa929e1844..8cd9e340f843e240e1ee80953c18bd1e7d0b5899 100644 GIT binary patch delta 22 ccmX@dc8-nLiImf_Mm{HAUM>b8m{hhgW=8c!KKU#FXs-w9 delta 25 fcmZ2`g>mf_Mm{HAUM>b8;PR}E5v$tBC!YlXT^R;_ diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/big5prober.cpython-37.pyc index 07a5f6a96ca06337f471c06c2ad62f17b01d1559..f4290e6fd403af7e0f8d22865bae55a569e75d61 100644 GIT binary patch delta 23 dcmaFF@rZ-ZiImc1(=diImc1(=diI+5O05>QEU;qFB diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/compat.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/compat.cpython-37.pyc index 0e4ced20c5825082968300e13ac71c1bf622884e..21a2692d216784a21102326c7176bc5d4063f1a9 100644 GIT binary patch delta 22 ccmaFL^puI$iIZb=>Px# delta 22 ccmdlZvPXp1iI?m}1;qdW delta 23 dcmaDa^j?V1iI1%3bk diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/euctwfreq.cpython-37.pyc index ce56e5382e3547dde13104e00f6056a2926be540..9b5587a097de5e21c57c026f21c21c348be09184 100644 GIT binary patch delta 25 fcmdmZg>mB*Mm{HAUM>b8m{hhghNE^PpK=xeW*rA- delta 25 fcmdmZg>mB*Mm{HAUM>b8;PR}EX|3MKrb8m{hhghAn6#-*hhkSi1)J delta 25 fcmZ2Fm2v4*Mm{HAUM>b8;PR}Ec^$BkZ@L!%Rf-1k diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/gb2312prober.cpython-37.pyc index 61752cf7f679ac7374948e5468d703583c726fb3..c8146b0d7675fbe06e87e89b47297696ba55c688 100644 GIT binary patch delta 23 dcmeyw@ri@aiIb8m{hhg=3DAUzU(jnapefH delta 25 fcmeylhVkbbMm{HAUM>b8;PR}E*_g7CFFOnXXT1l4 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/jpcntx.cpython-37.pyc index fa741e931b4b918ba9c7662c6d34ae36d028d399..4e735fc0af0efdbe2b19ed301b2912bceead6d3e 100644 GIT binary patch delta 25 fcmZoz$<(ltiO-3bmx}=iCY5cBS>n5quV@MYSvm)n delta 25 fcmZoz$<(ltiO-3bmx}=ixIAlPcKdAPE1CiTQ91_0 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-37.pyc index 97036acd7769ba3cc5616430919c978ffe097246..4882c1682714e2bc64bcc1e557ff8c43df525172 100644 GIT binary patch delta 25 fcmX@NgYn!BMm{HAUM>b8m{hhghTC`}pF<1)Wl#q( delta 25 fcmX@NgYn!BMm{HAUM>b8;PR}EQ8(Ji=MVz`U2Xb8m{hhgCewW*--JQ{XIuyV delta 25 fcmbRDm~q}?Mm{HAUM>b8;PR}Ek#XC|H=z&!T?7Wl diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-37.pyc index feb143905fd75e431f75fb6021fe38d82afe50e8..8de6005734ba9d2ba65a1a398a2909805c6a8523 100644 GIT binary patch delta 25 fcmZ3ogK^0YMm{HAUM>b8m{hhgrqF03pI8h4U!?~a delta 25 fcmZ3ogK^0YMm{HAUM>b8;PR}EnP9k)Pb>xiSJehh diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-37.pyc index 18dac787c521902d34ee3049524ee70432205a2e..fe516904a88b194faffc6c963eaf553ab0070745 100644 GIT binary patch delta 25 fcmX@Pmht3TMm{HAUM>b8m{hhgMpAbp-|jE~W1I($ delta 25 fcmX@Pmht3TMm{HAUM>b8;PR}E3Dnuhw>t~~Tw(^? diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/langthaimodel.cpython-37.pyc index 07f7986eac87723d917413704ece014d342e75f4..6eb43cb4f3ab049dba1ef7697b7b9c40581b1fd2 100644 GIT binary patch delta 24 ecmdn8mT}8kMqVdgUM>b8m{hhg=HW)(b8;PR}Ek=n?+JPZI)r3N_w diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-37.pyc index 17c339845d1a0ae15f0c533730e80cb35f506d19..a2f20520cf33498b153a98e17d1dc9df1b795d95 100644 GIT binary patch delta 25 fcmX@TmhtpjMm{HAUM>b8m{hhgMqXzl-`+3)WE}^Y delta 25 fcmX@TmhtpjMm{HAUM>b8;PR}EiPPT5w>Jy`T@42A diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/chardet/__pycache__/latin1prober.cpython-37.pyc index aba608f968695c6a778ea4d6b01b51fcee0eaffc..c5211ae2d26713f4cb989bd5c1969b7dc7fb1eae 100644 GIT binary patch delta 23 dcmew;_EC(_iIo0suzN1(*N; delta 23 dcmaFL@sxwliI!060?xfdBvi diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/colorama/__pycache__/ansi.cpython-37.pyc index d8f77028a82bd2b67e3431a4eb478c08c4bc38ba..0efebb57bb03d6748fcf4bcf7b41554b8372d92a 100644 GIT binary patch delta 23 dcmbOrH9?BciI1o!{| delta 23 dcmbOrH9?BciIZiIt<8 delta 22 ccmeyb{9l>ZiIb8m{hhgMrPSYK8;!cZx{#? delta 25 fcmdn?i*eg8Mm{HAUM>b8;PR}E*|TsXpGGYJYB~qR diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/distlib/__pycache__/resources.cpython-37.pyc index f6e35dcaf514712885adbc06c424b6ce73655c58..2d78fde1a4ddcf0a3df3e9586fd24841a9154c50 100644 GIT binary patch delta 23 dcmeAO?Fi*_;^pOH0D?(n8)FK!H}X|!0RTqH215V< delta 23 ccmeAO?Fi*_;^pOH00J)0+892qjeJ#F06Xmj_5c6? diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/distlib/__pycache__/scripts.cpython-37.pyc index f75bb1053216052145e0a227ca2245fe19daa0be..edbb9afb75bfed0131e204ef58011ad4d66687be 100644 GIT binary patch delta 20 acmcZ|b~}vQiI(`US)Q delta 20 acmcZ|b~}vQiIb8m{hhg=I{HBd~Uk|dp-%y delta 25 fcmccejp@oaCO#)#UM>b8;PR}EQGB_P&uupVZF2|% diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/__pycache__/__init__.cpython-37.pyc index c4802589063d7776cbc08aef5ffa0c0afadd04e0..6f4dbd996ac3a145205c00b0b1b42748c1687e0e 100644 GIT binary patch delta 22 ccmZ3?wU~?7iIt<8 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_ihatexml.cpython-37.pyc index 784d9f1861edef8d6b4ce021ad97d0ffb0fdd226..bba032b29b36a924a4dea1de4944ae6d6efef22b 100644 GIT binary patch delta 23 dcmX?1|b8m{hhg=5W(SzWfLPa=r+$ delta 25 fcmeynf${GKMm{HAUM>b8;PR}E(Wu|ZmmdKDW{3wW diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_tokenizer.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_tokenizer.cpython-37.pyc index 78d10a10f6e021d8736c47d5c570c50b2d081203..7e1df2e22f3164eb8e81936ec82f4b6934461c02 100644 GIT binary patch delta 25 fcmca~gz3@|CO#)#UM>b8m{hhg=C0vJK9@xRZG#AH delta 25 fcmca~gz3@|CO#)#UM>b8;PR}EQPJMW=duU@V2TFC diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_utils.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/__pycache__/_utils.cpython-37.pyc index eb4c688f7cb84dbec975c7648ac43ddf83d22b96..e1f845c143af1d967edd16d8f067d4d3ecc199b5 100644 GIT binary patch delta 23 dcmaDY`C5|CiIE~WdZb8m{hhgX4dUSzO8(WTy+45q6rKD delta 28 icmbR7hjqpuRz4?QUM>b8;PR}E*?ggqZz~@oR~-O->j*Ib diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/__pycache__/serializer.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/__pycache__/serializer.cpython-37.pyc index 6139eeb4d499e4835f0f24a57a5102f71d443262..e989dbc864dae6cbbad768c855eb6c6ddb7426f3 100644 GIT binary patch delta 23 dcmcZ*av_AziIpby diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/__init__.cpython-37.pyc index fd8337c9972917a96ada27981a8e4135f36f2cf1..68b6dddbbc723dc8cec6cddf9bc1b90f2ecb3e3c 100644 GIT binary patch delta 22 ccmZ3(yoQR diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/datrie.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/_trie/__pycache__/datrie.cpython-37.pyc index 0eaaf43a015ee5713d1ed99fe5dbe6461ba481f4..021d47b0a2cbd13e7bc55e91f2e9cdf003cadce0 100644 GIT binary patch delta 22 ccmaFI|Bj#6iI>wUO_EHUL_W2dn@9 delta 23 dcmaDC{w|!)iIfb3TU8iIu2LMu625|rY delta 23 dcmX>fb3TU8iI+0{~6r1~dQw diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/html5lib/treewalkers/__pycache__/__init__.cpython-37.pyc index 0d4f5a1cdc5ae62aefb4e9d42aec34dcd8bc3f44..a5c5052a3487b9e60b0b01be45034a8ebd4ef9e9 100644 GIT binary patch delta 22 ccmZ1=zd)YXiIeyx##Pz65;$ diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/idna/__pycache__/core.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/idna/__pycache__/core.cpython-37.pyc index 18811566536456e2665f39f75acc1136aea96353..23b2ee873342faa859beb625af601d17dce80265 100644 GIT binary patch delta 23 dcmaFv_S}uniIb8m{hhgrf&I0zBR!BWNZjA delta 25 fcmdnBoN?E3Mm{HAUM>b8;PI@DIXr(O-)_*a;^pOH0D?(n8)LZGH}d^r0{}ST1%?0s delta 23 dcmeC+>)_*a;^pOH00JJ*+L)_s8~J{*0RS~E1!({P diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/idna/__pycache__/package_data.cpython-37.pyc index 57cefb40b1427a06b786f889eacd5f4a711022de..d02a4494e12d2c18836931787579a712936fd290 100644 GIT binary patch delta 21 bcmcb{c#V7L06^IVvH$=8 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/lockfile/__pycache__/mkdirlockfile.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/lockfile/__pycache__/mkdirlockfile.cpython-37.pyc index 81f7ea6b60c6e5aa13a68a06500201fa86016b5d..1ed4f60effee90930bcb1a5ca90d5d2578c2f649 100644 GIT binary patch delta 22 ccmcaBa#w`ciIn+a delta 22 ccmbOsFhhXXiIb8m{hhghG)`7zU%P-ZPo~9 delta 25 fcmaF5pYiE_Mm{HAUM>b8;PI@DvF_W*cRd~eW@`tl diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/packaging/__pycache__/__about__.cpython-37.pyc index 5bfb99ecbd62352f45081133b24d99aab096387a..efacaf057a7aa53c4c7074372ed593602cc0677f 100644 GIT binary patch delta 23 dcmcb|dXJUQiI2>?Zz1?K<& delta 23 dcmcb|dXJUQiI^t# diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/packaging/__pycache__/__init__.cpython-37.pyc index adc05c2aca44f0c9a1f45d3863dcc2ee659f0451..892c95e49335c74f06329755e54c5d7577f3f0a7 100644 GIT binary patch delta 22 ccmdnPvWJD&iI7iI7iI?hL21Eb= delta 23 dcmZ4Ny4aP^iIb8m|V6oCO>~8pNcO4UM&YR delta 25 fcmdlqi*eH|Mm{HAUM>b8;PI@DY0BBir{W6$Ruu+Y diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/packaging/__pycache__/utils.cpython-37.pyc index 0902f0b4bca32125afcc6bc6a5e880b8449d19c7..5f0e0c3a8d050f5d7569ffc913b24cfc1a937d18 100644 GIT binary patch delta 23 dcmZ3*y^5R9iIiIiI@~ delta 22 ccmaE-^-hb|iI~B(Rz4?QUM>b8m|V6oMtf-^-&Q_GjVb_#?g*{` delta 28 icmdn?g>~B(Rz4?QUM>b8;PI@DIWeP=Zz~_8Mil^o*a%ht diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-37.pyc index 2eaa47a5e7f69e2637f788aca53c469a6c6d5d16..29f811b9c8a21fe7db156ab1b0085675f7ce3b14 100644 GIT binary patch delta 22 ccmZo=ZDr+k;^pOH0D{S78)G~-@>Vbb05d-Y9{>OV delta 22 bcmZo=ZDr+k;^pOH00JJ*+8CpaycJ9UD>(!p diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/progress/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/progress/__pycache__/__init__.cpython-37.pyc index 7aea1cfc4d5f348c82a7e02a7726770a702b3afc..0aca99b12e91d21cc5219b335e7ed254f63caf24 100644 GIT binary patch delta 22 ccmX>pcT$emiIpcT$emiItep;N@iItep;N@iI06aMbj{pDw diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/pytoml/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/pytoml/__pycache__/__init__.cpython-37.pyc index 1ca51c6b76ae70505e26c9b8ec60f9e8d00670f5..d3a7b9ab5fe464b8996eb07e8caf14c512354041 100644 GIT binary patch delta 22 ccmey(^qYy-iI1#JKT diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/pytoml/__pycache__/parser.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/pytoml/__pycache__/parser.cpython-37.pyc index 3ed8d72c68cc969f8c15ca61f410912ba20a0445..07da5d6b5a2655d83aabd02d53c2cc45fc1b1243 100644 GIT binary patch delta 23 dcmX@@ciNB7iI1pr1W1^)m5 delta 23 dcmcb`d5e?JiI^t# delta 23 dcmZ1^y-1qRiIjmx}=iCYNoDaSYqY_sS6fX6pz9 delta 25 fcmey-%=n|3kjmx}=icsy%kbV4@ry>bKqUFZh| diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/requests/__pycache__/api.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/requests/__pycache__/api.cpython-37.pyc index 7868806e2d0c6f326a06b6d334853e5a215dc046..5bee20445ec79788cc91795b7ad42e40db6dbfdf 100644 GIT binary patch delta 23 dcmca-bkB&-iI?vG1@`~| delta 23 dcmca-bkB&-iIpby delta 23 dcmbQ~IMb2OiI(^b delta 22 ccmX@lbDoFSiIb8m|V6oM%im4UxX(BWHbj# delta 25 fcmaDhiSgMaMm{HAUM>b8;PI@D`RBfoFTxW5V9W

pby diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/requests/__pycache__/models.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/requests/__pycache__/models.cpython-37.pyc index e1cbb821b09eeb4feaa15ef3b687f3dc8a756c49..858a79df9fccc11de7f0132fc9cc2c034addd92b 100644 GIT binary patch delta 25 fcmZ3#hjINLMm{HAUM>b8m|V6oW=`iuKE*fyWib8;PI@DdEB~@PcaSvUQh=i diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/requests/__pycache__/packages.cpython-37.pyc index 34ff82209a344ee4751cbbf62f7e31a85e67f94d..098652e2a0bf5ee34509f59f48633270d162ae3a 100644 GIT binary patch delta 22 ccmZoi}Mm{HAUM>b8m|V6oW?Jb+zMI|vY0(IG delta 25 fcmaDpo$>i}Mm{HAUM>b8;PI@DnNqZo@1{2ZVLJzk diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/requests/__pycache__/status_codes.cpython-37.pyc index f96be583a86e438a490bcef15ae5c7d605818045..93bac7f1e4dca0cd310c2302d0dfedd9f16928ba 100644 GIT binary patch delta 22 ccmX@9a8iNSiIb8m|V6o#;9^5A5RznTZ{(f delta 25 fcmbQWhH=&!Mm{HAUM>b8;PI@DNi5yS#}ftsR2K#) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/__pycache__/__init__.cpython-37.pyc index 984bbcc6674950e827141f996100a8d3270961a3..d063008e94ab84e7e743af18a7f20b49e9085052 100644 GIT binary patch delta 22 ccmX>ma7=*LiIma7=*LiI?nf26O-b diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connection.cpython-37.pyc index 215d21edf1971fab09d0a398003ae51908800b1d..8e2ec8b93760a1588c27457c4cbec9c61ee3eb50 100644 GIT binary patch delta 23 dcmZ4PzuceCiI_zL9UHIsi<72EzaV delta 23 dcmZ4PzuceCiI2LM3U1ycY3 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/__pycache__/connectionpool.cpython-37.pyc index 02e656c12bdbb415b971723270032a295d3ecb4f..01e2655768390ef4c5958edf71d872951686747d 100644 GIT binary patch delta 25 fcmaE{gYm@b8m|V6oW@gVuzNi=gZ)FH) delta 25 fcmaE{gYm@b8;PI@Dk?h>a7Zn2lW7`J& diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/__pycache__/exceptions.cpython-37.pyc index b5568e272e7404717ab83b6cee42a3352aeddf1f..9caa86753baa1708568bf56bdf0b414bb932b73d 100644 GIT binary patch delta 23 dcmZ1+xHyo{iItdRmm%iI#07T#hwg3PC delta 22 ccmX>tdRmm%iIb8m|V6o=2Y57J_AnxVFCx0 delta 25 fcmdltiE-Z~Mm{HAUM>b8;PI@D;Y``cXW$6{Q}+ex diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-37.pyc index 5b8ee37526fca633a25514378d37a10b7ff295f1..4bf5a73f8abc46c395b0c7bb0d624815f14918ed 100644 GIT binary patch delta 19 ZcmX@bc#4tRiI diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-37.pyc index 4e6ff9a5aaf092c36932f9aaab6b7f6c5e87969b..d9ca530ed5027b819fceb09e9d5a04dd1423f0e7 100644 GIT binary patch delta 22 ccmdnPw1n+a diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/packages/__pycache__/six.cpython-37.pyc index adcc6c06506fde16544b89b024c802c94b217320..6dee3d7762e046a885ca01aa5dd8332220bb7a15 100644 GIT binary patch delta 25 fcmcbzkMYVrMm{HAUM>b8m|V6o=3B)^KDT%PZfppH delta 25 fcmcbzkMYVrMm{HAUM>b8;PI@DnN+%w&n+GRV~Phf diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/packages/ssl_match_hostname/__pycache__/__init__.cpython-37.pyc index 9b21c2b9f4ef94e5217aba423666684af4c17601..48505faad87cc6fb0b43b5bda9e29e9cf2fae64a 100644 GIT binary patch delta 22 ccmZ3>vX+I{iIvX+I{iII06Opm9smFU diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/pip/_vendor/urllib3/util/__pycache__/connection.cpython-37.pyc index 6030fb819d0d5ef504356d3fc2c1a95a980685d3..d76425d7033611bb690210ae74c7533b79aad6f7 100644 GIT binary patch delta 22 ccmaDT@lb--iI?vym^w5CB|X2VVdH delta 23 dcmeyA^eKtYiI07EYYrvLx| diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/INSTALLER b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/INSTALLER new file mode 100644 index 00000000..a1b589e3 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/INSTALLER @@ -0,0 +1 @@ +pip diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/LICENSE b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/LICENSE new file mode 100644 index 00000000..e91b1359 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/LICENSE @@ -0,0 +1,27 @@ +psutil is distributed under BSD license reproduced below. + +Copyright (c) 2009, Jay Loden, Dave Daeschler, Giampaolo Rodola' +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the psutil authors nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/METADATA b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/METADATA new file mode 100644 index 00000000..55332fbd --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/METADATA @@ -0,0 +1,522 @@ +Metadata-Version: 2.1 +Name: psutil +Version: 5.6.1 +Summary: Cross-platform lib for process and system monitoring in Python. +Home-page: https://github.com/giampaolo/psutil +Author: Giampaolo Rodola +Author-email: g.rodola@gmail.com +License: BSD +Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,pstree,monitoring,ulimit,prlimit,smem,performance,metrics,agent,observability +Platform: Platform Independent +Classifier: Development Status :: 5 - Production/Stable +Classifier: Environment :: Console +Classifier: Environment :: Win32 (MS Windows) +Classifier: Intended Audience :: Developers +Classifier: Intended Audience :: Information Technology +Classifier: Intended Audience :: System Administrators +Classifier: License :: OSI Approved :: BSD License +Classifier: Operating System :: MacOS :: MacOS X +Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000 +Classifier: Operating System :: Microsoft +Classifier: Operating System :: OS Independent +Classifier: Operating System :: POSIX :: BSD :: FreeBSD +Classifier: Operating System :: POSIX :: BSD :: NetBSD +Classifier: Operating System :: POSIX :: BSD :: OpenBSD +Classifier: Operating System :: POSIX :: BSD +Classifier: Operating System :: POSIX :: Linux +Classifier: Operating System :: POSIX :: SunOS/Solaris +Classifier: Operating System :: POSIX +Classifier: Programming Language :: C +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.6 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: Implementation :: CPython +Classifier: Programming Language :: Python :: Implementation :: PyPy +Classifier: Programming Language :: Python +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Topic :: Software Development :: Libraries +Classifier: Topic :: System :: Benchmark +Classifier: Topic :: System :: Hardware +Classifier: Topic :: System :: Monitoring +Classifier: Topic :: System :: Networking :: Monitoring +Classifier: Topic :: System :: Networking +Classifier: Topic :: System :: Operating System +Classifier: Topic :: System :: Systems Administration +Classifier: Topic :: Utilities +Requires-Python: >=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* + +.. image:: https://pepy.tech/badge/psutil/month + :target: https://pepy.tech/project/psutil + :alt: Downloads + +.. image:: https://img.shields.io/travis/giampaolo/psutil/master.svg?maxAge=3600&label=Linux%20/%20macOS + :target: https://travis-ci.org/giampaolo/psutil + :alt: Linux tests (Travis) + +.. image:: https://img.shields.io/appveyor/ci/giampaolo/psutil/master.svg?maxAge=3600&label=Windows + :target: https://ci.appveyor.com/project/giampaolo/psutil + :alt: Windows tests (Appveyor) + +.. image:: https://coveralls.io/repos/github/giampaolo/psutil/badge.svg?branch=master + :target: https://coveralls.io/github/giampaolo/psutil?branch=master + :alt: Test coverage (coverall.io) + +.. image:: https://readthedocs.org/projects/psutil/badge/?version=latest + :target: http://psutil.readthedocs.io/en/latest/?badge=latest + :alt: Documentation Status + +.. image:: https://img.shields.io/pypi/v/psutil.svg?label=pypi + :target: https://pypi.org/project/psutil + :alt: Latest version + +.. image:: https://img.shields.io/github/stars/giampaolo/psutil.svg + :target: https://github.com/giampaolo/psutil/ + :alt: Github stars + +.. image:: https://img.shields.io/pypi/l/psutil.svg + :target: https://pypi.org/project/psutil + :alt: License + + +Quick links +=========== + +- `Home page `_ +- `Install `_ +- `Documentation `_ +- `Download `_ +- `Forum `_ +- `StackOverflow `_ +- `Blog `_ +- `Development guide `_ +- `What's new `_ + + +Summary +======= + +psutil (process and system utilities) is a cross-platform library for +retrieving information on **running processes** and **system utilization** +(CPU, memory, disks, network, sensors) in Python. +It is useful mainly for **system monitoring**, **profiling and limiting process +resources** and **management of running processes**. +It implements many functionalities offered by UNIX command line tools such as: +ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice, ionice, iostat, +iotop, uptime, pidof, tty, taskset, pmap. +psutil currently supports the following platforms: + +- **Linux** +- **Windows** +- **macOS** +- **FreeBSD, OpenBSD**, **NetBSD** +- **Sun Solaris** +- **AIX** + +...both **32-bit** and **64-bit** architectures. Supported Python versions are **2.6**, **2.7** and **3.4+**. `PyPy `__ is also known to work. + + +Author +====== + +psutil was created and is maintained by +`Giampaolo Rodola `__ and it +received many useful `contributions `__ +over the years. +A lot of time and effort went into making psutil as it is right now. +If you feel psutil is useful to you or your business and want to support its +future development consider making a small donation: + +.. image:: http://www.paypal.com/en_US/i/btn/x-click-but04.gif + :target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8 + :alt: Donate via PayPal + +Don't want to donate money? Then maybe you could `write me a recommendation on Linkedin `_. + + +Example applications +==================== + ++------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/top-small.png | +| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procinfo.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/top.png | ++------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ +| .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem-small.png | .. image:: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap-small.png | +| :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/procsmem.png | :target: https://github.com/giampaolo/psutil/blob/master/docs/_static/pmap.png | ++------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------+ + +Also see `scripts directory `__ +and `doc recipes `__. + +Projects using psutil +===================== + +psutil has roughly the following monthly downloads: + +.. image:: https://pepy.tech/badge/psutil/month + :target: https://pepy.tech/project/psutil + :alt: Downloads + +There are over +`10.000 open source projects `__ +on github which depend from psutil. +Here's some I find particularly interesting: + +- https://github.com/google/grr +- https://github.com/facebook/osquery/ +- https://github.com/nicolargo/glances +- https://github.com/Jahaja/psdash +- https://github.com/ajenti/ajenti +- https://github.com/home-assistant/home-assistant/ + + +Portings +======== + +- Go: https://github.com/shirou/gopsutil +- C: https://github.com/hamon-in/cpslib +- Node: https://github.com/christkv/node-psutil +- Rust: https://github.com/borntyping/rust-psutil +- Ruby: https://github.com/spacewander/posixpsutil +- Nim: https://github.com/johnscillieri/psutil-nim + + +Example usages +============== + +This represents pretty much the whole psutil API. + +CPU +--- + +.. code-block:: python + + >>> import psutil + >>> + >>> psutil.cpu_times() + scputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540, iowait=629.59, irq=0.0, softirq=19.42, steal=0.0, guest=0, nice=0.0) + >>> + >>> for x in range(3): + ... psutil.cpu_percent(interval=1) + ... + 4.0 + 5.9 + 3.8 + >>> + >>> for x in range(3): + ... psutil.cpu_percent(interval=1, percpu=True) + ... + [4.0, 6.9, 3.7, 9.2] + [7.0, 8.5, 2.4, 2.1] + [1.2, 9.0, 9.9, 7.2] + >>> + >>> for x in range(3): + ... psutil.cpu_times_percent(interval=1, percpu=False) + ... + scputimes(user=1.5, nice=0.0, system=0.5, idle=96.5, iowait=1.5, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) + scputimes(user=1.0, nice=0.0, system=0.0, idle=99.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) + scputimes(user=2.0, nice=0.0, system=0.0, idle=98.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) + >>> + >>> psutil.cpu_count() + 4 + >>> psutil.cpu_count(logical=False) + 2 + >>> + >>> psutil.cpu_stats() + scpustats(ctx_switches=20455687, interrupts=6598984, soft_interrupts=2134212, syscalls=0) + >>> + >>> psutil.cpu_freq() + scpufreq(current=931.42925, min=800.0, max=3500.0) + >>> + +Memory +------ + +.. code-block:: python + + >>> psutil.virtual_memory() + svmem(total=10367352832, available=6472179712, percent=37.6, used=8186245120, free=2181107712, active=4748992512, inactive=2758115328, buffers=790724608, cached=3500347392, shared=787554304) + >>> psutil.swap_memory() + sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944) + >>> + +Disks +----- + +.. code-block:: python + + >>> psutil.disk_partitions() + [sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'), + sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')] + >>> + >>> psutil.disk_usage('/') + sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5) + >>> + >>> psutil.disk_io_counters(perdisk=False) + sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568, read_merged_count=619166, write_merged_count=812396, busy_time=4523412) + >>> + +Network +------- + +.. code-block:: python + + >>> psutil.net_io_counters(pernic=True) + {'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, packets_sent=3251564, packets_recv=4787798, errin=0, errout=0, dropin=0, dropout=0), + 'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)} + >>> + >>> psutil.net_connections() + [sconn(fd=115, family=, type=, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED', pid=1254), + sconn(fd=117, family=, type=, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING', pid=2987), + ...] + >>> + >>> psutil.net_if_addrs() + {'lo': [snicaddr(family=, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1', ptp=None), + snicaddr(family=, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None), + snicaddr(family=, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00', ptp=None)], + 'wlan0': [snicaddr(family=, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255', ptp=None), + snicaddr(family=, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None), + snicaddr(family=, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]} + >>> + >>> psutil.net_if_stats() + {'lo': snicstats(isup=True, duplex=, speed=0, mtu=65536), + 'wlan0': snicstats(isup=True, duplex=, speed=100, mtu=1500)} + >>> + +Sensors +------- + +.. code-block:: python + + >>> import psutil + >>> psutil.sensors_temperatures() + {'acpitz': [shwtemp(label='', current=47.0, high=103.0, critical=103.0)], + 'asus': [shwtemp(label='', current=47.0, high=None, critical=None)], + 'coretemp': [shwtemp(label='Physical id 0', current=52.0, high=100.0, critical=100.0), + shwtemp(label='Core 0', current=45.0, high=100.0, critical=100.0)]} + >>> + >>> psutil.sensors_fans() + {'asus': [sfan(label='cpu_fan', current=3200)]} + >>> + >>> psutil.sensors_battery() + sbattery(percent=93, secsleft=16628, power_plugged=False) + >>> + +Other system info +----------------- + +.. code-block:: python + + >>> import psutil + >>> psutil.users() + [suser(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0, pid=1352), + suser(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0, pid=1788)] + >>> + >>> psutil.boot_time() + 1365519115.0 + >>> + +Process management +------------------ + +.. code-block:: python + + >>> import psutil + >>> psutil.pids() + [1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224, 268, 1215, 1216, 1220, 1221, 1243, 1244, + 1301, 1601, 2237, 2355, 2637, 2774, 3932, 4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245, 4263, 4282, + 4306, 4311, 4312, 4313, 4314, 4337, 4339, 4357, 4358, 4363, 4383, 4395, 4408, 4433, 4443, 4445, 4446, + 5167, 5234, 5235, 5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071] + >>> + >>> p = psutil.Process(7055) + >>> p + psutil.Process(pid=7055, name='python', started='09:04:44') + >>> p.name() + 'python' + >>> p.exe() + '/usr/bin/python' + >>> p.cwd() + '/home/giampaolo' + >>> p.cmdline() + ['/usr/bin/python', 'main.py'] + >>> + >>> p.pid + 7055 + >>> p.ppid() + 7054 + >>> p.children(recursive=True) + [psutil.Process(pid=29835, name='python2.7', started='11:45:38'), + psutil.Process(pid=29836, name='python2.7', started='11:43:39')] + >>> + >>> p.parent() + psutil.Process(pid=4699, name='bash', started='09:06:44') + >>> p.parents() + [psutil.Process(pid=4699, name='bash', started='09:06:44'), + psutil.Process(pid=4689, name='gnome-terminal-server', started='0:06:44'), + psutil.Process(pid=1, name='systemd', started='05:56:55')] + >>> + >>> p.status() + 'running' + >>> p.username() + 'giampaolo' + >>> p.create_time() + 1267551141.5019531 + >>> p.terminal() + '/dev/pts/0' + >>> + >>> p.uids() + puids(real=1000, effective=1000, saved=1000) + >>> p.gids() + pgids(real=1000, effective=1000, saved=1000) + >>> + >>> p.cpu_times() + pcputimes(user=1.02, system=0.31, children_user=0.32, children_system=0.1) + >>> p.cpu_percent(interval=1.0) + 12.1 + >>> p.cpu_affinity() + [0, 1, 2, 3] + >>> p.cpu_affinity([0, 1]) # set + >>> p.cpu_num() + 1 + >>> + >>> p.memory_info() + pmem(rss=10915840, vms=67608576, shared=3313664, text=2310144, lib=0, data=7262208, dirty=0) + >>> p.memory_full_info() # "real" USS memory usage (Linux, macOS, Win only) + pfullmem(rss=10199040, vms=52133888, shared=3887104, text=2867200, lib=0, data=5967872, dirty=0, uss=6545408, pss=6872064, swap=0) + >>> p.memory_percent() + 0.7823 + >>> p.memory_maps() + [pmmap_grouped(path='/lib/x8664-linux-gnu/libutil-2.15.so', rss=32768, size=2125824, pss=32768, shared_clean=0, shared_dirty=0, private_clean=20480, private_dirty=12288, referenced=32768, anonymous=12288, swap=0), + pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=3821568, size=3842048, pss=3821568, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=3821568, referenced=3575808, anonymous=3821568, swap=0), + pmmap_grouped(path='[heap]', rss=32768, size=139264, pss=32768, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=32768, referenced=32768, anonymous=32768, swap=0), + pmmap_grouped(path='[stack]', rss=2465792, size=2494464, pss=2465792, shared_clean=0, shared_dirty=0, private_clean=0, private_dirty=2465792, referenced=2277376, anonymous=2465792, swap=0), + ...] + >>> + >>> p.io_counters() + pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632, read_chars=456232, write_chars=517543) + >>> + >>> p.open_files() + [popenfile(path='/home/giampaolo/svn/psutil/setup.py', fd=3, position=0, mode='r', flags=32768), + popenfile(path='/var/log/monitd', fd=4, position=235542, mode='a', flags=33793)] + >>> + >>> p.connections() + [pconn(fd=115, family=, type=, laddr=addr(ip='10.0.0.1', port=48776), raddr=addr(ip='93.186.135.91', port=80), status='ESTABLISHED'), + pconn(fd=117, family=, type=, laddr=addr(ip='10.0.0.1', port=43761), raddr=addr(ip='72.14.234.100', port=80), status='CLOSING')] + >>> + >>> p.num_threads() + 4 + >>> p.num_fds() + 8 + >>> p.threads() + [pthread(id=5234, user_time=22.5, system_time=9.2891), + pthread(id=5237, user_time=0.0707, system_time=1.1)] + >>> + >>> p.num_ctx_switches() + pctxsw(voluntary=78, involuntary=19) + >>> + >>> p.nice() + 0 + >>> p.nice(10) # set + >>> + >>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only) + >>> p.ionice() + pionice(ioclass=, value=0) + >>> + >>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) # set resource limits (Linux only) + >>> p.rlimit(psutil.RLIMIT_NOFILE) + (5, 5) + >>> + >>> p.environ() + {'LC_PAPER': 'it_IT.UTF-8', 'SHELL': '/bin/bash', 'GREP_OPTIONS': '--color=auto', + 'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg', + ...} + >>> + >>> p.as_dict() + {'status': 'running', 'num_ctx_switches': pctxsw(voluntary=63, involuntary=1), 'pid': 5457, ...} + >>> p.is_running() + True + >>> p.suspend() + >>> p.resume() + >>> + >>> p.terminate() + >>> p.wait(timeout=3) + 0 + >>> + >>> psutil.test() + USER PID %CPU %MEM VSZ RSS TTY START TIME COMMAND + root 1 0.0 0.0 24584 2240 Jun17 00:00 init + root 2 0.0 0.0 0 0 Jun17 00:00 kthreadd + ... + giampaolo 31475 0.0 0.0 20760 3024 /dev/pts/0 Jun19 00:00 python2.4 + giampaolo 31721 0.0 2.2 773060 181896 00:04 10:30 chrome + root 31763 0.0 0.0 0 0 00:05 00:00 kworker/0:1 + >>> + +Further process APIs +-------------------- + +.. code-block:: python + + >>> import psutil + >>> for proc in psutil.process_iter(attrs=['pid', 'name']): + ... print(proc.info) + ... + {'pid': 1, 'name': 'systemd'} + {'pid': 2, 'name': 'kthreadd'} + {'pid': 3, 'name': 'ksoftirqd/0'} + ... + >>> + >>> psutil.pid_exists(3) + True + >>> + >>> def on_terminate(proc): + ... print("process {} terminated".format(proc)) + ... + >>> # waits for multiple processes to terminate + >>> gone, alive = psutil.wait_procs(procs_list, timeout=3, callback=on_terminate) + >>> + +Popen wrapper: + +.. code-block:: python + + >>> import psutil + >>> from subprocess import PIPE + >>> p = psutil.Popen(["/usr/bin/python", "-c", "print('hello')"], stdout=PIPE) + >>> p.name() + 'python' + >>> p.username() + 'giampaolo' + >>> p.communicate() + ('hello\n', None) + >>> p.wait(timeout=2) + 0 + >>> + +Windows services +---------------- + +.. code-block:: python + + >>> list(psutil.win_service_iter()) + [, + , + , + , + ...] + >>> s = psutil.win_service_get('alg') + >>> s.as_dict() + {'binpath': 'C:\\Windows\\System32\\alg.exe', + 'description': 'Provides support for 3rd party protocol plug-ins for Internet Connection Sharing', + 'display_name': 'Application Layer Gateway Service', + 'name': 'alg', + 'pid': None, + 'start_type': 'manual', + 'status': 'stopped', + 'username': 'NT AUTHORITY\\LocalService'} + + diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/RECORD b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/RECORD new file mode 100644 index 00000000..9d0dcf51 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/RECORD @@ -0,0 +1,59 @@ +psutil-5.6.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 +psutil-5.6.1.dist-info/LICENSE,sha256=uwc4JrDftDtjHDitXZhEzadMxjHSpVaa2HmL5CdKPhc,1584 +psutil-5.6.1.dist-info/METADATA,sha256=6jSaLf_lDgWxSYOiz4I415mVT6f3mtwmRSAxUnn6O1Q,21332 +psutil-5.6.1.dist-info/RECORD,, +psutil-5.6.1.dist-info/WHEEL,sha256=u4Efs1ohefs6i6rm-BSBkNuQzwmF2Y4Na3ETsbtk2VM,102 +psutil-5.6.1.dist-info/top_level.txt,sha256=gCNhn57wzksDjSAISmgMJ0aiXzQulk0GJhb2-BAyYgw,7 +psutil/__init__.py,sha256=1aX3C2lbCCRoQtwl1QivNhqa9UzZghQg11g2UkPAJz4,89598 +psutil/__pycache__/__init__.cpython-37.pyc,, +psutil/__pycache__/_common.cpython-37.pyc,, +psutil/__pycache__/_compat.cpython-37.pyc,, +psutil/__pycache__/_psaix.cpython-37.pyc,, +psutil/__pycache__/_psbsd.cpython-37.pyc,, +psutil/__pycache__/_pslinux.cpython-37.pyc,, +psutil/__pycache__/_psosx.cpython-37.pyc,, +psutil/__pycache__/_psposix.cpython-37.pyc,, +psutil/__pycache__/_pssunos.cpython-37.pyc,, +psutil/__pycache__/_pswindows.cpython-37.pyc,, +psutil/_common.py,sha256=CZ0iMdeZQiSusuNtHdm0gZsGvmdSjWNPR0RGFURPkf4,18777 +psutil/_compat.py,sha256=TK53hJ42mVD2_2pI4sM4c29LGllp9JHsvAIGDvmZZko,7968 +psutil/_psaix.py,sha256=X0Qw3X0-_pSLXN-uBwK-Kw04M0k6fkhXrxabyGCtlHI,19544 +psutil/_psbsd.py,sha256=AH3zp0fgF4TvF7BKiT8O0AaXUAJwuecLiowLB5O-n_c,31757 +psutil/_pslinux.py,sha256=o8l5Z51umpsT3ZbwqDK1zUvMgL3b3UY8P6qaklRm008,80942 +psutil/_psosx.py,sha256=rBER1IA_EhTNt0CfPG92OxU2SO7Cf6MAhotr_hZTn8A,17572 +psutil/_psposix.py,sha256=b5269ImmjNtO-T8CCtJE6mtyX5XZHoNca1tsHKVB3eQ,6453 +psutil/_pssunos.py,sha256=dZppa-TmjZm6dVmnZSi2PnbTsLyJdEzbEO5YGTejtzk,25495 +psutil/_psutil_windows.cp37-win32.pyd,sha256=pUnZ7MxarxaBbTWWFXcdEX5VV37xt2jzZcRvkunOFYU,61952 +psutil/_pswindows.py,sha256=r6yolP2ZlzVM6MA8JmUAuwAz-rCNuflRofT1gPCKDnI,35545 +psutil/tests/__init__.py,sha256=LNyMF_b3ZICocIRoJDx_nRuGYqtRaI2Czh2dbqGvsfk,39303 +psutil/tests/__main__.py,sha256=-b0IquvXkCfYAC9fmIfOy_CXpHHjvbBC0oO_gNw3Sd8,2719 +psutil/tests/__pycache__/__init__.cpython-37.pyc,, +psutil/tests/__pycache__/__main__.cpython-37.pyc,, +psutil/tests/__pycache__/test_aix.cpython-37.pyc,, +psutil/tests/__pycache__/test_bsd.cpython-37.pyc,, +psutil/tests/__pycache__/test_connections.cpython-37.pyc,, +psutil/tests/__pycache__/test_contracts.cpython-37.pyc,, +psutil/tests/__pycache__/test_linux.cpython-37.pyc,, +psutil/tests/__pycache__/test_memory_leaks.cpython-37.pyc,, +psutil/tests/__pycache__/test_misc.cpython-37.pyc,, +psutil/tests/__pycache__/test_osx.cpython-37.pyc,, +psutil/tests/__pycache__/test_posix.cpython-37.pyc,, +psutil/tests/__pycache__/test_process.cpython-37.pyc,, +psutil/tests/__pycache__/test_sunos.cpython-37.pyc,, +psutil/tests/__pycache__/test_system.cpython-37.pyc,, +psutil/tests/__pycache__/test_unicode.cpython-37.pyc,, +psutil/tests/__pycache__/test_windows.cpython-37.pyc,, +psutil/tests/test_aix.py,sha256=PsjUyrbMG5egnvpfZqcz2L0z9zEh9d_vRooTs_R1aWM,4492 +psutil/tests/test_bsd.py,sha256=o1zeBzMfIYnTZ5RTmzm4dpTqfWRkZzqDpYO8lqdw5lE,20343 +psutil/tests/test_connections.py,sha256=clVB10KsXMHg8hpq5DE4HOTep7pSZ9x1gRXOx5HR7jc,20717 +psutil/tests/test_contracts.py,sha256=AnmJdyKc-zkSagc14gccoNN9Q7kH6jXwZgq2kmEM1rQ,23902 +psutil/tests/test_linux.py,sha256=G7Tc6xxFfmugrC-d9yOYB0maEHQnHrufE_rD216AiUA,86355 +psutil/tests/test_memory_leaks.py,sha256=0eVIlFDE9FLB7yPZxgrU7hR49hV31wmiTpgRKfBKXis,18656 +psutil/tests/test_misc.py,sha256=o_NXL6oKOXx-HVMm067cb8CzkeHBMhWNDW_Xj9gEyYg,38447 +psutil/tests/test_osx.py,sha256=eLQHq7NtWEJDd-YEYJOyJ7Ntyc7STCE-OYWsUdSrzhs,9313 +psutil/tests/test_posix.py,sha256=P42-a868UXNsBkAUa4SM--JU1iHPkxMsRyzGYXm8Uqw,16406 +psutil/tests/test_process.py,sha256=cHaXCh4j3JWoxyHAcJtZXn68Kb-nPjeaIvKG0scBDi4,62196 +psutil/tests/test_sunos.py,sha256=UNywEx_qlSOyUHV48lMKqmnu8RKPBDCQrO0llulCUHY,1322 +psutil/tests/test_system.py,sha256=VzdU_WQUOUofwz1s2Vl0TG7cj6aEdefpctXNEtd-lyU,35287 +psutil/tests/test_unicode.py,sha256=HfAcnHHSZOYQVzwdKIRZeO_uIDwsWfH456SVon6RiCo,13115 +psutil/tests/test_windows.py,sha256=ZxU5eL_8woLRHAO7_RbC0hxsib6VZXk-vQO-15soua0,33680 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/WHEEL b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/WHEEL new file mode 100644 index 00000000..bb93ff5e --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/WHEEL @@ -0,0 +1,5 @@ +Wheel-Version: 1.0 +Generator: bdist_wheel (0.33.1) +Root-Is-Purelib: false +Tag: cp37-cp37m-win32 + diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/top_level.txt b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/top_level.txt new file mode 100644 index 00000000..a4d92cc0 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil-5.6.1.dist-info/top_level.txt @@ -0,0 +1 @@ +psutil diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__init__.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__init__.py new file mode 100644 index 00000000..bd0d5e4d --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__init__.py @@ -0,0 +1,2489 @@ +# -*- coding: utf-8 -*- + +# 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. + +"""psutil is a cross-platform library for retrieving information on +running processes and system utilization (CPU, memory, disks, network, +sensors) in Python. Supported platforms: + + - Linux + - Windows + - macOS + - FreeBSD + - OpenBSD + - NetBSD + - Sun Solaris + - AIX + +Works with Python versions from 2.6 to 3.4+. +""" + +from __future__ import division + +import collections +import contextlib +import datetime +import errno +import functools +import os +import signal +import subprocess +import sys +import threading +import time +try: + import pwd +except ImportError: + pwd = None + +from . import _common +from ._common import deprecated_method +from ._common import memoize +from ._common import memoize_when_activated +from ._common import wrap_numbers as _wrap_numbers +from ._compat import long +from ._compat import PY3 as _PY3 + +from ._common import STATUS_DEAD +from ._common import STATUS_DISK_SLEEP +from ._common import STATUS_IDLE +from ._common import STATUS_LOCKED +from ._common import STATUS_PARKED +from ._common import STATUS_RUNNING +from ._common import STATUS_SLEEPING +from ._common import STATUS_STOPPED +from ._common import STATUS_TRACING_STOP +from ._common import STATUS_WAITING +from ._common import STATUS_WAKING +from ._common import STATUS_ZOMBIE + +from ._common import CONN_CLOSE +from ._common import CONN_CLOSE_WAIT +from ._common import CONN_CLOSING +from ._common import CONN_ESTABLISHED +from ._common import CONN_FIN_WAIT1 +from ._common import CONN_FIN_WAIT2 +from ._common import CONN_LAST_ACK +from ._common import CONN_LISTEN +from ._common import CONN_NONE +from ._common import CONN_SYN_RECV +from ._common import CONN_SYN_SENT +from ._common import CONN_TIME_WAIT +from ._common import NIC_DUPLEX_FULL +from ._common import NIC_DUPLEX_HALF +from ._common import NIC_DUPLEX_UNKNOWN + +from ._common import AIX +from ._common import BSD +from ._common import FREEBSD # NOQA +from ._common import LINUX +from ._common import MACOS +from ._common import NETBSD # NOQA +from ._common import OPENBSD # NOQA +from ._common import OSX # deprecated alias +from ._common import POSIX # NOQA +from ._common import SUNOS +from ._common import WINDOWS + +if LINUX: + # This is public API and it will be retrieved from _pslinux.py + # via sys.modules. + PROCFS_PATH = "/proc" + + from . import _pslinux as _psplatform + + from ._pslinux import IOPRIO_CLASS_BE # NOQA + from ._pslinux import IOPRIO_CLASS_IDLE # NOQA + from ._pslinux import IOPRIO_CLASS_NONE # NOQA + from ._pslinux import IOPRIO_CLASS_RT # NOQA + # Linux >= 2.6.36 + if _psplatform.HAS_PRLIMIT: + from ._psutil_linux import RLIM_INFINITY # NOQA + from ._psutil_linux import RLIMIT_AS # NOQA + from ._psutil_linux import RLIMIT_CORE # NOQA + from ._psutil_linux import RLIMIT_CPU # NOQA + from ._psutil_linux import RLIMIT_DATA # NOQA + from ._psutil_linux import RLIMIT_FSIZE # NOQA + from ._psutil_linux import RLIMIT_LOCKS # NOQA + from ._psutil_linux import RLIMIT_MEMLOCK # NOQA + from ._psutil_linux import RLIMIT_NOFILE # NOQA + from ._psutil_linux import RLIMIT_NPROC # NOQA + from ._psutil_linux import RLIMIT_RSS # NOQA + from ._psutil_linux import RLIMIT_STACK # NOQA + # Kinda ugly but considerably faster than using hasattr() and + # setattr() against the module object (we are at import time: + # speed matters). + from . import _psutil_linux + try: + RLIMIT_MSGQUEUE = _psutil_linux.RLIMIT_MSGQUEUE + except AttributeError: + pass + try: + RLIMIT_NICE = _psutil_linux.RLIMIT_NICE + except AttributeError: + pass + try: + RLIMIT_RTPRIO = _psutil_linux.RLIMIT_RTPRIO + except AttributeError: + pass + try: + RLIMIT_RTTIME = _psutil_linux.RLIMIT_RTTIME + except AttributeError: + pass + try: + RLIMIT_SIGPENDING = _psutil_linux.RLIMIT_SIGPENDING + except AttributeError: + pass + +elif WINDOWS: + from . import _pswindows as _psplatform + from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS # NOQA + from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS # NOQA + from ._psutil_windows import HIGH_PRIORITY_CLASS # NOQA + from ._psutil_windows import IDLE_PRIORITY_CLASS # NOQA + from ._psutil_windows import NORMAL_PRIORITY_CLASS # NOQA + from ._psutil_windows import REALTIME_PRIORITY_CLASS # NOQA + from ._pswindows import CONN_DELETE_TCB # NOQA + +elif MACOS: + from . import _psosx as _psplatform + +elif BSD: + from . import _psbsd as _psplatform + +elif SUNOS: + from . import _pssunos as _psplatform + from ._pssunos import CONN_BOUND # NOQA + from ._pssunos import CONN_IDLE # NOQA + + # This is public writable API which is read from _pslinux.py and + # _pssunos.py via sys.modules. + PROCFS_PATH = "/proc" + +elif AIX: + from . import _psaix as _psplatform + + # This is public API and it will be retrieved from _pslinux.py + # via sys.modules. + PROCFS_PATH = "/proc" + +else: # pragma: no cover + raise NotImplementedError('platform %s is not supported' % sys.platform) + + +__all__ = [ + # exceptions + "Error", "NoSuchProcess", "ZombieProcess", "AccessDenied", + "TimeoutExpired", + + # constants + "version_info", "__version__", + + "STATUS_RUNNING", "STATUS_IDLE", "STATUS_SLEEPING", "STATUS_DISK_SLEEP", + "STATUS_STOPPED", "STATUS_TRACING_STOP", "STATUS_ZOMBIE", "STATUS_DEAD", + "STATUS_WAKING", "STATUS_LOCKED", "STATUS_WAITING", "STATUS_LOCKED", + "STATUS_PARKED", + + "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1", + "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT", + "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", "CONN_NONE", + + "AF_LINK", + + "NIC_DUPLEX_FULL", "NIC_DUPLEX_HALF", "NIC_DUPLEX_UNKNOWN", + + "POWER_TIME_UNKNOWN", "POWER_TIME_UNLIMITED", + + "BSD", "FREEBSD", "LINUX", "NETBSD", "OPENBSD", "MACOS", "OSX", "POSIX", + "SUNOS", "WINDOWS", "AIX", + + # classes + "Process", "Popen", + + # functions + "pid_exists", "pids", "process_iter", "wait_procs", # proc + "virtual_memory", "swap_memory", # memory + "cpu_times", "cpu_percent", "cpu_times_percent", "cpu_count", # cpu + "cpu_stats", # "cpu_freq", + "net_io_counters", "net_connections", "net_if_addrs", # network + "net_if_stats", + "disk_io_counters", "disk_partitions", "disk_usage", # disk + # "sensors_temperatures", "sensors_battery", "sensors_fans" # sensors + "users", "boot_time", # others +] + + +__all__.extend(_psplatform.__extra__all__) +__author__ = "Giampaolo Rodola'" +__version__ = "5.6.1" +version_info = tuple([int(num) for num in __version__.split('.')]) + +_timer = getattr(time, 'monotonic', time.time) +AF_LINK = _psplatform.AF_LINK +POWER_TIME_UNLIMITED = _common.POWER_TIME_UNLIMITED +POWER_TIME_UNKNOWN = _common.POWER_TIME_UNKNOWN +_TOTAL_PHYMEM = None +_LOWEST_PID = None + +# Sanity check in case the user messed up with psutil installation +# or did something weird with sys.path. In this case we might end +# up importing a python module using a C extension module which +# was compiled for a different version of psutil. +# We want to prevent that by failing sooner rather than later. +# See: https://github.com/giampaolo/psutil/issues/564 +if (int(__version__.replace('.', '')) != + getattr(_psplatform.cext, 'version', None)): + msg = "version conflict: %r C extension module was built for another " \ + "version of psutil" % getattr(_psplatform.cext, "__file__") + if hasattr(_psplatform.cext, 'version'): + msg += " (%s instead of %s)" % ( + '.'.join([x for x in str(_psplatform.cext.version)]), __version__) + else: + msg += " (different than %s)" % __version__ + msg += "; you may try to 'pip uninstall psutil', manually remove %s" % ( + getattr(_psplatform.cext, "__file__", + "the existing psutil install directory")) + msg += " or clean the virtual env somehow, then reinstall" + raise ImportError(msg) + + +# ===================================================================== +# --- Exceptions +# ===================================================================== + + +class Error(Exception): + """Base exception class. All other psutil exceptions inherit + from this one. + """ + + def __init__(self, msg=""): + Exception.__init__(self, msg) + self.msg = msg + + def __repr__(self): + ret = "psutil.%s %s" % (self.__class__.__name__, self.msg) + return ret.strip() + + __str__ = __repr__ + + +class NoSuchProcess(Error): + """Exception raised when a process with a certain PID doesn't + or no longer exists. + """ + + def __init__(self, pid, name=None, msg=None): + Error.__init__(self, msg) + self.pid = pid + self.name = name + self.msg = msg + if msg is None: + if name: + details = "(pid=%s, name=%s)" % (self.pid, repr(self.name)) + else: + details = "(pid=%s)" % self.pid + self.msg = "process no longer exists " + details + + +class ZombieProcess(NoSuchProcess): + """Exception raised when querying a zombie process. This is + raised on macOS, BSD and Solaris only, and not always: depending + on the query the OS may be able to succeed anyway. + On Linux all zombie processes are querable (hence this is never + raised). Windows doesn't have zombie processes. + """ + + def __init__(self, pid, name=None, ppid=None, msg=None): + NoSuchProcess.__init__(self, msg) + self.pid = pid + self.ppid = ppid + self.name = name + self.msg = msg + if msg is None: + args = ["pid=%s" % pid] + if name: + args.append("name=%s" % repr(self.name)) + if ppid: + args.append("ppid=%s" % self.ppid) + details = "(%s)" % ", ".join(args) + self.msg = "process still exists but it's a zombie " + details + + +class AccessDenied(Error): + """Exception raised when permission to perform an action is denied.""" + + def __init__(self, pid=None, name=None, msg=None): + Error.__init__(self, msg) + self.pid = pid + self.name = name + self.msg = msg + if msg is None: + if (pid is not None) and (name is not None): + self.msg = "(pid=%s, name=%s)" % (pid, repr(name)) + elif (pid is not None): + self.msg = "(pid=%s)" % self.pid + else: + self.msg = "" + + +class TimeoutExpired(Error): + """Raised on Process.wait(timeout) if timeout expires and process + is still alive. + """ + + def __init__(self, seconds, pid=None, name=None): + Error.__init__(self, "timeout after %s seconds" % seconds) + self.seconds = seconds + self.pid = pid + self.name = name + if (pid is not None) and (name is not None): + self.msg += " (pid=%s, name=%s)" % (pid, repr(name)) + elif (pid is not None): + self.msg += " (pid=%s)" % self.pid + + +# Push exception classes into platform specific module namespace. +_psplatform.NoSuchProcess = NoSuchProcess +_psplatform.ZombieProcess = ZombieProcess +_psplatform.AccessDenied = AccessDenied +_psplatform.TimeoutExpired = TimeoutExpired +if POSIX: + from . import _psposix + _psposix.TimeoutExpired = TimeoutExpired + + +# ===================================================================== +# --- Utils +# ===================================================================== + + +if hasattr(_psplatform, 'ppid_map'): + # Faster version (Windows and Linux). + _ppid_map = _psplatform.ppid_map +else: + def _ppid_map(): + """Return a {pid: ppid, ...} dict for all running processes in + one shot. Used to speed up Process.children(). + """ + ret = {} + for pid in pids(): + try: + ret[pid] = _psplatform.Process(pid).ppid() + except (NoSuchProcess, ZombieProcess): + pass + return ret + + +def _assert_pid_not_reused(fun): + """Decorator which raises NoSuchProcess in case a process is no + longer running or its PID has been reused. + """ + @functools.wraps(fun) + def wrapper(self, *args, **kwargs): + if not self.is_running(): + raise NoSuchProcess(self.pid, self._name) + return fun(self, *args, **kwargs) + return wrapper + + +def _pprint_secs(secs): + """Format seconds in a human readable form.""" + now = time.time() + secs_ago = int(now - secs) + if secs_ago < 60 * 60 * 24: + fmt = "%H:%M:%S" + else: + fmt = "%Y-%m-%d %H:%M:%S" + return datetime.datetime.fromtimestamp(secs).strftime(fmt) + + +# ===================================================================== +# --- Process class +# ===================================================================== + + +class Process(object): + """Represents an OS process with the given PID. + If PID is omitted current process PID (os.getpid()) is used. + Raise NoSuchProcess if PID does not exist. + + Note that most of the methods of this class do not make sure + the PID of the process being queried has been reused over time. + That means you might end up retrieving an information referring + to another process in case the original one this instance + refers to is gone in the meantime. + + The only exceptions for which process identity is pre-emptively + checked and guaranteed are: + + - parent() + - children() + - nice() (set) + - ionice() (set) + - rlimit() (set) + - cpu_affinity (set) + - suspend() + - resume() + - send_signal() + - terminate() + - kill() + + To prevent this problem for all other methods you can: + - use is_running() before querying the process + - if you're continuously iterating over a set of Process + instances use process_iter() which pre-emptively checks + process identity for every yielded instance + """ + + def __init__(self, pid=None): + self._init(pid) + + def _init(self, pid, _ignore_nsp=False): + if pid is None: + pid = os.getpid() + else: + if not _PY3 and not isinstance(pid, (int, long)): + raise TypeError('pid must be an integer (got %r)' % pid) + if pid < 0: + raise ValueError('pid must be a positive integer (got %s)' + % pid) + self._pid = pid + self._name = None + self._exe = None + self._create_time = None + self._gone = False + self._hash = None + self._lock = threading.RLock() + # used for caching on Windows only (on POSIX ppid may change) + self._ppid = None + # platform-specific modules define an _psplatform.Process + # implementation class + self._proc = _psplatform.Process(pid) + self._last_sys_cpu_times = None + self._last_proc_cpu_times = None + # cache creation time for later use in is_running() method + try: + self.create_time() + except AccessDenied: + # We should never get here as AFAIK we're able to get + # process creation time on all platforms even as a + # limited user. + pass + except ZombieProcess: + # Zombies can still be queried by this class (although + # not always) and pids() return them so just go on. + pass + except NoSuchProcess: + if not _ignore_nsp: + msg = 'no process found with pid %s' % pid + raise NoSuchProcess(pid, None, msg) + else: + self._gone = True + # This pair is supposed to indentify a Process instance + # univocally over time (the PID alone is not enough as + # it might refer to a process whose PID has been reused). + # This will be used later in __eq__() and is_running(). + self._ident = (self.pid, self._create_time) + + def __str__(self): + try: + info = collections.OrderedDict() + except AttributeError: + info = {} # Python 2.6 + info["pid"] = self.pid + try: + info["name"] = self.name() + if self._create_time: + info['started'] = _pprint_secs(self._create_time) + except ZombieProcess: + info["status"] = "zombie" + except NoSuchProcess: + info["status"] = "terminated" + except AccessDenied: + pass + return "%s.%s(%s)" % ( + self.__class__.__module__, + self.__class__.__name__, + ", ".join(["%s=%r" % (k, v) for k, v in info.items()])) + + __repr__ = __str__ + + def __eq__(self, other): + # Test for equality with another Process object based + # on PID and creation time. + if not isinstance(other, Process): + return NotImplemented + return self._ident == other._ident + + def __ne__(self, other): + return not self == other + + def __hash__(self): + if self._hash is None: + self._hash = hash(self._ident) + return self._hash + + @property + def pid(self): + """The process PID.""" + return self._pid + + # --- utility methods + + @contextlib.contextmanager + def oneshot(self): + """Utility context manager which considerably speeds up the + retrieval of multiple process information at the same time. + + Internally different process info (e.g. name, ppid, uids, + gids, ...) may be fetched by using the same routine, but + only one information is returned and the others are discarded. + When using this context manager the internal routine is + executed once (in the example below on name()) and the + other info are cached. + + The cache is cleared when exiting the context manager block. + The advice is to use this every time you retrieve more than + one information about the process. If you're lucky, you'll + get a hell of a speedup. + + >>> import psutil + >>> p = psutil.Process() + >>> with p.oneshot(): + ... p.name() # collect multiple info + ... p.cpu_times() # return cached value + ... p.cpu_percent() # return cached value + ... p.create_time() # return cached value + ... + >>> + """ + with self._lock: + if hasattr(self, "_cache"): + # NOOP: this covers the use case where the user enters the + # context twice: + # + # >>> with p.oneshot(): + # ... with p.oneshot(): + # ... + # + # Also, since as_dict() internally uses oneshot() + # I expect that the code below will be a pretty common + # "mistake" that the user will make, so let's guard + # against that: + # + # >>> with p.oneshot(): + # ... p.as_dict() + # ... + yield + else: + try: + # cached in case cpu_percent() is used + self.cpu_times.cache_activate(self) + # cached in case memory_percent() is used + self.memory_info.cache_activate(self) + # cached in case parent() is used + self.ppid.cache_activate(self) + # cached in case username() is used + if POSIX: + self.uids.cache_activate(self) + # specific implementation cache + self._proc.oneshot_enter() + yield + finally: + self.cpu_times.cache_deactivate(self) + self.memory_info.cache_deactivate(self) + self.ppid.cache_deactivate(self) + if POSIX: + self.uids.cache_deactivate(self) + self._proc.oneshot_exit() + + def as_dict(self, attrs=None, ad_value=None): + """Utility method returning process information as a + hashable dictionary. + If *attrs* is specified it must be a list of strings + reflecting available Process class' attribute names + (e.g. ['cpu_times', 'name']) else all public (read + only) attributes are assumed. + *ad_value* is the value which gets assigned in case + AccessDenied or ZombieProcess exception is raised when + retrieving that particular process information. + """ + valid_names = _as_dict_attrnames + if attrs is not None: + if not isinstance(attrs, (list, tuple, set, frozenset)): + raise TypeError("invalid attrs type %s" % type(attrs)) + attrs = set(attrs) + invalid_names = attrs - valid_names + if invalid_names: + raise ValueError("invalid attr name%s %s" % ( + "s" if len(invalid_names) > 1 else "", + ", ".join(map(repr, invalid_names)))) + + retdict = dict() + ls = attrs or valid_names + with self.oneshot(): + for name in ls: + try: + if name == 'pid': + ret = self.pid + else: + meth = getattr(self, name) + ret = meth() + except (AccessDenied, ZombieProcess): + ret = ad_value + except NotImplementedError: + # in case of not implemented functionality (may happen + # on old or exotic systems) we want to crash only if + # the user explicitly asked for that particular attr + if attrs: + raise + continue + retdict[name] = ret + return retdict + + def parent(self): + """Return the parent process as a Process object pre-emptively + checking whether PID has been reused. + If no parent is known return None. + """ + lowest_pid = _LOWEST_PID if _LOWEST_PID is not None else pids()[0] + if self.pid == lowest_pid: + return None + ppid = self.ppid() + if ppid is not None: + ctime = self.create_time() + try: + parent = Process(ppid) + if parent.create_time() <= ctime: + return parent + # ...else ppid has been reused by another process + except NoSuchProcess: + pass + + def parents(self): + """Return the parents of this process as a list of Process + instances. If no parents are known return an empty list. + """ + parents = [] + proc = self.parent() + while proc is not None: + parents.append(proc) + proc = proc.parent() + return parents + + def is_running(self): + """Return whether this process is running. + It also checks if PID has been reused by another process in + which case return False. + """ + if self._gone: + return False + try: + # Checking if PID is alive is not enough as the PID might + # have been reused by another process: we also want to + # verify process identity. + # Process identity / uniqueness over time is guaranteed by + # (PID + creation time) and that is verified in __eq__. + return self == Process(self.pid) + except ZombieProcess: + # We should never get here as it's already handled in + # Process.__init__; here just for extra safety. + return True + except NoSuchProcess: + self._gone = True + return False + + # --- actual API + + @memoize_when_activated + def ppid(self): + """The process parent PID. + On Windows the return value is cached after first call. + """ + # On POSIX we don't want to cache the ppid as it may unexpectedly + # change to 1 (init) in case this process turns into a zombie: + # https://github.com/giampaolo/psutil/issues/321 + # http://stackoverflow.com/questions/356722/ + + # XXX should we check creation time here rather than in + # Process.parent()? + if POSIX: + return self._proc.ppid() + else: # pragma: no cover + self._ppid = self._ppid or self._proc.ppid() + return self._ppid + + def name(self): + """The process name. The return value is cached after first call.""" + # Process name is only cached on Windows as on POSIX it may + # change, see: + # https://github.com/giampaolo/psutil/issues/692 + if WINDOWS and self._name is not None: + return self._name + name = self._proc.name() + if POSIX and len(name) >= 15: + # On UNIX the name gets truncated to the first 15 characters. + # If it matches the first part of the cmdline we return that + # one instead because it's usually more explicative. + # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon". + try: + cmdline = self.cmdline() + except AccessDenied: + pass + else: + if cmdline: + extended_name = os.path.basename(cmdline[0]) + if extended_name.startswith(name): + name = extended_name + self._name = name + self._proc._name = name + return name + + def exe(self): + """The process executable as an absolute path. + May also be an empty string. + The return value is cached after first call. + """ + def guess_it(fallback): + # try to guess exe from cmdline[0] in absence of a native + # exe representation + cmdline = self.cmdline() + if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'): + exe = cmdline[0] # the possible exe + # Attempt to guess only in case of an absolute path. + # It is not safe otherwise as the process might have + # changed cwd. + if (os.path.isabs(exe) and + os.path.isfile(exe) and + os.access(exe, os.X_OK)): + return exe + if isinstance(fallback, AccessDenied): + raise fallback + return fallback + + if self._exe is None: + try: + exe = self._proc.exe() + except AccessDenied as err: + return guess_it(fallback=err) + else: + if not exe: + # underlying implementation can legitimately return an + # empty string; if that's the case we don't want to + # raise AD while guessing from the cmdline + try: + exe = guess_it(fallback=exe) + except AccessDenied: + pass + self._exe = exe + return self._exe + + def cmdline(self): + """The command line this process has been called with.""" + return self._proc.cmdline() + + def status(self): + """The process current status as a STATUS_* constant.""" + try: + return self._proc.status() + except ZombieProcess: + return STATUS_ZOMBIE + + def username(self): + """The name of the user that owns the process. + On UNIX this is calculated by using *real* process uid. + """ + if POSIX: + if pwd is None: + # might happen if python was installed from sources + raise ImportError( + "requires pwd module shipped with standard python") + real_uid = self.uids().real + try: + return pwd.getpwuid(real_uid).pw_name + except KeyError: + # the uid can't be resolved by the system + return str(real_uid) + else: + return self._proc.username() + + def create_time(self): + """The process creation time as a floating point number + expressed in seconds since the epoch, in UTC. + The return value is cached after first call. + """ + if self._create_time is None: + self._create_time = self._proc.create_time() + return self._create_time + + def cwd(self): + """Process current working directory as an absolute path.""" + return self._proc.cwd() + + def nice(self, value=None): + """Get or set process niceness (priority).""" + if value is None: + return self._proc.nice_get() + else: + if not self.is_running(): + raise NoSuchProcess(self.pid, self._name) + self._proc.nice_set(value) + + if POSIX: + + @memoize_when_activated + def uids(self): + """Return process UIDs as a (real, effective, saved) + namedtuple. + """ + return self._proc.uids() + + def gids(self): + """Return process GIDs as a (real, effective, saved) + namedtuple. + """ + return self._proc.gids() + + def terminal(self): + """The terminal associated with this process, if any, + else None. + """ + return self._proc.terminal() + + def num_fds(self): + """Return the number of file descriptors opened by this + process (POSIX only). + """ + return self._proc.num_fds() + + # Linux, BSD, AIX and Windows only + if hasattr(_psplatform.Process, "io_counters"): + + def io_counters(self): + """Return process I/O statistics as a + (read_count, write_count, read_bytes, write_bytes) + namedtuple. + Those are the number of read/write calls performed and the + amount of bytes read and written by the process. + """ + return self._proc.io_counters() + + # Linux and Windows >= Vista only + if hasattr(_psplatform.Process, "ionice_get"): + + def ionice(self, ioclass=None, value=None): + """Get or set process I/O niceness (priority). + + On Linux *ioclass* is one of the IOPRIO_CLASS_* constants. + *value* is a number which goes from 0 to 7. The higher the + value, the lower the I/O priority of the process. + + On Windows only *ioclass* is used and it can be set to 2 + (normal), 1 (low) or 0 (very low). + + Available on Linux and Windows > Vista only. + """ + if ioclass is None: + if value is not None: + raise ValueError("'ioclass' argument must be specified") + return self._proc.ionice_get() + else: + return self._proc.ionice_set(ioclass, value) + + # Linux only + if hasattr(_psplatform.Process, "rlimit"): + + def rlimit(self, resource, limits=None): + """Get or set process resource limits as a (soft, hard) + tuple. + + *resource* is one of the RLIMIT_* constants. + *limits* is supposed to be a (soft, hard) tuple. + + See "man prlimit" for further info. + Available on Linux only. + """ + if limits is None: + return self._proc.rlimit(resource) + else: + return self._proc.rlimit(resource, limits) + + # Windows, Linux and FreeBSD only + if hasattr(_psplatform.Process, "cpu_affinity_get"): + + def cpu_affinity(self, cpus=None): + """Get or set process CPU affinity. + If specified, *cpus* must be a list of CPUs for which you + want to set the affinity (e.g. [0, 1]). + If an empty list is passed, all egible CPUs are assumed + (and set). + (Windows, Linux and BSD only). + """ + if cpus is None: + return list(set(self._proc.cpu_affinity_get())) + else: + if not cpus: + if hasattr(self._proc, "_get_eligible_cpus"): + cpus = self._proc._get_eligible_cpus() + else: + cpus = tuple(range(len(cpu_times(percpu=True)))) + self._proc.cpu_affinity_set(list(set(cpus))) + + # Linux, FreeBSD, SunOS + if hasattr(_psplatform.Process, "cpu_num"): + + def cpu_num(self): + """Return what CPU this process is currently running on. + The returned number should be <= psutil.cpu_count() + and <= len(psutil.cpu_percent(percpu=True)). + It may be used in conjunction with + psutil.cpu_percent(percpu=True) to observe the system + workload distributed across CPUs. + """ + return self._proc.cpu_num() + + # Linux, macOS and Windows only + if hasattr(_psplatform.Process, "environ"): + + def environ(self): + """The environment variables of the process as a dict. Note: this + might not reflect changes made after the process started. """ + return self._proc.environ() + + if WINDOWS: + + def num_handles(self): + """Return the number of handles opened by this process + (Windows only). + """ + return self._proc.num_handles() + + def num_ctx_switches(self): + """Return the number of voluntary and involuntary context + switches performed by this process. + """ + return self._proc.num_ctx_switches() + + def num_threads(self): + """Return the number of threads used by this process.""" + return self._proc.num_threads() + + if hasattr(_psplatform.Process, "threads"): + + def threads(self): + """Return threads opened by process as a list of + (id, user_time, system_time) namedtuples representing + thread id and thread CPU times (user/system). + On OpenBSD this method requires root access. + """ + return self._proc.threads() + + @_assert_pid_not_reused + def children(self, recursive=False): + """Return the children of this process as a list of Process + instances, pre-emptively checking whether PID has been reused. + If *recursive* is True return all the parent descendants. + + Example (A == this process): + + A ─┐ + │ + ├─ B (child) ─┐ + │ └─ X (grandchild) ─┐ + │ └─ Y (great grandchild) + ├─ C (child) + └─ D (child) + + >>> import psutil + >>> p = psutil.Process() + >>> p.children() + B, C, D + >>> p.children(recursive=True) + B, X, Y, C, D + + Note that in the example above if process X disappears + process Y won't be listed as the reference to process A + is lost. + """ + ppid_map = _ppid_map() + ret = [] + if not recursive: + for pid, ppid in ppid_map.items(): + if ppid == self.pid: + try: + child = Process(pid) + # if child happens to be older than its parent + # (self) it means child's PID has been reused + if self.create_time() <= child.create_time(): + ret.append(child) + except (NoSuchProcess, ZombieProcess): + pass + else: + # Construct a {pid: [child pids]} dict + reverse_ppid_map = collections.defaultdict(list) + for pid, ppid in ppid_map.items(): + reverse_ppid_map[ppid].append(pid) + # Recursively traverse that dict, starting from self.pid, + # such that we only call Process() on actual children + seen = set() + stack = [self.pid] + while stack: + pid = stack.pop() + if pid in seen: + # Since pids can be reused while the ppid_map is + # constructed, there may be rare instances where + # there's a cycle in the recorded process "tree". + continue + seen.add(pid) + for child_pid in reverse_ppid_map[pid]: + try: + child = Process(child_pid) + # if child happens to be older than its parent + # (self) it means child's PID has been reused + intime = self.create_time() <= child.create_time() + if intime: + ret.append(child) + stack.append(child_pid) + except (NoSuchProcess, ZombieProcess): + pass + return ret + + def cpu_percent(self, interval=None): + """Return a float representing the current process CPU + utilization as a percentage. + + When *interval* is 0.0 or None (default) compares process times + to system CPU times elapsed since last call, returning + immediately (non-blocking). That means that the first time + this is called it will return a meaningful 0.0 value. + + When *interval* is > 0.0 compares process times to system CPU + times elapsed before and after the interval (blocking). + + In this case is recommended for accuracy that this function + be called with at least 0.1 seconds between calls. + + A value > 100.0 can be returned in case of processes running + multiple threads on different CPU cores. + + The returned value is explicitly NOT split evenly between + all available logical CPUs. This means that a busy loop process + running on a system with 2 logical CPUs will be reported as + having 100% CPU utilization instead of 50%. + + Examples: + + >>> import psutil + >>> p = psutil.Process(os.getpid()) + >>> # blocking + >>> p.cpu_percent(interval=1) + 2.0 + >>> # non-blocking (percentage since last call) + >>> p.cpu_percent(interval=None) + 2.9 + >>> + """ + blocking = interval is not None and interval > 0.0 + if interval is not None and interval < 0: + raise ValueError("interval is not positive (got %r)" % interval) + num_cpus = cpu_count() or 1 + + def timer(): + return _timer() * num_cpus + + if blocking: + st1 = timer() + pt1 = self._proc.cpu_times() + time.sleep(interval) + st2 = timer() + pt2 = self._proc.cpu_times() + else: + st1 = self._last_sys_cpu_times + pt1 = self._last_proc_cpu_times + st2 = timer() + pt2 = self._proc.cpu_times() + if st1 is None or pt1 is None: + self._last_sys_cpu_times = st2 + self._last_proc_cpu_times = pt2 + return 0.0 + + delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system) + delta_time = st2 - st1 + # reset values for next call in case of interval == None + self._last_sys_cpu_times = st2 + self._last_proc_cpu_times = pt2 + + try: + # This is the utilization split evenly between all CPUs. + # E.g. a busy loop process on a 2-CPU-cores system at this + # point is reported as 50% instead of 100%. + overall_cpus_percent = ((delta_proc / delta_time) * 100) + except ZeroDivisionError: + # interval was too low + return 0.0 + else: + # Note 1: + # in order to emulate "top" we multiply the value for the num + # of CPU cores. This way the busy process will be reported as + # having 100% (or more) usage. + # + # Note 2: + # taskmgr.exe on Windows differs in that it will show 50% + # instead. + # + # Note 3: + # a percentage > 100 is legitimate as it can result from a + # process with multiple threads running on different CPU + # cores (top does the same), see: + # http://stackoverflow.com/questions/1032357 + # https://github.com/giampaolo/psutil/issues/474 + single_cpu_percent = overall_cpus_percent * num_cpus + return round(single_cpu_percent, 1) + + @memoize_when_activated + def cpu_times(self): + """Return a (user, system, children_user, children_system) + namedtuple representing the accumulated process time, in + seconds. + This is similar to os.times() but per-process. + On macOS and Windows children_user and children_system are + always set to 0. + """ + return self._proc.cpu_times() + + @memoize_when_activated + def memory_info(self): + """Return a namedtuple with variable fields depending on the + platform, representing memory information about the process. + + The "portable" fields available on all plaforms are `rss` and `vms`. + + All numbers are expressed in bytes. + """ + return self._proc.memory_info() + + @deprecated_method(replacement="memory_info") + def memory_info_ex(self): + return self.memory_info() + + def memory_full_info(self): + """This method returns the same information as memory_info(), + plus, on some platform (Linux, macOS, Windows), also provides + additional metrics (USS, PSS and swap). + The additional metrics provide a better representation of actual + process memory usage. + + Namely USS is the memory which is unique to a process and which + would be freed if the process was terminated right now. + + It does so by passing through the whole process address. + As such it usually requires higher user privileges than + memory_info() and is considerably slower. + """ + return self._proc.memory_full_info() + + def memory_percent(self, memtype="rss"): + """Compare process memory to total physical system memory and + calculate process memory utilization as a percentage. + *memtype* argument is a string that dictates what type of + process memory you want to compare against (defaults to "rss"). + The list of available strings can be obtained like this: + + >>> psutil.Process().memory_info()._fields + ('rss', 'vms', 'shared', 'text', 'lib', 'data', 'dirty', 'uss', 'pss') + """ + valid_types = list(_psplatform.pfullmem._fields) + if memtype not in valid_types: + raise ValueError("invalid memtype %r; valid types are %r" % ( + memtype, tuple(valid_types))) + fun = self.memory_info if memtype in _psplatform.pmem._fields else \ + self.memory_full_info + metrics = fun() + value = getattr(metrics, memtype) + + # use cached value if available + total_phymem = _TOTAL_PHYMEM or virtual_memory().total + if not total_phymem > 0: + # we should never get here + raise ValueError( + "can't calculate process memory percent because " + "total physical system memory is not positive (%r)" + % total_phymem) + return (value / float(total_phymem)) * 100 + + if hasattr(_psplatform.Process, "memory_maps"): + def memory_maps(self, grouped=True): + """Return process' mapped memory regions as a list of namedtuples + whose fields are variable depending on the platform. + + If *grouped* is True the mapped regions with the same 'path' + are grouped together and the different memory fields are summed. + + If *grouped* is False every mapped region is shown as a single + entity and the namedtuple will also include the mapped region's + address space ('addr') and permission set ('perms'). + """ + it = self._proc.memory_maps() + if grouped: + d = {} + for tupl in it: + path = tupl[2] + nums = tupl[3:] + try: + d[path] = map(lambda x, y: x + y, d[path], nums) + except KeyError: + d[path] = nums + nt = _psplatform.pmmap_grouped + return [nt(path, *d[path]) for path in d] # NOQA + else: + nt = _psplatform.pmmap_ext + return [nt(*x) for x in it] + + def open_files(self): + """Return files opened by process as a list of + (path, fd) namedtuples including the absolute file name + and file descriptor number. + """ + return self._proc.open_files() + + def connections(self, kind='inet'): + """Return socket connections opened by process as a list of + (fd, family, type, laddr, raddr, status) namedtuples. + The *kind* parameter filters for connections that match the + following criteria: + + +------------+----------------------------------------------------+ + | Kind Value | Connections using | + +------------+----------------------------------------------------+ + | inet | IPv4 and IPv6 | + | inet4 | IPv4 | + | inet6 | IPv6 | + | tcp | TCP | + | tcp4 | TCP over IPv4 | + | tcp6 | TCP over IPv6 | + | udp | UDP | + | udp4 | UDP over IPv4 | + | udp6 | UDP over IPv6 | + | unix | UNIX socket (both UDP and TCP protocols) | + | all | the sum of all the possible families and protocols | + +------------+----------------------------------------------------+ + """ + return self._proc.connections(kind) + + # --- signals + + if POSIX: + def _send_signal(self, sig): + assert not self.pid < 0, self.pid + if self.pid == 0: + # see "man 2 kill" + raise ValueError( + "preventing sending signal to process with PID 0 as it " + "would affect every process in the process group of the " + "calling process (os.getpid()) instead of PID 0") + try: + os.kill(self.pid, sig) + except OSError as err: + if err.errno == errno.ESRCH: + if OPENBSD and pid_exists(self.pid): + # We do this because os.kill() lies in case of + # zombie processes. + raise ZombieProcess(self.pid, self._name, self._ppid) + else: + self._gone = True + raise NoSuchProcess(self.pid, self._name) + if err.errno in (errno.EPERM, errno.EACCES): + raise AccessDenied(self.pid, self._name) + raise + + @_assert_pid_not_reused + def send_signal(self, sig): + """Send a signal *sig* to process pre-emptively checking + whether PID has been reused (see signal module constants) . + On Windows only SIGTERM is valid and is treated as an alias + for kill(). + """ + if POSIX: + self._send_signal(sig) + else: # pragma: no cover + if sig == signal.SIGTERM: + self._proc.kill() + # py >= 2.7 + elif sig in (getattr(signal, "CTRL_C_EVENT", object()), + getattr(signal, "CTRL_BREAK_EVENT", object())): + self._proc.send_signal(sig) + else: + raise ValueError( + "only SIGTERM, CTRL_C_EVENT and CTRL_BREAK_EVENT signals " + "are supported on Windows") + + @_assert_pid_not_reused + def suspend(self): + """Suspend process execution with SIGSTOP pre-emptively checking + whether PID has been reused. + On Windows this has the effect ot suspending all process threads. + """ + if POSIX: + self._send_signal(signal.SIGSTOP) + else: # pragma: no cover + self._proc.suspend() + + @_assert_pid_not_reused + def resume(self): + """Resume process execution with SIGCONT pre-emptively checking + whether PID has been reused. + On Windows this has the effect of resuming all process threads. + """ + if POSIX: + self._send_signal(signal.SIGCONT) + else: # pragma: no cover + self._proc.resume() + + @_assert_pid_not_reused + def terminate(self): + """Terminate the process with SIGTERM pre-emptively checking + whether PID has been reused. + On Windows this is an alias for kill(). + """ + if POSIX: + self._send_signal(signal.SIGTERM) + else: # pragma: no cover + self._proc.kill() + + @_assert_pid_not_reused + def kill(self): + """Kill the current process with SIGKILL pre-emptively checking + whether PID has been reused. + """ + if POSIX: + self._send_signal(signal.SIGKILL) + else: # pragma: no cover + self._proc.kill() + + def wait(self, timeout=None): + """Wait for process to terminate and, if process is a children + of os.getpid(), also return its exit code, else None. + + If the process is already terminated immediately return None + instead of raising NoSuchProcess. + + If *timeout* (in seconds) is specified and process is still + alive raise TimeoutExpired. + + To wait for multiple Process(es) use psutil.wait_procs(). + """ + if timeout is not None and not timeout >= 0: + raise ValueError("timeout must be a positive integer") + return self._proc.wait(timeout) + + +# ===================================================================== +# --- Popen class +# ===================================================================== + + +class Popen(Process): + """A more convenient interface to stdlib subprocess.Popen class. + It starts a sub process and deals with it exactly as when using + subprocess.Popen class but in addition also provides all the + properties and methods of psutil.Process class as a unified + interface: + + >>> import psutil + >>> from subprocess import PIPE + >>> p = psutil.Popen(["python", "-c", "print 'hi'"], stdout=PIPE) + >>> p.name() + 'python' + >>> p.uids() + user(real=1000, effective=1000, saved=1000) + >>> p.username() + 'giampaolo' + >>> p.communicate() + ('hi\n', None) + >>> p.terminate() + >>> p.wait(timeout=2) + 0 + >>> + + For method names common to both classes such as kill(), terminate() + and wait(), psutil.Process implementation takes precedence. + + Unlike subprocess.Popen this class pre-emptively checks whether PID + has been reused on send_signal(), terminate() and kill() so that + you don't accidentally terminate another process, fixing + http://bugs.python.org/issue6973. + + For a complete documentation refer to: + http://docs.python.org/library/subprocess.html + """ + + def __init__(self, *args, **kwargs): + # Explicitly avoid to raise NoSuchProcess in case the process + # spawned by subprocess.Popen terminates too quickly, see: + # https://github.com/giampaolo/psutil/issues/193 + self.__subproc = subprocess.Popen(*args, **kwargs) + self._init(self.__subproc.pid, _ignore_nsp=True) + + def __dir__(self): + return sorted(set(dir(Popen) + dir(subprocess.Popen))) + + def __enter__(self): + if hasattr(self.__subproc, '__enter__'): + self.__subproc.__enter__() + return self + + def __exit__(self, *args, **kwargs): + if hasattr(self.__subproc, '__exit__'): + return self.__subproc.__exit__(*args, **kwargs) + else: + if self.stdout: + self.stdout.close() + if self.stderr: + self.stderr.close() + try: + # Flushing a BufferedWriter may raise an error. + if self.stdin: + self.stdin.close() + finally: + # Wait for the process to terminate, to avoid zombies. + self.wait() + + def __getattribute__(self, name): + try: + return object.__getattribute__(self, name) + except AttributeError: + try: + return object.__getattribute__(self.__subproc, name) + except AttributeError: + raise AttributeError("%s instance has no attribute '%s'" + % (self.__class__.__name__, name)) + + def wait(self, timeout=None): + if self.__subproc.returncode is not None: + return self.__subproc.returncode + ret = super(Popen, self).wait(timeout) + self.__subproc.returncode = ret + return ret + + +# The valid attr names which can be processed by Process.as_dict(). +_as_dict_attrnames = set( + [x for x in dir(Process) if not x.startswith('_') and x not in + ['send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait', + 'is_running', 'as_dict', 'parent', 'parents', 'children', 'rlimit', + 'memory_info_ex', 'oneshot']]) + + +# ===================================================================== +# --- system processes related functions +# ===================================================================== + + +def pids(): + """Return a list of current running PIDs.""" + global _LOWEST_PID + ret = sorted(_psplatform.pids()) + _LOWEST_PID = ret[0] + return ret + + +def pid_exists(pid): + """Return True if given PID exists in the current process list. + This is faster than doing "pid in psutil.pids()" and + should be preferred. + """ + if pid < 0: + return False + elif pid == 0 and POSIX: + # On POSIX we use os.kill() to determine PID existence. + # According to "man 2 kill" PID 0 has a special meaning + # though: it refers to <> and that is not we want + # to do here. + return pid in pids() + else: + return _psplatform.pid_exists(pid) + + +_pmap = {} +_lock = threading.Lock() + + +def process_iter(attrs=None, ad_value=None): + """Return a generator yielding a Process instance for all + running processes. + + Every new Process instance is only created once and then cached + into an internal table which is updated every time this is used. + + Cached Process instances are checked for identity so that you're + safe in case a PID has been reused by another process, in which + case the cached instance is updated. + + The sorting order in which processes are yielded is based on + their PIDs. + + *attrs* and *ad_value* have the same meaning as in + Process.as_dict(). If *attrs* is specified as_dict() is called + and the resulting dict is stored as a 'info' attribute attached + to returned Process instance. + If *attrs* is an empty list it will retrieve all process info + (slow). + """ + def add(pid): + proc = Process(pid) + if attrs is not None: + proc.info = proc.as_dict(attrs=attrs, ad_value=ad_value) + with _lock: + _pmap[proc.pid] = proc + return proc + + def remove(pid): + with _lock: + _pmap.pop(pid, None) + + a = set(pids()) + b = set(_pmap.keys()) + new_pids = a - b + gone_pids = b - a + for pid in gone_pids: + remove(pid) + + with _lock: + ls = sorted(list(_pmap.items()) + + list(dict.fromkeys(new_pids).items())) + + for pid, proc in ls: + try: + if proc is None: # new process + yield add(pid) + else: + # use is_running() to check whether PID has been reused by + # another process in which case yield a new Process instance + if proc.is_running(): + if attrs is not None: + proc.info = proc.as_dict( + attrs=attrs, ad_value=ad_value) + yield proc + else: + yield add(pid) + except NoSuchProcess: + remove(pid) + except AccessDenied: + # Process creation time can't be determined hence there's + # no way to tell whether the pid of the cached process + # has been reused. Just return the cached version. + if proc is None and pid in _pmap: + try: + yield _pmap[pid] + except KeyError: + # If we get here it is likely that 2 threads were + # using process_iter(). + pass + else: + raise + + +def wait_procs(procs, timeout=None, callback=None): + """Convenience function which waits for a list of processes to + terminate. + + Return a (gone, alive) tuple indicating which processes + are gone and which ones are still alive. + + The gone ones will have a new *returncode* attribute indicating + process exit status (may be None). + + *callback* is a function which gets called every time a process + terminates (a Process instance is passed as callback argument). + + Function will return as soon as all processes terminate or when + *timeout* occurs. + Differently from Process.wait() it will not raise TimeoutExpired if + *timeout* occurs. + + Typical use case is: + + - send SIGTERM to a list of processes + - give them some time to terminate + - send SIGKILL to those ones which are still alive + + Example: + + >>> def on_terminate(proc): + ... print("process {} terminated".format(proc)) + ... + >>> for p in procs: + ... p.terminate() + ... + >>> gone, alive = wait_procs(procs, timeout=3, callback=on_terminate) + >>> for p in alive: + ... p.kill() + """ + def check_gone(proc, timeout): + try: + returncode = proc.wait(timeout=timeout) + except TimeoutExpired: + pass + else: + if returncode is not None or not proc.is_running(): + proc.returncode = returncode + gone.add(proc) + if callback is not None: + callback(proc) + + if timeout is not None and not timeout >= 0: + msg = "timeout must be a positive integer, got %s" % timeout + raise ValueError(msg) + gone = set() + alive = set(procs) + if callback is not None and not callable(callback): + raise TypeError("callback %r is not a callable" % callable) + if timeout is not None: + deadline = _timer() + timeout + + while alive: + if timeout is not None and timeout <= 0: + break + for proc in alive: + # Make sure that every complete iteration (all processes) + # will last max 1 sec. + # We do this because we don't want to wait too long on a + # single process: in case it terminates too late other + # processes may disappear in the meantime and their PID + # reused. + max_timeout = 1.0 / len(alive) + if timeout is not None: + timeout = min((deadline - _timer()), max_timeout) + if timeout <= 0: + break + check_gone(proc, timeout) + else: + check_gone(proc, max_timeout) + alive = alive - gone + + if alive: + # Last attempt over processes survived so far. + # timeout == 0 won't make this function wait any further. + for proc in alive: + check_gone(proc, 0) + alive = alive - gone + + return (list(gone), list(alive)) + + +# ===================================================================== +# --- CPU related functions +# ===================================================================== + + +def cpu_count(logical=True): + """Return the number of logical CPUs in the system (same as + os.cpu_count() in Python 3.4). + + If *logical* is False return the number of physical cores only + (e.g. hyper thread CPUs are excluded). + + Return None if undetermined. + + The return value is cached after first call. + If desired cache can be cleared like this: + + >>> psutil.cpu_count.cache_clear() + """ + if logical: + ret = _psplatform.cpu_count_logical() + else: + ret = _psplatform.cpu_count_physical() + if ret is not None and ret < 1: + ret = None + return ret + + +def cpu_times(percpu=False): + """Return system-wide CPU times as a namedtuple. + Every CPU time represents the seconds the CPU has spent in the + given mode. The namedtuple's fields availability varies depending on the + platform: + + - user + - system + - idle + - nice (UNIX) + - iowait (Linux) + - irq (Linux, FreeBSD) + - softirq (Linux) + - steal (Linux >= 2.6.11) + - guest (Linux >= 2.6.24) + - guest_nice (Linux >= 3.2.0) + + When *percpu* is True return a list of namedtuples for each CPU. + First element of the list refers to first CPU, second element + to second CPU and so on. + The order of the list is consistent across calls. + """ + if not percpu: + return _psplatform.cpu_times() + else: + return _psplatform.per_cpu_times() + + +try: + _last_cpu_times = cpu_times() +except Exception: + # Don't want to crash at import time. + _last_cpu_times = None + +try: + _last_per_cpu_times = cpu_times(percpu=True) +except Exception: + # Don't want to crash at import time. + _last_per_cpu_times = None + + +def _cpu_tot_time(times): + """Given a cpu_time() ntuple calculates the total CPU time + (including idle time). + """ + tot = sum(times) + if LINUX: + # On Linux guest times are already accounted in "user" or + # "nice" times, so we subtract them from total. + # Htop does the same. References: + # https://github.com/giampaolo/psutil/pull/940 + # http://unix.stackexchange.com/questions/178045 + # https://github.com/torvalds/linux/blob/ + # 447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/ + # cputime.c#L158 + tot -= getattr(times, "guest", 0) # Linux 2.6.24+ + tot -= getattr(times, "guest_nice", 0) # Linux 3.2.0+ + return tot + + +def _cpu_busy_time(times): + """Given a cpu_time() ntuple calculates the busy CPU time. + We do so by subtracting all idle CPU times. + """ + busy = _cpu_tot_time(times) + busy -= times.idle + # Linux: "iowait" is time during which the CPU does not do anything + # (waits for IO to complete). On Linux IO wait is *not* accounted + # in "idle" time so we subtract it. Htop does the same. + # References: + # https://github.com/torvalds/linux/blob/ + # 447976ef4fd09b1be88b316d1a81553f1aa7cd07/kernel/sched/cputime.c#L244 + busy -= getattr(times, "iowait", 0) + return busy + + +def _cpu_times_deltas(t1, t2): + assert t1._fields == t2._fields, (t1, t2) + field_deltas = [] + for field in _psplatform.scputimes._fields: + field_delta = getattr(t2, field) - getattr(t1, field) + # CPU times are always supposed to increase over time + # or at least remain the same and that's because time + # cannot go backwards. + # Surprisingly sometimes this might not be the case (at + # least on Windows and Linux), see: + # https://github.com/giampaolo/psutil/issues/392 + # https://github.com/giampaolo/psutil/issues/645 + # https://github.com/giampaolo/psutil/issues/1210 + # Trim negative deltas to zero to ignore decreasing fields. + # top does the same. Reference: + # https://gitlab.com/procps-ng/procps/blob/v3.3.12/top/top.c#L5063 + field_delta = max(0, field_delta) + field_deltas.append(field_delta) + return _psplatform.scputimes(*field_deltas) + + +def cpu_percent(interval=None, percpu=False): + """Return a float representing the current system-wide CPU + utilization as a percentage. + + When *interval* is > 0.0 compares system CPU times elapsed before + and after the interval (blocking). + + When *interval* is 0.0 or None compares system CPU times elapsed + since last call or module import, returning immediately (non + blocking). That means the first time this is called it will + return a meaningless 0.0 value which you should ignore. + In this case is recommended for accuracy that this function be + called with at least 0.1 seconds between calls. + + When *percpu* is True returns a list of floats representing the + utilization as a percentage for each CPU. + First element of the list refers to first CPU, second element + to second CPU and so on. + The order of the list is consistent across calls. + + Examples: + + >>> # blocking, system-wide + >>> psutil.cpu_percent(interval=1) + 2.0 + >>> + >>> # blocking, per-cpu + >>> psutil.cpu_percent(interval=1, percpu=True) + [2.0, 1.0] + >>> + >>> # non-blocking (percentage since last call) + >>> psutil.cpu_percent(interval=None) + 2.9 + >>> + """ + global _last_cpu_times + global _last_per_cpu_times + blocking = interval is not None and interval > 0.0 + if interval is not None and interval < 0: + raise ValueError("interval is not positive (got %r)" % interval) + + def calculate(t1, t2): + times_delta = _cpu_times_deltas(t1, t2) + + all_delta = _cpu_tot_time(times_delta) + busy_delta = _cpu_busy_time(times_delta) + + try: + busy_perc = (busy_delta / all_delta) * 100 + except ZeroDivisionError: + return 0.0 + else: + return round(busy_perc, 1) + + # system-wide usage + if not percpu: + if blocking: + t1 = cpu_times() + time.sleep(interval) + else: + t1 = _last_cpu_times + if t1 is None: + # Something bad happened at import time. We'll + # get a meaningful result on the next call. See: + # https://github.com/giampaolo/psutil/pull/715 + t1 = cpu_times() + _last_cpu_times = cpu_times() + return calculate(t1, _last_cpu_times) + # per-cpu usage + else: + ret = [] + if blocking: + tot1 = cpu_times(percpu=True) + time.sleep(interval) + else: + tot1 = _last_per_cpu_times + if tot1 is None: + # Something bad happened at import time. We'll + # get a meaningful result on the next call. See: + # https://github.com/giampaolo/psutil/pull/715 + tot1 = cpu_times(percpu=True) + _last_per_cpu_times = cpu_times(percpu=True) + for t1, t2 in zip(tot1, _last_per_cpu_times): + ret.append(calculate(t1, t2)) + return ret + + +# Use separate global vars for cpu_times_percent() so that it's +# independent from cpu_percent() and they can both be used within +# the same program. +_last_cpu_times_2 = _last_cpu_times +_last_per_cpu_times_2 = _last_per_cpu_times + + +def cpu_times_percent(interval=None, percpu=False): + """Same as cpu_percent() but provides utilization percentages + for each specific CPU time as is returned by cpu_times(). + For instance, on Linux we'll get: + + >>> cpu_times_percent() + cpupercent(user=4.8, nice=0.0, system=4.8, idle=90.5, iowait=0.0, + irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) + >>> + + *interval* and *percpu* arguments have the same meaning as in + cpu_percent(). + """ + global _last_cpu_times_2 + global _last_per_cpu_times_2 + blocking = interval is not None and interval > 0.0 + if interval is not None and interval < 0: + raise ValueError("interval is not positive (got %r)" % interval) + + def calculate(t1, t2): + nums = [] + times_delta = _cpu_times_deltas(t1, t2) + all_delta = _cpu_tot_time(times_delta) + # "scale" is the value to multiply each delta with to get percentages. + # We use "max" to avoid division by zero (if all_delta is 0, then all + # fields are 0 so percentages will be 0 too. all_delta cannot be a + # fraction because cpu times are integers) + scale = 100.0 / max(1, all_delta) + for field_delta in times_delta: + field_perc = field_delta * scale + field_perc = round(field_perc, 1) + # make sure we don't return negative values or values over 100% + field_perc = min(max(0.0, field_perc), 100.0) + nums.append(field_perc) + return _psplatform.scputimes(*nums) + + # system-wide usage + if not percpu: + if blocking: + t1 = cpu_times() + time.sleep(interval) + else: + t1 = _last_cpu_times_2 + if t1 is None: + # Something bad happened at import time. We'll + # get a meaningful result on the next call. See: + # https://github.com/giampaolo/psutil/pull/715 + t1 = cpu_times() + _last_cpu_times_2 = cpu_times() + return calculate(t1, _last_cpu_times_2) + # per-cpu usage + else: + ret = [] + if blocking: + tot1 = cpu_times(percpu=True) + time.sleep(interval) + else: + tot1 = _last_per_cpu_times_2 + if tot1 is None: + # Something bad happened at import time. We'll + # get a meaningful result on the next call. See: + # https://github.com/giampaolo/psutil/pull/715 + tot1 = cpu_times(percpu=True) + _last_per_cpu_times_2 = cpu_times(percpu=True) + for t1, t2 in zip(tot1, _last_per_cpu_times_2): + ret.append(calculate(t1, t2)) + return ret + + +def cpu_stats(): + """Return CPU statistics.""" + return _psplatform.cpu_stats() + + +if hasattr(_psplatform, "cpu_freq"): + + def cpu_freq(percpu=False): + """Return CPU frequency as a nameduple including current, + min and max frequency expressed in Mhz. + + 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 one element is returned. + """ + ret = _psplatform.cpu_freq() + if percpu: + return ret + else: + num_cpus = float(len(ret)) + if num_cpus == 0: + return None + elif num_cpus == 1: + return ret[0] + else: + currs, mins, maxs = 0.0, 0.0, 0.0 + set_none = False + for cpu in ret: + currs += cpu.current + # On Linux if /proc/cpuinfo is used min/max are set + # to None. + if LINUX and cpu.min is None: + set_none = True + continue + mins += cpu.min + maxs += cpu.max + + current = currs / num_cpus + + if set_none: + min_ = max_ = None + else: + min_ = mins / num_cpus + max_ = maxs / num_cpus + + return _common.scpufreq(current, min_, max_) + + __all__.append("cpu_freq") + + +# ===================================================================== +# --- system memory related functions +# ===================================================================== + + +def virtual_memory(): + """Return statistics about system memory usage as a namedtuple + including the following fields, expressed in bytes: + + - total: + total physical memory available. + + - available: + the memory that can be given instantly to processes without the + system going into swap. + This is calculated by summing different memory values depending + on the platform and it is supposed to be used to monitor actual + memory usage in a cross platform fashion. + + - percent: + the percentage usage calculated as (total - available) / total * 100 + + - used: + memory used, calculated differently depending on the platform and + designed for informational purposes only: + macOS: active + inactive + wired + BSD: active + wired + cached + Linux: total - free + + - free: + memory not being used at all (zeroed) that is readily available; + note that this doesn't reflect the actual memory available + (use 'available' instead) + + Platform-specific fields: + + - active (UNIX): + memory currently in use or very recently used, and so it is in RAM. + + - inactive (UNIX): + memory that is marked as not used. + + - buffers (BSD, Linux): + cache for things like file system metadata. + + - cached (BSD, macOS): + cache for various things. + + - wired (macOS, BSD): + memory that is marked to always stay in RAM. It is never moved to disk. + + - shared (BSD): + memory that may be simultaneously accessed by multiple processes. + + The sum of 'used' and 'available' does not necessarily equal total. + On Windows 'available' and 'free' are the same. + """ + global _TOTAL_PHYMEM + ret = _psplatform.virtual_memory() + # cached for later use in Process.memory_percent() + _TOTAL_PHYMEM = ret.total + return ret + + +def swap_memory(): + """Return system swap memory statistics as a namedtuple including + the following fields: + + - total: total swap memory in bytes + - used: used swap memory in bytes + - free: free swap memory in bytes + - percent: the percentage usage + - sin: no. of bytes the system has swapped in from disk (cumulative) + - sout: no. of bytes the system has swapped out from disk (cumulative) + + 'sin' and 'sout' on Windows are meaningless and always set to 0. + """ + return _psplatform.swap_memory() + + +# ===================================================================== +# --- disks/paritions related functions +# ===================================================================== + + +def disk_usage(path): + """Return disk usage statistics about the given *path* as a + namedtuple including total, used and free space expressed in bytes + plus the percentage usage. + """ + return _psplatform.disk_usage(path) + + +def disk_partitions(all=False): + """Return mounted partitions as a list of + (device, mountpoint, fstype, opts) namedtuple. + 'opts' field is a raw string separated by commas indicating mount + options which may vary depending on the platform. + + If *all* parameter is False return physical devices only and ignore + all others. + """ + return _psplatform.disk_partitions(all) + + +def disk_io_counters(perdisk=False, nowrap=True): + """Return system disk I/O statistics as a namedtuple including + the following fields: + + - read_count: number of reads + - write_count: number of writes + - read_bytes: number of bytes read + - write_bytes: number of bytes written + - read_time: time spent reading from disk (in ms) + - write_time: time spent writing to disk (in ms) + + Platform specific: + + - busy_time: (Linux, FreeBSD) time spent doing actual I/Os (in ms) + - read_merged_count (Linux): number of merged reads + - write_merged_count (Linux): number of merged writes + + If *perdisk* is True return the same information for every + physical disk installed on the system as a dictionary + with partition names as the keys and the namedtuple + described above as the values. + + If *nowrap* is True it detects and adjust the numbers which overflow + and wrap (restart from 0) and add "old value" to "new value" so that + the returned numbers will always be increasing or remain the same, + but never decrease. + "disk_io_counters.cache_clear()" can be used to invalidate the + cache. + + On recent Windows versions 'diskperf -y' command may need to be + executed first otherwise this function won't find any disk. + """ + kwargs = dict(perdisk=perdisk) if LINUX else {} + rawdict = _psplatform.disk_io_counters(**kwargs) + if not rawdict: + return {} if perdisk else None + if nowrap: + rawdict = _wrap_numbers(rawdict, 'psutil.disk_io_counters') + nt = getattr(_psplatform, "sdiskio", _common.sdiskio) + if perdisk: + for disk, fields in rawdict.items(): + rawdict[disk] = nt(*fields) + return rawdict + else: + return nt(*[sum(x) for x in zip(*rawdict.values())]) + + +disk_io_counters.cache_clear = functools.partial( + _wrap_numbers.cache_clear, 'psutil.disk_io_counters') +disk_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache" + + +# ===================================================================== +# --- network related functions +# ===================================================================== + + +def net_io_counters(pernic=False, nowrap=True): + """Return network I/O statistics as a namedtuple including + the following fields: + + - bytes_sent: number of bytes sent + - bytes_recv: number of bytes received + - packets_sent: number of packets sent + - packets_recv: number of packets received + - errin: total number of errors while receiving + - errout: total number of errors while sending + - dropin: total number of incoming packets which were dropped + - dropout: total number of outgoing packets which were dropped + (always 0 on macOS and BSD) + + If *pernic* is True return the same information for every + network interface installed on the system as a dictionary + with network interface names as the keys and the namedtuple + described above as the values. + + If *nowrap* is True it detects and adjust the numbers which overflow + and wrap (restart from 0) and add "old value" to "new value" so that + the returned numbers will always be increasing or remain the same, + but never decrease. + "disk_io_counters.cache_clear()" can be used to invalidate the + cache. + """ + rawdict = _psplatform.net_io_counters() + if not rawdict: + return {} if pernic else None + if nowrap: + rawdict = _wrap_numbers(rawdict, 'psutil.net_io_counters') + if pernic: + for nic, fields in rawdict.items(): + rawdict[nic] = _common.snetio(*fields) + return rawdict + else: + return _common.snetio(*[sum(x) for x in zip(*rawdict.values())]) + + +net_io_counters.cache_clear = functools.partial( + _wrap_numbers.cache_clear, 'psutil.net_io_counters') +net_io_counters.cache_clear.__doc__ = "Clears nowrap argument cache" + + +def net_connections(kind='inet'): + """Return system-wide socket connections as a list of + (fd, family, type, laddr, raddr, status, pid) namedtuples. + In case of limited privileges 'fd' and 'pid' may be set to -1 + and None respectively. + The *kind* parameter filters for connections that fit the + following criteria: + + +------------+----------------------------------------------------+ + | Kind Value | Connections using | + +------------+----------------------------------------------------+ + | inet | IPv4 and IPv6 | + | inet4 | IPv4 | + | inet6 | IPv6 | + | tcp | TCP | + | tcp4 | TCP over IPv4 | + | tcp6 | TCP over IPv6 | + | udp | UDP | + | udp4 | UDP over IPv4 | + | udp6 | UDP over IPv6 | + | unix | UNIX socket (both UDP and TCP protocols) | + | all | the sum of all the possible families and protocols | + +------------+----------------------------------------------------+ + + On macOS this function requires root privileges. + """ + return _psplatform.net_connections(kind) + + +def net_if_addrs(): + """Return the addresses associated to each NIC (network interface + card) installed on the system as a dictionary whose keys are the + NIC names and value is a list of namedtuples for each address + assigned to the NIC. Each namedtuple includes 5 fields: + + - family: can be either socket.AF_INET, socket.AF_INET6 or + psutil.AF_LINK, which refers to a MAC address. + - address: is the primary address and it is always set. + - netmask: and 'broadcast' and 'ptp' may be None. + - ptp: stands for "point to point" and references the + destination address on a point to point interface + (typically a VPN). + - broadcast: and *ptp* are mutually exclusive. + + Note: you can have more than one address of the same family + associated with each interface. + """ + has_enums = sys.version_info >= (3, 4) + if has_enums: + import socket + rawlist = _psplatform.net_if_addrs() + rawlist.sort(key=lambda x: x[1]) # sort by family + ret = collections.defaultdict(list) + for name, fam, addr, mask, broadcast, ptp in rawlist: + if has_enums: + try: + fam = socket.AddressFamily(fam) + except ValueError: + if WINDOWS and fam == -1: + fam = _psplatform.AF_LINK + elif (hasattr(_psplatform, "AF_LINK") and + _psplatform.AF_LINK == fam): + # Linux defines AF_LINK as an alias for AF_PACKET. + # We re-set the family here so that repr(family) + # will show AF_LINK rather than AF_PACKET + fam = _psplatform.AF_LINK + if fam == _psplatform.AF_LINK: + # The underlying C function may return an incomplete MAC + # address in which case we fill it with null bytes, see: + # https://github.com/giampaolo/psutil/issues/786 + separator = ":" if POSIX else "-" + while addr.count(separator) < 5: + addr += "%s00" % separator + ret[name].append(_common.snicaddr(fam, addr, mask, broadcast, ptp)) + return dict(ret) + + +def net_if_stats(): + """Return information about each NIC (network interface card) + installed on the system as a dictionary whose keys are the + NIC names and value is a namedtuple with the following fields: + + - isup: whether the interface is up (bool) + - duplex: can be either NIC_DUPLEX_FULL, NIC_DUPLEX_HALF or + NIC_DUPLEX_UNKNOWN + - speed: the NIC speed expressed in mega bits (MB); if it can't + be determined (e.g. 'localhost') it will be set to 0. + - mtu: the maximum transmission unit expressed in bytes. + """ + return _psplatform.net_if_stats() + + +# ===================================================================== +# --- sensors +# ===================================================================== + + +# Linux, macOS +if hasattr(_psplatform, "sensors_temperatures"): + + def sensors_temperatures(fahrenheit=False): + """Return hardware temperatures. Each entry is a namedtuple + representing a certain hardware sensor (it may be a CPU, an + hard disk or something else, depending on the OS and its + configuration). + All temperatures are expressed in celsius unless *fahrenheit* + is set to True. + """ + def convert(n): + if n is not None: + return (float(n) * 9 / 5) + 32 if fahrenheit else n + + ret = collections.defaultdict(list) + rawdict = _psplatform.sensors_temperatures() + + for name, values in rawdict.items(): + while values: + label, current, high, critical = values.pop(0) + current = convert(current) + high = convert(high) + critical = convert(critical) + + if high and not critical: + critical = high + elif critical and not high: + high = critical + + ret[name].append( + _common.shwtemp(label, current, high, critical)) + + return dict(ret) + + __all__.append("sensors_temperatures") + + +# Linux, macOS +if hasattr(_psplatform, "sensors_fans"): + + def sensors_fans(): + """Return fans speed. Each entry is a namedtuple + representing a certain hardware sensor. + All speed are expressed in RPM (rounds per minute). + """ + return _psplatform.sensors_fans() + + __all__.append("sensors_fans") + + +# Linux, Windows, FreeBSD, macOS +if hasattr(_psplatform, "sensors_battery"): + + def sensors_battery(): + """Return battery information. If no battery is installed + returns None. + + - percent: battery power left as a percentage. + - secsleft: a rough approximation of how many seconds are left + before the battery runs out of power. May be + POWER_TIME_UNLIMITED or POWER_TIME_UNLIMITED. + - power_plugged: True if the AC power cable is connected. + """ + return _psplatform.sensors_battery() + + __all__.append("sensors_battery") + + +# ===================================================================== +# --- other system related functions +# ===================================================================== + + +def boot_time(): + """Return the system boot time expressed in seconds since the epoch.""" + # Note: we are not caching this because it is subject to + # system clock updates. + return _psplatform.boot_time() + + +def users(): + """Return users currently connected on the system as a list of + namedtuples including the following fields. + + - user: the name of the user + - terminal: the tty or pseudo-tty associated with the user, if any. + - host: the host name associated with the entry, if any. + - started: the creation time as a floating point number expressed in + seconds since the epoch. + """ + return _psplatform.users() + + +# ===================================================================== +# --- Windows services +# ===================================================================== + + +if WINDOWS: + + def win_service_iter(): + """Return a generator yielding a WindowsService instance for all + Windows services installed. + """ + return _psplatform.win_service_iter() + + def win_service_get(name): + """Get a Windows service by *name*. + Raise NoSuchProcess if no service with such name exists. + """ + return _psplatform.win_service_get(name) + + +# ===================================================================== + + +def test(): # pragma: no cover + """List info of all currently running processes emulating ps aux + output. + """ + today_day = datetime.date.today() + templ = "%-10s %5s %4s %7s %7s %-13s %5s %7s %s" + attrs = ['pid', 'memory_percent', 'name', 'cpu_times', 'create_time', + 'memory_info'] + if POSIX: + attrs.append('uids') + attrs.append('terminal') + print(templ % ("USER", "PID", "%MEM", "VSZ", "RSS", "TTY", "START", "TIME", + "COMMAND")) + for p in process_iter(attrs=attrs, ad_value=''): + if p.info['create_time']: + ctime = datetime.datetime.fromtimestamp(p.info['create_time']) + if ctime.date() == today_day: + ctime = ctime.strftime("%H:%M") + else: + ctime = ctime.strftime("%b%d") + else: + ctime = '' + cputime = time.strftime("%M:%S", + time.localtime(sum(p.info['cpu_times']))) + try: + user = p.username() + except Error: + user = '' + if WINDOWS and '\\' in user: + user = user.split('\\')[1] + vms = p.info['memory_info'] and \ + int(p.info['memory_info'].vms / 1024) or '?' + rss = p.info['memory_info'] and \ + int(p.info['memory_info'].rss / 1024) or '?' + memp = p.info['memory_percent'] and \ + round(p.info['memory_percent'], 1) or '?' + print(templ % ( + user[:10], + p.info['pid'], + memp, + vms, + rss, + p.info.get('terminal', '') or '?', + ctime, + cputime, + p.info['name'].strip() or '?')) + + +del memoize, memoize_when_activated, division, deprecated_method +if sys.version_info[0] < 3: + del num, x + +if __name__ == "__main__": + test() diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8395947c00bd68641c53d6cbff94cba3a2b7ffe4 GIT binary patch literal 66535 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%0AHtvr93hGvX7?fP1s`@yf-YqO}fuV6Ypg<3W zW@u@nb~6ijAY{hpGV|NWY_BR!9iHN`MUOv)^OF2B^Rfb*?W`y_Ok{AE=ajLJcB85E zSE7#ck)Uhwi*ftp?GiwnpX>6Hv6Rg8{Zm}(^ngwj8FrJKXx3>K6tR@(QJsPt>J>E3 zyd3V$$DZ0?D#Qi!x?sSnH2#85;er*d8cMB25H<(e{qZ>8Ls71V#-@>zYa=Ck@ z6&|UU=TEBg-rwUILzzT#%Y+ew^++=?b`XidwtUDs^21zAB8zj^n}prkh`nkcqcaSc zjHUBd>h**UycIP7;tM}0yQC1lIH}sHnhC%wJ9f_E;qO}_kGNX{U!z?x0+7_~?PwX^ z*Dd1)411;%+jRBzaHPO@@Q6#@*swK!5Vgkm)%$d$@_!$1_rJt2f38DIWwx$RIOKpW<9}y+Z}@9 zoXsT^E-|jFE|+a1kVTMhP5VWZMA*H27cVX^BuO9d*!-3=H8NpuuJ^aAF4INKBkPjDv@&qlRb5wIwp*Qb+1#&DW4x|K z73<^C1K(61QCHMQ*7Z&F5p~(#w48WdHuvl4W36(|6h~d$ENPI>;7PO+N(G{*@55Z;S|Ctb!1$6QhS7MZba@Vs+Ss5$}NU z3g^I6>z#GTOZj)%9kI*n8r&9+=fM9^dcyMiB6#^Mc==yS!XpV=>rb^(bGb%tE|2$K zYv6Qo$p2CwQnFPTcMN>mC$W4t$N@ZvDJ*s3iR|dpHLON0Yv7TT^MAatHvaqt#-zf3 z=TjfRR(unYhWuP+Tnmlg16>tERui2w=(YSx+-nNemJ$ie&3GL<$lKDSD!L_jT{BpX zj$3ET8ea^1D;x@8gz!NtBfnrDc13xQOk(n_siAc`R#E>xIl2PEh~8)`MiU)yfdRPN zd7RiR=f7q>->=o(?C9i?k;nBxr_W->^p5CHGWB_0BtXa!q)>8V^vIL#+~~fMk0q|H$H9GG!mma0sJ=|5t*MglK@zLy>!O(<#W5G^-j)4gp`3u-OAZbKa zV_INgO3Gr-wbUVA{e)GO!Te{N?Md{)DZ>uIDCf>r{BDiUIRImO7}Y)W)Cviz4g9iF z6cOrO{(JA-las?)Kxv;wN-Yb0YpZxD~}p3&!ex!E{FJ zTf$R^sev}_A4i<5VZzFzKrJxRN#EOf(;;o!RB$ zIcp&7!Ih(m1K+3qUm4XIsCYoZiIKmNF=adTnC7IO&PXEyz9Mlxjv?LEHKbvLFa72> zHKL!GvIjG0Cd67e5YWT1DCNHekOEFEIuf6pZZvcyC^DdyvGfxgtPFyPT5tQauWQso zt7}-|n;N*eC+Ha^gt_Yo7Q4Wo7&~<6TLOw#j)g2s)*oTVmB+*9P#p?KA}dQW3>3gY z@1Ub0n!6M0*Z2``62HQ1z}>g7(Fnh0j$I=!RDKIzIF8f#WEw-%0;`Fg2vP;vz-}LM z?n5VnkSK!9iMibv!=tZV5V$dtVS*v_D+ukejql;>P&En{Z2*|xsB#Mcyu55fKo4Us za;9qf%Y>E09E%v@l8d|J(6gAFTc(P7ckIJ*EW_l=UW8dMAH$> zM(uu+HbKU9EYCmYn_uDOPkH$SFSJhTU~dv^>~DDc=e$UCAV!k$#V47;M*RPq7a^Fx z#S~*g_>8JR?^Ltxkh(}6PY=9k!cX(U-Ksvr3i!ReaI2LLm&RR6KKJnW+#2I^ZDoO z!xPkN>fpbcn;HYt#qD;)bSM`xEM&?NZn_EsE-5UQHT>?U>6{7K5MqIe;4Te?BobF=`N=7=>e@&pBv=PjA+tp*C-GHgBKiRnGcz22NE5Ha`oe zvxWkS-NS0EaaZaw@y|`w1G*Ax%hDwnNhaJtL1zhxX|o3|rP$&e2DUNx65U49ouA=* zR0oF@4a`;$62Dxp);qsOA7hN(G^DMt>>zqkgo!%tl&RYm5~Z-L&L_&W=iKhuX`5ob zMo~t4U>$_yrsq?1)%5I`pNDV(=oHPA%qUby;zELn)$A3N-j)`c&k`QxlkoKE0t&dy z>Z3xmD^3H)y3ujnoAz*Q)wK10KUx#>e>CrAEr=wd;c5l;QD7ZlDp7c43d4wU`e;pY zP>KXRI55SVE>u-_2?{yT{jxqyfesH!_M^bPP!13RYaU|&@SZ-Vz^q#s11jf0G+g&*@4?y9i{7q>AH2`devUl27udL}FaY3l@M8pq(1RqqUN8wd zUjHdwBZ_p?2;AXgqv$=cF+0_m*Dg*WOPU5QBBncxzu-<>8i+PV@0i!2H!JZ(4o0U+ z&B0Gbr9KLcn4C$K9w#CF1r*15oW)JWFhd2@3(B) zZ>JFjOd9JSMnx<0wD6Zem~X#S`c5`T3`j|w*kqa`PdZw|p&Y@VIrtXCh7B?Z-Vg?G z7Odwj_MV1a9x>hz ztsUKyvFC~UyENjd*s+jSbVwV$ct<9NL!pn-qRpId6rP|zOvq$6_T{G^R`OgcXjxe^dg z?4N|{M)wFOJat|I&CFr-a80!m7gA7^LrKYS>nw#}z8F4PS<>EiQOh|LoG`U;5Hag3 zKEF?(x&B4=Dd|i9B3_WiewIBcN>AwdBRqal_rY@by;tYiCs{dHkWXmwIWz)XaAztB zftbcQDj4E$2yG(-@sKC0^85Wr6y9lh(88KRF;~~?F43Qy#;^QC10uusCfpETG5{gmA+et6@>Iq=6F)WYGM)jEN0HsUW_R2` zqZ|y2bplb6-pkI30Kx_4{|PQ=D(AVod3^qxY@T2-`g0}2(d}s94isdgV8Q8=-F!^r zBwgs-H#08!g~Vw@E^U}or;NW;ruiMF;j-trG7}wZOQ}8pmuw6lwmXJCJ9M1V47GSZ zL#Us@CM>WGbae&orGUN}+cNpSVP9|urf)M@1R?8Ds1xuZJQ3C&mm#BcFpTmoLnMPm zs|Uu3bg_G!_~>77oMbg*=>^x9E2cuMMvT^nzdP_35ax|<8E7>2SwcR+$ZkzYt-Q9MY*)d;#|&K`s+00lt93K{z-d5@{^%Bo=qF1U}*o zsG4991$msqNu%T>%~4EZ&0>uA{|0eMlIJh(tZ>-}1 zh?l?tf!sqFih3Y?FyxH1G}ABPWgmsFg5VME5AM5Xy#m`tQk_7nnzydpCSA01aMtM9 zV?s>$E%;D)%Ypv3kYn-x{$*6`|7%mqr9O3n#$m;Q7z7 z@?^Q4Jc+o$-V$RI1a1${@0FyUfj?p;oCcv|9djYfRSA#&lH}|WBoa6D7oflc6VK_u zFBtf~qyrx+b#$PY`ZCT}Vv>AIm?^3&)N3!A7*Pg8=eivoy%d zFn%+qv%#=Aco}4n!DDb785oFHa20rkyS9`*(ZDGP7m~q=Mp}XBnN1wJrnyGu0w5Ow z1ajvZt*rlt<_j;#7n1%96Nz&Ztt`mj&ihW^72X6$@01kti0?4cjD+~4&$8WqPx)ogjcbedc)k4=6L-zaza5u_GkN`o; zh;<6;iAXa%D2Xx$HnW82F=~N)(PA?(>}bzRXV6596NQ=i)>a~B9?Kxe8*v=M5OP9O zAw*f+9Ve>c?k-JRtlkUz)S?5ULTM0)T}Lw{8L^)Wx8cC~TPisie%N4U^pP(Fb!gu3 zi)LCyFXza9l7S$o+LbyYn^B!n2#kB_feO5Ve5ebctr9)zgrQ+tHy2U^ZYx>IT!am3 zSE*gHrIEyBFSEPb{d zy(n0vSU^!F_ABDc8dPM?2y8K+(!*;u?;B+^)u9NSfwxNGNFt_secBv`86Ini)A<^M zP#Wv4dG9|T4ZPYs3>FDaxcWVwu{P?L!T^!IS5yTQkDN}zued-$*TAPv6{*~&H4<7NeTWR!f5C1!c~Ad6*X zQriVseDrBY94NPUzI;w1Bfzd<3A4O7!xx1xKZkO=I6S+MNZi>kc2%BXPdh<2JWgbJytkY6G{$iET%1+-SSU}UuC*5epI0SKXdJlYQjz+uZ| z!r!VGyq5f5y4*y=3~eFbtv6~DLv%#*z&aAHTt{>n6z<$Oo58Rj3optQHzDVNIQI?T zZ?P*4>ZU$H^m?z5rX*5v^x1GLri4HNil{Ej8qvpVo`PdPH3YQ&OYjnrI=pkTH%Qsf znf{Q_0DEFvu%bUd<~5YTrqEUM`7oM_k%Cq}H4Ht#9%-D1q5xL_R$OJLq&@Apd!r=R zztLKRqcbdTLNSJLTgFB+E+<}MnSC5{=dKNlmdt3m>!K_>GFXFo^LRyt&kU;i4gwgp z6^VWxS4J?(BoBsQgE^1DhKi{cN^7uzhDU(L#92y}-vE4>0oA)>w=Y33mAEZLg&>Xi zKenqvqhKv=+gL{!YiMXdIzY|^j!cvtrdfs>Te`8?h-EV4vv8n5a0f6NI*fX>abp17 zQ%6h!ecCv8)}cM!`|6}JyBXe^JGWCJ_vI0YpYE8ws~~`>O*5!Gw!gzY+}P{3JC!;S zn4@>qN4fqPleNt`h>hh4a~wWnxa~^#JjzC(o2q%q*}KQtIlOE5UK>*e6d8w6+0WR= zJMRzQmd7RCJ{{E_Ropj>Ff>D&=IYQ@ST6vfXyc%P`iK*VhE?;VI57DXCq>WWK{-9o z)7C=kt}J^VMdL?c8U?83rCs%gjMeXQJVe_G0Wj0UP&9rWW4H2%+!Y%USh8TVh>b&R zTu4=#)$1Myi8N)0LBrf}nqCPdh^_#0W&`oOM6@9fE(2qW8*o72K3S47Isgs!!OgIw z84|ySoOXtv>K>7P84*5_A^9^72|2I?hNPIsfSlog5H$FY;1PnzbGXsm*<9ju3O;lg z6k4e$>>{pe>fA&0O`pTA<7c-)FAN0?q8Y$Uice=a^O959sAE9Vc95HkY979xnB zge{~gp$DsoQh&mPElg->U%{D&igSjcMXIpD3#>@bB{&kHE21r5=`p=oCC{xB} z@m2=%J!EbSH^NEyujBYN9B2+!nF@4RR>XsQV2Q`exGX(zt@<0j!bO3G)l$a_Cc|W9WMsbWiwm}rk z(5Ob}NMZ~}*o^>)9I!FG$NSM{G{4E_(QJB*+U%2%Z$k97r4p8oUzln}Lb~m>2HaiAQF`_wWS{mPgB7$T^=(o^a-{I{$ae-x`!So_7 z?Oq{!nn1OCfChBZEeaVIYUlPyngiBN<9b3y?0z@|8!rxuNQ`r$RTa(KWAGHyQCJR+ zj#y+etwMp!r9>z6Z)5vbmxu!+QrcdxGtin?X1ZBf&;+~SZ)V?wZM}o3_wyqCy@;CI z8E|s;>7?#1;uAm?}WzV=%$K6u8`s1QJZ^SOz+W2c&Pnf8k{R_eZ{e z1_L}v3nS#t*i_p%gVy0Tj#tgvLr5~c$Bz0%!K-FJz_bXmgiKZn`lN{wC=|F@enWuP zy6zvu+g3v@5!oZWN(@I%|=9JD>4-WFx* zT(ZM^9^Nth0F1!GElUxDJDlhrMOB>?;Ukt55tR3~QA9sdZ!B!Gn0eV$ zilX-TFK%bMwz-!*w;eQ+&^Lk92&6yD zD=lIR?a?REO>lrZW1JMBo`vJ*omYU`*N^?yc45EL&h`x};J?yN{{!p*dx^eX69f7m zWJ%)w?k;(FyAmS6)dm5syG{g%m&1Rd7L`z9RbeR@Ih{0CD zb?0HsP;9u^+eP@3%LWLeB19-2`mIhUdSb%lK3(dNC7-_|9Ookm$^LSCk;b(!Y>537lmu9T7R->VpYA^6$#T!71#i7T9}%3*v5G#Bh-}gQ=B4 zfvOzj7o(ssPqRvs`4I;!pShN@s`v~S1E1R0|WfDEKTQ@CJ6+s`>&r#GKL7Xt~bpV^h zr?u30JG7k$7pX0Im@=)yvwC?ORWgjKXrXj_6nH&)6`wXOm2g7FoS=2ynlqrm7|K&) z{RG?*j@VHv_Mrs^!e_->Qry!RoHYb0>scAHyuytzoSXK0GL~uE5;29u6zCSRx%mX` zwK{ZJppd%(#$88C(#wr)#&(qooT<73ymrhC*Es?u@%*;1UO0fB!Z!M7+zjpS7&Vi} zDC&BSW1R!%HK->gHs(XlJ!Yo1GUUAGO`!B=W5b&55HM2=yINPv^X4M+eYa&HYB?~D z9W1dE%`$iZ5i9qT&6C5*-9Kl#+h2UBd zEWgV(3l-3555+_`!`QeCxCsM6m0?f_I_MAL+}c47SBR~FLCBqfFnd6FW0?4iC1b)w zGTt8Y+Ip=<>(Y#uHq>-?(BMV19YDt~VP3==lpCJJFGJ5d$p*B}8nRLJ$i62dPz>i} zuEK$q{}feP zny1yT#PN15#mQi&Ar{bX*eqFQY#2=o_bSy%>juy^19+@=00`cOz!9*CE2Ifgb{*+6xy_LSR;D-!U|3P6 z-~$KpiIyo=g^~mSB-&>}gC2P&T0g**C!0TLfJa6`lgv2K2=Bx})V#-52AhP84p@?& zMdslMp7gSj0~OH~bVtvxL|na+dy;AxntsK}H4DjzQ#CXm%jc{3iH*P_Z~5qfu=CmL z>wNjXXz|SB7!Z2r!;*n;vsXm$m1ZJz_E}i`5i6gC7r<8GsP36S$CIotFicZ4AiC)T z%pTAV38a%{c=0VkRD|yuLx(Y(B)>{65ccs>HxxN*%2(vWs6<+%y)%gpfwq^g@MQ=& z4ukwC{eW7>qgJ8`9qu(Dd#bx;_BwFZwE06mPl_+wXN^hKg5tc)2Ton9R=ekekM@M~ z(GzMDf#D*t_SU@>k3dN(_YEmvhz(u*nIR|Gq7UZPL4KUTww3lh+UZ>a!_x3X`(ikwbx;9fXs!bQ-f)jUWWm5#b3<@4K&XpAi$IX_wv) zX4pu~61b?&c1eeDc;BpNM%_B-?2Zk-eh$v`iaEH>H>LN1?v&9y5N@t;uMwg|1#^u5 z7v_#!l6Gi|)+H&Fh!_+~=QW_p*KTeIOwD&lv1@i|AsHB=j~ zbVEc>ib4r<3L4DqNhm#!(+i}5WYx5Ci3bR29#whV=oJ_iZZqevRH^G#2==_wOK&q6 zb8++|YsqGslLvs)`2lI6u;FI>z(s1QA|(G9lt57X0KWv@X2#jRJfMjI#)zoC#&bwe zx3MGZ$Y;pXj#Yw}mnx83M7)Yz+PJDBD`>;;QgS1prp*zyHeraBKt{WRFJG;wyYv5h-k}8b^o;UEu?@# zco^4H`0Q?i#C%ykpj^5n7S36cqwbPiP~hA{ItM-zLBa!5b5z>obJs&yvn{LZzOrn0 z-PlBIr3|!0>rkS%@U)Jp1-gS4TfYjNV|&4;MyB{$@1lt$v-VAe;8xLRyT1xKt}Y5Y z+d++Pm$0kE;hPY5;uS@0=&lG)w5ITDRfOhu{2Mf=76+fkk6RNTSNXJ|h44m=$c9GR zAsW60DYURBo*NR0>FXwkS5`sd2ZHrK$m0LUWRZY0-rQ)&5auaPZ2#L4pHIh#&mCP~ zU6J+_G{rduTbtEQN8663m7Y-3>zPglO{v@bLhd`s<^jA1gL0C%TRwj%0I*(3( z%TuNE2nx+^j73M@R&jQth}hA=Wdk!-BZs$nk`9li1&Rg(S$DSID-9s8NLMDHR0;^x zf>)Py5Wt3>{7AxQTu8nn~N9 zZ_N=5->TymbUh|I|2J{;Ld*Hq9J?U(+;3=G=P?O3w}bFqd80%1OFgDrT}LbSY) zqKZAdTMPY=@5Eq&Z$r@*%3|~mfTa#zUv=0SqH`OKKxVX?6<~14PIQy#rV)Jfwk27K zn?u6@okXb79l>9a!i$U*2Un0R4debs1y_(Nwzl(3h0D;a;pBv@j**GzE=dGV$X&`e z3J4*UKKD;}&e^j+`%I3GBIk4G^N1LOa~1qgE%zgq5*#~Fitd~HGl@nKJ4}B-yKgpn z{fltjTNu@PtR3ieRw&UD!aLAy>~ z6I?%cI%@@swggEftl#jOAY&qeYBjL++>W#`u?<$H$(sD(a1b#Vqsi)AV|gXnvFzAMoTf!UUB_-slK#-*q(6=$CnlEcN_NtSq^j(-9XpPtTuCJH z$WtI;rZa_^3=JI~GGKS66nHE%Jn+QUd3d3bj*F&TCy>AGc_4urR9TE%a{bk zIdFw*fByo?HY0+ zbCw;+iZOPeMj;Er5CvsI;_fl!$8t4Q7M3s=D>bj9TTYB@z$?&n9Xxcnl5;@PboNn9 z2QcQIGnB~-(;4HL$Z@P&0bQXXl#}j`aP_Eh{+rW|3{|Z_!7=ut4Cc;9NbDnTPy8W~ zW00mEn4PE+dBxKl*b;fGU$`qfuE2{~P(u+qcu&-tPDN(W)3oP&+>Fkg*K7?;)`#<=n-ognF z10xRu!`n21tcUw6$Bz&8AeIe;Di^SY%#j@AYn^YSmqV05yYAG9+ zPe6xv(-&Iqph*$wlLQ__&gW>CN>S;p3bb_=Rk&IPQ~f#Ts}{O5x-zP zmHR#}k`LjzJ7J#Wz)cDUq^S44nJ&JJm@GZrQ&Kx06>IQ2KC0)i(9%uSpPVZR3<3^d zSoxl*}T+XO`a>2R=vpxo9=|ScD8(IKMQAOrzcZy6~<>LCqdEM z*l=!ia(s`b&v(RZ=6q)AVn%=Q2n{a7I16tY-7f3ZW*4#R3rof194TFnrcV!^WW+hz zJD80Jj1|gjVlnV(M4~5kMEk&M2~7#QmMXGT;ymG7X^fEEZ1ls)>(!br20ZlOCUG6v zUy5rLH=!leE%Hq>%9@61n7_rQ<~0D~rf?0i=abBavnqG|+tWVUogUby@VQk$&v6~& zTqMrJb-hM|`bZQ%biz8bt8i{>9=rhUm{o+#VU|zpB%xb%%)zyay|OI9b*;A+LFe-! zLhK@TXe)3z>}ewb_)-VpxEdf69f^GEQT&b8;j~(hR@Um!Sk~I>QMF#TD(m$qj)0#w zbOz`+WXUrcLs&G1=fPrk6j}p#?L=z`7f<24HlGRd58F4{F#9WLI$c-~(S1SO{88;* z2jE4rbFu**Y~ZBlWP^7>{p2t^RdvU@MI9RL%iqm|#a_?Z3ev5JYYyB)E0}rSIrZt@|uI>o{o}+lH?56-61z>WQ1S3zs*8*||tlfc%+Jos_L0d4N0X`GamQiNn404sDgIH~AcO=MYny+`UD(%hJEkC3Xpl#vrE^G$RYE z;w9^ZnZF&*-kc4^cP*7b9pwVz#=v`avmQyD-(t0cmCFh;*>bn^2o?g7NCg5i)WG4O z)9%)B5#Rbe&v5^-*B--9qLuaJfp~j-WF(v?=+^3gDAo;GprlFDxLd@s(`iilp}&Q4 zhQ=ca({-)7;FD6P6SV5%2tR3Fi3Z>cS$t zC)skC1K_3FcxE^cOb8Vo1pN?0#oE%rS%Io|gv zWpF_U`%3@h)&&%p@baith3ARo`dTtAX1BesFgFP4HviPnX{QOaJz#S=14w_R% zJWBpY%{yl)%p5vY28<2p3-CEmHn>Fl^*qSx#J!01KY`R$ zy~>0Y*PD9r5NbPypU{9bc@3_dg^9knvrKej8=@o)HHwr)HYFG>O1awn)oDZ3hGqbb zt0|uZF2HVQ3>x?fF|IO>X1;d7>GanLL6GP-rIT%R5z>SH0+m?zRf_B0H%Q&I!>!bB zS$){c$cnZB|FaF~sGJd}Z9@AhW=Hy3)K74SmQCvd?pAgkC6Y(eRP1?&e{j@ljEdgFmC z@8j}X*p6e~K8Agrz<9M?&Ts9*9k;-PztMUdTQ)mT?g(shhhUQf=d${%38{{6M6{)? z+NnOb6ZHr(oPG}LTEb4iy4KZ4rfHU^tq-MDhmrf#tgUq0-A~{i_X6c3_I`$lc}KnB zJ8Hjo)M*^0>lTu0%~gBk9IV-0cY?T%jU%FbUa;r&*uCEm_Q3-WSLNTRXyjPi?6sqI ze2d55xA((iuT_qr?tWkkWi0>7-oF^t&-+Fe6t6u{W)7@pCLt-(ZL{UVx8iFycM&~< zVz-7s0cj)91=nuLhlPF+JSkdQ*9ZECPaLl#`(MKEMf_eizu^-vn620XMmbHfDruKQ z0x4cPH_)OsdPScA(zjGvbkJ7G&6I_Y0b@yW@qwY z_OJQ2v8i-=G;>DX=E*+h-SyV~b0hs}Tw<=@#!7mmKldQ@95Y zs!jZH!lar8*H6hV-qv}lsJ=R2tizC5k^NOO_-=9OBf`(PKPtmbc821@qa^Fqo7_#a z39<;3SC^}b4k=FP+pvWU;1iOVR40TlQr*Fh!B{>jw=Lk-`Bv)5t3qMx1j_2~I3VAK zpfS0{Q#||E1YQThW7MgeKW9X@!x(p$-*X1%wm=`|)M!MIOtlBFMjxE^Aj8)qu$O=i z51u$=vn5yUVe_LMg`uoL`QI(5e#3jy_~js32ED?NEF*|KW&8yY#?Rzs`iDiXA-aw~ zH)GlO;AiSRl*)+}3X8DesRd*+pz5K=6KP(4ldG?C=>eBMA&hZ#itqv9Q*Pt)SN|aV zlRy#BZcH?RDFy}T3}qOH>ltVyLlNSYs>0JjRx!da32_41-4vTTwU5wAND#UR-2{%$ zR1cw-aDZ@-K+h)CM_?8g^#tJv;Yq?%gf9`2gfA1mLij4-X+l5Y8NvX8V?gb?HN>T7 z3AA*nVFE31>KK7CmXA+or^d!}h3V0mbLs>)|CsPR;RV8rgqHyM__2`H8CFe}-a z>FmUmZ&g0uF0&W(r_-s-nTgCXw!KC9hhCZSy5+r&lF*taF%e6FhTex;XGlI zkS0*})f8cx@D~7b-kG>3X2n6{S133Urhax4@;rl@(ALhL!LkyGM0es)qASs*k0!PUA{L%@(CV<-alpGR{{P=f%mxEJ zam%v6DPV)Y(V~oVozGftzI0Hgqv2iTNc literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_common.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_common.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8a537aefe6417742ae88810d35294f262b2d6c95 GIT binary patch literal 13882 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 literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_compat.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_compat.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..4aa751011f4a7e0620a340e74fdbfd58dde3184c GIT binary patch literal 6561 zcmbVR&2t+^cJH1U3;atM`hc-cx)KITAH?O~Iu9CFVowYOCE59m`;$wmLb9(>C0^?-n>*tJQ( zn(m(NH?Lp6e&780!a|wh_peX?Y2AOFvHzr(!(Ro1ck#r3!5I^*!2}mppEtPat%hZK zyJ4H&X*j|bjwlFM6on^BqAV(%QllW9O;_+UOjLVTqbQ3ilwPAG%Z-YxHWu*I#Def% zu*NY_6D9PEp)X5-r~qOC5H&y?n?fw+5ZjB`^LXDH9B&-w>@ybbJ4`P1%74w(EzaoA zKrHo743-1#i3|-VoI7IoFZv&Uc&Q(pEF^#E#Zp_zP^}$Evz+GzcBvUN0AuyrT=WB z+uHDlDtg)#GWJ{1VAxE$PrChXvh6?XCL4a#7gG5Tx08)1^q)!f$Kuwjv>Q`AIXDaiY3dyJ&A$7rQ{L%)N7G%Qw zsHf*Pp4dT?GSJFb{~nFzv8rOqG+(dYzOnvE3|iLTYe}{K-f(!QnKaiQM6G6j{gE6D z*N5HV)ovIk&3^xC`&s;4^?n?$593kN?H_hQe%O`awkiViDcaRS!}t-3h(tpXiFeBO zA-e}0bXlw8VjsK;ul^Cpb7e?}u5+~jusNx!Mz0>4vv~d>{scP+zC(9ptu|^?Rt7R| zHHU<}03_eB2c6-%|BQ6MVN0hCiy&;sX@N8!y6XxT zTqx>t@If=)kYY`4>Cy&5(j}I zmZ;aLId^ntqfJISPh#N)o|s7XxMNivMRP5>bovn}NgnY!{yQ`&o0L+n-cAcC-)9GG zhfm6BDYf6h{PX3se20Beom4PWp_#1J7hcNl;JY185Ww}-Y}Gca zz;U=5UP`^Rw8Mqdv(#4^OG~0~2CJ#lbLl&JTVn|)7~HbEI=c{3XCnGK5l%-+*%!45 z2MTQbDU8jQH5H6p8!T69?JZph)G|UZgylSpAXfoUlKCH?6C2(+!%ERX`j|1G50>J5CQc~6m2LvAmko71C6 zgZ>oHl#-VucZ!<2r3>9e4q|hM^{RH7suOFc_e{jPK&KMg!wV=^(ByVAPG}N397ig_ zVgWkQmu5e0_hqPU9IsK$R|A7uJJjVon^Hzh(xn+Y?ht8oROUF`f#!I;jMm|2@tnh- z2l2t`OM&KIi`YrOLrzg2FQM6GyBsdeNX*1a$uQdEKYt)W^;IQXGEDm0S4XiFev3?! zFJvoH%_LG+{8-8xWq?9ky2lwY+2PEeLDf+GBfG!uQHqansuK5_`{0 z9Ke)1Y_FQ(k1SQk$$PR`S+&FWD#BiO_MAO?kM9+-V}e8O!(D54VYk*cfzbivEi91Ik)p2>Dg~*Z<(&2!%U~l7 z7YGWn59x3-euNu(kH@Gc`NJ~wco7<%_p`&(?NSV3F0>EDNO|mKHFYv88z$6< z2_YB)R+Pwra5h#rE=(b@1Y%uMf16d;`NT<~3X{Ubomi7%>ZXOvzRBQr+{{7mWX>5j z@lxAisb^L&gL%y4>*xWWExf|q;u<1-!LT={y&tpe7|{iRE6(Wohw1)SR)m}RZTMGU zesPCqm0kh4!THpI+p^M9#<5=!eF1$bv(MnxC#2B0F3^W;Wl|QHqp_I*TvklWKPBj5 z3aIeP>>OU|0B5n|5El;5WWL3za%h~z`lbjRJx7X@)$OTzOua#|+1eU)6(Vyb`!Jlc zUU@}G5W#oDp1Oq_Ym{gh43&I39m44)Mv4FhtJ^3dAs{JfxER1Q)E5;658D3l?&rCH zIjeUcKhn;_kMDk}-H-3CeewWr0X&KN2>{hif=15J>M4q?)H1y zZ~R})*c{!A9VA9Gc09yO#;5G~QO0rw%HW|P=q$ybu!PltYEw@hE%$~QqPqMY0t>6Y zZ%vs+_S_y{x(&%xegY3}DDa!%p+}!{&iIhkx}CGH(4tQa(-0kz?1HgIzznnQW8zh2 zRr1rB5C0MCF$FEmaEpXu8DcR0$^VaI24}sj9noziCbH2sOly9zi`Ye1f*|)10#W&g zm{A|mbZHi8=-Ox~nu(l(DICX`UoyJ$59(Gf2V|b>$8tHjO%P<;)g5Z?Qge@*_oR_AwFMiEnXo4Zy`$&@iJ#$Pm!y&oV|7+buaBKVNz4>dDel#l@V< z$Cv+ijLZezo*zoB5m`nJzH!t%kEVp=Q#^S-=G0oad6M{9Hb{<#ytqw37a+MNa%2-b zVVjV-j2&=w8BPJle#cT5GUN>cJ~Tz@iAd@epzM7|IOq!p7R8(Ky?lM&#a!_K5lP~0 zBI7_r_Rp9pr&h11lGNI-2!bddSR7HH!GhA&fi?TiNvbCIK`{%tkCSIN>Ngqd@JV6o zU(8xXR1eoCg%A+|ttAUPY~ntDlv>ED9!!eB&i896(c;0;x!C`Ask?tH^$s{^&)-Z7 zfb%CM1Gh-72`4EdPAi);|2{3Rv8~^K#izCh8Tw7C01cpgSA3+F z@`};JrvLE0M<4ikDd&o>WHM5r(N)xnHu4hEJUEVEiqs(XlgNN{3|>O!qkcpRPROqK zk@8ogQ2O0AO)3mxKaBi%)Y_QgYIpl`r96B6lCXS<5Wn3-kY{#?;+1>BFF*8CAEU<@ zt@vLOQAeR@*E}+u;fmVyg$$o|6;c6c>YEpct_yWTS*scPPe3rrU8*Yt7-LFd;La#c zq5)Eiruqh*wByPQ^(>jmb3_IigD_r3W3B|D?E#N2C2Ze@x#R~Hjd7(gnFqWIU{t*7 z1#Lyh*$6R8OV8mske@YMEg2(+>&Bw1kmgzKP&>pEqb+%3lz1V?K?7t&t=_-U_7sXT zIJ)sUQ+S)ltw%st;kCg9ROh_dJV zzfI1vLxffHeE$^t8*2-Gdd{oq_UZ{BVMoZ{&A0!$e6tU(Q;G1_e;rccvhkT$shC04 zkE=(7;uAEwh#R6>j4n<^Oi|SU)3R;uv=9$bVbw)?iRDn+@pi1eA?k^wJlaL|3>dVF z5~fs%wwvKLU?@}%vED)uhdCj%vl(?m#B+vtveRaJ^=D=?LJrpI0_hQ?2?;ThdBR&H zEM@=*TGb9wYmR@&3X&vaTz`u}Odf)jJcmMl2PL9B>_=j60<4;KlAlDdwQRW-f-2(@ zDDbM8F&Isfa<6__7lQyPIOQFy1koy@mr`3rV~Gn&^4iQ*OsW-XOf*M{?U0$8OW|DPw09HAjH3K4(yjOb8sfA0vufZjg}T!}%d^Y&eC(Ae-di+L WUyUyTZqZtVBVOW5#}<3}+J6IS;@uno literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_psaix.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_psaix.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ef6150024d09174e82c70b9bda63cc1788373353 GIT binary patch literal 15465 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

_;E399Ep41SLiW*pX{ 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

ka!dW3G_mW4{cC7rJ@ zZpW`$tt6p`bw)dV5!PhJb%EKWL}{}6`4l(1S*pUs2w0{L$|wufaUBDI!$3=8=!pz z8yoN_O92=~$1z3ualZG9On!n%jzIfxrNEr zV_Nf8hpx=8@-#dhD^**M3Oxus+%aXT{4&pa2XU|IdAsJgf Vrt$iD{5H$gk7<{j^ELU{e*?(6eQf{$ literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_memory_leaks.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_memory_leaks.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8ae72fd1def14cd289afa80cbc9168b787a77682 GIT binary patch literal 22534 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 literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_misc.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_misc.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..aa67bd2157691fc9ec7e54faa551d36e39fa11cb GIT binary patch literal 34343 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 literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_posix.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_posix.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5112a2df42f16c07aac56fbd6404b346749c4508 GIT binary patch literal 13267 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

N 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 Q1QV3ir)7P7Vpf;`2ZP_xaR2}S literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_windows.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_windows.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6764c29e409720bd6ca4fda6131ed97ba65bde7b GIT binary patch literal 29204 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\S+)\s+" % (field,) + matchobj = re.search(re_pattern, out) + + self.assertIsNotNone( + matchobj, "svmon command returned unexpected output") + + KB = 1024 + total = int(matchobj.group("size")) * KB + available = int(matchobj.group("available")) * KB + used = int(matchobj.group("inuse")) * KB + free = int(matchobj.group("free")) * KB + + psutil_result = psutil.virtual_memory() + + # MEMORY_TOLERANCE from psutil.tests is not enough. For some reason + # we're seeing differences of ~1.2 MB. 2 MB is still a good tolerance + # when compared to GBs. + MEMORY_TOLERANCE = 2 * KB * KB # 2 MB + self.assertEqual(psutil_result.total, total) + self.assertAlmostEqual( + psutil_result.used, used, delta=MEMORY_TOLERANCE) + self.assertAlmostEqual( + psutil_result.available, available, delta=MEMORY_TOLERANCE) + self.assertAlmostEqual( + psutil_result.free, free, delta=MEMORY_TOLERANCE) + + def test_swap_memory(self): + out = sh('/usr/sbin/lsps -a') + # From the man page, "The size is given in megabytes" so we assume + # we'll always have 'MB' in the result + # TODO maybe try to use "swap -l" to check "used" too, but its units + # are not guaranteed to be "MB" so parsing may not be consistent + matchobj = re.search(r"(?P\S+)\s+" + r"(?P\S+)\s+" + r"(?P\S+)\s+" + r"(?P\d+)MB", out) + + self.assertIsNotNone( + matchobj, "lsps command returned unexpected output") + + total_mb = int(matchobj.group("size")) + MB = 1024 ** 2 + psutil_result = psutil.swap_memory() + # we divide our result by MB instead of multiplying the lsps value by + # MB because lsps may round down, so we round down too + self.assertEqual(int(psutil_result.total / MB), total_mb) + + def test_cpu_stats(self): + out = sh('/usr/bin/mpstat -a') + + re_pattern = r"ALL\s*" + for field in ("min maj mpcs mpcr dev soft dec ph cs ics bound rq " + "push S3pull S3grd S0rd S1rd S2rd S3rd S4rd S5rd " + "sysc").split(): + re_pattern += r"(?P<%s>\S+)\s+" % (field,) + matchobj = re.search(re_pattern, out) + + self.assertIsNotNone( + matchobj, "mpstat command returned unexpected output") + + # numbers are usually in the millions so 1000 is ok for tolerance + CPU_STATS_TOLERANCE = 1000 + psutil_result = psutil.cpu_stats() + self.assertAlmostEqual( + psutil_result.ctx_switches, + int(matchobj.group("cs")), + delta=CPU_STATS_TOLERANCE) + self.assertAlmostEqual( + psutil_result.syscalls, + int(matchobj.group("sysc")), + delta=CPU_STATS_TOLERANCE) + self.assertAlmostEqual( + psutil_result.interrupts, + int(matchobj.group("dev")), + delta=CPU_STATS_TOLERANCE) + self.assertAlmostEqual( + psutil_result.soft_interrupts, + int(matchobj.group("soft")), + delta=CPU_STATS_TOLERANCE) + + def test_cpu_count_logical(self): + out = sh('/usr/bin/mpstat -a') + mpstat_lcpu = int(re.search(r"lcpu=(\d+)", out).group(1)) + psutil_lcpu = psutil.cpu_count(logical=True) + self.assertEqual(mpstat_lcpu, psutil_lcpu) + + def test_net_if_addrs_names(self): + out = sh('/etc/ifconfig -l') + ifconfig_names = set(out.split()) + psutil_names = set(psutil.net_if_addrs().keys()) + self.assertSetEqual(ifconfig_names, psutil_names) + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_bsd.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_bsd.py new file mode 100644 index 00000000..34b66ca6 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_bsd.py @@ -0,0 +1,553 @@ +#!/usr/bin/env python + +# 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. + +# TODO: (FreeBSD) add test for comparing connections with 'sockstat' cmd. + + +"""Tests specific to all BSD platforms.""" + + +import datetime +import os +import re +import time + +import psutil +from psutil import BSD +from psutil import FREEBSD +from psutil import NETBSD +from psutil import OPENBSD +from psutil.tests import get_test_subprocess +from psutil.tests import HAS_BATTERY +from psutil.tests import MEMORY_TOLERANCE +from psutil.tests import reap_children +from psutil.tests import retry_before_failing +from psutil.tests import run_test_module_by_name +from psutil.tests import sh +from psutil.tests import unittest +from psutil.tests import which + + +if BSD: + PAGESIZE = os.sysconf("SC_PAGE_SIZE") + if os.getuid() == 0: # muse requires root privileges + MUSE_AVAILABLE = which('muse') + else: + MUSE_AVAILABLE = False +else: + MUSE_AVAILABLE = False + + +def sysctl(cmdline): + """Expects a sysctl command with an argument and parse the result + returning only the value of interest. + """ + result = sh("sysctl " + cmdline) + if FREEBSD: + result = result[result.find(": ") + 2:] + elif OPENBSD or NETBSD: + result = result[result.find("=") + 1:] + try: + return int(result) + except ValueError: + return result + + +def muse(field): + """Thin wrapper around 'muse' cmdline utility.""" + out = sh('muse') + for line in out.split('\n'): + if line.startswith(field): + break + else: + raise ValueError("line not found") + return int(line.split()[1]) + + +# ===================================================================== +# --- All BSD* +# ===================================================================== + + +@unittest.skipIf(not BSD, "BSD only") +class BSDSpecificTestCase(unittest.TestCase): + """Generic tests common to all BSD variants.""" + + @classmethod + def setUpClass(cls): + cls.pid = get_test_subprocess().pid + + @classmethod + def tearDownClass(cls): + reap_children() + + @unittest.skipIf(NETBSD, "-o lstart doesn't work on NETBSD") + def test_process_create_time(self): + output = sh("ps -o lstart -p %s" % self.pid) + start_ps = output.replace('STARTED', '').strip() + start_psutil = psutil.Process(self.pid).create_time() + start_psutil = time.strftime("%a %b %e %H:%M:%S %Y", + time.localtime(start_psutil)) + self.assertEqual(start_ps, start_psutil) + + def test_disks(self): + # test psutil.disk_usage() and psutil.disk_partitions() + # against "df -a" + def df(path): + out = sh('df -k "%s"' % path).strip() + lines = out.split('\n') + lines.pop(0) + line = lines.pop(0) + dev, total, used, free = line.split()[:4] + if dev == 'none': + dev = '' + total = int(total) * 1024 + used = int(used) * 1024 + free = int(free) * 1024 + return dev, total, used, free + + for part in psutil.disk_partitions(all=False): + usage = psutil.disk_usage(part.mountpoint) + dev, total, used, free = df(part.mountpoint) + self.assertEqual(part.device, dev) + self.assertEqual(usage.total, total) + # 10 MB tollerance + if abs(usage.free - free) > 10 * 1024 * 1024: + self.fail("psutil=%s, df=%s" % (usage.free, free)) + if abs(usage.used - used) > 10 * 1024 * 1024: + self.fail("psutil=%s, df=%s" % (usage.used, used)) + + @unittest.skipIf(not which('sysctl'), "sysctl cmd not available") + def test_cpu_count_logical(self): + syst = sysctl("hw.ncpu") + self.assertEqual(psutil.cpu_count(logical=True), syst) + + @unittest.skipIf(not which('sysctl'), "sysctl cmd not available") + def test_virtual_memory_total(self): + num = sysctl('hw.physmem') + self.assertEqual(num, psutil.virtual_memory().total) + + def test_net_if_stats(self): + for name, stats in psutil.net_if_stats().items(): + try: + out = sh("ifconfig %s" % name) + except RuntimeError: + pass + else: + self.assertEqual(stats.isup, 'RUNNING' in out, msg=out) + if "mtu" in out: + self.assertEqual(stats.mtu, + int(re.findall(r'mtu (\d+)', out)[0])) + + +# ===================================================================== +# --- FreeBSD +# ===================================================================== + + +@unittest.skipIf(not FREEBSD, "FREEBSD only") +class FreeBSDSpecificTestCase(unittest.TestCase): + + @classmethod + def setUpClass(cls): + cls.pid = get_test_subprocess().pid + + @classmethod + def tearDownClass(cls): + reap_children() + + @staticmethod + def parse_swapinfo(): + # the last line is always the total + output = sh("swapinfo -k").splitlines()[-1] + parts = re.split(r'\s+', output) + + if not parts: + raise ValueError("Can't parse swapinfo: %s" % output) + + # the size is in 1k units, so multiply by 1024 + total, used, free = (int(p) * 1024 for p in parts[1:4]) + return total, used, free + + @retry_before_failing() + def test_proc_memory_maps(self): + out = sh('procstat -v %s' % self.pid) + maps = psutil.Process(self.pid).memory_maps(grouped=False) + lines = out.split('\n')[1:] + while lines: + line = lines.pop() + fields = line.split() + _, start, stop, perms, res = fields[:5] + map = maps.pop() + self.assertEqual("%s-%s" % (start, stop), map.addr) + self.assertEqual(int(res), map.rss) + if not map.path.startswith('['): + self.assertEqual(fields[10], map.path) + + def test_proc_exe(self): + out = sh('procstat -b %s' % self.pid) + self.assertEqual(psutil.Process(self.pid).exe(), + out.split('\n')[1].split()[-1]) + + def test_proc_cmdline(self): + out = sh('procstat -c %s' % self.pid) + self.assertEqual(' '.join(psutil.Process(self.pid).cmdline()), + ' '.join(out.split('\n')[1].split()[2:])) + + def test_proc_uids_gids(self): + out = sh('procstat -s %s' % self.pid) + euid, ruid, suid, egid, rgid, sgid = out.split('\n')[1].split()[2:8] + p = psutil.Process(self.pid) + uids = p.uids() + gids = p.gids() + self.assertEqual(uids.real, int(ruid)) + self.assertEqual(uids.effective, int(euid)) + self.assertEqual(uids.saved, int(suid)) + self.assertEqual(gids.real, int(rgid)) + self.assertEqual(gids.effective, int(egid)) + self.assertEqual(gids.saved, int(sgid)) + + @retry_before_failing() + def test_proc_ctx_switches(self): + tested = [] + out = sh('procstat -r %s' % self.pid) + p = psutil.Process(self.pid) + for line in out.split('\n'): + line = line.lower().strip() + if ' voluntary context' in line: + pstat_value = int(line.split()[-1]) + psutil_value = p.num_ctx_switches().voluntary + self.assertEqual(pstat_value, psutil_value) + tested.append(None) + elif ' involuntary context' in line: + pstat_value = int(line.split()[-1]) + psutil_value = p.num_ctx_switches().involuntary + self.assertEqual(pstat_value, psutil_value) + tested.append(None) + if len(tested) != 2: + raise RuntimeError("couldn't find lines match in procstat out") + + @retry_before_failing() + def test_proc_cpu_times(self): + tested = [] + out = sh('procstat -r %s' % self.pid) + p = psutil.Process(self.pid) + for line in out.split('\n'): + line = line.lower().strip() + if 'user time' in line: + pstat_value = float('0.' + line.split()[-1].split('.')[-1]) + psutil_value = p.cpu_times().user + self.assertEqual(pstat_value, psutil_value) + tested.append(None) + elif 'system time' in line: + pstat_value = float('0.' + line.split()[-1].split('.')[-1]) + psutil_value = p.cpu_times().system + self.assertEqual(pstat_value, psutil_value) + tested.append(None) + if len(tested) != 2: + raise RuntimeError("couldn't find lines match in procstat out") + + def test_cpu_frequency_against_sysctl(self): + # Currently only cpu 0 is frequency is supported in FreeBSD + # All other cores use the same frequency. + sensor = "dev.cpu.0.freq" + sysctl_result = int(sysctl(sensor)) + self.assertEqual(psutil.cpu_freq().current, sysctl_result) + + sensor = "dev.cpu.0.freq_levels" + sysctl_result = sysctl(sensor) + # sysctl returns a string of the format: + # / /... + # Ordered highest available to lowest available. + max_freq = int(sysctl_result.split()[0].split("/")[0]) + min_freq = int(sysctl_result.split()[-1].split("/")[0]) + self.assertEqual(psutil.cpu_freq().max, max_freq) + self.assertEqual(psutil.cpu_freq().min, min_freq) + + # --- virtual_memory(); tests against sysctl + + @retry_before_failing() + def test_vmem_active(self): + syst = sysctl("vm.stats.vm.v_active_count") * PAGESIZE + self.assertAlmostEqual(psutil.virtual_memory().active, syst, + delta=MEMORY_TOLERANCE) + + @retry_before_failing() + def test_vmem_inactive(self): + syst = sysctl("vm.stats.vm.v_inactive_count") * PAGESIZE + self.assertAlmostEqual(psutil.virtual_memory().inactive, syst, + delta=MEMORY_TOLERANCE) + + @retry_before_failing() + def test_vmem_wired(self): + syst = sysctl("vm.stats.vm.v_wire_count") * PAGESIZE + self.assertAlmostEqual(psutil.virtual_memory().wired, syst, + delta=MEMORY_TOLERANCE) + + @retry_before_failing() + def test_vmem_cached(self): + syst = sysctl("vm.stats.vm.v_cache_count") * PAGESIZE + self.assertAlmostEqual(psutil.virtual_memory().cached, syst, + delta=MEMORY_TOLERANCE) + + @retry_before_failing() + def test_vmem_free(self): + syst = sysctl("vm.stats.vm.v_free_count") * PAGESIZE + self.assertAlmostEqual(psutil.virtual_memory().free, syst, + delta=MEMORY_TOLERANCE) + + @retry_before_failing() + def test_vmem_buffers(self): + syst = sysctl("vfs.bufspace") + self.assertAlmostEqual(psutil.virtual_memory().buffers, syst, + delta=MEMORY_TOLERANCE) + + # --- virtual_memory(); tests against muse + + @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") + def test_muse_vmem_total(self): + num = muse('Total') + self.assertEqual(psutil.virtual_memory().total, num) + + @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") + @retry_before_failing() + def test_muse_vmem_active(self): + num = muse('Active') + self.assertAlmostEqual(psutil.virtual_memory().active, num, + delta=MEMORY_TOLERANCE) + + @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") + @retry_before_failing() + def test_muse_vmem_inactive(self): + num = muse('Inactive') + self.assertAlmostEqual(psutil.virtual_memory().inactive, num, + delta=MEMORY_TOLERANCE) + + @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") + @retry_before_failing() + def test_muse_vmem_wired(self): + num = muse('Wired') + self.assertAlmostEqual(psutil.virtual_memory().wired, num, + delta=MEMORY_TOLERANCE) + + @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") + @retry_before_failing() + def test_muse_vmem_cached(self): + num = muse('Cache') + self.assertAlmostEqual(psutil.virtual_memory().cached, num, + delta=MEMORY_TOLERANCE) + + @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") + @retry_before_failing() + def test_muse_vmem_free(self): + num = muse('Free') + self.assertAlmostEqual(psutil.virtual_memory().free, num, + delta=MEMORY_TOLERANCE) + + @unittest.skipIf(not MUSE_AVAILABLE, "muse not installed") + @retry_before_failing() + def test_muse_vmem_buffers(self): + num = muse('Buffer') + self.assertAlmostEqual(psutil.virtual_memory().buffers, num, + delta=MEMORY_TOLERANCE) + + def test_cpu_stats_ctx_switches(self): + self.assertAlmostEqual(psutil.cpu_stats().ctx_switches, + sysctl('vm.stats.sys.v_swtch'), delta=1000) + + def test_cpu_stats_interrupts(self): + self.assertAlmostEqual(psutil.cpu_stats().interrupts, + sysctl('vm.stats.sys.v_intr'), delta=1000) + + def test_cpu_stats_soft_interrupts(self): + self.assertAlmostEqual(psutil.cpu_stats().soft_interrupts, + sysctl('vm.stats.sys.v_soft'), delta=1000) + + def test_cpu_stats_syscalls(self): + self.assertAlmostEqual(psutil.cpu_stats().syscalls, + sysctl('vm.stats.sys.v_syscall'), delta=1000) + + # def test_cpu_stats_traps(self): + # self.assertAlmostEqual(psutil.cpu_stats().traps, + # sysctl('vm.stats.sys.v_trap'), delta=1000) + + # --- swap memory + + def test_swapmem_free(self): + total, used, free = self.parse_swapinfo() + self.assertAlmostEqual( + psutil.swap_memory().free, free, delta=MEMORY_TOLERANCE) + + def test_swapmem_used(self): + total, used, free = self.parse_swapinfo() + self.assertAlmostEqual( + psutil.swap_memory().used, used, delta=MEMORY_TOLERANCE) + + def test_swapmem_total(self): + total, used, free = self.parse_swapinfo() + self.assertAlmostEqual( + psutil.swap_memory().total, total, delta=MEMORY_TOLERANCE) + + # --- others + + def test_boot_time(self): + s = sysctl('sysctl kern.boottime') + s = s[s.find(" sec = ") + 7:] + s = s[:s.find(',')] + btime = int(s) + self.assertEqual(btime, psutil.boot_time()) + + # --- sensors_battery + + @unittest.skipIf(not HAS_BATTERY, "no battery") + def test_sensors_battery(self): + def secs2hours(secs): + m, s = divmod(secs, 60) + h, m = divmod(m, 60) + return "%d:%02d" % (h, m) + + out = sh("acpiconf -i 0") + fields = dict([(x.split('\t')[0], x.split('\t')[-1]) + for x in out.split("\n")]) + metrics = psutil.sensors_battery() + percent = int(fields['Remaining capacity:'].replace('%', '')) + remaining_time = fields['Remaining time:'] + self.assertEqual(metrics.percent, percent) + if remaining_time == 'unknown': + self.assertEqual(metrics.secsleft, psutil.POWER_TIME_UNLIMITED) + else: + self.assertEqual(secs2hours(metrics.secsleft), remaining_time) + + @unittest.skipIf(not HAS_BATTERY, "no battery") + def test_sensors_battery_against_sysctl(self): + self.assertEqual(psutil.sensors_battery().percent, + sysctl("hw.acpi.battery.life")) + self.assertEqual(psutil.sensors_battery().power_plugged, + sysctl("hw.acpi.acline") == 1) + secsleft = psutil.sensors_battery().secsleft + if secsleft < 0: + self.assertEqual(sysctl("hw.acpi.battery.time"), -1) + else: + self.assertEqual(secsleft, sysctl("hw.acpi.battery.time") * 60) + + @unittest.skipIf(HAS_BATTERY, "has battery") + def test_sensors_battery_no_battery(self): + # If no battery is present one of these calls is supposed + # to fail, see: + # https://github.com/giampaolo/psutil/issues/1074 + with self.assertRaises(RuntimeError): + sysctl("hw.acpi.battery.life") + sysctl("hw.acpi.battery.time") + sysctl("hw.acpi.acline") + self.assertIsNone(psutil.sensors_battery()) + + # --- sensors_temperatures + + def test_sensors_temperatures_against_sysctl(self): + num_cpus = psutil.cpu_count(True) + for cpu in range(num_cpus): + sensor = "dev.cpu.%s.temperature" % cpu + # sysctl returns a string in the format 46.0C + sysctl_result = int(float(sysctl(sensor)[:-1])) + self.assertAlmostEqual( + psutil.sensors_temperatures()["coretemp"][cpu].current, + sysctl_result, delta=10) + + sensor = "dev.cpu.%s.coretemp.tjmax" % cpu + sysctl_result = int(float(sysctl(sensor)[:-1])) + self.assertEqual( + psutil.sensors_temperatures()["coretemp"][cpu].high, + sysctl_result) + +# ===================================================================== +# --- OpenBSD +# ===================================================================== + + +@unittest.skipIf(not OPENBSD, "OPENBSD only") +class OpenBSDSpecificTestCase(unittest.TestCase): + + def test_boot_time(self): + s = sysctl('kern.boottime') + sys_bt = datetime.datetime.strptime(s, "%a %b %d %H:%M:%S %Y") + psutil_bt = datetime.datetime.fromtimestamp(psutil.boot_time()) + self.assertEqual(sys_bt, psutil_bt) + + +# ===================================================================== +# --- NetBSD +# ===================================================================== + + +@unittest.skipIf(not NETBSD, "NETBSD only") +class NetBSDSpecificTestCase(unittest.TestCase): + + @staticmethod + def parse_meminfo(look_for): + with open('/proc/meminfo', 'rb') as f: + for line in f: + if line.startswith(look_for): + return int(line.split()[1]) * 1024 + raise ValueError("can't find %s" % look_for) + + def test_vmem_total(self): + self.assertEqual( + psutil.virtual_memory().total, self.parse_meminfo("MemTotal:")) + + def test_vmem_free(self): + self.assertAlmostEqual( + psutil.virtual_memory().free, self.parse_meminfo("MemFree:"), + delta=MEMORY_TOLERANCE) + + def test_vmem_buffers(self): + self.assertAlmostEqual( + psutil.virtual_memory().buffers, self.parse_meminfo("Buffers:"), + delta=MEMORY_TOLERANCE) + + def test_vmem_shared(self): + self.assertAlmostEqual( + psutil.virtual_memory().shared, self.parse_meminfo("MemShared:"), + delta=MEMORY_TOLERANCE) + + def test_swapmem_total(self): + self.assertAlmostEqual( + psutil.swap_memory().total, self.parse_meminfo("SwapTotal:"), + delta=MEMORY_TOLERANCE) + + def test_swapmem_free(self): + self.assertAlmostEqual( + psutil.swap_memory().free, self.parse_meminfo("SwapFree:"), + delta=MEMORY_TOLERANCE) + + def test_swapmem_used(self): + smem = psutil.swap_memory() + self.assertEqual(smem.used, smem.total - smem.free) + + def test_cpu_stats_interrupts(self): + with open('/proc/stat', 'rb') as f: + for line in f: + if line.startswith(b'intr'): + interrupts = int(line.split()[1]) + break + else: + raise ValueError("couldn't find line") + self.assertAlmostEqual( + psutil.cpu_stats().interrupts, interrupts, delta=1000) + + def test_cpu_stats_ctx_switches(self): + with open('/proc/stat', 'rb') as f: + for line in f: + if line.startswith(b'ctxt'): + ctx_switches = int(line.split()[1]) + break + else: + raise ValueError("couldn't find line") + self.assertAlmostEqual( + psutil.cpu_stats().ctx_switches, ctx_switches, delta=1000) + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_connections.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_connections.py new file mode 100644 index 00000000..c97fc409 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_connections.py @@ -0,0 +1,526 @@ +#!/usr/bin/env python + +# 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. + +"""Tests for net_connections() and Process.connections() APIs.""" + +import os +import socket +import textwrap +from contextlib import closing +from socket import AF_INET +from socket import AF_INET6 +from socket import SOCK_DGRAM +from socket import SOCK_STREAM + +import psutil +from psutil import FREEBSD +from psutil import LINUX +from psutil import MACOS +from psutil import NETBSD +from psutil import OPENBSD +from psutil import POSIX +from psutil import SUNOS +from psutil import WINDOWS +from psutil._common import supports_ipv6 +from psutil._compat import PY3 +from psutil.tests import AF_UNIX +from psutil.tests import bind_socket +from psutil.tests import bind_unix_socket +from psutil.tests import check_connection_ntuple +from psutil.tests import create_sockets +from psutil.tests import get_free_port +from psutil.tests import HAS_CONNECTIONS_UNIX +from psutil.tests import pyrun +from psutil.tests import reap_children +from psutil.tests import run_test_module_by_name +from psutil.tests import safe_rmpath +from psutil.tests import skip_on_access_denied +from psutil.tests import tcp_socketpair +from psutil.tests import TESTFN +from psutil.tests import TRAVIS +from psutil.tests import unittest +from psutil.tests import unix_socket_path +from psutil.tests import unix_socketpair +from psutil.tests import wait_for_file + + +thisproc = psutil.Process() + + +class Base(object): + + def setUp(self): + safe_rmpath(TESTFN) + if not NETBSD: + # NetBSD opens a UNIX socket to /var/log/run. + cons = thisproc.connections(kind='all') + assert not cons, cons + + def tearDown(self): + safe_rmpath(TESTFN) + reap_children() + if not NETBSD: + # Make sure we closed all resources. + # NetBSD opens a UNIX socket to /var/log/run. + cons = thisproc.connections(kind='all') + assert not cons, cons + + def get_conn_from_sock(self, sock): + cons = thisproc.connections(kind='all') + smap = dict([(c.fd, c) for c in cons]) + if NETBSD: + # NetBSD opens a UNIX socket to /var/log/run + # so there may be more connections. + return smap[sock.fileno()] + else: + self.assertEqual(len(cons), 1) + if cons[0].fd != -1: + self.assertEqual(smap[sock.fileno()].fd, sock.fileno()) + return cons[0] + + def check_socket(self, sock, conn=None): + """Given a socket, makes sure it matches the one obtained + via psutil. It assumes this process created one connection + only (the one supposed to be checked). + """ + if conn is None: + conn = self.get_conn_from_sock(sock) + check_connection_ntuple(conn) + + # fd, family, type + if conn.fd != -1: + self.assertEqual(conn.fd, sock.fileno()) + self.assertEqual(conn.family, sock.family) + # see: http://bugs.python.org/issue30204 + self.assertEqual( + conn.type, sock.getsockopt(socket.SOL_SOCKET, socket.SO_TYPE)) + + # local address + laddr = sock.getsockname() + if not laddr and PY3 and isinstance(laddr, bytes): + # See: http://bugs.python.org/issue30205 + laddr = laddr.decode() + if sock.family == AF_INET6: + laddr = laddr[:2] + if sock.family == AF_UNIX and OPENBSD: + # No addresses are set for UNIX sockets on OpenBSD. + pass + else: + self.assertEqual(conn.laddr, laddr) + + # XXX Solaris can't retrieve system-wide UNIX sockets + if sock.family == AF_UNIX and HAS_CONNECTIONS_UNIX: + cons = thisproc.connections(kind='all') + self.compare_procsys_connections(os.getpid(), cons) + return conn + + def compare_procsys_connections(self, pid, proc_cons, kind='all'): + """Given a process PID and its list of connections compare + those against system-wide connections retrieved via + psutil.net_connections. + """ + try: + sys_cons = psutil.net_connections(kind=kind) + except psutil.AccessDenied: + # On MACOS, system-wide connections are retrieved by iterating + # over all processes + if MACOS: + return + else: + raise + # Filter for this proc PID and exlucde PIDs from the tuple. + sys_cons = [c[:-1] for c in sys_cons if c.pid == pid] + sys_cons.sort() + proc_cons.sort() + self.assertEqual(proc_cons, sys_cons) + + +# ===================================================================== +# --- Test unconnected sockets +# ===================================================================== + + +class TestUnconnectedSockets(Base, unittest.TestCase): + """Tests sockets which are open but not connected to anything.""" + + def test_tcp_v4(self): + addr = ("127.0.0.1", get_free_port()) + with closing(bind_socket(AF_INET, SOCK_STREAM, addr=addr)) as sock: + conn = self.check_socket(sock) + assert not conn.raddr + self.assertEqual(conn.status, psutil.CONN_LISTEN) + + @unittest.skipIf(not supports_ipv6(), "IPv6 not supported") + def test_tcp_v6(self): + addr = ("::1", get_free_port()) + with closing(bind_socket(AF_INET6, SOCK_STREAM, addr=addr)) as sock: + conn = self.check_socket(sock) + assert not conn.raddr + self.assertEqual(conn.status, psutil.CONN_LISTEN) + + def test_udp_v4(self): + addr = ("127.0.0.1", get_free_port()) + with closing(bind_socket(AF_INET, SOCK_DGRAM, addr=addr)) as sock: + conn = self.check_socket(sock) + assert not conn.raddr + self.assertEqual(conn.status, psutil.CONN_NONE) + + @unittest.skipIf(not supports_ipv6(), "IPv6 not supported") + def test_udp_v6(self): + addr = ("::1", get_free_port()) + with closing(bind_socket(AF_INET6, SOCK_DGRAM, addr=addr)) as sock: + conn = self.check_socket(sock) + assert not conn.raddr + self.assertEqual(conn.status, psutil.CONN_NONE) + + @unittest.skipIf(not POSIX, 'POSIX only') + def test_unix_tcp(self): + with unix_socket_path() as name: + with closing(bind_unix_socket(name, type=SOCK_STREAM)) as sock: + conn = self.check_socket(sock) + assert not conn.raddr + self.assertEqual(conn.status, psutil.CONN_NONE) + + @unittest.skipIf(not POSIX, 'POSIX only') + def test_unix_udp(self): + with unix_socket_path() as name: + with closing(bind_unix_socket(name, type=SOCK_STREAM)) as sock: + conn = self.check_socket(sock) + assert not conn.raddr + self.assertEqual(conn.status, psutil.CONN_NONE) + + +# ===================================================================== +# --- Test connected sockets +# ===================================================================== + + +class TestConnectedSocketPairs(Base, unittest.TestCase): + """Test socket pairs which are are actually connected to + each other. + """ + + # On SunOS, even after we close() it, the server socket stays around + # in TIME_WAIT state. + @unittest.skipIf(SUNOS, "unreliable on SUONS") + def test_tcp(self): + addr = ("127.0.0.1", get_free_port()) + assert not thisproc.connections(kind='tcp4') + server, client = tcp_socketpair(AF_INET, addr=addr) + try: + cons = thisproc.connections(kind='tcp4') + self.assertEqual(len(cons), 2) + self.assertEqual(cons[0].status, psutil.CONN_ESTABLISHED) + self.assertEqual(cons[1].status, psutil.CONN_ESTABLISHED) + # May not be fast enough to change state so it stays + # commenteed. + # client.close() + # cons = thisproc.connections(kind='all') + # self.assertEqual(len(cons), 1) + # self.assertEqual(cons[0].status, psutil.CONN_CLOSE_WAIT) + finally: + server.close() + client.close() + + @unittest.skipIf(not POSIX, 'POSIX only') + def test_unix(self): + with unix_socket_path() as name: + server, client = unix_socketpair(name) + try: + cons = thisproc.connections(kind='unix') + assert not (cons[0].laddr and cons[0].raddr) + assert not (cons[1].laddr and cons[1].raddr) + if NETBSD: + # On NetBSD creating a UNIX socket will cause + # a UNIX connection to /var/run/log. + cons = [c for c in cons if c.raddr != '/var/run/log'] + self.assertEqual(len(cons), 2) + if LINUX or FREEBSD or SUNOS: + # remote path is never set + self.assertEqual(cons[0].raddr, "") + self.assertEqual(cons[1].raddr, "") + # one local address should though + self.assertEqual(name, cons[0].laddr or cons[1].laddr) + elif OPENBSD: + # No addresses whatsoever here. + for addr in (cons[0].laddr, cons[0].raddr, + cons[1].laddr, cons[1].raddr): + self.assertEqual(addr, "") + else: + # On other systems either the laddr or raddr + # of both peers are set. + self.assertEqual(cons[0].laddr or cons[1].laddr, name) + self.assertEqual(cons[0].raddr or cons[1].raddr, name) + finally: + server.close() + client.close() + + @skip_on_access_denied(only_if=MACOS) + def test_combos(self): + def check_conn(proc, conn, family, type, laddr, raddr, status, kinds): + all_kinds = ("all", "inet", "inet4", "inet6", "tcp", "tcp4", + "tcp6", "udp", "udp4", "udp6") + check_connection_ntuple(conn) + self.assertEqual(conn.family, family) + self.assertEqual(conn.type, type) + self.assertEqual(conn.laddr, laddr) + self.assertEqual(conn.raddr, raddr) + self.assertEqual(conn.status, status) + for kind in all_kinds: + cons = proc.connections(kind=kind) + if kind in kinds: + assert cons + else: + assert not cons, cons + # compare against system-wide connections + # XXX Solaris can't retrieve system-wide UNIX + # sockets. + if HAS_CONNECTIONS_UNIX: + self.compare_procsys_connections(proc.pid, [conn]) + + tcp_template = textwrap.dedent(""" + import socket, time + s = socket.socket($family, socket.SOCK_STREAM) + s.bind(('$addr', 0)) + s.listen(1) + with open('$testfn', 'w') as f: + f.write(str(s.getsockname()[:2])) + time.sleep(60) + """) + + udp_template = textwrap.dedent(""" + import socket, time + s = socket.socket($family, socket.SOCK_DGRAM) + s.bind(('$addr', 0)) + with open('$testfn', 'w') as f: + f.write(str(s.getsockname()[:2])) + time.sleep(60) + """) + + from string import Template + testfile = os.path.basename(TESTFN) + tcp4_template = Template(tcp_template).substitute( + family=int(AF_INET), addr="127.0.0.1", testfn=testfile) + udp4_template = Template(udp_template).substitute( + family=int(AF_INET), addr="127.0.0.1", testfn=testfile) + tcp6_template = Template(tcp_template).substitute( + family=int(AF_INET6), addr="::1", testfn=testfile) + udp6_template = Template(udp_template).substitute( + family=int(AF_INET6), addr="::1", testfn=testfile) + + # launch various subprocess instantiating a socket of various + # families and types to enrich psutil results + tcp4_proc = pyrun(tcp4_template) + tcp4_addr = eval(wait_for_file(testfile)) + udp4_proc = pyrun(udp4_template) + udp4_addr = eval(wait_for_file(testfile)) + if supports_ipv6(): + tcp6_proc = pyrun(tcp6_template) + tcp6_addr = eval(wait_for_file(testfile)) + udp6_proc = pyrun(udp6_template) + udp6_addr = eval(wait_for_file(testfile)) + else: + tcp6_proc = None + udp6_proc = None + tcp6_addr = None + udp6_addr = None + + for p in thisproc.children(): + cons = p.connections() + self.assertEqual(len(cons), 1) + for conn in cons: + # TCP v4 + if p.pid == tcp4_proc.pid: + check_conn(p, conn, AF_INET, SOCK_STREAM, tcp4_addr, (), + psutil.CONN_LISTEN, + ("all", "inet", "inet4", "tcp", "tcp4")) + # UDP v4 + elif p.pid == udp4_proc.pid: + check_conn(p, conn, AF_INET, SOCK_DGRAM, udp4_addr, (), + psutil.CONN_NONE, + ("all", "inet", "inet4", "udp", "udp4")) + # TCP v6 + elif p.pid == getattr(tcp6_proc, "pid", None): + check_conn(p, conn, AF_INET6, SOCK_STREAM, tcp6_addr, (), + psutil.CONN_LISTEN, + ("all", "inet", "inet6", "tcp", "tcp6")) + # UDP v6 + elif p.pid == getattr(udp6_proc, "pid", None): + check_conn(p, conn, AF_INET6, SOCK_DGRAM, udp6_addr, (), + psutil.CONN_NONE, + ("all", "inet", "inet6", "udp", "udp6")) + + # err + self.assertRaises(ValueError, p.connections, kind='???') + + def test_multi_sockets_filtering(self): + with create_sockets() as socks: + cons = thisproc.connections(kind='all') + self.assertEqual(len(cons), len(socks)) + # tcp + cons = thisproc.connections(kind='tcp') + self.assertEqual(len(cons), 2 if supports_ipv6() else 1) + for conn in cons: + self.assertIn(conn.family, (AF_INET, AF_INET6)) + self.assertEqual(conn.type, SOCK_STREAM) + # tcp4 + cons = thisproc.connections(kind='tcp4') + self.assertEqual(len(cons), 1) + self.assertEqual(cons[0].family, AF_INET) + self.assertEqual(cons[0].type, SOCK_STREAM) + # tcp6 + if supports_ipv6(): + cons = thisproc.connections(kind='tcp6') + self.assertEqual(len(cons), 1) + self.assertEqual(cons[0].family, AF_INET6) + self.assertEqual(cons[0].type, SOCK_STREAM) + # udp + cons = thisproc.connections(kind='udp') + self.assertEqual(len(cons), 2 if supports_ipv6() else 1) + for conn in cons: + self.assertIn(conn.family, (AF_INET, AF_INET6)) + self.assertEqual(conn.type, SOCK_DGRAM) + # udp4 + cons = thisproc.connections(kind='udp4') + self.assertEqual(len(cons), 1) + self.assertEqual(cons[0].family, AF_INET) + self.assertEqual(cons[0].type, SOCK_DGRAM) + # udp6 + if supports_ipv6(): + cons = thisproc.connections(kind='udp6') + self.assertEqual(len(cons), 1) + self.assertEqual(cons[0].family, AF_INET6) + self.assertEqual(cons[0].type, SOCK_DGRAM) + # inet + cons = thisproc.connections(kind='inet') + self.assertEqual(len(cons), 4 if supports_ipv6() else 2) + for conn in cons: + self.assertIn(conn.family, (AF_INET, AF_INET6)) + self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM)) + # inet6 + if supports_ipv6(): + cons = thisproc.connections(kind='inet6') + self.assertEqual(len(cons), 2) + for conn in cons: + self.assertEqual(conn.family, AF_INET6) + self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM)) + # unix + if HAS_CONNECTIONS_UNIX: + cons = thisproc.connections(kind='unix') + self.assertEqual(len(cons), 3) + for conn in cons: + self.assertEqual(conn.family, AF_UNIX) + self.assertIn(conn.type, (SOCK_STREAM, SOCK_DGRAM)) + + +# ===================================================================== +# --- Miscellaneous tests +# ===================================================================== + + +class TestSystemWideConnections(Base, unittest.TestCase): + """Tests for net_connections().""" + + @skip_on_access_denied() + def test_it(self): + def check(cons, families, types_): + AF_UNIX = getattr(socket, 'AF_UNIX', object()) + for conn in cons: + self.assertIn(conn.family, families, msg=conn) + if conn.family != AF_UNIX: + self.assertIn(conn.type, types_, msg=conn) + check_connection_ntuple(conn) + + with create_sockets(): + from psutil._common import conn_tmap + for kind, groups in conn_tmap.items(): + # XXX: SunOS does not retrieve UNIX sockets. + if kind == 'unix' and not HAS_CONNECTIONS_UNIX: + continue + families, types_ = groups + cons = psutil.net_connections(kind) + self.assertEqual(len(cons), len(set(cons))) + check(cons, families, types_) + + self.assertRaises(ValueError, psutil.net_connections, kind='???') + + @skip_on_access_denied() + def test_multi_socks(self): + with create_sockets() as socks: + cons = [x for x in psutil.net_connections(kind='all') + if x.pid == os.getpid()] + self.assertEqual(len(cons), len(socks)) + + @skip_on_access_denied() + # See: https://travis-ci.org/giampaolo/psutil/jobs/237566297 + @unittest.skipIf(MACOS and TRAVIS, "unreliable on MACOS + TRAVIS") + def test_multi_sockets_procs(self): + # Creates multiple sub processes, each creating different + # sockets. For each process check that proc.connections() + # and net_connections() return the same results. + # This is done mainly to check whether net_connections()'s + # pid is properly set, see: + # https://github.com/giampaolo/psutil/issues/1013 + with create_sockets() as socks: + expected = len(socks) + pids = [] + times = 10 + for i in range(times): + fname = os.path.realpath(TESTFN) + str(i) + src = textwrap.dedent("""\ + import time, os + from psutil.tests import create_sockets + with create_sockets(): + with open(r'%s', 'w') as f: + f.write(str(os.getpid())) + time.sleep(60) + """ % fname) + sproc = pyrun(src) + pids.append(sproc.pid) + self.addCleanup(safe_rmpath, fname) + + # sync + for i in range(times): + fname = TESTFN + str(i) + wait_for_file(fname) + + syscons = [x for x in psutil.net_connections(kind='all') if x.pid + in pids] + for pid in pids: + self.assertEqual(len([x for x in syscons if x.pid == pid]), + expected) + p = psutil.Process(pid) + self.assertEqual(len(p.connections('all')), expected) + + +# ===================================================================== +# --- Miscellaneous tests +# ===================================================================== + + +class TestMisc(unittest.TestCase): + + def test_connection_constants(self): + ints = [] + strs = [] + for name in dir(psutil): + if name.startswith('CONN_'): + num = getattr(psutil, name) + str_ = str(num) + assert str_.isupper(), str_ + self.assertNotIn(str, strs) + self.assertNotIn(num, ints) + ints.append(num) + strs.append(str_) + if SUNOS: + psutil.CONN_IDLE + psutil.CONN_BOUND + if WINDOWS: + psutil.CONN_DELETE_TCB + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_contracts.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_contracts.py new file mode 100644 index 00000000..90fa8a15 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_contracts.py @@ -0,0 +1,657 @@ +#!/usr/bin/env python + +# 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. + +"""Contracts tests. These tests mainly check API sanity in terms of +returned types and APIs availability. +Some of these are duplicates of tests test_system.py and test_process.py +""" + +import errno +import os +import stat +import time +import traceback +import warnings +from contextlib import closing + +from psutil import AIX +from psutil import BSD +from psutil import FREEBSD +from psutil import LINUX +from psutil import MACOS +from psutil import NETBSD +from psutil import OPENBSD +from psutil import OSX +from psutil import POSIX +from psutil import SUNOS +from psutil import WINDOWS +from psutil._compat import long +from psutil.tests import bind_unix_socket +from psutil.tests import check_connection_ntuple +from psutil.tests import get_kernel_version +from psutil.tests import HAS_CONNECTIONS_UNIX +from psutil.tests import HAS_NET_IO_COUNTERS +from psutil.tests import HAS_RLIMIT +from psutil.tests import HAS_SENSORS_FANS +from psutil.tests import HAS_SENSORS_TEMPERATURES +from psutil.tests import is_namedtuple +from psutil.tests import run_test_module_by_name +from psutil.tests import safe_rmpath +from psutil.tests import skip_on_access_denied +from psutil.tests import TESTFN +from psutil.tests import unittest +from psutil.tests import unix_socket_path +from psutil.tests import VALID_PROC_STATUSES +from psutil.tests import warn +import psutil + + +# =================================================================== +# --- APIs availability +# =================================================================== + + +class TestAvailability(unittest.TestCase): + """Make sure code reflects what doc promises in terms of APIs + availability. + """ + + def test_cpu_affinity(self): + hasit = LINUX or WINDOWS or FREEBSD + self.assertEqual(hasattr(psutil.Process, "cpu_affinity"), hasit) + + def test_win_service(self): + self.assertEqual(hasattr(psutil, "win_service_iter"), WINDOWS) + self.assertEqual(hasattr(psutil, "win_service_get"), WINDOWS) + + def test_PROCFS_PATH(self): + self.assertEqual(hasattr(psutil, "PROCFS_PATH"), + LINUX or SUNOS or AIX) + + def test_win_priority(self): + ae = self.assertEqual + ae(hasattr(psutil, "ABOVE_NORMAL_PRIORITY_CLASS"), WINDOWS) + ae(hasattr(psutil, "BELOW_NORMAL_PRIORITY_CLASS"), WINDOWS) + ae(hasattr(psutil, "HIGH_PRIORITY_CLASS"), WINDOWS) + ae(hasattr(psutil, "IDLE_PRIORITY_CLASS"), WINDOWS) + ae(hasattr(psutil, "NORMAL_PRIORITY_CLASS"), WINDOWS) + ae(hasattr(psutil, "REALTIME_PRIORITY_CLASS"), WINDOWS) + + def test_linux_ioprio(self): + ae = self.assertEqual + ae(hasattr(psutil, "IOPRIO_CLASS_NONE"), LINUX) + ae(hasattr(psutil, "IOPRIO_CLASS_RT"), LINUX) + ae(hasattr(psutil, "IOPRIO_CLASS_BE"), LINUX) + ae(hasattr(psutil, "IOPRIO_CLASS_IDLE"), LINUX) + + def test_linux_rlimit(self): + ae = self.assertEqual + hasit = LINUX and get_kernel_version() >= (2, 6, 36) + ae(hasattr(psutil.Process, "rlimit"), hasit) + ae(hasattr(psutil, "RLIM_INFINITY"), hasit) + ae(hasattr(psutil, "RLIMIT_AS"), hasit) + ae(hasattr(psutil, "RLIMIT_CORE"), hasit) + ae(hasattr(psutil, "RLIMIT_CPU"), hasit) + ae(hasattr(psutil, "RLIMIT_DATA"), hasit) + ae(hasattr(psutil, "RLIMIT_FSIZE"), hasit) + ae(hasattr(psutil, "RLIMIT_LOCKS"), hasit) + ae(hasattr(psutil, "RLIMIT_MEMLOCK"), hasit) + ae(hasattr(psutil, "RLIMIT_NOFILE"), hasit) + ae(hasattr(psutil, "RLIMIT_NPROC"), hasit) + ae(hasattr(psutil, "RLIMIT_RSS"), hasit) + ae(hasattr(psutil, "RLIMIT_STACK"), hasit) + + hasit = LINUX and get_kernel_version() >= (3, 0) + ae(hasattr(psutil, "RLIMIT_MSGQUEUE"), hasit) + ae(hasattr(psutil, "RLIMIT_NICE"), hasit) + ae(hasattr(psutil, "RLIMIT_RTPRIO"), hasit) + ae(hasattr(psutil, "RLIMIT_RTTIME"), hasit) + ae(hasattr(psutil, "RLIMIT_SIGPENDING"), hasit) + + def test_cpu_freq(self): + linux = (LINUX and + (os.path.exists("/sys/devices/system/cpu/cpufreq") or + os.path.exists("/sys/devices/system/cpu/cpu0/cpufreq"))) + self.assertEqual(hasattr(psutil, "cpu_freq"), + linux or MACOS or WINDOWS or FREEBSD) + + def test_sensors_temperatures(self): + self.assertEqual( + hasattr(psutil, "sensors_temperatures"), LINUX or FREEBSD) + + def test_sensors_fans(self): + self.assertEqual(hasattr(psutil, "sensors_fans"), LINUX) + + def test_battery(self): + self.assertEqual(hasattr(psutil, "sensors_battery"), + LINUX or WINDOWS or FREEBSD or MACOS) + + def test_proc_environ(self): + self.assertEqual(hasattr(psutil.Process, "environ"), + LINUX or MACOS or WINDOWS) + + def test_proc_uids(self): + self.assertEqual(hasattr(psutil.Process, "uids"), POSIX) + + def test_proc_gids(self): + self.assertEqual(hasattr(psutil.Process, "uids"), POSIX) + + def test_proc_terminal(self): + self.assertEqual(hasattr(psutil.Process, "terminal"), POSIX) + + def test_proc_ionice(self): + self.assertEqual(hasattr(psutil.Process, "ionice"), LINUX or WINDOWS) + + def test_proc_rlimit(self): + self.assertEqual(hasattr(psutil.Process, "rlimit"), LINUX) + + def test_proc_io_counters(self): + hasit = hasattr(psutil.Process, "io_counters") + self.assertEqual(hasit, False if MACOS or SUNOS else True) + + def test_proc_num_fds(self): + self.assertEqual(hasattr(psutil.Process, "num_fds"), POSIX) + + def test_proc_num_handles(self): + self.assertEqual(hasattr(psutil.Process, "num_handles"), WINDOWS) + + def test_proc_cpu_affinity(self): + self.assertEqual(hasattr(psutil.Process, "cpu_affinity"), + LINUX or WINDOWS or FREEBSD) + + def test_proc_cpu_num(self): + self.assertEqual(hasattr(psutil.Process, "cpu_num"), + LINUX or FREEBSD or SUNOS) + + def test_proc_memory_maps(self): + hasit = hasattr(psutil.Process, "memory_maps") + self.assertEqual( + hasit, False if OPENBSD or NETBSD or AIX or MACOS else True) + + +# =================================================================== +# --- Test deprecations +# =================================================================== + + +class TestDeprecations(unittest.TestCase): + + def test_memory_info_ex(self): + with warnings.catch_warnings(record=True) as ws: + psutil.Process().memory_info_ex() + w = ws[0] + self.assertIsInstance(w.category(), DeprecationWarning) + self.assertIn("memory_info_ex() is deprecated", str(w.message)) + self.assertIn("use memory_info() instead", str(w.message)) + + +# =================================================================== +# --- System API types +# =================================================================== + + +class TestSystem(unittest.TestCase): + """Check the return types of system related APIs. + Mainly we want to test we never return unicode on Python 2, see: + https://github.com/giampaolo/psutil/issues/1039 + """ + + @classmethod + def setUpClass(cls): + cls.proc = psutil.Process() + + def tearDown(self): + safe_rmpath(TESTFN) + + def test_cpu_times(self): + # Duplicate of test_system.py. Keep it anyway. + ret = psutil.cpu_times() + assert is_namedtuple(ret) + for n in ret: + self.assertIsInstance(n, float) + self.assertGreaterEqual(n, 0) + + def test_io_counters(self): + # Duplicate of test_system.py. Keep it anyway. + for k in psutil.disk_io_counters(perdisk=True): + self.assertIsInstance(k, str) + + def test_disk_partitions(self): + # Duplicate of test_system.py. Keep it anyway. + for disk in psutil.disk_partitions(): + self.assertIsInstance(disk.device, str) + self.assertIsInstance(disk.mountpoint, str) + self.assertIsInstance(disk.fstype, str) + self.assertIsInstance(disk.opts, str) + + @unittest.skipIf(not POSIX, 'POSIX only') + @unittest.skipIf(not HAS_CONNECTIONS_UNIX, "can't list UNIX sockets") + @skip_on_access_denied(only_if=MACOS) + def test_net_connections(self): + with unix_socket_path() as name: + with closing(bind_unix_socket(name)): + cons = psutil.net_connections(kind='unix') + assert cons + for conn in cons: + self.assertIsInstance(conn.laddr, str) + + def test_net_if_addrs(self): + # Duplicate of test_system.py. Keep it anyway. + for ifname, addrs in psutil.net_if_addrs().items(): + self.assertIsInstance(ifname, str) + for addr in addrs: + self.assertIsInstance(addr.address, str) + self.assertIsInstance(addr.netmask, (str, type(None))) + self.assertIsInstance(addr.broadcast, (str, type(None))) + + def test_net_if_stats(self): + # Duplicate of test_system.py. Keep it anyway. + for ifname, _ in psutil.net_if_stats().items(): + self.assertIsInstance(ifname, str) + + @unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported') + def test_net_io_counters(self): + # Duplicate of test_system.py. Keep it anyway. + for ifname, _ in psutil.net_io_counters(pernic=True).items(): + self.assertIsInstance(ifname, str) + + @unittest.skipIf(not HAS_SENSORS_FANS, "not supported") + def test_sensors_fans(self): + # Duplicate of test_system.py. Keep it anyway. + for name, units in psutil.sensors_fans().items(): + self.assertIsInstance(name, str) + for unit in units: + self.assertIsInstance(unit.label, str) + + @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") + def test_sensors_temperatures(self): + # Duplicate of test_system.py. Keep it anyway. + for name, units in psutil.sensors_temperatures().items(): + self.assertIsInstance(name, str) + for unit in units: + self.assertIsInstance(unit.label, str) + + def test_users(self): + # Duplicate of test_system.py. Keep it anyway. + for user in psutil.users(): + self.assertIsInstance(user.name, str) + self.assertIsInstance(user.terminal, (str, type(None))) + self.assertIsInstance(user.host, (str, type(None))) + self.assertIsInstance(user.pid, (int, type(None))) + + +# =================================================================== +# --- Featch all processes test +# =================================================================== + + +class TestFetchAllProcesses(unittest.TestCase): + """Test which iterates over all running processes and performs + some sanity checks against Process API's returned values. + """ + + def get_attr_names(self): + excluded_names = set([ + 'send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait', + 'as_dict', 'parent', 'parents', 'children', 'memory_info_ex', + 'oneshot', + ]) + if LINUX and not HAS_RLIMIT: + excluded_names.add('rlimit') + attrs = [] + for name in dir(psutil.Process): + if name.startswith("_"): + continue + if name in excluded_names: + continue + attrs.append(name) + return attrs + + def iter_procs(self): + attrs = self.get_attr_names() + for p in psutil.process_iter(): + with p.oneshot(): + for name in attrs: + yield (p, name) + + def call_meth(self, p, name): + args = () + kwargs = {} + attr = getattr(p, name, None) + if attr is not None and callable(attr): + if name == 'rlimit': + args = (psutil.RLIMIT_NOFILE,) + elif name == 'memory_maps': + kwargs = {'grouped': False} + return attr(*args, **kwargs) + else: + return attr + + def test_fetch_all(self): + valid_procs = 0 + default = object() + failures = [] + for p, name in self.iter_procs(): + ret = default + try: + ret = self.call_meth(p, name) + except NotImplementedError: + msg = "%r was skipped because not implemented" % ( + self.__class__.__name__ + '.test_' + name) + warn(msg) + except (psutil.NoSuchProcess, psutil.AccessDenied) as err: + self.assertEqual(err.pid, p.pid) + if err.name: + # make sure exception's name attr is set + # with the actual process name + self.assertEqual(err.name, p.name()) + assert str(err) + assert err.msg + except Exception: + s = '\n' + '=' * 70 + '\n' + s += "FAIL: test_%s (proc=%s" % (name, p) + if ret != default: + s += ", ret=%s)" % repr(ret) + s += ')\n' + s += '-' * 70 + s += "\n%s" % traceback.format_exc() + s = "\n".join((" " * 4) + i for i in s.splitlines()) + s += '\n' + failures.append(s) + break + else: + valid_procs += 1 + if ret not in (0, 0.0, [], None, '', {}): + assert ret, ret + meth = getattr(self, name) + meth(ret, p) + + if failures: + self.fail(''.join(failures)) + + # we should always have a non-empty list, not including PID 0 etc. + # special cases. + assert valid_procs + + def cmdline(self, ret, proc): + self.assertIsInstance(ret, list) + for part in ret: + self.assertIsInstance(part, str) + + def exe(self, ret, proc): + self.assertIsInstance(ret, (str, type(None))) + if not ret: + self.assertEqual(ret, '') + else: + assert os.path.isabs(ret), ret + # Note: os.stat() may return False even if the file is there + # hence we skip the test, see: + # http://stackoverflow.com/questions/3112546/os-path-exists-lies + if POSIX and os.path.isfile(ret): + if hasattr(os, 'access') and hasattr(os, "X_OK"): + # XXX may fail on MACOS + assert os.access(ret, os.X_OK) + + def pid(self, ret, proc): + self.assertIsInstance(ret, int) + self.assertGreaterEqual(ret, 0) + + def ppid(self, ret, proc): + self.assertIsInstance(ret, (int, long)) + self.assertGreaterEqual(ret, 0) + + def name(self, ret, proc): + self.assertIsInstance(ret, str) + # on AIX, "" processes don't have names + if not AIX: + assert ret + + def create_time(self, ret, proc): + self.assertIsInstance(ret, float) + try: + self.assertGreaterEqual(ret, 0) + except AssertionError: + # XXX + if OPENBSD and proc.status() == psutil.STATUS_ZOMBIE: + pass + else: + raise + # this can't be taken for granted on all platforms + # self.assertGreaterEqual(ret, psutil.boot_time()) + # make sure returned value can be pretty printed + # with strftime + time.strftime("%Y %m %d %H:%M:%S", time.localtime(ret)) + + def uids(self, ret, proc): + assert is_namedtuple(ret) + for uid in ret: + self.assertIsInstance(uid, int) + self.assertGreaterEqual(uid, 0) + + def gids(self, ret, proc): + assert is_namedtuple(ret) + # note: testing all gids as above seems not to be reliable for + # gid == 30 (nodoby); not sure why. + for gid in ret: + self.assertIsInstance(gid, int) + if not MACOS and not NETBSD: + self.assertGreaterEqual(gid, 0) + + def username(self, ret, proc): + self.assertIsInstance(ret, str) + assert ret + + def status(self, ret, proc): + self.assertIsInstance(ret, str) + assert ret + self.assertNotEqual(ret, '?') # XXX + self.assertIn(ret, VALID_PROC_STATUSES) + + def io_counters(self, ret, proc): + assert is_namedtuple(ret) + for field in ret: + self.assertIsInstance(field, (int, long)) + if field != -1: + self.assertGreaterEqual(field, 0) + + def ionice(self, ret, proc): + if POSIX: + assert is_namedtuple(ret) + for field in ret: + self.assertIsInstance(field, int) + if LINUX: + self.assertGreaterEqual(ret.ioclass, 0) + self.assertGreaterEqual(ret.value, 0) + else: + self.assertGreaterEqual(ret, 0) + self.assertIn(ret, (0, 1, 2)) + + def num_threads(self, ret, proc): + self.assertIsInstance(ret, int) + self.assertGreaterEqual(ret, 1) + + def threads(self, ret, proc): + self.assertIsInstance(ret, list) + for t in ret: + assert is_namedtuple(t) + self.assertGreaterEqual(t.id, 0) + self.assertGreaterEqual(t.user_time, 0) + self.assertGreaterEqual(t.system_time, 0) + for field in t: + self.assertIsInstance(field, (int, float)) + + def cpu_times(self, ret, proc): + assert is_namedtuple(ret) + for n in ret: + self.assertIsInstance(n, float) + self.assertGreaterEqual(n, 0) + # TODO: check ntuple fields + + def cpu_percent(self, ret, proc): + self.assertIsInstance(ret, float) + assert 0.0 <= ret <= 100.0, ret + + def cpu_num(self, ret, proc): + self.assertIsInstance(ret, int) + if FREEBSD and ret == -1: + return + self.assertGreaterEqual(ret, 0) + if psutil.cpu_count() == 1: + self.assertEqual(ret, 0) + self.assertIn(ret, list(range(psutil.cpu_count()))) + + def memory_info(self, ret, proc): + assert is_namedtuple(ret) + for value in ret: + self.assertIsInstance(value, (int, long)) + self.assertGreaterEqual(value, 0) + if POSIX and not AIX and ret.vms != 0: + # VMS is always supposed to be the highest + for name in ret._fields: + if name != 'vms': + value = getattr(ret, name) + self.assertGreater(ret.vms, value, msg=ret) + elif WINDOWS: + self.assertGreaterEqual(ret.peak_wset, ret.wset) + self.assertGreaterEqual(ret.peak_paged_pool, ret.paged_pool) + self.assertGreaterEqual(ret.peak_nonpaged_pool, ret.nonpaged_pool) + self.assertGreaterEqual(ret.peak_pagefile, ret.pagefile) + + def memory_full_info(self, ret, proc): + assert is_namedtuple(ret) + total = psutil.virtual_memory().total + for name in ret._fields: + value = getattr(ret, name) + self.assertIsInstance(value, (int, long)) + self.assertGreaterEqual(value, 0, msg=(name, value)) + if LINUX or OSX and name in ('vms', 'data'): + # On Linux there are processes (e.g. 'goa-daemon') whose + # VMS is incredibly high for some reason. + continue + self.assertLessEqual(value, total, msg=(name, value, total)) + + if LINUX: + self.assertGreaterEqual(ret.pss, ret.uss) + + def open_files(self, ret, proc): + self.assertIsInstance(ret, list) + for f in ret: + self.assertIsInstance(f.fd, int) + self.assertIsInstance(f.path, str) + if WINDOWS: + self.assertEqual(f.fd, -1) + elif LINUX: + self.assertIsInstance(f.position, int) + self.assertIsInstance(f.mode, str) + self.assertIsInstance(f.flags, int) + self.assertGreaterEqual(f.position, 0) + self.assertIn(f.mode, ('r', 'w', 'a', 'r+', 'a+')) + self.assertGreater(f.flags, 0) + elif BSD and not f.path: + # XXX see: https://github.com/giampaolo/psutil/issues/595 + continue + assert os.path.isabs(f.path), f + assert os.path.isfile(f.path), f + + def num_fds(self, ret, proc): + self.assertIsInstance(ret, int) + self.assertGreaterEqual(ret, 0) + + def connections(self, ret, proc): + self.assertEqual(len(ret), len(set(ret))) + for conn in ret: + check_connection_ntuple(conn) + + def cwd(self, ret, proc): + if ret: # 'ret' can be None or empty + self.assertIsInstance(ret, str) + assert os.path.isabs(ret), ret + try: + st = os.stat(ret) + except OSError as err: + if WINDOWS and err.errno in \ + psutil._psplatform.ACCESS_DENIED_SET: + pass + # directory has been removed in mean time + elif err.errno != errno.ENOENT: + raise + else: + assert stat.S_ISDIR(st.st_mode) + + def memory_percent(self, ret, proc): + self.assertIsInstance(ret, float) + assert 0 <= ret <= 100, ret + + def is_running(self, ret, proc): + self.assertIsInstance(ret, bool) + + def cpu_affinity(self, ret, proc): + self.assertIsInstance(ret, list) + assert ret != [], ret + cpus = range(psutil.cpu_count()) + for n in ret: + self.assertIsInstance(n, int) + self.assertIn(n, cpus) + + def terminal(self, ret, proc): + self.assertIsInstance(ret, (str, type(None))) + if ret is not None: + assert os.path.isabs(ret), ret + assert os.path.exists(ret), ret + + def memory_maps(self, ret, proc): + for nt in ret: + self.assertIsInstance(nt.addr, str) + self.assertIsInstance(nt.perms, str) + self.assertIsInstance(nt.path, str) + for fname in nt._fields: + value = getattr(nt, fname) + if fname == 'path': + if not value.startswith('['): + assert os.path.isabs(nt.path), nt.path + # commented as on Linux we might get + # '/foo/bar (deleted)' + # assert os.path.exists(nt.path), nt.path + elif fname in ('addr', 'perms'): + assert value + else: + self.assertIsInstance(value, (int, long)) + self.assertGreaterEqual(value, 0) + + def num_handles(self, ret, proc): + self.assertIsInstance(ret, int) + self.assertGreaterEqual(ret, 0) + + def nice(self, ret, proc): + self.assertIsInstance(ret, int) + if POSIX: + assert -20 <= ret <= 20, ret + else: + priorities = [getattr(psutil, x) for x in dir(psutil) + if x.endswith('_PRIORITY_CLASS')] + self.assertIn(ret, priorities) + + def num_ctx_switches(self, ret, proc): + assert is_namedtuple(ret) + for value in ret: + self.assertIsInstance(value, (int, long)) + self.assertGreaterEqual(value, 0) + + def rlimit(self, ret, proc): + self.assertIsInstance(ret, tuple) + self.assertEqual(len(ret), 2) + self.assertGreaterEqual(ret[0], -1) + self.assertGreaterEqual(ret[1], -1) + + def environ(self, ret, proc): + self.assertIsInstance(ret, dict) + for k, v in ret.items(): + self.assertIsInstance(k, str) + self.assertIsInstance(v, str) + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_linux.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_linux.py new file mode 100644 index 00000000..0f981b6b --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_linux.py @@ -0,0 +1,2083 @@ +#!/usr/bin/env python + +# 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. + +"""Linux specific tests.""" + +from __future__ import division +import collections +import contextlib +import errno +import glob +import io +import os +import re +import shutil +import socket +import struct +import tempfile +import textwrap +import time +import warnings + +import psutil +from psutil import LINUX +from psutil._compat import basestring +from psutil._compat import PY3 +from psutil._compat import u +from psutil.tests import call_until +from psutil.tests import HAS_BATTERY +from psutil.tests import HAS_CPU_FREQ +from psutil.tests import HAS_RLIMIT +from psutil.tests import MEMORY_TOLERANCE +from psutil.tests import mock +from psutil.tests import PYPY +from psutil.tests import pyrun +from psutil.tests import reap_children +from psutil.tests import reload_module +from psutil.tests import retry_before_failing +from psutil.tests import run_test_module_by_name +from psutil.tests import safe_rmpath +from psutil.tests import sh +from psutil.tests import skip_on_not_implemented +from psutil.tests import TESTFN +from psutil.tests import ThreadTask +from psutil.tests import TRAVIS +from psutil.tests import unittest +from psutil.tests import which + + +HERE = os.path.abspath(os.path.dirname(__file__)) +SIOCGIFADDR = 0x8915 +SIOCGIFCONF = 0x8912 +SIOCGIFHWADDR = 0x8927 +if LINUX: + SECTOR_SIZE = 512 + + +# ===================================================================== +# --- utils +# ===================================================================== + + +def get_ipv4_address(ifname): + import fcntl + ifname = ifname[:15] + if PY3: + ifname = bytes(ifname, 'ascii') + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + with contextlib.closing(s): + return socket.inet_ntoa( + fcntl.ioctl(s.fileno(), + SIOCGIFADDR, + struct.pack('256s', ifname))[20:24]) + + +def get_mac_address(ifname): + import fcntl + ifname = ifname[:15] + if PY3: + ifname = bytes(ifname, 'ascii') + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + with contextlib.closing(s): + info = fcntl.ioctl( + s.fileno(), SIOCGIFHWADDR, struct.pack('256s', ifname)) + if PY3: + def ord(x): + return x + else: + import __builtin__ + ord = __builtin__.ord + return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1] + + +def free_swap(): + """Parse 'free' cmd and return swap memory's s total, used and free + values. + """ + out = sh('free -b') + lines = out.split('\n') + for line in lines: + if line.startswith('Swap'): + _, total, used, free = line.split() + nt = collections.namedtuple('free', 'total used free') + return nt(int(total), int(used), int(free)) + raise ValueError( + "can't find 'Swap' in 'free' output:\n%s" % '\n'.join(lines)) + + +def free_physmem(): + """Parse 'free' cmd and return physical memory's total, used + and free values. + """ + # Note: free can have 2 different formats, invalidating 'shared' + # and 'cached' memory which may have different positions so we + # do not return them. + # https://github.com/giampaolo/psutil/issues/538#issuecomment-57059946 + out = sh('free -b') + lines = out.split('\n') + for line in lines: + if line.startswith('Mem'): + total, used, free, shared = \ + [int(x) for x in line.split()[1:5]] + nt = collections.namedtuple( + 'free', 'total used free shared output') + return nt(total, used, free, shared, out) + raise ValueError( + "can't find 'Mem' in 'free' output:\n%s" % '\n'.join(lines)) + + +def vmstat(stat): + out = sh("vmstat -s") + for line in out.split("\n"): + line = line.strip() + if stat in line: + return int(line.split(' ')[0]) + raise ValueError("can't find %r in 'vmstat' output" % stat) + + +def get_free_version_info(): + out = sh("free -V").strip() + return tuple(map(int, out.split()[-1].split('.'))) + + +@contextlib.contextmanager +def mock_open_content(for_path, content): + """Mock open() builtin and forces it to return a certain `content` + on read() if the path being opened matches `for_path`. + """ + def open_mock(name, *args, **kwargs): + if name == for_path: + if PY3: + if isinstance(content, basestring): + return io.StringIO(content) + else: + return io.BytesIO(content) + else: + return io.BytesIO(content) + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, create=True, side_effect=open_mock) as m: + yield m + + +@contextlib.contextmanager +def mock_open_exception(for_path, exc): + """Mock open() builtin and raises `exc` if the path being opened + matches `for_path`. + """ + def open_mock(name, *args, **kwargs): + if name == for_path: + raise exc + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, create=True, side_effect=open_mock) as m: + yield m + + +# ===================================================================== +# --- system virtual memory +# ===================================================================== + + +@unittest.skipIf(not LINUX, "LINUX only") +class TestSystemVirtualMemory(unittest.TestCase): + + def test_total(self): + # free_value = free_physmem().total + # psutil_value = psutil.virtual_memory().total + # self.assertEqual(free_value, psutil_value) + vmstat_value = vmstat('total memory') * 1024 + psutil_value = psutil.virtual_memory().total + self.assertAlmostEqual(vmstat_value, psutil_value) + + # Older versions of procps used slab memory to calculate used memory. + # This got changed in: + # https://gitlab.com/procps-ng/procps/commit/ + # 05d751c4f076a2f0118b914c5e51cfbb4762ad8e + @unittest.skipIf(LINUX and get_free_version_info() < (3, 3, 12), + "old free version") + @retry_before_failing() + def test_used(self): + free = free_physmem() + free_value = free.used + psutil_value = psutil.virtual_memory().used + self.assertAlmostEqual( + free_value, psutil_value, delta=MEMORY_TOLERANCE, + msg='%s %s \n%s' % (free_value, psutil_value, free.output)) + + @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") + @retry_before_failing() + def test_free(self): + # _, _, free_value, _ = free_physmem() + # psutil_value = psutil.virtual_memory().free + # self.assertAlmostEqual( + # free_value, psutil_value, delta=MEMORY_TOLERANCE) + vmstat_value = vmstat('free memory') * 1024 + psutil_value = psutil.virtual_memory().free + self.assertAlmostEqual( + vmstat_value, psutil_value, delta=MEMORY_TOLERANCE) + + @retry_before_failing() + def test_buffers(self): + vmstat_value = vmstat('buffer memory') * 1024 + psutil_value = psutil.virtual_memory().buffers + self.assertAlmostEqual( + vmstat_value, psutil_value, delta=MEMORY_TOLERANCE) + + # https://travis-ci.org/giampaolo/psutil/jobs/226719664 + @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") + @retry_before_failing() + def test_active(self): + vmstat_value = vmstat('active memory') * 1024 + psutil_value = psutil.virtual_memory().active + self.assertAlmostEqual( + vmstat_value, psutil_value, delta=MEMORY_TOLERANCE) + + # https://travis-ci.org/giampaolo/psutil/jobs/227242952 + @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") + @retry_before_failing() + def test_inactive(self): + vmstat_value = vmstat('inactive memory') * 1024 + psutil_value = psutil.virtual_memory().inactive + self.assertAlmostEqual( + vmstat_value, psutil_value, delta=MEMORY_TOLERANCE) + + @retry_before_failing() + def test_shared(self): + free = free_physmem() + free_value = free.shared + if free_value == 0: + raise unittest.SkipTest("free does not support 'shared' column") + psutil_value = psutil.virtual_memory().shared + self.assertAlmostEqual( + free_value, psutil_value, delta=MEMORY_TOLERANCE, + msg='%s %s \n%s' % (free_value, psutil_value, free.output)) + + @retry_before_failing() + def test_available(self): + # "free" output format has changed at some point: + # https://github.com/giampaolo/psutil/issues/538#issuecomment-147192098 + out = sh("free -b") + lines = out.split('\n') + if 'available' not in lines[0]: + raise unittest.SkipTest("free does not support 'available' column") + else: + free_value = int(lines[1].split()[-1]) + psutil_value = psutil.virtual_memory().available + self.assertAlmostEqual( + free_value, psutil_value, delta=MEMORY_TOLERANCE, + msg='%s %s \n%s' % (free_value, psutil_value, out)) + + def test_warnings_on_misses(self): + # Emulate a case where /proc/meminfo provides few info. + # psutil is supposed to set the missing fields to 0 and + # raise a warning. + with mock_open_content( + '/proc/meminfo', + textwrap.dedent("""\ + Active(anon): 6145416 kB + Active(file): 2950064 kB + Inactive(anon): 574764 kB + Inactive(file): 1567648 kB + MemAvailable: -1 kB + MemFree: 2057400 kB + MemTotal: 16325648 kB + SReclaimable: 346648 kB + """).encode()) as m: + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter("always") + ret = psutil.virtual_memory() + assert m.called + self.assertEqual(len(ws), 1) + w = ws[0] + assert w.filename.endswith('psutil/_pslinux.py') + self.assertIn( + "memory stats couldn't be determined", str(w.message)) + self.assertIn("cached", str(w.message)) + self.assertIn("shared", str(w.message)) + self.assertIn("active", str(w.message)) + self.assertIn("inactive", str(w.message)) + self.assertIn("buffers", str(w.message)) + self.assertIn("available", str(w.message)) + self.assertEqual(ret.cached, 0) + self.assertEqual(ret.active, 0) + self.assertEqual(ret.inactive, 0) + self.assertEqual(ret.shared, 0) + self.assertEqual(ret.buffers, 0) + self.assertEqual(ret.available, 0) + self.assertEqual(ret.slab, 0) + + def test_avail_old_percent(self): + # Make sure that our calculation of avail mem for old kernels + # is off by max 10%. + from psutil._pslinux import calculate_avail_vmem + from psutil._pslinux import open_binary + + mems = {} + with open_binary('/proc/meminfo') as f: + for line in f: + fields = line.split() + mems[fields[0]] = int(fields[1]) * 1024 + + a = calculate_avail_vmem(mems) + if b'MemAvailable:' in mems: + b = mems[b'MemAvailable:'] + diff_percent = abs(a - b) / a * 100 + self.assertLess(diff_percent, 10) + + def test_avail_old_comes_from_kernel(self): + # Make sure "MemAvailable:" coluimn is used instead of relying + # on our internal algorithm to calculate avail mem. + with mock_open_content( + '/proc/meminfo', + textwrap.dedent("""\ + Active: 9444728 kB + Active(anon): 6145416 kB + Active(file): 2950064 kB + Buffers: 287952 kB + Cached: 4818144 kB + Inactive(file): 1578132 kB + Inactive(anon): 574764 kB + Inactive(file): 1567648 kB + MemAvailable: 6574984 kB + MemFree: 2057400 kB + MemTotal: 16325648 kB + Shmem: 577588 kB + SReclaimable: 346648 kB + """).encode()) as m: + with warnings.catch_warnings(record=True) as ws: + ret = psutil.virtual_memory() + assert m.called + self.assertEqual(ret.available, 6574984 * 1024) + w = ws[0] + self.assertIn( + "inactive memory stats couldn't be determined", str(w.message)) + + def test_avail_old_missing_fields(self): + # Remove Active(file), Inactive(file) and SReclaimable + # from /proc/meminfo and make sure the fallback is used + # (free + cached), + with mock_open_content( + "/proc/meminfo", + textwrap.dedent("""\ + Active: 9444728 kB + Active(anon): 6145416 kB + Buffers: 287952 kB + Cached: 4818144 kB + Inactive(file): 1578132 kB + Inactive(anon): 574764 kB + MemFree: 2057400 kB + MemTotal: 16325648 kB + Shmem: 577588 kB + """).encode()) as m: + with warnings.catch_warnings(record=True) as ws: + ret = psutil.virtual_memory() + assert m.called + self.assertEqual(ret.available, 2057400 * 1024 + 4818144 * 1024) + w = ws[0] + self.assertIn( + "inactive memory stats couldn't be determined", str(w.message)) + + def test_avail_old_missing_zoneinfo(self): + # Remove /proc/zoneinfo file. Make sure fallback is used + # (free + cached). + with mock_open_content( + "/proc/meminfo", + textwrap.dedent("""\ + Active: 9444728 kB + Active(anon): 6145416 kB + Active(file): 2950064 kB + Buffers: 287952 kB + Cached: 4818144 kB + Inactive(file): 1578132 kB + Inactive(anon): 574764 kB + Inactive(file): 1567648 kB + MemFree: 2057400 kB + MemTotal: 16325648 kB + Shmem: 577588 kB + SReclaimable: 346648 kB + """).encode()): + with mock_open_exception( + "/proc/zoneinfo", + IOError(errno.ENOENT, 'no such file or directory')): + with warnings.catch_warnings(record=True) as ws: + ret = psutil.virtual_memory() + self.assertEqual( + ret.available, 2057400 * 1024 + 4818144 * 1024) + w = ws[0] + self.assertIn( + "inactive memory stats couldn't be determined", + str(w.message)) + + def test_virtual_memory_mocked(self): + # Emulate /proc/meminfo because neither vmstat nor free return slab. + def open_mock(name, *args, **kwargs): + if name == '/proc/meminfo': + return io.BytesIO(textwrap.dedent("""\ + MemTotal: 100 kB + MemFree: 2 kB + MemAvailable: 3 kB + Buffers: 4 kB + Cached: 5 kB + SwapCached: 6 kB + Active: 7 kB + Inactive: 8 kB + Active(anon): 9 kB + Inactive(anon): 10 kB + Active(file): 11 kB + Inactive(file): 12 kB + Unevictable: 13 kB + Mlocked: 14 kB + SwapTotal: 15 kB + SwapFree: 16 kB + Dirty: 17 kB + Writeback: 18 kB + AnonPages: 19 kB + Mapped: 20 kB + Shmem: 21 kB + Slab: 22 kB + SReclaimable: 23 kB + SUnreclaim: 24 kB + KernelStack: 25 kB + PageTables: 26 kB + NFS_Unstable: 27 kB + Bounce: 28 kB + WritebackTmp: 29 kB + CommitLimit: 30 kB + Committed_AS: 31 kB + VmallocTotal: 32 kB + VmallocUsed: 33 kB + VmallocChunk: 34 kB + HardwareCorrupted: 35 kB + AnonHugePages: 36 kB + ShmemHugePages: 37 kB + ShmemPmdMapped: 38 kB + CmaTotal: 39 kB + CmaFree: 40 kB + HugePages_Total: 41 kB + HugePages_Free: 42 kB + HugePages_Rsvd: 43 kB + HugePages_Surp: 44 kB + Hugepagesize: 45 kB + DirectMap46k: 46 kB + DirectMap47M: 47 kB + DirectMap48G: 48 kB + """).encode()) + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, create=True, side_effect=open_mock) as m: + mem = psutil.virtual_memory() + assert m.called + self.assertEqual(mem.total, 100 * 1024) + self.assertEqual(mem.free, 2 * 1024) + self.assertEqual(mem.buffers, 4 * 1024) + # cached mem also includes reclaimable memory + self.assertEqual(mem.cached, (5 + 23) * 1024) + self.assertEqual(mem.shared, 21 * 1024) + self.assertEqual(mem.active, 7 * 1024) + self.assertEqual(mem.inactive, 8 * 1024) + self.assertEqual(mem.slab, 22 * 1024) + self.assertEqual(mem.available, 3 * 1024) + + +# ===================================================================== +# --- system swap memory +# ===================================================================== + + +@unittest.skipIf(not LINUX, "LINUX only") +class TestSystemSwapMemory(unittest.TestCase): + + @staticmethod + def meminfo_has_swap_info(): + """Return True if /proc/meminfo provides swap metrics.""" + with open("/proc/meminfo") as f: + data = f.read() + return 'SwapTotal:' in data and 'SwapFree:' in data + + def test_total(self): + free_value = free_swap().total + psutil_value = psutil.swap_memory().total + return self.assertAlmostEqual( + free_value, psutil_value, delta=MEMORY_TOLERANCE) + + @retry_before_failing() + def test_used(self): + free_value = free_swap().used + psutil_value = psutil.swap_memory().used + return self.assertAlmostEqual( + free_value, psutil_value, delta=MEMORY_TOLERANCE) + + @retry_before_failing() + def test_free(self): + free_value = free_swap().free + psutil_value = psutil.swap_memory().free + return self.assertAlmostEqual( + free_value, psutil_value, delta=MEMORY_TOLERANCE) + + def test_missing_sin_sout(self): + with mock.patch('psutil._common.open', create=True) as m: + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter("always") + ret = psutil.swap_memory() + assert m.called + self.assertEqual(len(ws), 1) + w = ws[0] + assert w.filename.endswith('psutil/_pslinux.py') + self.assertIn( + "'sin' and 'sout' swap memory stats couldn't " + "be determined", str(w.message)) + self.assertEqual(ret.sin, 0) + self.assertEqual(ret.sout, 0) + + def test_no_vmstat_mocked(self): + # see https://github.com/giampaolo/psutil/issues/722 + with mock_open_exception( + "/proc/vmstat", + IOError(errno.ENOENT, 'no such file or directory')) as m: + with warnings.catch_warnings(record=True) as ws: + warnings.simplefilter("always") + ret = psutil.swap_memory() + assert m.called + self.assertEqual(len(ws), 1) + w = ws[0] + assert w.filename.endswith('psutil/_pslinux.py') + self.assertIn( + "'sin' and 'sout' swap memory stats couldn't " + "be determined and were set to 0", + str(w.message)) + self.assertEqual(ret.sin, 0) + self.assertEqual(ret.sout, 0) + + def test_meminfo_against_sysinfo(self): + # Make sure the content of /proc/meminfo about swap memory + # matches sysinfo() syscall, see: + # https://github.com/giampaolo/psutil/issues/1015 + if not self.meminfo_has_swap_info(): + return unittest.skip("/proc/meminfo has no swap metrics") + with mock.patch('psutil._pslinux.cext.linux_sysinfo') as m: + swap = psutil.swap_memory() + assert not m.called + import psutil._psutil_linux as cext + _, _, _, _, total, free, unit_multiplier = cext.linux_sysinfo() + total *= unit_multiplier + free *= unit_multiplier + self.assertEqual(swap.total, total) + self.assertAlmostEqual(swap.free, free, delta=MEMORY_TOLERANCE) + + def test_emulate_meminfo_has_no_metrics(self): + # Emulate a case where /proc/meminfo provides no swap metrics + # in which case sysinfo() syscall is supposed to be used + # as a fallback. + with mock_open_content("/proc/meminfo", b"") as m: + psutil.swap_memory() + assert m.called + + +# ===================================================================== +# --- system CPU +# ===================================================================== + + +@unittest.skipIf(not LINUX, "LINUX only") +class TestSystemCPU(unittest.TestCase): + + @unittest.skipIf(TRAVIS, "unknown failure on travis") + def test_cpu_times(self): + fields = psutil.cpu_times()._fields + kernel_ver = re.findall(r'\d+\.\d+\.\d+', os.uname()[2])[0] + kernel_ver_info = tuple(map(int, kernel_ver.split('.'))) + if kernel_ver_info >= (2, 6, 11): + self.assertIn('steal', fields) + else: + self.assertNotIn('steal', fields) + if kernel_ver_info >= (2, 6, 24): + self.assertIn('guest', fields) + else: + self.assertNotIn('guest', fields) + if kernel_ver_info >= (3, 2, 0): + self.assertIn('guest_nice', fields) + else: + self.assertNotIn('guest_nice', fields) + + @unittest.skipIf(not os.path.exists("/sys/devices/system/cpu/online"), + "/sys/devices/system/cpu/online does not exist") + def test_cpu_count_logical_w_sysdev_cpu_online(self): + with open("/sys/devices/system/cpu/online") as f: + value = f.read().strip() + if "-" in str(value): + value = int(value.split('-')[1]) + 1 + self.assertEqual(psutil.cpu_count(), value) + + @unittest.skipIf(not os.path.exists("/sys/devices/system/cpu"), + "/sys/devices/system/cpu does not exist") + def test_cpu_count_logical_w_sysdev_cpu_num(self): + ls = os.listdir("/sys/devices/system/cpu") + count = len([x for x in ls if re.search(r"cpu\d+$", x) is not None]) + self.assertEqual(psutil.cpu_count(), count) + + @unittest.skipIf(not which("nproc"), "nproc utility not available") + def test_cpu_count_logical_w_nproc(self): + num = int(sh("nproc --all")) + self.assertEqual(psutil.cpu_count(logical=True), num) + + @unittest.skipIf(not which("lscpu"), "lscpu utility not available") + def test_cpu_count_logical_w_lscpu(self): + out = sh("lscpu -p") + num = len([x for x in out.split('\n') if not x.startswith('#')]) + self.assertEqual(psutil.cpu_count(logical=True), num) + + @unittest.skipIf(not which("lscpu"), "lscpu utility not available") + def test_cpu_count_physical_w_lscpu(self): + out = sh("lscpu -p") + core_ids = set() + for line in out.split('\n'): + if not line.startswith('#'): + fields = line.split(',') + core_ids.add(fields[1]) + self.assertEqual(psutil.cpu_count(logical=False), len(core_ids)) + + def test_cpu_count_logical_mocked(self): + import psutil._pslinux + original = psutil._pslinux.cpu_count_logical() + # Here we want to mock os.sysconf("SC_NPROCESSORS_ONLN") in + # order to cause the parsing of /proc/cpuinfo and /proc/stat. + with mock.patch( + 'psutil._pslinux.os.sysconf', side_effect=ValueError) as m: + self.assertEqual(psutil._pslinux.cpu_count_logical(), original) + assert m.called + + # Let's have open() return emtpy data and make sure None is + # returned ('cause we mimick os.cpu_count()). + with mock.patch('psutil._common.open', create=True) as m: + self.assertIsNone(psutil._pslinux.cpu_count_logical()) + self.assertEqual(m.call_count, 2) + # /proc/stat should be the last one + self.assertEqual(m.call_args[0][0], '/proc/stat') + + # Let's push this a bit further and make sure /proc/cpuinfo + # parsing works as expected. + with open('/proc/cpuinfo', 'rb') as f: + cpuinfo_data = f.read() + fake_file = io.BytesIO(cpuinfo_data) + with mock.patch('psutil._common.open', + return_value=fake_file, create=True) as m: + self.assertEqual(psutil._pslinux.cpu_count_logical(), original) + + # Finally, let's make /proc/cpuinfo return meaningless data; + # 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 + + def test_cpu_count_physical_mocked(self): + # Have open() return emtpy data and make sure None is returned + # ('cause we want to mimick os.cpu_count()) + with mock.patch('psutil._common.open', create=True) as m: + self.assertIsNone(psutil._pslinux.cpu_count_physical()) + assert m.called + + @unittest.skipIf(not HAS_CPU_FREQ, "not supported") + def test_cpu_freq_no_result(self): + with mock.patch("psutil._pslinux.glob.glob", return_value=[]): + self.assertIsNone(psutil.cpu_freq()) + + @unittest.skipIf(TRAVIS, "fails on Travis") + @unittest.skipIf(not HAS_CPU_FREQ, "not supported") + def test_cpu_freq_use_second_file(self): + # https://github.com/giampaolo/psutil/issues/981 + def glob_mock(pattern): + if pattern.startswith("/sys/devices/system/cpu/cpufreq/policy"): + flags.append(None) + return [] + else: + flags.append(None) + return orig_glob(pattern) + + flags = [] + orig_glob = glob.glob + with mock.patch("psutil._pslinux.glob.glob", side_effect=glob_mock, + create=True): + assert psutil.cpu_freq() + self.assertEqual(len(flags), 2) + + @unittest.skipIf(not HAS_CPU_FREQ, "not supported") + def test_cpu_freq_use_cpuinfo(self): + # Emulate a case where /sys/devices/system/cpu/cpufreq* does not + # exist and /proc/cpuinfo is used instead. + def path_exists_mock(path): + if path.startswith('/sys/devices/system/cpu/'): + return False + else: + if path == "/proc/cpuinfo": + flags.append(None) + return os_path_exists(path) + + flags = [] + os_path_exists = os.path.exists + try: + with mock.patch("os.path.exists", side_effect=path_exists_mock): + reload_module(psutil._pslinux) + ret = psutil.cpu_freq() + assert ret + assert flags + self.assertIsNone(ret.min) + self.assertIsNone(ret.max) + for freq in psutil.cpu_freq(percpu=True): + self.assertIsNone(freq.min) + self.assertIsNone(freq.max) + finally: + reload_module(psutil._pslinux) + reload_module(psutil) + + @unittest.skipIf(not HAS_CPU_FREQ, "not supported") + def test_cpu_freq_emulate_data(self): + def open_mock(name, *args, **kwargs): + if name.endswith('/scaling_cur_freq'): + return io.BytesIO(b"500000") + elif name.endswith('/scaling_min_freq'): + return io.BytesIO(b"600000") + elif name.endswith('/scaling_max_freq'): + return io.BytesIO(b"700000") + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, side_effect=open_mock): + with mock.patch( + 'glob.glob', + return_value=['/sys/devices/system/cpu/cpufreq/policy0']): + freq = psutil.cpu_freq() + self.assertEqual(freq.current, 500.0) + self.assertEqual(freq.min, 600.0) + self.assertEqual(freq.max, 700.0) + + @unittest.skipIf(not HAS_CPU_FREQ, "not supported") + def test_cpu_freq_emulate_multi_cpu(self): + def open_mock(name, *args, **kwargs): + if name.endswith('/scaling_cur_freq'): + return io.BytesIO(b"100000") + elif name.endswith('/scaling_min_freq'): + return io.BytesIO(b"200000") + elif name.endswith('/scaling_max_freq'): + return io.BytesIO(b"300000") + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + policies = ['/sys/devices/system/cpu/cpufreq/policy0', + '/sys/devices/system/cpu/cpufreq/policy1', + '/sys/devices/system/cpu/cpufreq/policy2'] + with mock.patch(patch_point, side_effect=open_mock): + with mock.patch('glob.glob', return_value=policies): + freq = psutil.cpu_freq() + self.assertEqual(freq.current, 100.0) + self.assertEqual(freq.min, 200.0) + self.assertEqual(freq.max, 300.0) + + @unittest.skipIf(TRAVIS, "fails on Travis") + @unittest.skipIf(not HAS_CPU_FREQ, "not supported") + def test_cpu_freq_no_scaling_cur_freq_file(self): + # See: https://github.com/giampaolo/psutil/issues/1071 + def open_mock(name, *args, **kwargs): + if name.endswith('/scaling_cur_freq'): + raise IOError(errno.ENOENT, "") + elif name.endswith('/cpuinfo_cur_freq'): + return io.BytesIO(b"200000") + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + policies = ['/sys/devices/system/cpu/cpufreq/policy0', + '/sys/devices/system/cpu/cpufreq/policy1', + '/sys/devices/system/cpu/cpufreq/policy2'] + + with mock.patch(patch_point, side_effect=open_mock): + with mock.patch('glob.glob', return_value=policies): + freq = psutil.cpu_freq() + self.assertEqual(freq.current, 200) + + # Also test that NotImplementedError is raised in case no + # current freq file is present. + + def open_mock(name, *args, **kwargs): + if name.endswith('/scaling_cur_freq'): + raise IOError(errno.ENOENT, "") + elif name.endswith('/cpuinfo_cur_freq'): + raise IOError(errno.ENOENT, "") + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, side_effect=open_mock): + with mock.patch('glob.glob', return_value=policies): + self.assertRaises(NotImplementedError, psutil.cpu_freq) + + +# ===================================================================== +# --- system CPU stats +# ===================================================================== + + +@unittest.skipIf(not LINUX, "LINUX only") +class TestSystemCPUStats(unittest.TestCase): + + @unittest.skipIf(TRAVIS, "fails on Travis") + def test_ctx_switches(self): + vmstat_value = vmstat("context switches") + psutil_value = psutil.cpu_stats().ctx_switches + self.assertAlmostEqual(vmstat_value, psutil_value, delta=500) + + @unittest.skipIf(TRAVIS, "fails on Travis") + def test_interrupts(self): + vmstat_value = vmstat("interrupts") + psutil_value = psutil.cpu_stats().interrupts + self.assertAlmostEqual(vmstat_value, psutil_value, delta=500) + + +# ===================================================================== +# --- system network +# ===================================================================== + + +@unittest.skipIf(not LINUX, "LINUX only") +class TestSystemNetwork(unittest.TestCase): + + def test_net_if_addrs_ips(self): + for name, addrs in psutil.net_if_addrs().items(): + for addr in addrs: + if addr.family == psutil.AF_LINK: + self.assertEqual(addr.address, get_mac_address(name)) + elif addr.family == socket.AF_INET: + self.assertEqual(addr.address, get_ipv4_address(name)) + # TODO: test for AF_INET6 family + + def test_net_if_stats(self): + for name, stats in psutil.net_if_stats().items(): + try: + out = sh("ifconfig %s" % name) + except RuntimeError: + pass + else: + # Not always reliable. + # self.assertEqual(stats.isup, 'RUNNING' in out, msg=out) + self.assertEqual(stats.mtu, + int(re.findall(r'(?i)MTU[: ](\d+)', out)[0])) + + @retry_before_failing() + def test_net_io_counters(self): + def ifconfig(nic): + ret = {} + out = sh("ifconfig %s" % name) + ret['packets_recv'] = int( + re.findall(r'RX packets[: ](\d+)', out)[0]) + ret['packets_sent'] = int( + re.findall(r'TX packets[: ](\d+)', out)[0]) + ret['errin'] = int(re.findall(r'errors[: ](\d+)', out)[0]) + ret['errout'] = int(re.findall(r'errors[: ](\d+)', out)[1]) + ret['dropin'] = int(re.findall(r'dropped[: ](\d+)', out)[0]) + ret['dropout'] = int(re.findall(r'dropped[: ](\d+)', out)[1]) + ret['bytes_recv'] = int( + re.findall(r'RX (?:packets \d+ +)?bytes[: ](\d+)', out)[0]) + ret['bytes_sent'] = int( + re.findall(r'TX (?:packets \d+ +)?bytes[: ](\d+)', out)[0]) + return ret + + nio = psutil.net_io_counters(pernic=True, nowrap=False) + for name, stats in nio.items(): + try: + ifconfig_ret = ifconfig(name) + except RuntimeError: + continue + self.assertAlmostEqual( + stats.bytes_recv, ifconfig_ret['bytes_recv'], delta=1024 * 5) + self.assertAlmostEqual( + stats.bytes_sent, ifconfig_ret['bytes_sent'], delta=1024 * 5) + self.assertAlmostEqual( + stats.packets_recv, ifconfig_ret['packets_recv'], delta=1024) + self.assertAlmostEqual( + stats.packets_sent, ifconfig_ret['packets_sent'], delta=1024) + self.assertAlmostEqual( + stats.errin, ifconfig_ret['errin'], delta=10) + self.assertAlmostEqual( + stats.errout, ifconfig_ret['errout'], delta=10) + self.assertAlmostEqual( + stats.dropin, ifconfig_ret['dropin'], delta=10) + self.assertAlmostEqual( + stats.dropout, ifconfig_ret['dropout'], delta=10) + + # XXX - not reliable when having virtual NICs installed by Docker. + # @unittest.skipIf(not which('ip'), "'ip' utility not available") + # @unittest.skipIf(TRAVIS, "skipped on Travis") + # def test_net_if_names(self): + # out = sh("ip addr").strip() + # nics = [x for x in psutil.net_if_addrs().keys() if ':' not in x] + # found = 0 + # for line in out.split('\n'): + # line = line.strip() + # if re.search(r"^\d+:", line): + # found += 1 + # name = line.split(':')[1].strip() + # self.assertIn(name, nics) + # self.assertEqual(len(nics), found, msg="%s\n---\n%s" % ( + # pprint.pformat(nics), out)) + + @mock.patch('psutil._pslinux.socket.inet_ntop', side_effect=ValueError) + @mock.patch('psutil._pslinux.supports_ipv6', return_value=False) + def test_net_connections_ipv6_unsupported(self, supports_ipv6, inet_ntop): + # see: https://github.com/giampaolo/psutil/issues/623 + try: + s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + self.addCleanup(s.close) + s.bind(("::1", 0)) + except socket.error: + pass + psutil.net_connections(kind='inet6') + + def test_net_connections_mocked(self): + with mock_open_content( + '/proc/net/unix', + textwrap.dedent("""\ + 0: 00000003 000 000 0001 03 462170 @/tmp/dbus-Qw2hMPIU3n + 0: 00000003 000 000 0001 03 35010 @/tmp/dbus-tB2X8h69BQ + 0: 00000003 000 000 0001 03 34424 @/tmp/dbus-cHy80Y8O + 000000000000000000000000000000000000000000000000000000 + """)) as m: + psutil.net_connections(kind='unix') + assert m.called + + +# ===================================================================== +# --- system disk +# ===================================================================== + + +@unittest.skipIf(not LINUX, "LINUX only") +class TestSystemDisks(unittest.TestCase): + + @unittest.skipIf(not hasattr(os, 'statvfs'), "os.statvfs() not available") + @skip_on_not_implemented() + def test_disk_partitions_and_usage(self): + # test psutil.disk_usage() and psutil.disk_partitions() + # against "df -a" + def df(path): + out = sh('df -P -B 1 "%s"' % path).strip() + lines = out.split('\n') + lines.pop(0) + line = lines.pop(0) + dev, total, used, free = line.split()[:4] + if dev == 'none': + dev = '' + total, used, free = int(total), int(used), int(free) + return dev, total, used, free + + for part in psutil.disk_partitions(all=False): + usage = psutil.disk_usage(part.mountpoint) + dev, total, used, free = df(part.mountpoint) + self.assertEqual(usage.total, total) + # 10 MB tollerance + if abs(usage.free - free) > 10 * 1024 * 1024: + self.fail("psutil=%s, df=%s" % (usage.free, free)) + if abs(usage.used - used) > 10 * 1024 * 1024: + self.fail("psutil=%s, df=%s" % (usage.used, used)) + + def test_disk_partitions_mocked(self): + # Test that ZFS partitions are returned. + with open("/proc/filesystems", "r") as f: + data = f.read() + if 'zfs' in data: + for part in psutil.disk_partitions(): + if part.fstype == 'zfs': + break + else: + self.fail("couldn't find any ZFS partition") + else: + # No ZFS partitions on this system. Let's fake one. + fake_file = io.StringIO(u("nodev\tzfs\n")) + with mock.patch('psutil._common.open', + return_value=fake_file, create=True) as m1: + with mock.patch( + 'psutil._pslinux.cext.disk_partitions', + return_value=[('/dev/sdb3', '/', 'zfs', 'rw')]) as m2: + ret = psutil.disk_partitions() + assert m1.called + assert m2.called + assert ret + self.assertEqual(ret[0].fstype, 'zfs') + + def test_disk_partitions_procfs(self): + # See: https://github.com/giampaolo/psutil/issues/1307 + try: + with mock.patch('os.path.realpath', + return_value='/non/existent') as m: + with self.assertRaises(OSError) as cm: + psutil.disk_partitions() + assert m.called + self.assertEqual(cm.exception.errno, errno.ENOENT) + finally: + psutil.PROCFS_PATH = "/proc" + + def test_disk_io_counters_kernel_2_4_mocked(self): + # Tests /proc/diskstats parsing format for 2.4 kernels, see: + # https://github.com/giampaolo/psutil/issues/767 + with mock_open_content( + '/proc/diskstats', + " 3 0 1 hda 2 3 4 5 6 7 8 9 10 11 12"): + with mock.patch('psutil._pslinux.is_storage_device', + return_value=True): + ret = psutil.disk_io_counters(nowrap=False) + self.assertEqual(ret.read_count, 1) + self.assertEqual(ret.read_merged_count, 2) + self.assertEqual(ret.read_bytes, 3 * SECTOR_SIZE) + self.assertEqual(ret.read_time, 4) + self.assertEqual(ret.write_count, 5) + self.assertEqual(ret.write_merged_count, 6) + self.assertEqual(ret.write_bytes, 7 * SECTOR_SIZE) + self.assertEqual(ret.write_time, 8) + self.assertEqual(ret.busy_time, 10) + + def test_disk_io_counters_kernel_2_6_full_mocked(self): + # Tests /proc/diskstats parsing format for 2.6 kernels, + # lines reporting all metrics: + # https://github.com/giampaolo/psutil/issues/767 + with mock_open_content( + '/proc/diskstats', + " 3 0 hda 1 2 3 4 5 6 7 8 9 10 11"): + with mock.patch('psutil._pslinux.is_storage_device', + return_value=True): + ret = psutil.disk_io_counters(nowrap=False) + self.assertEqual(ret.read_count, 1) + self.assertEqual(ret.read_merged_count, 2) + self.assertEqual(ret.read_bytes, 3 * SECTOR_SIZE) + self.assertEqual(ret.read_time, 4) + self.assertEqual(ret.write_count, 5) + self.assertEqual(ret.write_merged_count, 6) + self.assertEqual(ret.write_bytes, 7 * SECTOR_SIZE) + self.assertEqual(ret.write_time, 8) + self.assertEqual(ret.busy_time, 10) + + def test_disk_io_counters_kernel_2_6_limited_mocked(self): + # Tests /proc/diskstats parsing format for 2.6 kernels, + # where one line of /proc/partitions return a limited + # amount of metrics when it bumps into a partition + # (instead of a disk). See: + # https://github.com/giampaolo/psutil/issues/767 + with mock_open_content( + '/proc/diskstats', + " 3 1 hda 1 2 3 4"): + with mock.patch('psutil._pslinux.is_storage_device', + return_value=True): + ret = psutil.disk_io_counters(nowrap=False) + self.assertEqual(ret.read_count, 1) + self.assertEqual(ret.read_bytes, 2 * SECTOR_SIZE) + self.assertEqual(ret.write_count, 3) + self.assertEqual(ret.write_bytes, 4 * SECTOR_SIZE) + + self.assertEqual(ret.read_merged_count, 0) + self.assertEqual(ret.read_time, 0) + self.assertEqual(ret.write_merged_count, 0) + self.assertEqual(ret.write_time, 0) + self.assertEqual(ret.busy_time, 0) + + def test_disk_io_counters_include_partitions(self): + # Make sure that when perdisk=True disk partitions are returned, + # see: + # https://github.com/giampaolo/psutil/pull/1313#issuecomment-408626842 + with mock_open_content( + '/proc/diskstats', + textwrap.dedent("""\ + 3 0 nvme0n1 1 2 3 4 5 6 7 8 9 10 11 + 3 0 nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11 + """)): + with mock.patch('psutil._pslinux.is_storage_device', + return_value=False): + ret = psutil.disk_io_counters(perdisk=True, nowrap=False) + self.assertEqual(len(ret), 2) + self.assertEqual(ret['nvme0n1'].read_count, 1) + self.assertEqual(ret['nvme0n1p1'].read_count, 1) + self.assertEqual(ret['nvme0n1'].write_count, 5) + self.assertEqual(ret['nvme0n1p1'].write_count, 5) + + def test_disk_io_counters_exclude_partitions(self): + # Make sure that when perdisk=False partitions (e.g. 'sda1', + # 'nvme0n1p1') are skipped and not included in the total count. + # https://github.com/giampaolo/psutil/pull/1313#issuecomment-408626842 + with mock_open_content( + '/proc/diskstats', + textwrap.dedent("""\ + 3 0 nvme0n1 1 2 3 4 5 6 7 8 9 10 11 + 3 0 nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11 + """)): + with mock.patch('psutil._pslinux.is_storage_device', + return_value=False): + ret = psutil.disk_io_counters(perdisk=False, nowrap=False) + self.assertIsNone(ret) + + # + def is_storage_device(name): + return name == 'nvme0n1' + + with mock_open_content( + '/proc/diskstats', + textwrap.dedent("""\ + 3 0 nvme0n1 1 2 3 4 5 6 7 8 9 10 11 + 3 0 nvme0n1p1 1 2 3 4 5 6 7 8 9 10 11 + """)): + with mock.patch('psutil._pslinux.is_storage_device', + create=True, side_effect=is_storage_device): + ret = psutil.disk_io_counters(perdisk=False, nowrap=False) + self.assertEqual(ret.read_count, 1) + self.assertEqual(ret.write_count, 5) + + def test_disk_io_counters_sysfs(self): + def exists(path): + if path == '/proc/diskstats': + return False + return True + + wprocfs = psutil.disk_io_counters(perdisk=True) + with mock.patch('psutil._pslinux.os.path.exists', + create=True, side_effect=exists): + wsysfs = psutil.disk_io_counters(perdisk=True) + self.assertEqual(len(wprocfs), len(wsysfs)) + + def test_disk_io_counters_not_impl(self): + def exists(path): + return False + + with mock.patch('psutil._pslinux.os.path.exists', + create=True, side_effect=exists): + self.assertRaises(NotImplementedError, psutil.disk_io_counters) + + +# ===================================================================== +# --- misc +# ===================================================================== + + +@unittest.skipIf(not LINUX, "LINUX only") +class TestMisc(unittest.TestCase): + + def test_boot_time(self): + vmstat_value = vmstat('boot time') + psutil_value = psutil.boot_time() + self.assertEqual(int(vmstat_value), int(psutil_value)) + + def test_no_procfs_on_import(self): + my_procfs = tempfile.mkdtemp() + + with open(os.path.join(my_procfs, 'stat'), 'w') as f: + f.write('cpu 0 0 0 0 0 0 0 0 0 0\n') + f.write('cpu0 0 0 0 0 0 0 0 0 0 0\n') + f.write('cpu1 0 0 0 0 0 0 0 0 0 0\n') + + try: + orig_open = open + + def open_mock(name, *args, **kwargs): + if name.startswith('/proc'): + raise IOError(errno.ENOENT, 'rejecting access for test') + return orig_open(name, *args, **kwargs) + + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, side_effect=open_mock): + reload_module(psutil) + + self.assertRaises(IOError, psutil.cpu_times) + self.assertRaises(IOError, psutil.cpu_times, percpu=True) + self.assertRaises(IOError, psutil.cpu_percent) + self.assertRaises(IOError, psutil.cpu_percent, percpu=True) + self.assertRaises(IOError, psutil.cpu_times_percent) + self.assertRaises( + IOError, psutil.cpu_times_percent, percpu=True) + + psutil.PROCFS_PATH = my_procfs + + self.assertEqual(psutil.cpu_percent(), 0) + self.assertEqual(sum(psutil.cpu_times_percent()), 0) + + # since we don't know the number of CPUs at import time, + # we awkwardly say there are none until the second call + per_cpu_percent = psutil.cpu_percent(percpu=True) + self.assertEqual(sum(per_cpu_percent), 0) + + # ditto awkward length + per_cpu_times_percent = psutil.cpu_times_percent(percpu=True) + self.assertEqual(sum(map(sum, per_cpu_times_percent)), 0) + + # much user, very busy + with open(os.path.join(my_procfs, 'stat'), 'w') as f: + f.write('cpu 1 0 0 0 0 0 0 0 0 0\n') + f.write('cpu0 1 0 0 0 0 0 0 0 0 0\n') + f.write('cpu1 1 0 0 0 0 0 0 0 0 0\n') + + self.assertNotEqual(psutil.cpu_percent(), 0) + self.assertNotEqual( + sum(psutil.cpu_percent(percpu=True)), 0) + self.assertNotEqual(sum(psutil.cpu_times_percent()), 0) + self.assertNotEqual( + sum(map(sum, psutil.cpu_times_percent(percpu=True))), 0) + finally: + shutil.rmtree(my_procfs) + reload_module(psutil) + + self.assertEqual(psutil.PROCFS_PATH, '/proc') + + def test_cpu_steal_decrease(self): + # Test cumulative cpu stats decrease. We should ignore this. + # See issue #1210. + with mock_open_content( + "/proc/stat", + textwrap.dedent("""\ + cpu 0 0 0 0 0 0 0 1 0 0 + cpu0 0 0 0 0 0 0 0 1 0 0 + cpu1 0 0 0 0 0 0 0 1 0 0 + """).encode()) as m: + # first call to "percent" functions should read the new stat file + # and compare to the "real" file read at import time - so the + # values are meaningless + psutil.cpu_percent() + assert m.called + psutil.cpu_percent(percpu=True) + psutil.cpu_times_percent() + psutil.cpu_times_percent(percpu=True) + + with mock_open_content( + "/proc/stat", + textwrap.dedent("""\ + cpu 1 0 0 0 0 0 0 0 0 0 + cpu0 1 0 0 0 0 0 0 0 0 0 + cpu1 1 0 0 0 0 0 0 0 0 0 + """).encode()) as m: + # Increase "user" while steal goes "backwards" to zero. + cpu_percent = psutil.cpu_percent() + assert m.called + cpu_percent_percpu = psutil.cpu_percent(percpu=True) + cpu_times_percent = psutil.cpu_times_percent() + cpu_times_percent_percpu = psutil.cpu_times_percent(percpu=True) + self.assertNotEqual(cpu_percent, 0) + self.assertNotEqual(sum(cpu_percent_percpu), 0) + self.assertNotEqual(sum(cpu_times_percent), 0) + self.assertNotEqual(sum(cpu_times_percent), 100.0) + self.assertNotEqual(sum(map(sum, cpu_times_percent_percpu)), 0) + self.assertNotEqual(sum(map(sum, cpu_times_percent_percpu)), 100.0) + self.assertEqual(cpu_times_percent.steal, 0) + self.assertNotEqual(cpu_times_percent.user, 0) + + def test_boot_time_mocked(self): + with mock.patch('psutil._common.open', create=True) as m: + self.assertRaises( + RuntimeError, + psutil._pslinux.boot_time) + assert m.called + + def test_users_mocked(self): + # Make sure ':0' and ':0.0' (returned by C ext) are converted + # to 'localhost'. + with mock.patch('psutil._pslinux.cext.users', + return_value=[('giampaolo', 'pts/2', ':0', + 1436573184.0, True, 2)]) as m: + self.assertEqual(psutil.users()[0].host, 'localhost') + assert m.called + with mock.patch('psutil._pslinux.cext.users', + return_value=[('giampaolo', 'pts/2', ':0.0', + 1436573184.0, True, 2)]) as m: + self.assertEqual(psutil.users()[0].host, 'localhost') + assert m.called + # ...otherwise it should be returned as-is + with mock.patch('psutil._pslinux.cext.users', + return_value=[('giampaolo', 'pts/2', 'foo', + 1436573184.0, True, 2)]) as m: + self.assertEqual(psutil.users()[0].host, 'foo') + assert m.called + + def test_procfs_path(self): + tdir = tempfile.mkdtemp() + try: + psutil.PROCFS_PATH = tdir + self.assertRaises(IOError, psutil.virtual_memory) + self.assertRaises(IOError, psutil.cpu_times) + self.assertRaises(IOError, psutil.cpu_times, percpu=True) + self.assertRaises(IOError, psutil.boot_time) + # self.assertRaises(IOError, psutil.pids) + self.assertRaises(IOError, psutil.net_connections) + self.assertRaises(IOError, psutil.net_io_counters) + self.assertRaises(IOError, psutil.net_if_stats) + # self.assertRaises(IOError, psutil.disk_io_counters) + self.assertRaises(IOError, psutil.disk_partitions) + self.assertRaises(psutil.NoSuchProcess, psutil.Process) + finally: + psutil.PROCFS_PATH = "/proc" + os.rmdir(tdir) + + def test_issue_687(self): + # In case of thread ID: + # - pid_exists() is supposed to return False + # - Process(tid) is supposed to work + # - pids() should not return the TID + # See: https://github.com/giampaolo/psutil/issues/687 + t = ThreadTask() + t.start() + try: + p = psutil.Process() + tid = p.threads()[1].id + assert not psutil.pid_exists(tid), tid + pt = psutil.Process(tid) + pt.as_dict() + self.assertNotIn(tid, psutil.pids()) + finally: + t.stop() + + def test_pid_exists_no_proc_status(self): + # Internally pid_exists relies on /proc/{pid}/status. + # Emulate a case where this file is empty in which case + # psutil is supposed to fall back on using pids(). + with mock_open_content("/proc/%s/status", "") as m: + assert psutil.pid_exists(os.getpid()) + assert m.called + + +# ===================================================================== +# --- sensors +# ===================================================================== + + +@unittest.skipIf(not LINUX, "LINUX only") +@unittest.skipIf(not HAS_BATTERY, "no battery") +class TestSensorsBattery(unittest.TestCase): + + @unittest.skipIf(not which("acpi"), "acpi utility not available") + def test_percent(self): + out = sh("acpi -b") + acpi_value = int(out.split(",")[1].strip().replace('%', '')) + psutil_value = psutil.sensors_battery().percent + self.assertAlmostEqual(acpi_value, psutil_value, delta=1) + + @unittest.skipIf(not which("acpi"), "acpi utility not available") + def test_power_plugged(self): + out = sh("acpi -b") + if 'unknown' in out.lower(): + return unittest.skip("acpi output not reliable") + if 'discharging at zero rate' in out: + plugged = True + else: + plugged = "Charging" in out.split('\n')[0] + self.assertEqual(psutil.sensors_battery().power_plugged, plugged) + + def test_emulate_power_plugged(self): + # Pretend the AC power cable is connected. + def open_mock(name, *args, **kwargs): + if name.endswith("AC0/online") or name.endswith("AC/online"): + return io.BytesIO(b"1") + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, side_effect=open_mock) as m: + self.assertEqual(psutil.sensors_battery().power_plugged, True) + self.assertEqual( + psutil.sensors_battery().secsleft, psutil.POWER_TIME_UNLIMITED) + assert m.called + + def test_emulate_power_plugged_2(self): + # Same as above but pretend /AC0/online does not exist in which + # case code relies on /status file. + def open_mock(name, *args, **kwargs): + if name.endswith("AC0/online") or name.endswith("AC/online"): + raise IOError(errno.ENOENT, "") + elif name.endswith("/status"): + return io.StringIO(u("charging")) + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, side_effect=open_mock) as m: + self.assertEqual(psutil.sensors_battery().power_plugged, True) + assert m.called + + def test_emulate_power_not_plugged(self): + # Pretend the AC power cable is not connected. + def open_mock(name, *args, **kwargs): + if name.endswith("AC0/online") or name.endswith("AC/online"): + return io.BytesIO(b"0") + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, side_effect=open_mock) as m: + self.assertEqual(psutil.sensors_battery().power_plugged, False) + assert m.called + + def test_emulate_power_not_plugged_2(self): + # Same as above but pretend /AC0/online does not exist in which + # case code relies on /status file. + def open_mock(name, *args, **kwargs): + if name.endswith("AC0/online") or name.endswith("AC/online"): + raise IOError(errno.ENOENT, "") + elif name.endswith("/status"): + return io.StringIO(u("discharging")) + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, side_effect=open_mock) as m: + self.assertEqual(psutil.sensors_battery().power_plugged, False) + assert m.called + + def test_emulate_power_undetermined(self): + # Pretend we can't know whether the AC power cable not + # connected (assert fallback to False). + def open_mock(name, *args, **kwargs): + if name.startswith("/sys/class/power_supply/AC0/online") or \ + name.startswith("/sys/class/power_supply/AC/online"): + raise IOError(errno.ENOENT, "") + elif name.startswith("/sys/class/power_supply/BAT0/status"): + return io.BytesIO(b"???") + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, side_effect=open_mock) as m: + self.assertIsNone(psutil.sensors_battery().power_plugged) + assert m.called + + def test_emulate_no_base_files(self): + # Emulate a case where base metrics files are not present, + # in which case we're supposed to get None. + with mock_open_exception( + "/sys/class/power_supply/BAT0/energy_now", + IOError(errno.ENOENT, "")): + with mock_open_exception( + "/sys/class/power_supply/BAT0/charge_now", + IOError(errno.ENOENT, "")): + self.assertIsNone(psutil.sensors_battery()) + + def test_emulate_energy_full_0(self): + # Emulate a case where energy_full files returns 0. + with mock_open_content( + "/sys/class/power_supply/BAT0/energy_full", b"0") as m: + self.assertEqual(psutil.sensors_battery().percent, 0) + assert m.called + + def test_emulate_energy_full_not_avail(self): + # Emulate a case where energy_full file does not exist. + # Expected fallback on /capacity. + with mock_open_exception( + "/sys/class/power_supply/BAT0/energy_full", + IOError(errno.ENOENT, "")): + with mock_open_exception( + "/sys/class/power_supply/BAT0/charge_full", + IOError(errno.ENOENT, "")): + with mock_open_content( + "/sys/class/power_supply/BAT0/capacity", b"88"): + self.assertEqual(psutil.sensors_battery().percent, 88) + + def test_emulate_no_power(self): + # Emulate a case where /AC0/online file nor /BAT0/status exist. + with mock_open_exception( + "/sys/class/power_supply/AC/online", + IOError(errno.ENOENT, "")): + with mock_open_exception( + "/sys/class/power_supply/AC0/online", + IOError(errno.ENOENT, "")): + with mock_open_exception( + "/sys/class/power_supply/BAT0/status", + IOError(errno.ENOENT, "")): + self.assertIsNone(psutil.sensors_battery().power_plugged) + + +@unittest.skipIf(not LINUX, "LINUX only") +class TestSensorsTemperatures(unittest.TestCase): + + @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") + def test_emulate_eio_error(self): + def open_mock(name, *args, **kwargs): + if name.endswith("_input"): + raise OSError(errno.EIO, "") + elif name.endswith("temp"): + raise OSError(errno.EIO, "") + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, side_effect=open_mock) as m: + with warnings.catch_warnings(record=True) as ws: + self.assertEqual(psutil.sensors_temperatures(), {}) + assert m.called + self.assertIn("ignoring", str(ws[0].message)) + + def test_emulate_class_hwmon(self): + def open_mock(name, *args, **kwargs): + if name.endswith('/name'): + return io.StringIO(u("name")) + elif name.endswith('/temp1_label'): + return io.StringIO(u("label")) + elif name.endswith('/temp1_input'): + return io.BytesIO(b"30000") + elif name.endswith('/temp1_max'): + return io.BytesIO(b"40000") + elif name.endswith('/temp1_crit'): + return io.BytesIO(b"50000") + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, side_effect=open_mock): + # Test case with /sys/class/hwmon + with mock.patch('glob.glob', + return_value=['/sys/class/hwmon/hwmon0/temp1']): + temp = psutil.sensors_temperatures()['name'][0] + self.assertEqual(temp.label, 'label') + self.assertEqual(temp.current, 30.0) + self.assertEqual(temp.high, 40.0) + self.assertEqual(temp.critical, 50.0) + + def test_emulate_class_thermal(self): + def open_mock(name, *args, **kwargs): + if name.endswith('0_temp'): + return io.BytesIO(b"50000") + elif name.endswith('temp'): + return io.BytesIO(b"30000") + elif name.endswith('0_type'): + return io.StringIO(u("critical")) + elif name.endswith('type'): + return io.StringIO(u("name")) + else: + return orig_open(name, *args, **kwargs) + + def glob_mock(path): + if path == '/sys/class/hwmon/hwmon*/temp*_*': + return [] + elif path == '/sys/class/hwmon/hwmon*/device/temp*_*': + return [] + elif path == '/sys/class/thermal/thermal_zone*': + return ['/sys/class/thermal/thermal_zone0'] + elif path == '/sys/class/thermal/thermal_zone0/trip_point*': + return ['/sys/class/thermal/thermal_zone1/trip_point_0_type', + '/sys/class/thermal/thermal_zone1/trip_point_0_temp'] + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, side_effect=open_mock): + with mock.patch('glob.glob', create=True, side_effect=glob_mock): + temp = psutil.sensors_temperatures()['name'][0] + self.assertEqual(temp.label, '') + self.assertEqual(temp.current, 30.0) + self.assertEqual(temp.high, 50.0) + self.assertEqual(temp.critical, 50.0) + + +@unittest.skipIf(not LINUX, "LINUX only") +class TestSensorsFans(unittest.TestCase): + + def test_emulate_data(self): + def open_mock(name, *args, **kwargs): + if name.endswith('/name'): + return io.StringIO(u("name")) + elif name.endswith('/fan1_label'): + return io.StringIO(u("label")) + elif name.endswith('/fan1_input'): + return io.StringIO(u("2000")) + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, side_effect=open_mock): + with mock.patch('glob.glob', + return_value=['/sys/class/hwmon/hwmon2/fan1']): + fan = psutil.sensors_fans()['name'][0] + self.assertEqual(fan.label, 'label') + self.assertEqual(fan.current, 2000) + + +# ===================================================================== +# --- test process +# ===================================================================== + + +@unittest.skipIf(not LINUX, "LINUX only") +class TestProcess(unittest.TestCase): + + def setUp(self): + safe_rmpath(TESTFN) + + tearDown = setUp + + def test_memory_full_info(self): + src = textwrap.dedent(""" + import time + with open("%s", "w") as f: + time.sleep(10) + """ % TESTFN) + sproc = pyrun(src) + self.addCleanup(reap_children) + call_until(lambda: os.listdir('.'), "'%s' not in ret" % TESTFN) + p = psutil.Process(sproc.pid) + time.sleep(.1) + mem = p.memory_full_info() + maps = p.memory_maps(grouped=False) + self.assertAlmostEqual( + mem.uss, sum([x.private_dirty + x.private_clean for x in maps]), + delta=4096) + self.assertAlmostEqual( + mem.pss, sum([x.pss for x in maps]), delta=4096) + self.assertAlmostEqual( + mem.swap, sum([x.swap for x in maps]), delta=4096) + + def test_memory_full_info_mocked(self): + # See: https://github.com/giampaolo/psutil/issues/1222 + with mock_open_content( + "/proc/%s/smaps" % os.getpid(), + textwrap.dedent("""\ + fffff0 r-xp 00000000 00:00 0 [vsyscall] + Size: 1 kB + Rss: 2 kB + Pss: 3 kB + Shared_Clean: 4 kB + Shared_Dirty: 5 kB + Private_Clean: 6 kB + Private_Dirty: 7 kB + Referenced: 8 kB + Anonymous: 9 kB + LazyFree: 10 kB + AnonHugePages: 11 kB + ShmemPmdMapped: 12 kB + Shared_Hugetlb: 13 kB + Private_Hugetlb: 14 kB + Swap: 15 kB + SwapPss: 16 kB + KernelPageSize: 17 kB + MMUPageSize: 18 kB + Locked: 19 kB + VmFlags: rd ex + """).encode()) as m: + p = psutil.Process() + mem = p.memory_full_info() + assert m.called + self.assertEqual(mem.uss, (6 + 7 + 14) * 1024) + self.assertEqual(mem.pss, 3 * 1024) + self.assertEqual(mem.swap, 15 * 1024) + + # On PYPY file descriptors are not closed fast enough. + @unittest.skipIf(PYPY, "unreliable on PYPY") + def test_open_files_mode(self): + def get_test_file(): + p = psutil.Process() + giveup_at = time.time() + 2 + while True: + for file in p.open_files(): + if file.path == os.path.abspath(TESTFN): + return file + elif time.time() > giveup_at: + break + raise RuntimeError("timeout looking for test file") + + # + with open(TESTFN, "w"): + self.assertEqual(get_test_file().mode, "w") + with open(TESTFN, "r"): + self.assertEqual(get_test_file().mode, "r") + with open(TESTFN, "a"): + self.assertEqual(get_test_file().mode, "a") + # + with open(TESTFN, "r+"): + self.assertEqual(get_test_file().mode, "r+") + with open(TESTFN, "w+"): + self.assertEqual(get_test_file().mode, "r+") + with open(TESTFN, "a+"): + self.assertEqual(get_test_file().mode, "a+") + # note: "x" bit is not supported + if PY3: + safe_rmpath(TESTFN) + with open(TESTFN, "x"): + self.assertEqual(get_test_file().mode, "w") + safe_rmpath(TESTFN) + with open(TESTFN, "x+"): + self.assertEqual(get_test_file().mode, "r+") + + def test_open_files_file_gone(self): + # simulates a file which gets deleted during open_files() + # execution + p = psutil.Process() + files = p.open_files() + with tempfile.NamedTemporaryFile(): + # give the kernel some time to see the new file + call_until(p.open_files, "len(ret) != %i" % len(files)) + with mock.patch('psutil._pslinux.os.readlink', + side_effect=OSError(errno.ENOENT, "")) as m: + files = p.open_files() + assert not files + assert m.called + # also simulate the case where os.readlink() returns EINVAL + # in which case psutil is supposed to 'continue' + with mock.patch('psutil._pslinux.os.readlink', + side_effect=OSError(errno.EINVAL, "")) as m: + self.assertEqual(p.open_files(), []) + assert m.called + + def test_open_files_fd_gone(self): + # Simulate a case where /proc/{pid}/fdinfo/{fd} disappears + # while iterating through fds. + # https://travis-ci.org/giampaolo/psutil/jobs/225694530 + p = psutil.Process() + files = p.open_files() + with tempfile.NamedTemporaryFile(): + # give the kernel some time to see the new file + call_until(p.open_files, "len(ret) != %i" % len(files)) + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, + side_effect=IOError(errno.ENOENT, "")) as m: + files = p.open_files() + assert not files + assert m.called + + # --- mocked tests + + def test_terminal_mocked(self): + with mock.patch('psutil._pslinux._psposix.get_terminal_map', + return_value={}) as m: + self.assertIsNone(psutil._pslinux.Process(os.getpid()).terminal()) + assert m.called + + # TODO: re-enable this test. + # def test_num_ctx_switches_mocked(self): + # with mock.patch('psutil._common.open', create=True) as m: + # self.assertRaises( + # NotImplementedError, + # psutil._pslinux.Process(os.getpid()).num_ctx_switches) + # assert m.called + + def test_cmdline_mocked(self): + # see: https://github.com/giampaolo/psutil/issues/639 + p = psutil.Process() + fake_file = io.StringIO(u('foo\x00bar\x00')) + with mock.patch('psutil._common.open', + return_value=fake_file, create=True) as m: + self.assertEqual(p.cmdline(), ['foo', 'bar']) + assert m.called + fake_file = io.StringIO(u('foo\x00bar\x00\x00')) + with mock.patch('psutil._common.open', + return_value=fake_file, create=True) as m: + self.assertEqual(p.cmdline(), ['foo', 'bar', '']) + assert m.called + + def test_cmdline_spaces_mocked(self): + # see: https://github.com/giampaolo/psutil/issues/1179 + p = psutil.Process() + fake_file = io.StringIO(u('foo bar ')) + with mock.patch('psutil._common.open', + return_value=fake_file, create=True) as m: + self.assertEqual(p.cmdline(), ['foo', 'bar']) + assert m.called + fake_file = io.StringIO(u('foo bar ')) + with mock.patch('psutil._common.open', + return_value=fake_file, create=True) as m: + self.assertEqual(p.cmdline(), ['foo', 'bar', '']) + assert m.called + + def test_readlink_path_deleted_mocked(self): + with mock.patch('psutil._pslinux.os.readlink', + return_value='/home/foo (deleted)'): + self.assertEqual(psutil.Process().exe(), "/home/foo") + self.assertEqual(psutil.Process().cwd(), "/home/foo") + + def test_threads_mocked(self): + # Test the case where os.listdir() returns a file (thread) + # 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): + if name.startswith('/proc/%s/task' % os.getpid()): + raise IOError(errno.ENOENT, "") + else: + return orig_open(name, *args, **kwargs) + + orig_open = open + patch_point = 'builtins.open' if PY3 else '__builtin__.open' + with mock.patch(patch_point, side_effect=open_mock) 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): + 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): + self.assertRaises(psutil.AccessDenied, psutil.Process().threads) + + def test_exe_mocked(self): + with mock.patch('psutil._pslinux.readlink', + side_effect=OSError(errno.ENOENT, "")) as m1: + with mock.patch('psutil.Process.cmdline', + side_effect=psutil.AccessDenied(0, "")) as m2: + # No such file error; might be raised also if /proc/pid/exe + # path actually exists for system processes with low pids + # (about 0-20). In this case psutil is supposed to return + # an empty string. + ret = psutil.Process().exe() + assert m1.called + assert m2.called + self.assertEqual(ret, "") + + # ...but if /proc/pid no longer exist we're supposed to treat + # it as an alias for zombie process + with mock.patch('psutil._pslinux.os.path.lexists', + return_value=False): + self.assertRaises( + psutil.ZombieProcess, psutil.Process().exe) + + def test_issue_1014(self): + # Emulates a case where smaps file does not exist. In this case + # wrap_exception decorator should not raise NoSuchProcess. + with mock_open_exception( + '/proc/%s/smaps' % os.getpid(), + IOError(errno.ENOENT, "")) as m: + p = psutil.Process() + with self.assertRaises(IOError) as err: + p.memory_maps() + self.assertEqual(err.exception.errno, errno.ENOENT) + assert m.called + + @unittest.skipIf(not HAS_RLIMIT, "not supported") + def test_rlimit_zombie(self): + # Emulate a case where rlimit() raises ENOSYS, which may + # happen in case of zombie process: + # https://travis-ci.org/giampaolo/psutil/jobs/51368273 + with mock.patch("psutil._pslinux.cext.linux_prlimit", + side_effect=OSError(errno.ENOSYS, "")) as m: + p = psutil.Process() + p.name() + with self.assertRaises(psutil.ZombieProcess) as exc: + p.rlimit(psutil.RLIMIT_NOFILE) + assert m.called + self.assertEqual(exc.exception.pid, p.pid) + self.assertEqual(exc.exception.name, p.name()) + + def test_cwd_zombie(self): + with mock.patch("psutil._pslinux.os.readlink", + side_effect=OSError(errno.ENOENT, "")) as m: + p = psutil.Process() + p.name() + with self.assertRaises(psutil.ZombieProcess) as exc: + p.cwd() + assert m.called + self.assertEqual(exc.exception.pid, p.pid) + self.assertEqual(exc.exception.name, p.name()) + + def test_stat_file_parsing(self): + from psutil._pslinux import CLOCK_TICKS + + args = [ + "0", # pid + "(cat)", # name + "Z", # status + "1", # ppid + "0", # pgrp + "0", # session + "0", # tty + "0", # tpgid + "0", # flags + "0", # minflt + "0", # cminflt + "0", # majflt + "0", # cmajflt + "2", # utime + "3", # stime + "4", # cutime + "5", # cstime + "0", # priority + "0", # nice + "0", # num_threads + "0", # itrealvalue + "6", # starttime + "0", # vsize + "0", # rss + "0", # rsslim + "0", # startcode + "0", # endcode + "0", # startstack + "0", # kstkesp + "0", # kstkeip + "0", # signal + "0", # blocked + "0", # sigignore + "0", # sigcatch + "0", # wchan + "0", # nswap + "0", # cnswap + "0", # exit_signal + "6", # processor + ] + content = " ".join(args).encode() + with mock_open_content('/proc/%s/stat' % os.getpid(), content): + p = psutil.Process() + self.assertEqual(p.name(), 'cat') + self.assertEqual(p.status(), psutil.STATUS_ZOMBIE) + self.assertEqual(p.ppid(), 1) + self.assertEqual( + p.create_time(), 6 / CLOCK_TICKS + psutil.boot_time()) + cpu = p.cpu_times() + self.assertEqual(cpu.user, 2 / CLOCK_TICKS) + self.assertEqual(cpu.system, 3 / CLOCK_TICKS) + self.assertEqual(cpu.children_user, 4 / CLOCK_TICKS) + self.assertEqual(cpu.children_system, 5 / CLOCK_TICKS) + self.assertEqual(p.cpu_num(), 6) + + def test_status_file_parsing(self): + with mock_open_content( + '/proc/%s/status' % os.getpid(), + textwrap.dedent("""\ + Uid:\t1000\t1001\t1002\t1003 + Gid:\t1004\t1005\t1006\t1007 + Threads:\t66 + Cpus_allowed:\tf + Cpus_allowed_list:\t0-7 + voluntary_ctxt_switches:\t12 + nonvoluntary_ctxt_switches:\t13""").encode()): + p = psutil.Process() + self.assertEqual(p.num_ctx_switches().voluntary, 12) + self.assertEqual(p.num_ctx_switches().involuntary, 13) + self.assertEqual(p.num_threads(), 66) + uids = p.uids() + self.assertEqual(uids.real, 1000) + self.assertEqual(uids.effective, 1001) + self.assertEqual(uids.saved, 1002) + gids = p.gids() + self.assertEqual(gids.real, 1004) + self.assertEqual(gids.effective, 1005) + self.assertEqual(gids.saved, 1006) + self.assertEqual(p._proc._get_eligible_cpus(), list(range(0, 8))) + + +@unittest.skipIf(not LINUX, "LINUX only") +class TestProcessAgainstStatus(unittest.TestCase): + """/proc/pid/stat and /proc/pid/status have many values in common. + Whenever possible, psutil uses /proc/pid/stat (it's faster). + For all those cases we check that the value found in + /proc/pid/stat (by psutil) matches the one found in + /proc/pid/status. + """ + + @classmethod + def setUpClass(cls): + cls.proc = psutil.Process() + + def read_status_file(self, linestart): + with psutil._psplatform.open_text( + '/proc/%s/status' % self.proc.pid) as f: + for line in f: + line = line.strip() + if line.startswith(linestart): + value = line.partition('\t')[2] + try: + return int(value) + except ValueError: + return value + raise ValueError("can't find %r" % linestart) + + def test_name(self): + value = self.read_status_file("Name:") + self.assertEqual(self.proc.name(), value) + + def test_status(self): + value = self.read_status_file("State:") + value = value[value.find('(') + 1:value.rfind(')')] + value = value.replace(' ', '-') + self.assertEqual(self.proc.status(), value) + + def test_ppid(self): + value = self.read_status_file("PPid:") + self.assertEqual(self.proc.ppid(), value) + + def test_num_threads(self): + value = self.read_status_file("Threads:") + self.assertEqual(self.proc.num_threads(), value) + + def test_uids(self): + value = self.read_status_file("Uid:") + value = tuple(map(int, value.split()[1:4])) + self.assertEqual(self.proc.uids(), value) + + def test_gids(self): + value = self.read_status_file("Gid:") + value = tuple(map(int, value.split()[1:4])) + self.assertEqual(self.proc.gids(), value) + + @retry_before_failing() + def test_num_ctx_switches(self): + value = self.read_status_file("voluntary_ctxt_switches:") + self.assertEqual(self.proc.num_ctx_switches().voluntary, value) + value = self.read_status_file("nonvoluntary_ctxt_switches:") + self.assertEqual(self.proc.num_ctx_switches().involuntary, value) + + def test_cpu_affinity(self): + value = self.read_status_file("Cpus_allowed_list:") + if '-' in str(value): + min_, max_ = map(int, value.split('-')) + self.assertEqual( + self.proc.cpu_affinity(), list(range(min_, max_ + 1))) + + def test_cpu_affinity_eligible_cpus(self): + value = self.read_status_file("Cpus_allowed_list:") + with mock.patch("psutil._pslinux.per_cpu_times") as m: + self.proc._proc._get_eligible_cpus() + if '-' in str(value): + assert not m.called + else: + assert m.called + + +# ===================================================================== +# --- test utils +# ===================================================================== + + +@unittest.skipIf(not LINUX, "LINUX only") +class TestUtils(unittest.TestCase): + + def test_readlink(self): + with mock.patch("os.readlink", return_value="foo (deleted)") as m: + self.assertEqual(psutil._psplatform.readlink("bar"), "foo") + assert m.called + + def test_cat(self): + fname = os.path.abspath(TESTFN) + with open(fname, "wt") as f: + f.write("foo ") + self.assertEqual(psutil._psplatform.cat(TESTFN, binary=False), "foo") + self.assertEqual(psutil._psplatform.cat(TESTFN, binary=True), b"foo") + self.assertEqual( + psutil._psplatform.cat(TESTFN + '??', fallback="bar"), "bar") + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_memory_leaks.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_memory_leaks.py new file mode 100644 index 00000000..cbe37d3e --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_memory_leaks.py @@ -0,0 +1,610 @@ +#!/usr/bin/env python + +# 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. + +""" +Tests for detecting function memory leaks (typically the ones +implemented in C). It does so by calling a function many times and +checking whether process memory usage keeps increasing between +calls or over time. +Note that this may produce false positives (especially on Windows +for some reason). +""" + +from __future__ import print_function +import errno +import functools +import gc +import os +import sys +import threading +import time + +import psutil +import psutil._common +from psutil import LINUX +from psutil import MACOS +from psutil import OPENBSD +from psutil import POSIX +from psutil import SUNOS +from psutil import WINDOWS +from psutil._compat import xrange +from psutil.tests import create_sockets +from psutil.tests import get_test_subprocess +from psutil.tests import HAS_CPU_AFFINITY +from psutil.tests import HAS_CPU_FREQ +from psutil.tests import HAS_ENVIRON +from psutil.tests import HAS_IONICE +from psutil.tests import HAS_MEMORY_MAPS +from psutil.tests import HAS_NET_IO_COUNTERS +from psutil.tests import HAS_PROC_CPU_NUM +from psutil.tests import HAS_PROC_IO_COUNTERS +from psutil.tests import HAS_RLIMIT +from psutil.tests import HAS_SENSORS_BATTERY +from psutil.tests import HAS_SENSORS_FANS +from psutil.tests import HAS_SENSORS_TEMPERATURES +from psutil.tests import reap_children +from psutil.tests import run_test_module_by_name +from psutil.tests import safe_rmpath +from psutil.tests import skip_on_access_denied +from psutil.tests import TESTFN +from psutil.tests import TRAVIS +from psutil.tests import unittest + + +LOOPS = 1000 +MEMORY_TOLERANCE = 4096 +RETRY_FOR = 3 + +SKIP_PYTHON_IMPL = True if TRAVIS else False +cext = psutil._psplatform.cext +thisproc = psutil.Process() +SKIP_PYTHON_IMPL = True if TRAVIS else False + + +# =================================================================== +# utils +# =================================================================== + + +def skip_if_linux(): + return unittest.skipIf(LINUX and SKIP_PYTHON_IMPL, + "worthless on LINUX (pure python)") + + +def bytes2human(n): + """ + http://code.activestate.com/recipes/578019 + >>> bytes2human(10000) + '9.8K' + >>> bytes2human(100001221) + '95.4M' + """ + symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') + prefix = {} + for i, s in enumerate(symbols): + prefix[s] = 1 << (i + 1) * 10 + for s in reversed(symbols): + if n >= prefix[s]: + value = float(n) / prefix[s] + return '%.2f%s' % (value, s) + return "%sB" % n + + +class TestMemLeak(unittest.TestCase): + """Base framework class which calls a function many times and + produces a failure if process memory usage keeps increasing + between calls or over time. + """ + tolerance = MEMORY_TOLERANCE + loops = LOOPS + retry_for = RETRY_FOR + + def setUp(self): + gc.collect() + + def execute(self, fun, *args, **kwargs): + """Test a callable.""" + def call_many_times(): + for x in xrange(loops): + self._call(fun, *args, **kwargs) + del x + gc.collect() + + tolerance = kwargs.pop('tolerance_', None) or self.tolerance + loops = kwargs.pop('loops_', None) or self.loops + retry_for = kwargs.pop('retry_for_', None) or self.retry_for + + # warm up + for x in range(10): + self._call(fun, *args, **kwargs) + self.assertEqual(gc.garbage, []) + self.assertEqual(threading.active_count(), 1) + self.assertEqual(thisproc.children(), []) + + # Get 2 distinct memory samples, before and after having + # called fun repeadetly. + # step 1 + call_many_times() + mem1 = self._get_mem() + # step 2 + call_many_times() + mem2 = self._get_mem() + + diff1 = mem2 - mem1 + if diff1 > tolerance: + # This doesn't necessarily mean we have a leak yet. + # At this point we assume that after having called the + # function so many times the memory usage is stabilized + # and if there are no leaks it should not increase + # anymore. + # Let's keep calling fun for 3 more seconds and fail if + # we notice any difference. + ncalls = 0 + stop_at = time.time() + retry_for + while time.time() <= stop_at: + self._call(fun, *args, **kwargs) + ncalls += 1 + + del stop_at + gc.collect() + mem3 = self._get_mem() + diff2 = mem3 - mem2 + + if mem3 > mem2: + # failure + extra_proc_mem = bytes2human(diff1 + diff2) + print("exta proc mem: %s" % extra_proc_mem, file=sys.stderr) + msg = "+%s after %s calls, +%s after another %s calls, " + msg += "+%s extra proc mem" + msg = msg % ( + bytes2human(diff1), loops, bytes2human(diff2), ncalls, + extra_proc_mem) + self.fail(msg) + + def execute_w_exc(self, exc, fun, *args, **kwargs): + """Convenience function which tests a callable raising + an exception. + """ + def call(): + self.assertRaises(exc, fun, *args, **kwargs) + + self.execute(call) + + @staticmethod + def _get_mem(): + # By using USS memory it seems it's less likely to bump + # into false positives. + if LINUX or WINDOWS or MACOS: + return thisproc.memory_full_info().uss + else: + return thisproc.memory_info().rss + + @staticmethod + def _call(fun, *args, **kwargs): + fun(*args, **kwargs) + + +# =================================================================== +# Process class +# =================================================================== + + +class TestProcessObjectLeaks(TestMemLeak): + """Test leaks of Process class methods.""" + + proc = thisproc + + def test_coverage(self): + skip = set(( + "pid", "as_dict", "children", "cpu_affinity", "cpu_percent", + "ionice", "is_running", "kill", "memory_info_ex", "memory_percent", + "nice", "oneshot", "parent", "parents", "rlimit", "send_signal", + "suspend", "terminate", "wait")) + for name in dir(psutil.Process): + if name.startswith('_'): + continue + if name in skip: + continue + self.assertTrue(hasattr(self, "test_" + name), msg=name) + + @skip_if_linux() + def test_name(self): + self.execute(self.proc.name) + + @skip_if_linux() + def test_cmdline(self): + self.execute(self.proc.cmdline) + + @skip_if_linux() + def test_exe(self): + self.execute(self.proc.exe) + + @skip_if_linux() + def test_ppid(self): + self.execute(self.proc.ppid) + + @unittest.skipIf(not POSIX, "POSIX only") + @skip_if_linux() + def test_uids(self): + self.execute(self.proc.uids) + + @unittest.skipIf(not POSIX, "POSIX only") + @skip_if_linux() + def test_gids(self): + self.execute(self.proc.gids) + + @skip_if_linux() + def test_status(self): + self.execute(self.proc.status) + + def test_nice_get(self): + self.execute(self.proc.nice) + + def test_nice_set(self): + niceness = thisproc.nice() + self.execute(self.proc.nice, niceness) + + @unittest.skipIf(not HAS_IONICE, "not supported") + def test_ionice_get(self): + self.execute(self.proc.ionice) + + @unittest.skipIf(not HAS_IONICE, "not supported") + def test_ionice_set(self): + if WINDOWS: + value = thisproc.ionice() + self.execute(self.proc.ionice, value) + else: + self.execute(self.proc.ionice, psutil.IOPRIO_CLASS_NONE) + fun = functools.partial(cext.proc_ioprio_set, os.getpid(), -1, 0) + self.execute_w_exc(OSError, fun) + + @unittest.skipIf(not HAS_PROC_IO_COUNTERS, "not supported") + @skip_if_linux() + def test_io_counters(self): + self.execute(self.proc.io_counters) + + @unittest.skipIf(POSIX, "worthless on POSIX") + def test_username(self): + self.execute(self.proc.username) + + @skip_if_linux() + def test_create_time(self): + self.execute(self.proc.create_time) + + @skip_if_linux() + @skip_on_access_denied(only_if=OPENBSD) + def test_num_threads(self): + self.execute(self.proc.num_threads) + + @unittest.skipIf(not WINDOWS, "WINDOWS only") + def test_num_handles(self): + self.execute(self.proc.num_handles) + + @unittest.skipIf(not POSIX, "POSIX only") + @skip_if_linux() + def test_num_fds(self): + self.execute(self.proc.num_fds) + + @skip_if_linux() + def test_num_ctx_switches(self): + self.execute(self.proc.num_ctx_switches) + + @skip_if_linux() + @skip_on_access_denied(only_if=OPENBSD) + def test_threads(self): + self.execute(self.proc.threads) + + @skip_if_linux() + def test_cpu_times(self): + self.execute(self.proc.cpu_times) + + @skip_if_linux() + @unittest.skipIf(not HAS_PROC_CPU_NUM, "not supported") + def test_cpu_num(self): + self.execute(self.proc.cpu_num) + + @skip_if_linux() + def test_memory_info(self): + self.execute(self.proc.memory_info) + + @skip_if_linux() + def test_memory_full_info(self): + self.execute(self.proc.memory_full_info) + + @unittest.skipIf(not POSIX, "POSIX only") + @skip_if_linux() + def test_terminal(self): + self.execute(self.proc.terminal) + + @unittest.skipIf(POSIX and SKIP_PYTHON_IMPL, + "worthless on POSIX (pure python)") + def test_resume(self): + self.execute(self.proc.resume) + + @skip_if_linux() + def test_cwd(self): + self.execute(self.proc.cwd) + + @unittest.skipIf(not HAS_CPU_AFFINITY, "not supported") + def test_cpu_affinity_get(self): + self.execute(self.proc.cpu_affinity) + + @unittest.skipIf(not HAS_CPU_AFFINITY, "not supported") + def test_cpu_affinity_set(self): + affinity = thisproc.cpu_affinity() + self.execute(self.proc.cpu_affinity, affinity) + if not TRAVIS: + self.execute_w_exc(ValueError, self.proc.cpu_affinity, [-1]) + + @skip_if_linux() + def test_open_files(self): + safe_rmpath(TESTFN) # needed after UNIX socket test has run + with open(TESTFN, 'w'): + self.execute(self.proc.open_files) + + @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") + @skip_if_linux() + def test_memory_maps(self): + self.execute(self.proc.memory_maps) + + @unittest.skipIf(not LINUX, "LINUX only") + @unittest.skipIf(not HAS_RLIMIT, "not supported") + def test_rlimit_get(self): + self.execute(self.proc.rlimit, psutil.RLIMIT_NOFILE) + + @unittest.skipIf(not LINUX, "LINUX only") + @unittest.skipIf(not HAS_RLIMIT, "not supported") + def test_rlimit_set(self): + limit = thisproc.rlimit(psutil.RLIMIT_NOFILE) + self.execute(self.proc.rlimit, psutil.RLIMIT_NOFILE, limit) + self.execute_w_exc(OSError, self.proc.rlimit, -1) + + @skip_if_linux() + # Windows implementation is based on a single system-wide + # function (tested later). + @unittest.skipIf(WINDOWS, "worthless on WINDOWS") + def test_connections(self): + # TODO: UNIX sockets are temporarily implemented by parsing + # 'pfiles' cmd output; we don't want that part of the code to + # be executed. + with create_sockets(): + kind = 'inet' if SUNOS else 'all' + self.execute(self.proc.connections, kind) + + @unittest.skipIf(not HAS_ENVIRON, "not supported") + def test_environ(self): + self.execute(self.proc.environ) + + @unittest.skipIf(not WINDOWS, "WINDOWS only") + def test_proc_info(self): + self.execute(cext.proc_info, os.getpid()) + + +class TestProcessDualImplementation(TestMemLeak): + + if WINDOWS: + def test_cmdline_peb_true(self): + self.execute(cext.proc_cmdline, os.getpid(), use_peb=True) + + def test_cmdline_peb_false(self): + self.execute(cext.proc_cmdline, os.getpid(), use_peb=False) + + +class TestTerminatedProcessLeaks(TestProcessObjectLeaks): + """Repeat the tests above looking for leaks occurring when dealing + with terminated processes raising NoSuchProcess exception. + The C functions are still invoked but will follow different code + paths. We'll check those code paths. + """ + + @classmethod + def setUpClass(cls): + super(TestTerminatedProcessLeaks, cls).setUpClass() + p = get_test_subprocess() + cls.proc = psutil.Process(p.pid) + cls.proc.kill() + cls.proc.wait() + + @classmethod + def tearDownClass(cls): + super(TestTerminatedProcessLeaks, cls).tearDownClass() + reap_children() + + def _call(self, fun, *args, **kwargs): + try: + fun(*args, **kwargs) + except psutil.NoSuchProcess: + pass + + if WINDOWS: + + def test_kill(self): + self.execute(self.proc.kill) + + def test_terminate(self): + self.execute(self.proc.terminate) + + def test_suspend(self): + self.execute(self.proc.suspend) + + def test_resume(self): + self.execute(self.proc.resume) + + def test_wait(self): + self.execute(self.proc.wait) + + def test_proc_info(self): + # test dual implementation + def call(): + try: + return cext.proc_info(self.proc.pid) + except OSError as err: + if err.errno != errno.ESRCH: + raise + + self.execute(call) + + +# =================================================================== +# system APIs +# =================================================================== + + +class TestModuleFunctionsLeaks(TestMemLeak): + """Test leaks of psutil module functions.""" + + def test_coverage(self): + skip = set(( + "version_info", "__version__", "process_iter", "wait_procs", + "cpu_percent", "cpu_times_percent", "cpu_count")) + for name in psutil.__all__: + if not name.islower(): + continue + if name in skip: + continue + self.assertTrue(hasattr(self, "test_" + name), msg=name) + + # --- cpu + + @skip_if_linux() + def test_cpu_count_logical(self): + self.execute(psutil.cpu_count, logical=True) + + @skip_if_linux() + def test_cpu_count_physical(self): + self.execute(psutil.cpu_count, logical=False) + + @skip_if_linux() + def test_cpu_times(self): + self.execute(psutil.cpu_times) + + @skip_if_linux() + def test_per_cpu_times(self): + self.execute(psutil.cpu_times, percpu=True) + + def test_cpu_stats(self): + self.execute(psutil.cpu_stats) + + @skip_if_linux() + @unittest.skipIf(not HAS_CPU_FREQ, "not supported") + def test_cpu_freq(self): + self.execute(psutil.cpu_freq) + + # --- mem + + def test_virtual_memory(self): + self.execute(psutil.virtual_memory) + + # TODO: remove this skip when this gets fixed + @unittest.skipIf(SUNOS, + "worthless on SUNOS (uses a subprocess)") + def test_swap_memory(self): + self.execute(psutil.swap_memory) + + @unittest.skipIf(POSIX and SKIP_PYTHON_IMPL, + "worthless on POSIX (pure python)") + def test_pid_exists(self): + self.execute(psutil.pid_exists, os.getpid()) + + # --- disk + + @unittest.skipIf(POSIX and SKIP_PYTHON_IMPL, + "worthless on POSIX (pure python)") + def test_disk_usage(self): + self.execute(psutil.disk_usage, '.') + + def test_disk_partitions(self): + self.execute(psutil.disk_partitions) + + @unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'), + '/proc/diskstats not available on this Linux version') + @skip_if_linux() + def test_disk_io_counters(self): + self.execute(psutil.disk_io_counters, nowrap=False) + + # --- proc + + @skip_if_linux() + def test_pids(self): + self.execute(psutil.pids) + + # --- net + + @unittest.skipIf(TRAVIS and MACOS, "false positive on travis") + @skip_if_linux() + @unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported') + def test_net_io_counters(self): + self.execute(psutil.net_io_counters, nowrap=False) + + @unittest.skipIf(LINUX, + "worthless on Linux (pure python)") + @unittest.skipIf(MACOS and os.getuid() != 0, "need root access") + def test_net_connections(self): + with create_sockets(): + self.execute(psutil.net_connections) + + def test_net_if_addrs(self): + # Note: verified that on Windows this was a false positive. + self.execute(psutil.net_if_addrs, + tolerance_=80 * 1024 if WINDOWS else None) + + @unittest.skipIf(TRAVIS, "EPERM on travis") + def test_net_if_stats(self): + self.execute(psutil.net_if_stats) + + # --- sensors + + @skip_if_linux() + @unittest.skipIf(not HAS_SENSORS_BATTERY, "not supported") + def test_sensors_battery(self): + self.execute(psutil.sensors_battery) + + @skip_if_linux() + @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") + def test_sensors_temperatures(self): + self.execute(psutil.sensors_temperatures) + + @skip_if_linux() + @unittest.skipIf(not HAS_SENSORS_FANS, "not supported") + def test_sensors_fans(self): + self.execute(psutil.sensors_fans) + + # --- others + + @skip_if_linux() + def test_boot_time(self): + self.execute(psutil.boot_time) + + # XXX - on Windows this produces a false positive + @unittest.skipIf(WINDOWS, "XXX produces a false positive on Windows") + def test_users(self): + self.execute(psutil.users) + + if WINDOWS: + + # --- win services + + def test_win_service_iter(self): + self.execute(cext.winservice_enumerate) + + def test_win_service_get(self): + pass + + def test_win_service_get_config(self): + name = next(psutil.win_service_iter()).name() + self.execute(cext.winservice_query_config, name) + + def test_win_service_get_status(self): + name = next(psutil.win_service_iter()).name() + self.execute(cext.winservice_query_status, name) + + def test_win_service_get_description(self): + name = next(psutil.win_service_iter()).name() + self.execute(cext.winservice_query_descr, name) + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_misc.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_misc.py new file mode 100644 index 00000000..04b45948 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_misc.py @@ -0,0 +1,1057 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# 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. + +""" +Miscellaneous tests. +""" + +import ast +import collections +import contextlib +import errno +import json +import os +import pickle +import socket +import stat + +from psutil import LINUX +from psutil import POSIX +from psutil import WINDOWS +from psutil._common import memoize +from psutil._common import memoize_when_activated +from psutil._common import supports_ipv6 +from psutil._common import wrap_numbers +from psutil._common import open_text +from psutil._common import open_binary +from psutil._compat import PY3 +from psutil.tests import APPVEYOR +from psutil.tests import bind_socket +from psutil.tests import bind_unix_socket +from psutil.tests import call_until +from psutil.tests import chdir +from psutil.tests import create_proc_children_pair +from psutil.tests import create_sockets +from psutil.tests import create_zombie_proc +from psutil.tests import DEVNULL +from psutil.tests import get_free_port +from psutil.tests import get_test_subprocess +from psutil.tests import HAS_BATTERY +from psutil.tests import HAS_CONNECTIONS_UNIX +from psutil.tests import HAS_MEMORY_MAPS +from psutil.tests import HAS_NET_IO_COUNTERS +from psutil.tests import HAS_SENSORS_BATTERY +from psutil.tests import HAS_SENSORS_FANS +from psutil.tests import HAS_SENSORS_TEMPERATURES +from psutil.tests import import_module_by_path +from psutil.tests import is_namedtuple +from psutil.tests import mock +from psutil.tests import PYTHON_EXE +from psutil.tests import reap_children +from psutil.tests import reload_module +from psutil.tests import retry +from psutil.tests import ROOT_DIR +from psutil.tests import run_test_module_by_name +from psutil.tests import safe_mkdir +from psutil.tests import safe_rmpath +from psutil.tests import SCRIPTS_DIR +from psutil.tests import sh +from psutil.tests import tcp_socketpair +from psutil.tests import TESTFN +from psutil.tests import TOX +from psutil.tests import TRAVIS +from psutil.tests import unittest +from psutil.tests import unix_socket_path +from psutil.tests import unix_socketpair +from psutil.tests import wait_for_file +from psutil.tests import wait_for_pid +import psutil +import psutil.tests + + +# =================================================================== +# --- Misc / generic tests. +# =================================================================== + + +class TestMisc(unittest.TestCase): + + def test_process__repr__(self, func=repr): + p = psutil.Process() + r = func(p) + self.assertIn("psutil.Process", r) + self.assertIn("pid=%s" % p.pid, r) + self.assertIn("name=", r) + self.assertIn(p.name(), r) + with mock.patch.object(psutil.Process, "name", + side_effect=psutil.ZombieProcess(os.getpid())): + p = psutil.Process() + r = func(p) + self.assertIn("pid=%s" % p.pid, r) + self.assertIn("zombie", r) + self.assertNotIn("name=", r) + with mock.patch.object(psutil.Process, "name", + side_effect=psutil.NoSuchProcess(os.getpid())): + p = psutil.Process() + r = func(p) + self.assertIn("pid=%s" % p.pid, r) + self.assertIn("terminated", r) + self.assertNotIn("name=", r) + with mock.patch.object(psutil.Process, "name", + side_effect=psutil.AccessDenied(os.getpid())): + p = psutil.Process() + r = func(p) + self.assertIn("pid=%s" % p.pid, r) + self.assertNotIn("name=", r) + + def test_process__str__(self): + self.test_process__repr__(func=str) + + def test_no_such_process__repr__(self, func=repr): + self.assertEqual( + repr(psutil.NoSuchProcess(321)), + "psutil.NoSuchProcess process no longer exists (pid=321)") + self.assertEqual( + repr(psutil.NoSuchProcess(321, name='foo')), + "psutil.NoSuchProcess process no longer exists (pid=321, " + "name='foo')") + self.assertEqual( + repr(psutil.NoSuchProcess(321, msg='foo')), + "psutil.NoSuchProcess foo") + + def test_zombie_process__repr__(self, func=repr): + self.assertEqual( + repr(psutil.ZombieProcess(321)), + "psutil.ZombieProcess process still exists but it's a zombie " + "(pid=321)") + self.assertEqual( + repr(psutil.ZombieProcess(321, name='foo')), + "psutil.ZombieProcess process still exists but it's a zombie " + "(pid=321, name='foo')") + self.assertEqual( + repr(psutil.ZombieProcess(321, name='foo', ppid=1)), + "psutil.ZombieProcess process still exists but it's a zombie " + "(pid=321, name='foo', ppid=1)") + self.assertEqual( + repr(psutil.ZombieProcess(321, msg='foo')), + "psutil.ZombieProcess foo") + + def test_access_denied__repr__(self, func=repr): + self.assertEqual( + repr(psutil.AccessDenied(321)), + "psutil.AccessDenied (pid=321)") + self.assertEqual( + repr(psutil.AccessDenied(321, name='foo')), + "psutil.AccessDenied (pid=321, name='foo')") + self.assertEqual( + repr(psutil.AccessDenied(321, msg='foo')), + "psutil.AccessDenied foo") + + def test_timeout_expired__repr__(self, func=repr): + self.assertEqual( + repr(psutil.TimeoutExpired(321)), + "psutil.TimeoutExpired timeout after 321 seconds") + self.assertEqual( + repr(psutil.TimeoutExpired(321, pid=111)), + "psutil.TimeoutExpired timeout after 321 seconds (pid=111)") + self.assertEqual( + repr(psutil.TimeoutExpired(321, pid=111, name='foo')), + "psutil.TimeoutExpired timeout after 321 seconds " + "(pid=111, name='foo')") + + def test_process__eq__(self): + p1 = psutil.Process() + p2 = psutil.Process() + self.assertEqual(p1, p2) + p2._ident = (0, 0) + self.assertNotEqual(p1, p2) + self.assertNotEqual(p1, 'foo') + + def test_process__hash__(self): + s = set([psutil.Process(), psutil.Process()]) + self.assertEqual(len(s), 1) + + def test__all__(self): + dir_psutil = dir(psutil) + for name in dir_psutil: + if name in ('callable', 'error', 'namedtuple', 'tests', + 'long', 'test', 'NUM_CPUS', 'BOOT_TIME', + 'TOTAL_PHYMEM'): + continue + if not name.startswith('_'): + try: + __import__(name) + except ImportError: + if name not in psutil.__all__: + fun = getattr(psutil, name) + if fun is None: + continue + if (fun.__doc__ is not None and + 'deprecated' not in fun.__doc__.lower()): + self.fail('%r not in psutil.__all__' % name) + + # Import 'star' will break if __all__ is inconsistent, see: + # https://github.com/giampaolo/psutil/issues/656 + # Can't do `from psutil import *` as it won't work on python 3 + # so we simply iterate over __all__. + for name in psutil.__all__: + self.assertIn(name, dir_psutil) + + def test_version(self): + self.assertEqual('.'.join([str(x) for x in psutil.version_info]), + psutil.__version__) + + def test_process_as_dict_no_new_names(self): + # See https://github.com/giampaolo/psutil/issues/813 + p = psutil.Process() + p.foo = '1' + self.assertNotIn('foo', p.as_dict()) + + def test_memoize(self): + @memoize + def foo(*args, **kwargs): + "foo docstring" + calls.append(None) + return (args, kwargs) + + calls = [] + # no args + for x in range(2): + ret = foo() + expected = ((), {}) + self.assertEqual(ret, expected) + self.assertEqual(len(calls), 1) + # with args + for x 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): + ret = foo(1, bar=2) + expected = ((1, ), {'bar': 2}) + self.assertEqual(ret, expected) + self.assertEqual(len(calls), 3) + # clear cache + foo.cache_clear() + ret = foo() + expected = ((), {}) + self.assertEqual(ret, expected) + self.assertEqual(len(calls), 4) + # docstring + self.assertEqual(foo.__doc__, "foo docstring") + + def test_memoize_when_activated(self): + class Foo: + + @memoize_when_activated + def foo(self): + calls.append(None) + + f = Foo() + calls = [] + f.foo() + f.foo() + self.assertEqual(len(calls), 2) + + # activate + calls = [] + f.foo.cache_activate(f) + f.foo() + f.foo() + self.assertEqual(len(calls), 1) + + # deactivate + calls = [] + f.foo.cache_deactivate(f) + f.foo() + f.foo() + self.assertEqual(len(calls), 2) + + def test_parse_environ_block(self): + from psutil._common import parse_environ_block + + def k(s): + return s.upper() if WINDOWS else s + + self.assertEqual(parse_environ_block("a=1\0"), + {k("a"): "1"}) + self.assertEqual(parse_environ_block("a=1\0b=2\0\0"), + {k("a"): "1", k("b"): "2"}) + self.assertEqual(parse_environ_block("a=1\0b=\0\0"), + {k("a"): "1", k("b"): ""}) + # ignore everything after \0\0 + self.assertEqual(parse_environ_block("a=1\0b=2\0\0c=3\0"), + {k("a"): "1", k("b"): "2"}) + # ignore everything that is not an assignment + self.assertEqual(parse_environ_block("xxx\0a=1\0"), {k("a"): "1"}) + self.assertEqual(parse_environ_block("a=1\0=b=2\0"), {k("a"): "1"}) + # do not fail if the block is incomplete + self.assertEqual(parse_environ_block("a=1\0b=2"), {k("a"): "1"}) + + def test_supports_ipv6(self): + self.addCleanup(supports_ipv6.cache_clear) + if supports_ipv6(): + with mock.patch('psutil._common.socket') as s: + s.has_ipv6 = False + supports_ipv6.cache_clear() + assert not supports_ipv6() + + supports_ipv6.cache_clear() + with mock.patch('psutil._common.socket.socket', + side_effect=socket.error) as s: + assert not supports_ipv6() + assert s.called + + supports_ipv6.cache_clear() + with mock.patch('psutil._common.socket.socket', + side_effect=socket.gaierror) as s: + assert not supports_ipv6() + supports_ipv6.cache_clear() + assert s.called + + supports_ipv6.cache_clear() + with mock.patch('psutil._common.socket.socket.bind', + side_effect=socket.gaierror) as s: + assert not supports_ipv6() + supports_ipv6.cache_clear() + assert s.called + else: + with self.assertRaises(Exception): + sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM) + sock.bind(("::1", 0)) + + def test_isfile_strict(self): + from psutil._common import isfile_strict + this_file = os.path.abspath(__file__) + assert isfile_strict(this_file) + assert not isfile_strict(os.path.dirname(this_file)) + with mock.patch('psutil._common.os.stat', + side_effect=OSError(errno.EPERM, "foo")): + self.assertRaises(OSError, isfile_strict, this_file) + with mock.patch('psutil._common.os.stat', + side_effect=OSError(errno.EACCES, "foo")): + self.assertRaises(OSError, isfile_strict, this_file) + with mock.patch('psutil._common.os.stat', + side_effect=OSError(errno.EINVAL, "foo")): + assert not isfile_strict(this_file) + with mock.patch('psutil._common.stat.S_ISREG', return_value=False): + assert not isfile_strict(this_file) + + def test_serialization(self): + def check(ret): + if json is not None: + json.loads(json.dumps(ret)) + a = pickle.dumps(ret) + b = pickle.loads(a) + self.assertEqual(ret, b) + + check(psutil.Process().as_dict()) + check(psutil.virtual_memory()) + check(psutil.swap_memory()) + check(psutil.cpu_times()) + check(psutil.cpu_times_percent(interval=0)) + check(psutil.net_io_counters()) + if LINUX and not os.path.exists('/proc/diskstats'): + pass + else: + if not APPVEYOR: + check(psutil.disk_io_counters()) + check(psutil.disk_partitions()) + check(psutil.disk_usage(os.getcwd())) + check(psutil.users()) + + def test_setup_script(self): + setup_py = os.path.join(ROOT_DIR, 'setup.py') + if TRAVIS and not os.path.exists(setup_py): + return self.skipTest("can't find setup.py") + module = import_module_by_path(setup_py) + self.assertRaises(SystemExit, module.setup) + self.assertEqual(module.get_version(), psutil.__version__) + + def test_ad_on_process_creation(self): + # We are supposed to be able to instantiate Process also in case + # of zombie processes or access denied. + with mock.patch.object(psutil.Process, 'create_time', + side_effect=psutil.AccessDenied) as meth: + psutil.Process() + assert meth.called + with mock.patch.object(psutil.Process, 'create_time', + side_effect=psutil.ZombieProcess(1)) as meth: + psutil.Process() + assert meth.called + with mock.patch.object(psutil.Process, 'create_time', + side_effect=ValueError) as meth: + with self.assertRaises(ValueError): + psutil.Process() + assert meth.called + + def test_sanity_version_check(self): + # see: https://github.com/giampaolo/psutil/issues/564 + with mock.patch( + "psutil._psplatform.cext.version", return_value="0.0.0"): + with self.assertRaises(ImportError) as cm: + reload_module(psutil) + self.assertIn("version conflict", str(cm.exception).lower()) + + +# =================================================================== +# --- Tests for wrap_numbers() function. +# =================================================================== + + +nt = collections.namedtuple('foo', 'a b c') + + +class TestWrapNumbers(unittest.TestCase): + + def setUp(self): + wrap_numbers.cache_clear() + + tearDown = setUp + + def test_first_call(self): + input = {'disk1': nt(5, 5, 5)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + + def test_input_hasnt_changed(self): + input = {'disk1': nt(5, 5, 5)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + + def test_increase_but_no_wrap(self): + input = {'disk1': nt(5, 5, 5)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + input = {'disk1': nt(10, 15, 20)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + input = {'disk1': nt(20, 25, 30)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + input = {'disk1': nt(20, 25, 30)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + + def test_wrap(self): + # let's say 100 is the threshold + input = {'disk1': nt(100, 100, 100)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + # first wrap restarts from 10 + input = {'disk1': nt(100, 100, 10)} + self.assertEqual(wrap_numbers(input, 'disk_io'), + {'disk1': nt(100, 100, 110)}) + # then it remains the same + input = {'disk1': nt(100, 100, 10)} + self.assertEqual(wrap_numbers(input, 'disk_io'), + {'disk1': nt(100, 100, 110)}) + # then it goes up + input = {'disk1': nt(100, 100, 90)} + self.assertEqual(wrap_numbers(input, 'disk_io'), + {'disk1': nt(100, 100, 190)}) + # then it wraps again + input = {'disk1': nt(100, 100, 20)} + self.assertEqual(wrap_numbers(input, 'disk_io'), + {'disk1': nt(100, 100, 210)}) + # and remains the same + input = {'disk1': nt(100, 100, 20)} + self.assertEqual(wrap_numbers(input, 'disk_io'), + {'disk1': nt(100, 100, 210)}) + # now wrap another num + input = {'disk1': nt(50, 100, 20)} + self.assertEqual(wrap_numbers(input, 'disk_io'), + {'disk1': nt(150, 100, 210)}) + # and again + input = {'disk1': nt(40, 100, 20)} + self.assertEqual(wrap_numbers(input, 'disk_io'), + {'disk1': nt(190, 100, 210)}) + # keep it the same + input = {'disk1': nt(40, 100, 20)} + self.assertEqual(wrap_numbers(input, 'disk_io'), + {'disk1': nt(190, 100, 210)}) + + def test_changing_keys(self): + # Emulate a case where the second call to disk_io() + # (or whatever) provides a new disk, then the new disk + # disappears on the third call. + input = {'disk1': nt(5, 5, 5)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + input = {'disk1': nt(5, 5, 5), + 'disk2': nt(7, 7, 7)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + input = {'disk1': nt(8, 8, 8)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + + def test_changing_keys_w_wrap(self): + input = {'disk1': nt(50, 50, 50), + 'disk2': nt(100, 100, 100)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + # disk 2 wraps + input = {'disk1': nt(50, 50, 50), + 'disk2': nt(100, 100, 10)} + self.assertEqual(wrap_numbers(input, 'disk_io'), + {'disk1': nt(50, 50, 50), + 'disk2': nt(100, 100, 110)}) + # disk 2 disappears + input = {'disk1': nt(50, 50, 50)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + + # then it appears again; the old wrap is supposed to be + # gone. + input = {'disk1': nt(50, 50, 50), + 'disk2': nt(100, 100, 100)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + # remains the same + input = {'disk1': nt(50, 50, 50), + 'disk2': nt(100, 100, 100)} + self.assertEqual(wrap_numbers(input, 'disk_io'), input) + # and then wraps again + input = {'disk1': nt(50, 50, 50), + 'disk2': nt(100, 100, 10)} + self.assertEqual(wrap_numbers(input, 'disk_io'), + {'disk1': nt(50, 50, 50), + 'disk2': nt(100, 100, 110)}) + + def test_real_data(self): + d = {'nvme0n1': (300, 508, 640, 1571, 5970, 1987, 2049, 451751, 47048), + 'nvme0n1p1': (1171, 2, 5600256, 1024, 516, 0, 0, 0, 8), + 'nvme0n1p2': (54, 54, 2396160, 5165056, 4, 24, 30, 1207, 28), + 'nvme0n1p3': (2389, 4539, 5154, 150, 4828, 1844, 2019, 398, 348)} + self.assertEqual(wrap_numbers(d, 'disk_io'), d) + self.assertEqual(wrap_numbers(d, 'disk_io'), d) + # decrease this ↓ + d = {'nvme0n1': (100, 508, 640, 1571, 5970, 1987, 2049, 451751, 47048), + 'nvme0n1p1': (1171, 2, 5600256, 1024, 516, 0, 0, 0, 8), + 'nvme0n1p2': (54, 54, 2396160, 5165056, 4, 24, 30, 1207, 28), + 'nvme0n1p3': (2389, 4539, 5154, 150, 4828, 1844, 2019, 398, 348)} + out = wrap_numbers(d, 'disk_io') + self.assertEqual(out['nvme0n1'][0], 400) + + # --- cache tests + + def test_cache_first_call(self): + input = {'disk1': nt(5, 5, 5)} + wrap_numbers(input, 'disk_io') + cache = wrap_numbers.cache_info() + self.assertEqual(cache[0], {'disk_io': input}) + self.assertEqual(cache[1], {'disk_io': {}}) + self.assertEqual(cache[2], {'disk_io': {}}) + + def test_cache_call_twice(self): + input = {'disk1': nt(5, 5, 5)} + wrap_numbers(input, 'disk_io') + input = {'disk1': nt(10, 10, 10)} + wrap_numbers(input, 'disk_io') + cache = wrap_numbers.cache_info() + self.assertEqual(cache[0], {'disk_io': input}) + self.assertEqual( + cache[1], + {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 0}}) + self.assertEqual(cache[2], {'disk_io': {}}) + + def test_cache_wrap(self): + # let's say 100 is the threshold + input = {'disk1': nt(100, 100, 100)} + wrap_numbers(input, 'disk_io') + + # first wrap restarts from 10 + input = {'disk1': nt(100, 100, 10)} + wrap_numbers(input, 'disk_io') + cache = wrap_numbers.cache_info() + self.assertEqual(cache[0], {'disk_io': input}) + self.assertEqual( + cache[1], + {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 100}}) + self.assertEqual(cache[2], {'disk_io': {'disk1': set([('disk1', 2)])}}) + + def assert_(): + cache = wrap_numbers.cache_info() + self.assertEqual( + cache[1], + {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, + ('disk1', 2): 100}}) + self.assertEqual(cache[2], + {'disk_io': {'disk1': set([('disk1', 2)])}}) + + # then it remains the same + input = {'disk1': nt(100, 100, 10)} + wrap_numbers(input, 'disk_io') + cache = wrap_numbers.cache_info() + self.assertEqual(cache[0], {'disk_io': input}) + assert_() + + # 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_() + + # then it wraps again + input = {'disk1': nt(100, 100, 20)} + wrap_numbers(input, 'disk_io') + cache = wrap_numbers.cache_info() + self.assertEqual(cache[0], {'disk_io': input}) + self.assertEqual( + cache[1], + {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 190}}) + self.assertEqual(cache[2], {'disk_io': {'disk1': set([('disk1', 2)])}}) + + def test_cache_changing_keys(self): + input = {'disk1': nt(5, 5, 5)} + wrap_numbers(input, 'disk_io') + input = {'disk1': nt(5, 5, 5), + 'disk2': nt(7, 7, 7)} + wrap_numbers(input, 'disk_io') + cache = wrap_numbers.cache_info() + self.assertEqual(cache[0], {'disk_io': input}) + self.assertEqual( + cache[1], + {'disk_io': {('disk1', 0): 0, ('disk1', 1): 0, ('disk1', 2): 0}}) + self.assertEqual(cache[2], {'disk_io': {}}) + + def test_cache_clear(self): + input = {'disk1': nt(5, 5, 5)} + wrap_numbers(input, 'disk_io') + wrap_numbers(input, 'disk_io') + wrap_numbers.cache_clear('disk_io') + self.assertEqual(wrap_numbers.cache_info(), ({}, {}, {})) + wrap_numbers.cache_clear('disk_io') + wrap_numbers.cache_clear('?!?') + + @unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported') + def test_cache_clear_public_apis(self): + if not psutil.disk_io_counters() or not psutil.net_io_counters(): + return self.skipTest("no disks or NICs available") + psutil.disk_io_counters() + psutil.net_io_counters() + caches = wrap_numbers.cache_info() + for cache in caches: + self.assertIn('psutil.disk_io_counters', cache) + self.assertIn('psutil.net_io_counters', cache) + + psutil.disk_io_counters.cache_clear() + caches = wrap_numbers.cache_info() + for cache in caches: + self.assertIn('psutil.net_io_counters', cache) + self.assertNotIn('psutil.disk_io_counters', cache) + + psutil.net_io_counters.cache_clear() + caches = wrap_numbers.cache_info() + self.assertEqual(caches, ({}, {}, {})) + + +# =================================================================== +# --- Example script tests +# =================================================================== + + +@unittest.skipIf(TOX, "can't test on TOX") +# See: https://travis-ci.org/giampaolo/psutil/jobs/295224806 +@unittest.skipIf(TRAVIS and not os.path.exists(SCRIPTS_DIR), + "can't locate scripts directory") +class TestScripts(unittest.TestCase): + """Tests for scripts in the "scripts" directory.""" + + @staticmethod + def assert_stdout(exe, *args, **kwargs): + exe = '%s' % os.path.join(SCRIPTS_DIR, exe) + cmd = [PYTHON_EXE, exe] + for arg in args: + cmd.append(arg) + try: + out = sh(cmd, **kwargs).strip() + except RuntimeError as err: + if 'AccessDenied' in str(err): + return str(err) + else: + raise + assert out, out + return out + + @staticmethod + def assert_syntax(exe, args=None): + exe = os.path.join(SCRIPTS_DIR, exe) + if PY3: + f = open(exe, 'rt', encoding='utf8') + else: + f = open(exe, 'rt') + with f: + src = f.read() + ast.parse(src) + + def test_coverage(self): + # make sure all example scripts have a test method defined + meths = dir(self) + for name in os.listdir(SCRIPTS_DIR): + if name.endswith('.py'): + if 'test_' + os.path.splitext(name)[0] not in meths: + # self.assert_stdout(name) + self.fail('no test defined for %r script' + % os.path.join(SCRIPTS_DIR, name)) + + @unittest.skipIf(not POSIX, "POSIX only") + def test_executable(self): + for name in os.listdir(SCRIPTS_DIR): + if name.endswith('.py'): + path = os.path.join(SCRIPTS_DIR, name) + if not stat.S_IXUSR & os.stat(path)[stat.ST_MODE]: + self.fail('%r is not executable' % path) + + def test_disk_usage(self): + self.assert_stdout('disk_usage.py') + + def test_free(self): + self.assert_stdout('free.py') + + def test_meminfo(self): + self.assert_stdout('meminfo.py') + + def test_procinfo(self): + self.assert_stdout('procinfo.py', str(os.getpid())) + + # can't find users on APPVEYOR or TRAVIS + @unittest.skipIf(APPVEYOR or TRAVIS and not psutil.users(), + "unreliable on APPVEYOR or TRAVIS") + def test_who(self): + self.assert_stdout('who.py') + + def test_ps(self): + self.assert_stdout('ps.py') + + def test_pstree(self): + self.assert_stdout('pstree.py') + + def test_netstat(self): + self.assert_stdout('netstat.py') + + # permission denied on travis + @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") + def test_ifconfig(self): + self.assert_stdout('ifconfig.py') + + @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") + def test_pmap(self): + self.assert_stdout('pmap.py', str(os.getpid())) + + def test_procsmem(self): + if 'uss' not in psutil.Process().memory_full_info()._fields: + raise self.skipTest("not supported") + self.assert_stdout('procsmem.py', stderr=DEVNULL) + + def test_killall(self): + self.assert_syntax('killall.py') + + def test_nettop(self): + self.assert_syntax('nettop.py') + + def test_top(self): + self.assert_syntax('top.py') + + def test_iotop(self): + self.assert_syntax('iotop.py') + + def test_pidof(self): + output = self.assert_stdout('pidof.py', psutil.Process().name()) + self.assertIn(str(os.getpid()), output) + + @unittest.skipIf(not WINDOWS, "WINDOWS only") + def test_winservices(self): + self.assert_stdout('winservices.py') + + def test_cpu_distribution(self): + self.assert_syntax('cpu_distribution.py') + + @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") + @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") + def test_temperatures(self): + self.assert_stdout('temperatures.py') + + @unittest.skipIf(not HAS_SENSORS_FANS, "not supported") + @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") + def test_fans(self): + self.assert_stdout('fans.py') + + @unittest.skipIf(not HAS_SENSORS_BATTERY, "not supported") + @unittest.skipIf(not HAS_BATTERY, "no battery") + def test_battery(self): + self.assert_stdout('battery.py') + + def test_sensors(self): + self.assert_stdout('sensors.py') + + +# =================================================================== +# --- Unit tests for test utilities. +# =================================================================== + + +class TestRetryDecorator(unittest.TestCase): + + @mock.patch('time.sleep') + def test_retry_success(self, sleep): + # Fail 3 times out of 5; make sure the decorated fun returns. + + @retry(retries=5, interval=1, logfun=None) + def foo(): + while queue: + queue.pop() + 1 / 0 + return 1 + + queue = list(range(3)) + self.assertEqual(foo(), 1) + self.assertEqual(sleep.call_count, 3) + + @mock.patch('time.sleep') + def test_retry_failure(self, sleep): + # Fail 6 times out of 5; th function is supposed to raise exc. + + @retry(retries=5, interval=1, logfun=None) + def foo(): + while queue: + queue.pop() + 1 / 0 + return 1 + + queue = list(range(6)) + self.assertRaises(ZeroDivisionError, foo) + self.assertEqual(sleep.call_count, 5) + + @mock.patch('time.sleep') + def test_exception_arg(self, sleep): + @retry(exception=ValueError, interval=1) + def foo(): + raise TypeError + + self.assertRaises(TypeError, foo) + self.assertEqual(sleep.call_count, 0) + + @mock.patch('time.sleep') + def test_no_interval_arg(self, sleep): + # if interval is not specified sleep is not supposed to be called + + @retry(retries=5, interval=None, logfun=None) + def foo(): + 1 / 0 + + self.assertRaises(ZeroDivisionError, foo) + self.assertEqual(sleep.call_count, 0) + + @mock.patch('time.sleep') + def test_retries_arg(self, sleep): + + @retry(retries=5, interval=1, logfun=None) + def foo(): + 1 / 0 + + self.assertRaises(ZeroDivisionError, foo) + self.assertEqual(sleep.call_count, 5) + + @mock.patch('time.sleep') + def test_retries_and_timeout_args(self, sleep): + self.assertRaises(ValueError, retry, retries=5, timeout=1) + + +class TestSyncTestUtils(unittest.TestCase): + + def tearDown(self): + safe_rmpath(TESTFN) + + def test_wait_for_pid(self): + wait_for_pid(os.getpid()) + nopid = max(psutil.pids()) + 99999 + with mock.patch('psutil.tests.retry.__iter__', return_value=iter([0])): + self.assertRaises(psutil.NoSuchProcess, wait_for_pid, nopid) + + def test_wait_for_file(self): + with open(TESTFN, 'w') as f: + f.write('foo') + wait_for_file(TESTFN) + assert not os.path.exists(TESTFN) + + def test_wait_for_file_empty(self): + with open(TESTFN, 'w'): + pass + wait_for_file(TESTFN, empty=True) + assert not os.path.exists(TESTFN) + + def test_wait_for_file_no_file(self): + with mock.patch('psutil.tests.retry.__iter__', return_value=iter([0])): + self.assertRaises(IOError, wait_for_file, TESTFN) + + def test_wait_for_file_no_delete(self): + with open(TESTFN, 'w') as f: + f.write('foo') + wait_for_file(TESTFN, delete=False) + assert os.path.exists(TESTFN) + + def test_call_until(self): + ret = call_until(lambda: 1, "ret == 1") + self.assertEqual(ret, 1) + + +class TestFSTestUtils(unittest.TestCase): + + def setUp(self): + safe_rmpath(TESTFN) + + tearDown = setUp + + def test_open_text(self): + with open_text(__file__) as f: + self.assertEqual(f.mode, 'rt') + + def test_open_binary(self): + with open_binary(__file__) as f: + self.assertEqual(f.mode, 'rb') + + def test_safe_mkdir(self): + safe_mkdir(TESTFN) + assert os.path.isdir(TESTFN) + safe_mkdir(TESTFN) + assert os.path.isdir(TESTFN) + + def test_safe_rmpath(self): + # test file is removed + open(TESTFN, 'w').close() + safe_rmpath(TESTFN) + assert not os.path.exists(TESTFN) + # test no exception if path does not exist + safe_rmpath(TESTFN) + # test dir is removed + os.mkdir(TESTFN) + safe_rmpath(TESTFN) + assert not os.path.exists(TESTFN) + # test other exceptions are raised + with mock.patch('psutil.tests.os.stat', + side_effect=OSError(errno.EINVAL, "")) as m: + with self.assertRaises(OSError): + safe_rmpath(TESTFN) + assert m.called + + def test_chdir(self): + base = os.getcwd() + os.mkdir(TESTFN) + with chdir(TESTFN): + self.assertEqual(os.getcwd(), os.path.join(base, TESTFN)) + self.assertEqual(os.getcwd(), base) + + +class TestProcessUtils(unittest.TestCase): + + def test_reap_children(self): + subp = get_test_subprocess() + p = psutil.Process(subp.pid) + assert p.is_running() + reap_children() + assert not p.is_running() + assert not psutil.tests._pids_started + assert not psutil.tests._subprocesses_started + + def test_create_proc_children_pair(self): + p1, p2 = create_proc_children_pair() + self.assertNotEqual(p1.pid, p2.pid) + assert p1.is_running() + assert p2.is_running() + children = psutil.Process().children(recursive=True) + self.assertEqual(len(children), 2) + self.assertIn(p1, children) + self.assertIn(p2, children) + self.assertEqual(p1.ppid(), os.getpid()) + self.assertEqual(p2.ppid(), p1.pid) + + # make sure both of them are cleaned up + reap_children() + assert not p1.is_running() + assert not p2.is_running() + assert not psutil.tests._pids_started + assert not psutil.tests._subprocesses_started + + @unittest.skipIf(not POSIX, "POSIX only") + def test_create_zombie_proc(self): + zpid = create_zombie_proc() + self.addCleanup(reap_children, recursive=True) + p = psutil.Process(zpid) + self.assertEqual(p.status(), psutil.STATUS_ZOMBIE) + + +class TestNetUtils(unittest.TestCase): + + def bind_socket(self): + port = get_free_port() + with contextlib.closing(bind_socket(addr=('', port))) as s: + self.assertEqual(s.getsockname()[1], port) + + @unittest.skipIf(not POSIX, "POSIX only") + def test_bind_unix_socket(self): + with unix_socket_path() as name: + sock = bind_unix_socket(name) + with contextlib.closing(sock): + self.assertEqual(sock.family, socket.AF_UNIX) + self.assertEqual(sock.type, socket.SOCK_STREAM) + self.assertEqual(sock.getsockname(), name) + assert os.path.exists(name) + assert stat.S_ISSOCK(os.stat(name).st_mode) + # UDP + with unix_socket_path() as name: + sock = bind_unix_socket(name, type=socket.SOCK_DGRAM) + with contextlib.closing(sock): + self.assertEqual(sock.type, socket.SOCK_DGRAM) + + def tcp_tcp_socketpair(self): + addr = ("127.0.0.1", get_free_port()) + server, client = tcp_socketpair(socket.AF_INET, addr=addr) + with contextlib.closing(server): + with contextlib.closing(client): + # Ensure they are connected and the positions are + # correct. + self.assertEqual(server.getsockname(), addr) + self.assertEqual(client.getpeername(), addr) + self.assertNotEqual(client.getsockname(), addr) + + @unittest.skipIf(not POSIX, "POSIX only") + def test_unix_socketpair(self): + p = psutil.Process() + num_fds = p.num_fds() + assert not p.connections(kind='unix') + with unix_socket_path() as name: + server, client = unix_socketpair(name) + try: + assert os.path.exists(name) + assert stat.S_ISSOCK(os.stat(name).st_mode) + self.assertEqual(p.num_fds() - num_fds, 2) + self.assertEqual(len(p.connections(kind='unix')), 2) + self.assertEqual(server.getsockname(), name) + self.assertEqual(client.getpeername(), name) + finally: + client.close() + server.close() + + def test_create_sockets(self): + with create_sockets() as socks: + fams = collections.defaultdict(int) + types = collections.defaultdict(int) + for s in socks: + fams[s.family] += 1 + # work around http://bugs.python.org/issue30204 + types[s.getsockopt(socket.SOL_SOCKET, socket.SO_TYPE)] += 1 + self.assertGreaterEqual(fams[socket.AF_INET], 2) + if supports_ipv6(): + self.assertGreaterEqual(fams[socket.AF_INET6], 2) + if POSIX and HAS_CONNECTIONS_UNIX: + self.assertGreaterEqual(fams[socket.AF_UNIX], 2) + self.assertGreaterEqual(types[socket.SOCK_STREAM], 2) + self.assertGreaterEqual(types[socket.SOCK_DGRAM], 2) + + +class TestOtherUtils(unittest.TestCase): + + def test_is_namedtuple(self): + assert is_namedtuple(collections.namedtuple('foo', 'a b c')(1, 2, 3)) + assert not is_namedtuple(tuple()) + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_osx.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_osx.py new file mode 100644 index 00000000..40257190 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_osx.py @@ -0,0 +1,294 @@ +#!/usr/bin/env python + +# 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. + +"""MACOS specific tests.""" + +import os +import re +import time + +import psutil +from psutil import MACOS +from psutil.tests import create_zombie_proc +from psutil.tests import get_test_subprocess +from psutil.tests import HAS_BATTERY +from psutil.tests import MEMORY_TOLERANCE +from psutil.tests import reap_children +from psutil.tests import retry_before_failing +from psutil.tests import run_test_module_by_name +from psutil.tests import sh +from psutil.tests import unittest + + +PAGESIZE = os.sysconf("SC_PAGE_SIZE") if MACOS else None + + +def sysctl(cmdline): + """Expects a sysctl command with an argument and parse the result + returning only the value of interest. + """ + out = sh(cmdline) + result = out.split()[1] + try: + return int(result) + except ValueError: + return result + + +def vm_stat(field): + """Wrapper around 'vm_stat' cmdline utility.""" + out = sh('vm_stat') + for line in out.split('\n'): + if field in line: + break + else: + raise ValueError("line not found") + return int(re.search(r'\d+', line).group(0)) * PAGESIZE + + +# 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(unittest.TestCase): + + @classmethod + def setUpClass(cls): + cls.pid = get_test_subprocess().pid + + @classmethod + def tearDownClass(cls): + reap_children() + + def test_process_create_time(self): + output = sh("ps -o lstart -p %s" % self.pid) + start_ps = output.replace('STARTED', '').strip() + hhmmss = start_ps.split(' ')[-2] + year = start_ps.split(' ')[-1] + start_psutil = psutil.Process(self.pid).create_time() + self.assertEqual( + hhmmss, + time.strftime("%H:%M:%S", time.localtime(start_psutil))) + self.assertEqual( + year, + time.strftime("%Y", time.localtime(start_psutil))) + + +@unittest.skipIf(not MACOS, "MACOS only") +class TestZombieProcessAPIs(unittest.TestCase): + + @classmethod + def setUpClass(cls): + zpid = create_zombie_proc() + cls.p = psutil.Process(zpid) + + @classmethod + def tearDownClass(cls): + reap_children(recursive=True) + + def test_pidtask_info(self): + self.assertEqual(self.p.status(), psutil.STATUS_ZOMBIE) + self.p.ppid() + self.p.uids() + self.p.gids() + self.p.terminal() + self.p.create_time() + + def test_exe(self): + self.assertRaises(psutil.ZombieProcess, self.p.exe) + + def test_cmdline(self): + self.assertRaises(psutil.ZombieProcess, self.p.cmdline) + + def test_environ(self): + self.assertRaises(psutil.ZombieProcess, self.p.environ) + + def test_cwd(self): + self.assertRaises(psutil.ZombieProcess, self.p.cwd) + + def test_memory_full_info(self): + self.assertRaises(psutil.ZombieProcess, self.p.memory_full_info) + + def test_cpu_times(self): + self.assertRaises(psutil.ZombieProcess, self.p.cpu_times) + + def test_num_ctx_switches(self): + self.assertRaises(psutil.ZombieProcess, self.p.num_ctx_switches) + + def test_num_threads(self): + self.assertRaises(psutil.ZombieProcess, self.p.num_threads) + + def test_open_files(self): + self.assertRaises(psutil.ZombieProcess, self.p.open_files) + + def test_connections(self): + self.assertRaises(psutil.ZombieProcess, self.p.connections) + + def test_num_fds(self): + self.assertRaises(psutil.ZombieProcess, self.p.num_fds) + + def test_threads(self): + self.assertRaises((psutil.ZombieProcess, psutil.AccessDenied), + self.p.threads) + + +@unittest.skipIf(not MACOS, "MACOS only") +class TestSystemAPIs(unittest.TestCase): + + # --- disk + + def test_disks(self): + # test psutil.disk_usage() and psutil.disk_partitions() + # against "df -a" + def df(path): + out = sh('df -k "%s"' % path).strip() + lines = out.split('\n') + lines.pop(0) + line = lines.pop(0) + dev, total, used, free = line.split()[:4] + if dev == 'none': + dev = '' + total = int(total) * 1024 + used = int(used) * 1024 + free = int(free) * 1024 + return dev, total, used, free + + for part in psutil.disk_partitions(all=False): + usage = psutil.disk_usage(part.mountpoint) + dev, total, used, free = df(part.mountpoint) + self.assertEqual(part.device, dev) + self.assertEqual(usage.total, total) + # 10 MB tollerance + if abs(usage.free - free) > 10 * 1024 * 1024: + self.fail("psutil=%s, df=%s" % usage.free, free) + if abs(usage.used - used) > 10 * 1024 * 1024: + self.fail("psutil=%s, df=%s" % usage.used, used) + + # --- cpu + + def test_cpu_count_logical(self): + num = sysctl("sysctl hw.logicalcpu") + self.assertEqual(num, psutil.cpu_count(logical=True)) + + def test_cpu_count_physical(self): + num = sysctl("sysctl hw.physicalcpu") + self.assertEqual(num, psutil.cpu_count(logical=False)) + + def test_cpu_freq(self): + freq = psutil.cpu_freq() + self.assertEqual( + freq.current * 1000 * 1000, sysctl("sysctl hw.cpufrequency")) + self.assertEqual( + freq.min * 1000 * 1000, sysctl("sysctl hw.cpufrequency_min")) + self.assertEqual( + freq.max * 1000 * 1000, sysctl("sysctl hw.cpufrequency_max")) + + # --- virtual mem + + def test_vmem_total(self): + sysctl_hwphymem = sysctl('sysctl hw.memsize') + self.assertEqual(sysctl_hwphymem, psutil.virtual_memory().total) + + @retry_before_failing() + def test_vmem_free(self): + vmstat_val = vm_stat("free") + psutil_val = psutil.virtual_memory().free + self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE) + + @retry_before_failing() + def test_vmem_active(self): + vmstat_val = vm_stat("active") + psutil_val = psutil.virtual_memory().active + self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE) + + @retry_before_failing() + def test_vmem_inactive(self): + vmstat_val = vm_stat("inactive") + psutil_val = psutil.virtual_memory().inactive + self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE) + + @retry_before_failing() + def test_vmem_wired(self): + vmstat_val = vm_stat("wired") + psutil_val = psutil.virtual_memory().wired + self.assertAlmostEqual(psutil_val, vmstat_val, delta=MEMORY_TOLERANCE) + + # --- swap mem + + @retry_before_failing() + def test_swapmem_sin(self): + vmstat_val = vm_stat("Pageins") + psutil_val = psutil.swap_memory().sin + self.assertEqual(psutil_val, vmstat_val) + + @retry_before_failing() + def test_swapmem_sout(self): + vmstat_val = vm_stat("Pageout") + psutil_val = psutil.swap_memory().sout + self.assertEqual(psutil_val, vmstat_val) + + # 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): + for name, stats in psutil.net_if_stats().items(): + try: + out = sh("ifconfig %s" % name) + except RuntimeError: + pass + else: + self.assertEqual(stats.isup, 'RUNNING' in out, msg=out) + self.assertEqual(stats.mtu, + int(re.findall(r'mtu (\d+)', out)[0])) + + # --- sensors_battery + + @unittest.skipIf(not HAS_BATTERY, "no battery") + def test_sensors_battery(self): + out = sh("pmset -g batt") + percent = re.search(r"(\d+)%", out).group(1) + drawing_from = re.search("Now drawing from '([^']+)'", out).group(1) + power_plugged = drawing_from == "AC Power" + psutil_result = psutil.sensors_battery() + self.assertEqual(psutil_result.power_plugged, power_plugged) + self.assertEqual(psutil_result.percent, int(percent)) + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_posix.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_posix.py new file mode 100644 index 00000000..79931283 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_posix.py @@ -0,0 +1,440 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# 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. + +"""POSIX specific tests.""" + +import datetime +import errno +import os +import re +import subprocess +import time + +import psutil +from psutil import AIX +from psutil import BSD +from psutil import LINUX +from psutil import MACOS +from psutil import OPENBSD +from psutil import POSIX +from psutil import SUNOS +from psutil.tests import APPVEYOR +from psutil.tests import get_kernel_version +from psutil.tests import get_test_subprocess +from psutil.tests import HAS_NET_IO_COUNTERS +from psutil.tests import mock +from psutil.tests import PYTHON_EXE +from psutil.tests import reap_children +from psutil.tests import retry_before_failing +from psutil.tests import run_test_module_by_name +from psutil.tests import sh +from psutil.tests import skip_on_access_denied +from psutil.tests import TRAVIS +from psutil.tests import unittest +from psutil.tests import wait_for_pid +from psutil.tests import which + + +def ps(fmt, pid=None): + """ + Wrapper for calling the ps command with a little bit of cross-platform + support for a narrow range of features. + """ + + cmd = ['ps'] + + if LINUX: + cmd.append('--no-headers') + + if pid is not None: + cmd.extend(['-p', str(pid)]) + else: + if SUNOS: + cmd.append('-A') + else: + cmd.append('ax') + + if SUNOS: + fmt_map = {'command', 'comm', + 'start', 'stime'} + fmt = fmt_map.get(fmt, fmt) + + cmd.extend(['-o', fmt]) + + output = sh(cmd) + + if LINUX: + output = output.splitlines() + else: + output = output.splitlines()[1:] + + all_output = [] + for line in output: + line = line.strip() + + try: + line = int(line) + except ValueError: + pass + + all_output.append(line) + + if pid is None: + return all_output + else: + return all_output[0] + +# ps "-o" field names differ wildly between platforms. +# "comm" means "only executable name" but is not available on BSD platforms. +# "args" means "command with all its arguments", and is also not available +# on BSD platforms. +# "command" is like "args" on most platforms, but like "comm" on AIX, +# and not available on SUNOS. +# so for the executable name we can use "comm" on Solaris and split "command" +# on other platforms. +# to get the cmdline (with args) we have to use "args" on AIX and +# Solaris, and can use "command" on all others. + + +def ps_name(pid): + field = "command" + if SUNOS: + field = "comm" + return ps(field, pid).split()[0] + + +def ps_args(pid): + field = "command" + if AIX or SUNOS: + field = "args" + return ps(field, pid) + + +@unittest.skipIf(not POSIX, "POSIX only") +class TestProcess(unittest.TestCase): + """Compare psutil results against 'ps' command line utility (mainly).""" + + @classmethod + def setUpClass(cls): + cls.pid = get_test_subprocess([PYTHON_EXE, "-E", "-O"], + stdin=subprocess.PIPE).pid + wait_for_pid(cls.pid) + + @classmethod + def tearDownClass(cls): + reap_children() + + def test_ppid(self): + ppid_ps = ps('ppid', self.pid) + ppid_psutil = psutil.Process(self.pid).ppid() + self.assertEqual(ppid_ps, ppid_psutil) + + def test_uid(self): + uid_ps = ps('uid', self.pid) + uid_psutil = psutil.Process(self.pid).uids().real + self.assertEqual(uid_ps, uid_psutil) + + def test_gid(self): + gid_ps = ps('rgid', self.pid) + gid_psutil = psutil.Process(self.pid).gids().real + self.assertEqual(gid_ps, gid_psutil) + + def test_username(self): + username_ps = ps('user', self.pid) + username_psutil = psutil.Process(self.pid).username() + self.assertEqual(username_ps, username_psutil) + + def test_username_no_resolution(self): + # Emulate a case where the system can't resolve the uid to + # a username in which case psutil is supposed to return + # the stringified uid. + p = psutil.Process() + with mock.patch("psutil.pwd.getpwuid", side_effect=KeyError) as fun: + self.assertEqual(p.username(), str(p.uids().real)) + assert fun.called + + @skip_on_access_denied() + @retry_before_failing() + def test_rss_memory(self): + # give python interpreter some time to properly initialize + # so that the results are the same + time.sleep(0.1) + rss_ps = ps('rss', self.pid) + rss_psutil = psutil.Process(self.pid).memory_info()[0] / 1024 + self.assertEqual(rss_ps, rss_psutil) + + @skip_on_access_denied() + @retry_before_failing() + def test_vsz_memory(self): + # give python interpreter some time to properly initialize + # so that the results are the same + time.sleep(0.1) + vsz_ps = ps('vsz', self.pid) + vsz_psutil = psutil.Process(self.pid).memory_info()[1] / 1024 + self.assertEqual(vsz_ps, vsz_psutil) + + def test_name(self): + name_ps = ps_name(self.pid) + # remove path if there is any, from the command + name_ps = os.path.basename(name_ps).lower() + name_psutil = psutil.Process(self.pid).name().lower() + # ...because of how we calculate PYTHON_EXE; on MACOS this may + # be "pythonX.Y". + name_ps = re.sub(r"\d.\d", "", name_ps) + name_psutil = re.sub(r"\d.\d", "", name_psutil) + # ...may also be "python.X" + name_ps = re.sub(r"\d", "", name_ps) + name_psutil = re.sub(r"\d", "", name_psutil) + self.assertEqual(name_ps, name_psutil) + + def test_name_long(self): + # On UNIX the kernel truncates the name to the first 15 + # characters. In such a case psutil tries to determine the + # full name from the cmdline. + name = "long-program-name" + cmdline = ["long-program-name-extended", "foo", "bar"] + with mock.patch("psutil._psplatform.Process.name", + return_value=name): + with mock.patch("psutil._psplatform.Process.cmdline", + return_value=cmdline): + p = psutil.Process() + self.assertEqual(p.name(), "long-program-name-extended") + + def test_name_long_cmdline_ad_exc(self): + # Same as above but emulates a case where cmdline() raises + # AccessDenied in which case psutil is supposed to return + # the truncated name instead of crashing. + name = "long-program-name" + with mock.patch("psutil._psplatform.Process.name", + return_value=name): + with mock.patch("psutil._psplatform.Process.cmdline", + side_effect=psutil.AccessDenied(0, "")): + p = psutil.Process() + self.assertEqual(p.name(), "long-program-name") + + def test_name_long_cmdline_nsp_exc(self): + # Same as above but emulates a case where cmdline() raises NSP + # which is supposed to propagate. + name = "long-program-name" + with mock.patch("psutil._psplatform.Process.name", + return_value=name): + with mock.patch("psutil._psplatform.Process.cmdline", + side_effect=psutil.NoSuchProcess(0, "")): + p = psutil.Process() + self.assertRaises(psutil.NoSuchProcess, p.name) + + @unittest.skipIf(MACOS or BSD, 'ps -o start not available') + def test_create_time(self): + time_ps = ps('start', self.pid) + time_psutil = psutil.Process(self.pid).create_time() + time_psutil_tstamp = datetime.datetime.fromtimestamp( + time_psutil).strftime("%H:%M:%S") + # sometimes ps shows the time rounded up instead of down, so we check + # for both possible values + round_time_psutil = round(time_psutil) + round_time_psutil_tstamp = datetime.datetime.fromtimestamp( + round_time_psutil).strftime("%H:%M:%S") + self.assertIn(time_ps, [time_psutil_tstamp, round_time_psutil_tstamp]) + + def test_exe(self): + ps_pathname = ps_name(self.pid) + psutil_pathname = psutil.Process(self.pid).exe() + try: + self.assertEqual(ps_pathname, psutil_pathname) + except AssertionError: + # certain platforms such as BSD are more accurate returning: + # "/usr/local/bin/python2.7" + # ...instead of: + # "/usr/local/bin/python" + # We do not want to consider this difference in accuracy + # an error. + adjusted_ps_pathname = ps_pathname[:len(ps_pathname)] + self.assertEqual(ps_pathname, adjusted_ps_pathname) + + def test_cmdline(self): + ps_cmdline = ps_args(self.pid) + psutil_cmdline = " ".join(psutil.Process(self.pid).cmdline()) + self.assertEqual(ps_cmdline, psutil_cmdline) + + # On SUNOS "ps" reads niceness /proc/pid/psinfo which returns an + # incorrect value (20); the real deal is getpriority(2) which + # returns 0; psutil relies on it, see: + # https://github.com/giampaolo/psutil/issues/1082 + # AIX has the same issue + @unittest.skipIf(SUNOS, "not reliable on SUNOS") + @unittest.skipIf(AIX, "not reliable on AIX") + def test_nice(self): + ps_nice = ps('nice', self.pid) + psutil_nice = psutil.Process().nice() + self.assertEqual(ps_nice, psutil_nice) + + def test_num_fds(self): + # Note: this fails from time to time; I'm keen on thinking + # it doesn't mean something is broken + def call(p, attr): + args = () + attr = getattr(p, name, None) + if attr is not None and callable(attr): + if name == 'rlimit': + args = (psutil.RLIMIT_NOFILE,) + attr(*args) + else: + attr + + p = psutil.Process(os.getpid()) + failures = [] + ignored_names = ['terminate', 'kill', 'suspend', 'resume', 'nice', + 'send_signal', 'wait', 'children', 'as_dict', + 'memory_info_ex', 'parent', 'parents'] + if LINUX and get_kernel_version() < (2, 6, 36): + ignored_names.append('rlimit') + if LINUX and get_kernel_version() < (2, 6, 23): + ignored_names.append('num_ctx_switches') + for name in dir(psutil.Process): + if (name.startswith('_') or name in ignored_names): + continue + else: + try: + num1 = p.num_fds() + for x in range(2): + call(p, name) + num2 = p.num_fds() + except psutil.AccessDenied: + pass + else: + if abs(num2 - num1) > 1: + fail = "failure while processing Process.%s method " \ + "(before=%s, after=%s)" % (name, num1, num2) + failures.append(fail) + if failures: + self.fail('\n' + '\n'.join(failures)) + + +@unittest.skipIf(not POSIX, "POSIX only") +class TestSystemAPIs(unittest.TestCase): + """Test some system APIs.""" + + @retry_before_failing() + def test_pids(self): + # Note: this test might fail if the OS is starting/killing + # other processes in the meantime + pids_ps = sorted(ps("pid")) + pids_psutil = psutil.pids() + + # on MACOS and OPENBSD ps doesn't show pid 0 + if MACOS or OPENBSD and 0 not in pids_ps: + pids_ps.insert(0, 0) + + # There will often be one more process in pids_ps for ps itself + if len(pids_ps) - len(pids_psutil) > 1: + difference = [x for x in pids_psutil if x not in pids_ps] + \ + [x for x in pids_ps if x not in pids_psutil] + self.fail("difference: " + str(difference)) + + # for some reason ifconfig -a does not report all interfaces + # returned by psutil + @unittest.skipIf(SUNOS, "unreliable on SUNOS") + @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") + @unittest.skipIf(not which('ifconfig'), "no ifconfig cmd") + @unittest.skipIf(not HAS_NET_IO_COUNTERS, "not supported") + def test_nic_names(self): + output = sh("ifconfig -a") + for nic in psutil.net_io_counters(pernic=True).keys(): + for line in output.split(): + if line.startswith(nic): + break + else: + self.fail( + "couldn't find %s nic in 'ifconfig -a' output\n%s" % ( + nic, output)) + + # can't find users on APPVEYOR or TRAVIS + @unittest.skipIf(APPVEYOR or TRAVIS and not psutil.users(), + "unreliable on APPVEYOR or TRAVIS") + @retry_before_failing() + def test_users(self): + out = sh("who") + lines = out.split('\n') + users = [x.split()[0] for x in lines] + terminals = [x.split()[1] for x in lines] + self.assertEqual(len(users), len(psutil.users())) + for u in psutil.users(): + self.assertIn(u.name, users) + self.assertIn(u.terminal, terminals) + + def test_pid_exists_let_raise(self): + # According to "man 2 kill" possible error values for kill + # are (EINVAL, EPERM, ESRCH). Test that any other errno + # results in an exception. + with mock.patch("psutil._psposix.os.kill", + side_effect=OSError(errno.EBADF, "")) as m: + self.assertRaises(OSError, psutil._psposix.pid_exists, os.getpid()) + assert m.called + + def test_os_waitpid_let_raise(self): + # os.waitpid() is supposed to catch EINTR and ECHILD only. + # Test that any other errno results in an exception. + with mock.patch("psutil._psposix.os.waitpid", + side_effect=OSError(errno.EBADF, "")) as m: + self.assertRaises(OSError, psutil._psposix.wait_pid, os.getpid()) + assert m.called + + def test_os_waitpid_eintr(self): + # os.waitpid() is supposed to "retry" on EINTR. + with mock.patch("psutil._psposix.os.waitpid", + side_effect=OSError(errno.EINTR, "")) as m: + self.assertRaises( + psutil._psposix.TimeoutExpired, + psutil._psposix.wait_pid, os.getpid(), timeout=0.01) + assert m.called + + def test_os_waitpid_bad_ret_status(self): + # Simulate os.waitpid() returning a bad status. + with mock.patch("psutil._psposix.os.waitpid", + return_value=(1, -1)) as m: + self.assertRaises(ValueError, + psutil._psposix.wait_pid, os.getpid()) + assert m.called + + # AIX can return '-' in df output instead of numbers, e.g. for /proc + @unittest.skipIf(AIX, "unreliable on AIX") + def test_disk_usage(self): + def df(device): + out = sh("df -k %s" % device).strip() + line = out.split('\n')[1] + fields = line.split() + total = int(fields[1]) * 1024 + used = int(fields[2]) * 1024 + free = int(fields[3]) * 1024 + percent = float(fields[4].replace('%', '')) + return (total, used, free, percent) + + tolerance = 4 * 1024 * 1024 # 4MB + for part in psutil.disk_partitions(all=False): + usage = psutil.disk_usage(part.mountpoint) + try: + total, used, free, percent = df(part.device) + except RuntimeError as err: + # see: + # https://travis-ci.org/giampaolo/psutil/jobs/138338464 + # https://travis-ci.org/giampaolo/psutil/jobs/138343361 + err = str(err).lower() + if "no such file or directory" in err or \ + "raw devices not supported" in err or \ + "permission denied" in err: + continue + else: + raise + else: + self.assertAlmostEqual(usage.total, total, delta=tolerance) + self.assertAlmostEqual(usage.used, used, delta=tolerance) + self.assertAlmostEqual(usage.free, free, delta=tolerance) + self.assertAlmostEqual(usage.percent, percent, delta=1) + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_process.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_process.py new file mode 100644 index 00000000..2af676ba --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_process.py @@ -0,0 +1,1611 @@ +#!/usr/bin/env python + +# 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. + +"""Tests for psutil.Process class.""" + +import collections +import errno +import getpass +import itertools +import os +import signal +import socket +import subprocess +import sys +import tempfile +import textwrap +import time +import types + +import psutil + +from psutil import AIX +from psutil import BSD +from psutil import LINUX +from psutil import MACOS +from psutil import NETBSD +from psutil import OPENBSD +from psutil import OSX +from psutil import POSIX +from psutil import SUNOS +from psutil import WINDOWS +from psutil._common import open_text +from psutil._compat import long +from psutil._compat import PY3 +from psutil.tests import APPVEYOR +from psutil.tests import call_until +from psutil.tests import copyload_shared_lib +from psutil.tests import create_exe +from psutil.tests import create_proc_children_pair +from psutil.tests import create_zombie_proc +from psutil.tests import enum +from psutil.tests import get_test_subprocess +from psutil.tests import get_winver +from psutil.tests import HAS_CPU_AFFINITY +from psutil.tests import HAS_ENVIRON +from psutil.tests import HAS_IONICE +from psutil.tests import HAS_MEMORY_MAPS +from psutil.tests import HAS_PROC_CPU_NUM +from psutil.tests import HAS_PROC_IO_COUNTERS +from psutil.tests import HAS_RLIMIT +from psutil.tests import HAS_THREADS +from psutil.tests import mock +from psutil.tests import PYPY +from psutil.tests import PYTHON_EXE +from psutil.tests import reap_children +from psutil.tests import retry_before_failing +from psutil.tests import run_test_module_by_name +from psutil.tests import safe_rmpath +from psutil.tests import sh +from psutil.tests import skip_on_access_denied +from psutil.tests import skip_on_not_implemented +from psutil.tests import TESTFILE_PREFIX +from psutil.tests import TESTFN +from psutil.tests import ThreadTask +from psutil.tests import TRAVIS +from psutil.tests import unittest +from psutil.tests import wait_for_pid +from psutil.tests import WIN_VISTA + + +# =================================================================== +# --- psutil.Process class tests +# =================================================================== + +class TestProcess(unittest.TestCase): + """Tests for psutil.Process class.""" + + def setUp(self): + safe_rmpath(TESTFN) + + def tearDown(self): + reap_children() + + def test_pid(self): + p = psutil.Process() + self.assertEqual(p.pid, os.getpid()) + sproc = get_test_subprocess() + self.assertEqual(psutil.Process(sproc.pid).pid, sproc.pid) + with self.assertRaises(AttributeError): + p.pid = 33 + + def test_kill(self): + sproc = get_test_subprocess() + test_pid = sproc.pid + p = psutil.Process(test_pid) + p.kill() + sig = p.wait() + self.assertFalse(psutil.pid_exists(test_pid)) + if POSIX: + self.assertEqual(sig, -signal.SIGKILL) + + def test_terminate(self): + sproc = get_test_subprocess() + test_pid = sproc.pid + p = psutil.Process(test_pid) + p.terminate() + sig = p.wait() + self.assertFalse(psutil.pid_exists(test_pid)) + if POSIX: + self.assertEqual(sig, -signal.SIGTERM) + + def test_send_signal(self): + sig = signal.SIGKILL if POSIX else signal.SIGTERM + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + p.send_signal(sig) + exit_sig = p.wait() + self.assertFalse(psutil.pid_exists(p.pid)) + if POSIX: + self.assertEqual(exit_sig, -sig) + # + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + p.send_signal(sig) + with mock.patch('psutil.os.kill', + side_effect=OSError(errno.ESRCH, "")): + with self.assertRaises(psutil.NoSuchProcess): + p.send_signal(sig) + # + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + p.send_signal(sig) + with mock.patch('psutil.os.kill', + side_effect=OSError(errno.EPERM, "")): + with self.assertRaises(psutil.AccessDenied): + psutil.Process().send_signal(sig) + # Sending a signal to process with PID 0 is not allowed as + # it would affect every process in the process group of + # the calling process (os.getpid()) instead of PID 0"). + if 0 in psutil.pids(): + p = psutil.Process(0) + self.assertRaises(ValueError, p.send_signal, signal.SIGTERM) + + def test_wait(self): + # check exit code signal + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + p.kill() + code = p.wait() + if POSIX: + self.assertEqual(code, -signal.SIGKILL) + else: + self.assertEqual(code, signal.SIGTERM) + self.assertFalse(p.is_running()) + + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + p.terminate() + code = p.wait() + if POSIX: + self.assertEqual(code, -signal.SIGTERM) + else: + self.assertEqual(code, signal.SIGTERM) + self.assertFalse(p.is_running()) + + # check sys.exit() code + code = "import time, sys; time.sleep(0.01); sys.exit(5);" + sproc = get_test_subprocess([PYTHON_EXE, "-c", code]) + p = psutil.Process(sproc.pid) + self.assertEqual(p.wait(), 5) + self.assertFalse(p.is_running()) + + # Test wait() issued twice. + # It is not supposed to raise NSP when the process is gone. + # On UNIX this should return None, on Windows it should keep + # returning the exit code. + sproc = get_test_subprocess([PYTHON_EXE, "-c", code]) + p = psutil.Process(sproc.pid) + self.assertEqual(p.wait(), 5) + self.assertIn(p.wait(), (5, None)) + + # test timeout + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + p.name() + self.assertRaises(psutil.TimeoutExpired, p.wait, 0.01) + + # timeout < 0 not allowed + self.assertRaises(ValueError, p.wait, -1) + + def test_wait_non_children(self): + # Test wait() against a process which is not our direct + # child. + p1, p2 = create_proc_children_pair() + self.assertRaises(psutil.TimeoutExpired, p1.wait, 0.01) + self.assertRaises(psutil.TimeoutExpired, p2.wait, 0.01) + # We also terminate the direct child otherwise the + # grandchild will hang until the parent is gone. + p1.terminate() + p2.terminate() + ret1 = p1.wait() + ret2 = p2.wait() + if POSIX: + self.assertEqual(ret1, -signal.SIGTERM) + # For processes which are not our children we're supposed + # to get None. + self.assertEqual(ret2, None) + else: + self.assertEqual(ret1, signal.SIGTERM) + self.assertEqual(ret1, signal.SIGTERM) + + def test_wait_timeout_0(self): + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + self.assertRaises(psutil.TimeoutExpired, p.wait, 0) + p.kill() + stop_at = time.time() + 2 + while True: + try: + code = p.wait(0) + except psutil.TimeoutExpired: + if time.time() >= stop_at: + raise + else: + break + if POSIX: + self.assertEqual(code, -signal.SIGKILL) + else: + self.assertEqual(code, signal.SIGTERM) + self.assertFalse(p.is_running()) + + def test_cpu_percent(self): + p = psutil.Process() + p.cpu_percent(interval=0.001) + p.cpu_percent(interval=0.001) + for x in range(100): + percent = p.cpu_percent(interval=None) + self.assertIsInstance(percent, float) + self.assertGreaterEqual(percent, 0.0) + with self.assertRaises(ValueError): + p.cpu_percent(interval=-1) + + def test_cpu_percent_numcpus_none(self): + # See: https://github.com/giampaolo/psutil/issues/1087 + with mock.patch('psutil.cpu_count', return_value=None) as m: + psutil.Process().cpu_percent() + assert m.called + + def test_cpu_times(self): + times = psutil.Process().cpu_times() + assert (times.user > 0.0) or (times.system > 0.0), times + assert (times.children_user >= 0.0), times + assert (times.children_system >= 0.0), times + # make sure returned values can be pretty printed with strftime + for name in times._fields: + time.strftime("%H:%M:%S", time.localtime(getattr(times, name))) + + def test_cpu_times_2(self): + user_time, kernel_time = psutil.Process().cpu_times()[:2] + utime, ktime = os.times()[:2] + + # Use os.times()[:2] as base values to compare our results + # using a tolerance of +/- 0.1 seconds. + # It will fail if the difference between the values is > 0.1s. + if (max([user_time, utime]) - min([user_time, utime])) > 0.1: + self.fail("expected: %s, found: %s" % (utime, user_time)) + + if (max([kernel_time, ktime]) - min([kernel_time, ktime])) > 0.1: + self.fail("expected: %s, found: %s" % (ktime, kernel_time)) + + @unittest.skipIf(not HAS_PROC_CPU_NUM, "not supported") + def test_cpu_num(self): + p = psutil.Process() + num = p.cpu_num() + self.assertGreaterEqual(num, 0) + if psutil.cpu_count() == 1: + self.assertEqual(num, 0) + self.assertIn(p.cpu_num(), range(psutil.cpu_count())) + + def test_create_time(self): + sproc = get_test_subprocess() + now = time.time() + p = psutil.Process(sproc.pid) + create_time = p.create_time() + + # Use time.time() as base value to compare our result using a + # tolerance of +/- 1 second. + # It will fail if the difference between the values is > 2s. + difference = abs(create_time - now) + if difference > 2: + self.fail("expected: %s, found: %s, difference: %s" + % (now, create_time, difference)) + + # make sure returned value can be pretty printed with strftime + time.strftime("%Y %m %d %H:%M:%S", time.localtime(p.create_time())) + + @unittest.skipIf(not POSIX, 'POSIX only') + @unittest.skipIf(TRAVIS, 'not reliable on TRAVIS') + def test_terminal(self): + terminal = psutil.Process().terminal() + if sys.stdin.isatty() or sys.stdout.isatty(): + tty = os.path.realpath(sh('tty')) + self.assertEqual(terminal, tty) + else: + self.assertIsNone(terminal) + + @unittest.skipIf(not HAS_PROC_IO_COUNTERS, 'not supported') + @skip_on_not_implemented(only_if=LINUX) + def test_io_counters(self): + p = psutil.Process() + + # test reads + io1 = p.io_counters() + with open(PYTHON_EXE, 'rb') as f: + f.read() + io2 = p.io_counters() + if not BSD and not AIX: + self.assertGreater(io2.read_count, io1.read_count) + self.assertEqual(io2.write_count, io1.write_count) + if LINUX: + self.assertGreater(io2.read_chars, io1.read_chars) + self.assertEqual(io2.write_chars, io1.write_chars) + else: + self.assertGreaterEqual(io2.read_bytes, io1.read_bytes) + self.assertGreaterEqual(io2.write_bytes, io1.write_bytes) + + # test writes + io1 = p.io_counters() + with tempfile.TemporaryFile(prefix=TESTFILE_PREFIX) as f: + if PY3: + f.write(bytes("x" * 1000000, 'ascii')) + else: + f.write("x" * 1000000) + io2 = p.io_counters() + self.assertGreaterEqual(io2.write_count, io1.write_count) + self.assertGreaterEqual(io2.write_bytes, io1.write_bytes) + self.assertGreaterEqual(io2.read_count, io1.read_count) + self.assertGreaterEqual(io2.read_bytes, io1.read_bytes) + if LINUX: + self.assertGreater(io2.write_chars, io1.write_chars) + self.assertGreaterEqual(io2.read_chars, io1.read_chars) + + # sanity check + for i in range(len(io2)): + if BSD and i >= 2: + # On BSD read_bytes and write_bytes are always set to -1. + continue + self.assertGreaterEqual(io2[i], 0) + self.assertGreaterEqual(io2[i], 0) + + @unittest.skipIf(not HAS_IONICE, "not supported") + @unittest.skipIf(WINDOWS and get_winver() < WIN_VISTA, 'not supported') + def test_ionice(self): + if LINUX: + from psutil import (IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, + IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE) + self.assertEqual(IOPRIO_CLASS_NONE, 0) + self.assertEqual(IOPRIO_CLASS_RT, 1) + self.assertEqual(IOPRIO_CLASS_BE, 2) + self.assertEqual(IOPRIO_CLASS_IDLE, 3) + p = psutil.Process() + try: + p.ionice(2) + ioclass, value = p.ionice() + if enum is not None: + self.assertIsInstance(ioclass, enum.IntEnum) + self.assertEqual(ioclass, 2) + self.assertEqual(value, 4) + # + p.ionice(3) + ioclass, value = p.ionice() + self.assertEqual(ioclass, 3) + self.assertEqual(value, 0) + # + p.ionice(2, 0) + ioclass, value = p.ionice() + self.assertEqual(ioclass, 2) + self.assertEqual(value, 0) + p.ionice(2, 7) + ioclass, value = p.ionice() + self.assertEqual(ioclass, 2) + self.assertEqual(value, 7) + finally: + p.ionice(IOPRIO_CLASS_NONE) + else: + p = psutil.Process() + original = p.ionice() + self.assertIsInstance(original, int) + try: + value = 0 # very low + if original == value: + value = 1 # low + p.ionice(value) + self.assertEqual(p.ionice(), value) + finally: + p.ionice(original) + + @unittest.skipIf(not HAS_IONICE, "not supported") + @unittest.skipIf(WINDOWS and get_winver() < WIN_VISTA, 'not supported') + def test_ionice_errs(self): + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + if LINUX: + self.assertRaises(ValueError, p.ionice, 2, 10) + self.assertRaises(ValueError, p.ionice, 2, -1) + self.assertRaises(ValueError, p.ionice, 4) + self.assertRaises(TypeError, p.ionice, 2, "foo") + self.assertRaisesRegex( + ValueError, "can't specify value with IOPRIO_CLASS_NONE", + p.ionice, psutil.IOPRIO_CLASS_NONE, 1) + self.assertRaisesRegex( + ValueError, "can't specify value with IOPRIO_CLASS_IDLE", + p.ionice, psutil.IOPRIO_CLASS_IDLE, 1) + self.assertRaisesRegex( + ValueError, "'ioclass' argument must be specified", + p.ionice, value=1) + else: + self.assertRaises(ValueError, p.ionice, 3) + self.assertRaises(TypeError, p.ionice, 2, 1) + + @unittest.skipIf(not HAS_RLIMIT, "not supported") + def test_rlimit_get(self): + import resource + p = psutil.Process(os.getpid()) + names = [x for x in dir(psutil) if x.startswith('RLIMIT')] + assert names, names + for name in names: + value = getattr(psutil, name) + self.assertGreaterEqual(value, 0) + if name in dir(resource): + self.assertEqual(value, getattr(resource, name)) + # XXX - On PyPy RLIMIT_INFINITY returned by + # resource.getrlimit() is reported as a very big long + # number instead of -1. It looks like a bug with PyPy. + if PYPY: + continue + self.assertEqual(p.rlimit(value), resource.getrlimit(value)) + else: + ret = p.rlimit(value) + self.assertEqual(len(ret), 2) + self.assertGreaterEqual(ret[0], -1) + self.assertGreaterEqual(ret[1], -1) + + @unittest.skipIf(not HAS_RLIMIT, "not supported") + def test_rlimit_set(self): + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) + self.assertEqual(p.rlimit(psutil.RLIMIT_NOFILE), (5, 5)) + # If pid is 0 prlimit() applies to the calling process and + # we don't want that. + with self.assertRaises(ValueError): + psutil._psplatform.Process(0).rlimit(0) + with self.assertRaises(ValueError): + p.rlimit(psutil.RLIMIT_NOFILE, (5, 5, 5)) + + @unittest.skipIf(not HAS_RLIMIT, "not supported") + def test_rlimit(self): + p = psutil.Process() + soft, hard = p.rlimit(psutil.RLIMIT_FSIZE) + try: + p.rlimit(psutil.RLIMIT_FSIZE, (1024, hard)) + with open(TESTFN, "wb") as f: + f.write(b"X" * 1024) + # write() or flush() doesn't always cause the exception + # but close() will. + with self.assertRaises(IOError) as exc: + with open(TESTFN, "wb") as f: + f.write(b"X" * 1025) + self.assertEqual(exc.exception.errno if PY3 else exc.exception[0], + errno.EFBIG) + finally: + p.rlimit(psutil.RLIMIT_FSIZE, (soft, hard)) + self.assertEqual(p.rlimit(psutil.RLIMIT_FSIZE), (soft, hard)) + + @unittest.skipIf(not HAS_RLIMIT, "not supported") + def test_rlimit_infinity(self): + # First set a limit, then re-set it by specifying INFINITY + # and assume we overridden the previous limit. + p = psutil.Process() + soft, hard = p.rlimit(psutil.RLIMIT_FSIZE) + try: + p.rlimit(psutil.RLIMIT_FSIZE, (1024, hard)) + p.rlimit(psutil.RLIMIT_FSIZE, (psutil.RLIM_INFINITY, hard)) + with open(TESTFN, "wb") as f: + f.write(b"X" * 2048) + finally: + p.rlimit(psutil.RLIMIT_FSIZE, (soft, hard)) + self.assertEqual(p.rlimit(psutil.RLIMIT_FSIZE), (soft, hard)) + + @unittest.skipIf(not HAS_RLIMIT, "not supported") + def test_rlimit_infinity_value(self): + # RLIMIT_FSIZE should be RLIM_INFINITY, which will be a really + # big number on a platform with large file support. On these + # platforms we need to test that the get/setrlimit functions + # properly convert the number to a C long long and that the + # conversion doesn't raise an error. + p = psutil.Process() + soft, hard = p.rlimit(psutil.RLIMIT_FSIZE) + self.assertEqual(psutil.RLIM_INFINITY, hard) + p.rlimit(psutil.RLIMIT_FSIZE, (soft, hard)) + + def test_num_threads(self): + # on certain platforms such as Linux we might test for exact + # thread number, since we always have with 1 thread per process, + # but this does not apply across all platforms (MACOS, Windows) + p = psutil.Process() + if OPENBSD: + try: + step1 = p.num_threads() + except psutil.AccessDenied: + raise unittest.SkipTest("on OpenBSD this requires root access") + else: + step1 = p.num_threads() + + with ThreadTask(): + step2 = p.num_threads() + self.assertEqual(step2, step1 + 1) + + @unittest.skipIf(not WINDOWS, 'WINDOWS only') + def test_num_handles(self): + # a better test is done later into test/_windows.py + p = psutil.Process() + self.assertGreater(p.num_handles(), 0) + + @unittest.skipIf(not HAS_THREADS, 'not supported') + def test_threads(self): + p = psutil.Process() + if OPENBSD: + try: + step1 = p.threads() + except psutil.AccessDenied: + raise unittest.SkipTest("on OpenBSD this requires root access") + else: + step1 = p.threads() + + with ThreadTask(): + step2 = p.threads() + self.assertEqual(len(step2), len(step1) + 1) + athread = step2[0] + # test named tuple + self.assertEqual(athread.id, athread[0]) + self.assertEqual(athread.user_time, athread[1]) + self.assertEqual(athread.system_time, athread[2]) + + @retry_before_failing() + @skip_on_access_denied(only_if=MACOS) + @unittest.skipIf(not HAS_THREADS, 'not supported') + def test_threads_2(self): + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + if OPENBSD: + try: + p.threads() + except psutil.AccessDenied: + raise unittest.SkipTest( + "on OpenBSD this requires root access") + self.assertAlmostEqual( + p.cpu_times().user, + sum([x.user_time for x in p.threads()]), delta=0.1) + self.assertAlmostEqual( + p.cpu_times().system, + sum([x.system_time for x in p.threads()]), delta=0.1) + + def test_memory_info(self): + p = psutil.Process() + + # step 1 - get a base value to compare our results + rss1, vms1 = p.memory_info()[:2] + percent1 = p.memory_percent() + self.assertGreater(rss1, 0) + self.assertGreater(vms1, 0) + + # step 2 - allocate some memory + memarr = [None] * 1500000 + + rss2, vms2 = p.memory_info()[:2] + percent2 = p.memory_percent() + + # step 3 - make sure that the memory usage bumped up + self.assertGreater(rss2, rss1) + self.assertGreaterEqual(vms2, vms1) # vms might be equal + self.assertGreater(percent2, percent1) + del memarr + + if WINDOWS: + mem = p.memory_info() + self.assertEqual(mem.rss, mem.wset) + self.assertEqual(mem.vms, mem.pagefile) + + mem = p.memory_info() + for name in mem._fields: + self.assertGreaterEqual(getattr(mem, name), 0) + + def test_memory_full_info(self): + total = psutil.virtual_memory().total + mem = psutil.Process().memory_full_info() + for name in mem._fields: + value = getattr(mem, name) + self.assertGreaterEqual(value, 0, msg=(name, value)) + if name == 'vms' and OSX or LINUX: + continue + self.assertLessEqual(value, total, msg=(name, value, total)) + if LINUX or WINDOWS or MACOS: + self.assertGreaterEqual(mem.uss, 0) + if LINUX: + self.assertGreaterEqual(mem.pss, 0) + self.assertGreaterEqual(mem.swap, 0) + + @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") + 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))) + ext_maps = p.memory_maps(grouped=False) + + for nt in maps: + if not nt.path.startswith('['): + assert os.path.isabs(nt.path), nt.path + if POSIX: + try: + assert os.path.exists(nt.path) or \ + os.path.islink(nt.path), nt.path + except AssertionError: + if not LINUX: + raise + else: + # https://github.com/giampaolo/psutil/issues/759 + with open_text('/proc/self/smaps') as f: + data = f.read() + if "%s (deleted)" % nt.path not in data: + raise + else: + # XXX - On Windows we have this strange behavior with + # 64 bit dlls: they are visible via explorer but cannot + # be accessed via os.stat() (wtf?). + if '64' not in os.path.basename(nt.path): + assert os.path.exists(nt.path), nt.path + for nt in ext_maps: + for fname in nt._fields: + value = getattr(nt, fname) + if fname == 'path': + continue + elif fname in ('addr', 'perms'): + assert value, value + else: + self.assertIsInstance(value, (int, long)) + assert value >= 0, value + + @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") + def test_memory_maps_lists_lib(self): + # Make sure a newly loaded shared lib is listed. + with copyload_shared_lib() as path: + def normpath(p): + return os.path.realpath(os.path.normcase(p)) + libpaths = [normpath(x.path) + for x in psutil.Process().memory_maps()] + self.assertIn(normpath(path), libpaths) + + def test_memory_percent(self): + p = psutil.Process() + p.memory_percent() + self.assertRaises(ValueError, p.memory_percent, memtype="?!?") + if LINUX or MACOS or WINDOWS: + p.memory_percent(memtype='uss') + + def test_is_running(self): + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + assert p.is_running() + assert p.is_running() + p.kill() + p.wait() + assert not p.is_running() + assert not p.is_running() + + def test_exe(self): + sproc = get_test_subprocess() + exe = psutil.Process(sproc.pid).exe() + try: + self.assertEqual(exe, PYTHON_EXE) + except AssertionError: + if WINDOWS and len(exe) == len(PYTHON_EXE): + # on Windows we don't care about case sensitivity + normcase = os.path.normcase + self.assertEqual(normcase(exe), normcase(PYTHON_EXE)) + else: + # certain platforms such as BSD are more accurate returning: + # "/usr/local/bin/python2.7" + # ...instead of: + # "/usr/local/bin/python" + # We do not want to consider this difference in accuracy + # an error. + ver = "%s.%s" % (sys.version_info[0], sys.version_info[1]) + try: + self.assertEqual(exe.replace(ver, ''), + PYTHON_EXE.replace(ver, '')) + except AssertionError: + # Tipically MACOS. Really not sure what to do here. + pass + + out = sh([exe, "-c", "import os; print('hey')"]) + self.assertEqual(out, 'hey') + + def test_cmdline(self): + cmdline = [PYTHON_EXE, "-c", "import time; time.sleep(60)"] + sproc = get_test_subprocess(cmdline) + try: + self.assertEqual(' '.join(psutil.Process(sproc.pid).cmdline()), + ' '.join(cmdline)) + except AssertionError: + # XXX - most of the times the underlying sysctl() call on Net + # and Open BSD returns a truncated string. + # Also /proc/pid/cmdline behaves the same so it looks + # like this is a kernel bug. + # XXX - AIX truncates long arguments in /proc/pid/cmdline + if NETBSD or OPENBSD or AIX: + self.assertEqual( + psutil.Process(sproc.pid).cmdline()[0], PYTHON_EXE) + else: + raise + + def test_name(self): + sproc = get_test_subprocess(PYTHON_EXE) + name = psutil.Process(sproc.pid).name().lower() + pyexe = os.path.basename(os.path.realpath(sys.executable)).lower() + assert pyexe.startswith(name), (pyexe, name) + + # XXX + @unittest.skipIf(SUNOS, "broken on SUNOS") + @unittest.skipIf(AIX, "broken on AIX") + def test_prog_w_funky_name(self): + # Test that name(), exe() and cmdline() correctly handle programs + # with funky chars such as spaces and ")", see: + # https://github.com/giampaolo/psutil/issues/628 + + def rm(): + # Try to limit occasional failures on Appveyor: + # https://ci.appveyor.com/project/giampaolo/psutil/build/1350/ + # job/lbo3bkju55le850n + try: + safe_rmpath(funky_path) + except OSError: + pass + + funky_path = TESTFN + 'foo bar )' + create_exe(funky_path) + self.addCleanup(rm) + cmdline = [funky_path, "-c", + "import time; [time.sleep(0.01) for x in range(3000)];" + "arg1", "arg2", "", "arg3", ""] + sproc = get_test_subprocess(cmdline) + p = psutil.Process(sproc.pid) + # ...in order to try to prevent occasional failures on travis + if TRAVIS: + wait_for_pid(p.pid) + self.assertEqual(p.cmdline(), cmdline) + self.assertEqual(p.name(), os.path.basename(funky_path)) + self.assertEqual(os.path.normcase(p.exe()), + os.path.normcase(funky_path)) + + @unittest.skipIf(not POSIX, 'POSIX only') + def test_uids(self): + p = psutil.Process() + real, effective, saved = p.uids() + # os.getuid() refers to "real" uid + self.assertEqual(real, os.getuid()) + # os.geteuid() refers to "effective" uid + self.assertEqual(effective, os.geteuid()) + # No such thing as os.getsuid() ("saved" uid), but starting + # from python 2.7 we have os.getresuid() which returns all + # of them. + if hasattr(os, "getresuid"): + self.assertEqual(os.getresuid(), p.uids()) + + @unittest.skipIf(not POSIX, 'POSIX only') + def test_gids(self): + p = psutil.Process() + real, effective, saved = p.gids() + # os.getuid() refers to "real" uid + self.assertEqual(real, os.getgid()) + # os.geteuid() refers to "effective" uid + self.assertEqual(effective, os.getegid()) + # No such thing as os.getsgid() ("saved" gid), but starting + # from python 2.7 we have os.getresgid() which returns all + # of them. + if hasattr(os, "getresuid"): + self.assertEqual(os.getresgid(), p.gids()) + + def test_nice(self): + p = psutil.Process() + self.assertRaises(TypeError, p.nice, "str") + if WINDOWS: + try: + init = p.nice() + if sys.version_info > (3, 4): + self.assertIsInstance(init, enum.IntEnum) + else: + self.assertIsInstance(init, int) + self.assertEqual(init, psutil.NORMAL_PRIORITY_CLASS) + p.nice(psutil.HIGH_PRIORITY_CLASS) + self.assertEqual(p.nice(), psutil.HIGH_PRIORITY_CLASS) + p.nice(psutil.NORMAL_PRIORITY_CLASS) + self.assertEqual(p.nice(), psutil.NORMAL_PRIORITY_CLASS) + finally: + p.nice(psutil.NORMAL_PRIORITY_CLASS) + else: + first_nice = p.nice() + try: + if hasattr(os, "getpriority"): + self.assertEqual( + os.getpriority(os.PRIO_PROCESS, os.getpid()), p.nice()) + p.nice(1) + self.assertEqual(p.nice(), 1) + if hasattr(os, "getpriority"): + self.assertEqual( + os.getpriority(os.PRIO_PROCESS, os.getpid()), p.nice()) + # XXX - going back to previous nice value raises + # AccessDenied on MACOS + if not MACOS: + p.nice(0) + self.assertEqual(p.nice(), 0) + except psutil.AccessDenied: + pass + finally: + try: + p.nice(first_nice) + except psutil.AccessDenied: + pass + + def test_status(self): + p = psutil.Process() + self.assertEqual(p.status(), psutil.STATUS_RUNNING) + + def test_username(self): + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + username = p.username() + if WINDOWS: + domain, username = username.split('\\') + self.assertEqual(username, getpass.getuser()) + if 'USERDOMAIN' in os.environ: + self.assertEqual(domain, os.environ['USERDOMAIN']) + else: + self.assertEqual(username, getpass.getuser()) + + def test_cwd(self): + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + self.assertEqual(p.cwd(), os.getcwd()) + + def test_cwd_2(self): + cmd = [PYTHON_EXE, "-c", + "import os, time; os.chdir('..'); time.sleep(60)"] + sproc = get_test_subprocess(cmd) + p = psutil.Process(sproc.pid) + call_until(p.cwd, "ret == os.path.dirname(os.getcwd())") + + @unittest.skipIf(not HAS_CPU_AFFINITY, 'not supported') + def test_cpu_affinity(self): + p = psutil.Process() + initial = p.cpu_affinity() + assert initial, initial + self.addCleanup(p.cpu_affinity, initial) + + if hasattr(os, "sched_getaffinity"): + self.assertEqual(initial, list(os.sched_getaffinity(p.pid))) + self.assertEqual(len(initial), len(set(initial))) + + all_cpus = list(range(len(psutil.cpu_percent(percpu=True)))) + # Work around travis failure: + # https://travis-ci.org/giampaolo/psutil/builds/284173194 + for n in all_cpus if not TRAVIS else initial: + p.cpu_affinity([n]) + self.assertEqual(p.cpu_affinity(), [n]) + if hasattr(os, "sched_getaffinity"): + self.assertEqual(p.cpu_affinity(), + list(os.sched_getaffinity(p.pid))) + # also test num_cpu() + if hasattr(p, "num_cpu"): + self.assertEqual(p.cpu_affinity()[0], p.num_cpu()) + + # [] is an alias for "all eligible CPUs"; on Linux this may + # not be equal to all available CPUs, see: + # https://github.com/giampaolo/psutil/issues/956 + p.cpu_affinity([]) + if LINUX: + self.assertEqual(p.cpu_affinity(), p._proc._get_eligible_cpus()) + else: + self.assertEqual(p.cpu_affinity(), all_cpus) + if hasattr(os, "sched_getaffinity"): + self.assertEqual(p.cpu_affinity(), + list(os.sched_getaffinity(p.pid))) + # + self.assertRaises(TypeError, p.cpu_affinity, 1) + p.cpu_affinity(initial) + # it should work with all iterables, not only lists + if not TRAVIS: + p.cpu_affinity(set(all_cpus)) + p.cpu_affinity(tuple(all_cpus)) + + @unittest.skipIf(not HAS_CPU_AFFINITY, 'not supported') + def test_cpu_affinity_errs(self): + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + invalid_cpu = [len(psutil.cpu_times(percpu=True)) + 10] + self.assertRaises(ValueError, p.cpu_affinity, invalid_cpu) + self.assertRaises(ValueError, p.cpu_affinity, range(10000, 11000)) + self.assertRaises(TypeError, p.cpu_affinity, [0, "1"]) + self.assertRaises(ValueError, p.cpu_affinity, [0, -1]) + + @unittest.skipIf(not HAS_CPU_AFFINITY, 'not supported') + def test_cpu_affinity_all_combinations(self): + p = psutil.Process() + initial = p.cpu_affinity() + assert initial, initial + self.addCleanup(p.cpu_affinity, initial) + + # All possible CPU set combinations. + combos = [] + for l in range(0, len(initial) + 1): + for subset in itertools.combinations(initial, l): + if subset: + combos.append(list(subset)) + + for combo in combos: + p.cpu_affinity(combo) + self.assertEqual(p.cpu_affinity(), combo) + + # TODO: #595 + @unittest.skipIf(BSD, "broken on BSD") + # can't find any process file on Appveyor + @unittest.skipIf(APPVEYOR, "unreliable on APPVEYOR") + def test_open_files(self): + # current process + p = psutil.Process() + files = p.open_files() + self.assertFalse(TESTFN in files) + with open(TESTFN, 'wb') as f: + f.write(b'x' * 1024) + f.flush() + # give the kernel some time to see the new file + files = call_until(p.open_files, "len(ret) != %i" % len(files)) + for file in files: + if file.path == TESTFN: + if LINUX: + self.assertEqual(file.position, 1024) + break + else: + self.fail("no file found; files=%s" % repr(files)) + for file in files: + assert os.path.isfile(file.path), file + + # another process + cmdline = "import time; f = open(r'%s', 'r'); time.sleep(60);" % TESTFN + sproc = get_test_subprocess([PYTHON_EXE, "-c", cmdline]) + p = psutil.Process(sproc.pid) + + for x in range(100): + filenames = [x.path for x in p.open_files()] + if TESTFN in filenames: + break + time.sleep(.01) + else: + self.assertIn(TESTFN, filenames) + for file in filenames: + assert os.path.isfile(file), file + + # TODO: #595 + @unittest.skipIf(BSD, "broken on BSD") + # can't find any process file on Appveyor + @unittest.skipIf(APPVEYOR, "unreliable on APPVEYOR") + def test_open_files_2(self): + # test fd and path fields + with open(TESTFN, 'w') as fileobj: + p = psutil.Process() + for file in p.open_files(): + if file.path == fileobj.name or file.fd == fileobj.fileno(): + break + else: + self.fail("no file found; files=%s" % repr(p.open_files())) + self.assertEqual(file.path, fileobj.name) + if WINDOWS: + self.assertEqual(file.fd, -1) + else: + self.assertEqual(file.fd, fileobj.fileno()) + # test positions + ntuple = p.open_files()[0] + self.assertEqual(ntuple[0], ntuple.path) + self.assertEqual(ntuple[1], ntuple.fd) + # test file is gone + self.assertNotIn(fileobj.name, p.open_files()) + + @unittest.skipIf(not POSIX, 'POSIX only') + def test_num_fds(self): + p = psutil.Process() + start = p.num_fds() + file = open(TESTFN, 'w') + self.addCleanup(file.close) + self.assertEqual(p.num_fds(), start + 1) + sock = socket.socket() + self.addCleanup(sock.close) + self.assertEqual(p.num_fds(), start + 2) + file.close() + sock.close() + self.assertEqual(p.num_fds(), start) + + @skip_on_not_implemented(only_if=LINUX) + @unittest.skipIf(OPENBSD or NETBSD, "not reliable on OPENBSD & NETBSD") + def test_num_ctx_switches(self): + p = psutil.Process() + before = sum(p.num_ctx_switches()) + for x in range(500000): + after = sum(p.num_ctx_switches()) + if after > before: + return + self.fail("num ctx switches still the same after 50.000 iterations") + + def test_ppid(self): + if hasattr(os, 'getppid'): + self.assertEqual(psutil.Process().ppid(), os.getppid()) + this_parent = os.getpid() + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + self.assertEqual(p.ppid(), this_parent) + # no other process is supposed to have us as parent + reap_children(recursive=True) + if APPVEYOR: + # Occasional failures, see: + # https://ci.appveyor.com/project/giampaolo/psutil/build/ + # job/0hs623nenj7w4m33 + return + for p in psutil.process_iter(): + if p.pid == sproc.pid: + continue + # XXX: sometimes this fails on Windows; not sure why. + self.assertNotEqual(p.ppid(), this_parent, msg=p) + + def test_parent(self): + this_parent = os.getpid() + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + self.assertEqual(p.parent().pid, this_parent) + + lowest_pid = psutil.pids()[0] + self.assertIsNone(psutil.Process(lowest_pid).parent()) + + def test_parent_multi(self): + p1, p2 = create_proc_children_pair() + self.assertEqual(p2.parent(), p1) + self.assertEqual(p1.parent(), psutil.Process()) + + def test_parent_disappeared(self): + # Emulate a case where the parent process disappeared. + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + with mock.patch("psutil.Process", + side_effect=psutil.NoSuchProcess(0, 'foo')): + self.assertIsNone(p.parent()) + + def test_parents(self): + assert psutil.Process().parents() + p1, p2 = create_proc_children_pair() + self.assertEqual(p1.parents()[0], psutil.Process()) + self.assertEqual(p2.parents()[0], p1) + self.assertEqual(p2.parents()[1], psutil.Process()) + if POSIX: + lowest_pid = psutil.pids()[0] + self.assertEqual(p1.parents()[-1].pid, lowest_pid) + self.assertEqual(p2.parents()[-1].pid, lowest_pid) + + def test_children(self): + reap_children(recursive=True) + p = psutil.Process() + self.assertEqual(p.children(), []) + self.assertEqual(p.children(recursive=True), []) + # On Windows we set the flag to 0 in order to cancel out the + # CREATE_NO_WINDOW flag (enabled by default) which creates + # an extra "conhost.exe" child. + sproc = get_test_subprocess(creationflags=0) + children1 = p.children() + children2 = p.children(recursive=True) + for children in (children1, children2): + self.assertEqual(len(children), 1) + self.assertEqual(children[0].pid, sproc.pid) + self.assertEqual(children[0].ppid(), os.getpid()) + + def test_children_recursive(self): + # Test children() against two sub processes, p1 and p2, where + # p1 (our child) spawned p2 (our grandchild). + p1, p2 = create_proc_children_pair() + p = psutil.Process() + self.assertEqual(p.children(), [p1]) + self.assertEqual(p.children(recursive=True), [p1, p2]) + # If the intermediate process is gone there's no way for + # children() to recursively find it. + p1.terminate() + p1.wait() + self.assertEqual(p.children(recursive=True), []) + + def test_children_duplicates(self): + # find the process which has the highest number of children + table = collections.defaultdict(int) + for p in psutil.process_iter(): + try: + table[p.ppid()] += 1 + except psutil.Error: + pass + # this is the one, now let's make sure there are no duplicates + pid = sorted(table.items(), key=lambda x: x[1])[-1][0] + p = psutil.Process(pid) + try: + c = p.children(recursive=True) + except psutil.AccessDenied: # windows + pass + else: + self.assertEqual(len(c), len(set(c))) + + def test_parents_and_children(self): + p1, p2 = create_proc_children_pair() + me = psutil.Process() + # forward + children = me.children(recursive=True) + self.assertEqual(len(children), 2) + self.assertEqual(children[0], p1) + self.assertEqual(children[1], p2) + # backward + parents = p2.parents() + self.assertEqual(parents[0], p1) + self.assertEqual(parents[1], me) + + def test_suspend_resume(self): + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + p.suspend() + for x in range(100): + if p.status() == psutil.STATUS_STOPPED: + break + time.sleep(0.01) + p.resume() + self.assertNotEqual(p.status(), psutil.STATUS_STOPPED) + + def test_invalid_pid(self): + self.assertRaises(TypeError, psutil.Process, "1") + self.assertRaises(ValueError, psutil.Process, -1) + + def test_as_dict(self): + p = psutil.Process() + d = p.as_dict(attrs=['exe', 'name']) + self.assertEqual(sorted(d.keys()), ['exe', 'name']) + + p = psutil.Process(min(psutil.pids())) + d = p.as_dict(attrs=['connections'], ad_value='foo') + if not isinstance(d['connections'], list): + self.assertEqual(d['connections'], 'foo') + + # Test ad_value is set on AccessDenied. + with mock.patch('psutil.Process.nice', create=True, + side_effect=psutil.AccessDenied): + self.assertEqual( + p.as_dict(attrs=["nice"], ad_value=1), {"nice": 1}) + + # Test that NoSuchProcess bubbles up. + with mock.patch('psutil.Process.nice', create=True, + side_effect=psutil.NoSuchProcess(p.pid, "name")): + self.assertRaises( + psutil.NoSuchProcess, p.as_dict, attrs=["nice"]) + + # Test that ZombieProcess is swallowed. + with mock.patch('psutil.Process.nice', create=True, + side_effect=psutil.ZombieProcess(p.pid, "name")): + self.assertEqual( + p.as_dict(attrs=["nice"], ad_value="foo"), {"nice": "foo"}) + + # By default APIs raising NotImplementedError are + # supposed to be skipped. + with mock.patch('psutil.Process.nice', create=True, + side_effect=NotImplementedError): + d = p.as_dict() + self.assertNotIn('nice', list(d.keys())) + # ...unless the user explicitly asked for some attr. + with self.assertRaises(NotImplementedError): + p.as_dict(attrs=["nice"]) + + # errors + with self.assertRaises(TypeError): + p.as_dict('name') + with self.assertRaises(ValueError): + p.as_dict(['foo']) + with self.assertRaises(ValueError): + p.as_dict(['foo', 'bar']) + + def test_oneshot(self): + with mock.patch("psutil._psplatform.Process.cpu_times") as m: + p = psutil.Process() + with p.oneshot(): + p.cpu_times() + p.cpu_times() + self.assertEqual(m.call_count, 1) + + with mock.patch("psutil._psplatform.Process.cpu_times") as m: + p.cpu_times() + p.cpu_times() + self.assertEqual(m.call_count, 2) + + def test_oneshot_twice(self): + # Test the case where the ctx manager is __enter__ed twice. + # The second __enter__ is supposed to resut in a NOOP. + with mock.patch("psutil._psplatform.Process.cpu_times") as m1: + with mock.patch("psutil._psplatform.Process.oneshot_enter") as m2: + p = psutil.Process() + with p.oneshot(): + p.cpu_times() + p.cpu_times() + with p.oneshot(): + p.cpu_times() + p.cpu_times() + self.assertEqual(m1.call_count, 1) + self.assertEqual(m2.call_count, 1) + + with mock.patch("psutil._psplatform.Process.cpu_times") as m: + p.cpu_times() + p.cpu_times() + self.assertEqual(m.call_count, 2) + + def test_oneshot_cache(self): + # Make sure oneshot() cache is nonglobal. Instead it's + # supposed to be bound to the Process instance, see: + # https://github.com/giampaolo/psutil/issues/1373 + p1, p2 = create_proc_children_pair() + p1_ppid = p1.ppid() + p2_ppid = p2.ppid() + self.assertNotEqual(p1_ppid, p2_ppid) + with p1.oneshot(): + self.assertEqual(p1.ppid(), p1_ppid) + self.assertEqual(p2.ppid(), p2_ppid) + with p2.oneshot(): + self.assertEqual(p1.ppid(), p1_ppid) + self.assertEqual(p2.ppid(), p2_ppid) + + def test_halfway_terminated_process(self): + # Test that NoSuchProcess exception gets raised in case the + # process dies after we create the Process object. + # Example: + # >>> proc = Process(1234) + # >>> time.sleep(2) # time-consuming task, process dies in meantime + # >>> proc.name() + # Refers to Issue #15 + sproc = get_test_subprocess() + p = psutil.Process(sproc.pid) + p.terminate() + p.wait() + if WINDOWS: + call_until(psutil.pids, "%s not in ret" % p.pid) + assert not p.is_running() + + if WINDOWS: + with self.assertRaises(psutil.NoSuchProcess): + p.send_signal(signal.CTRL_C_EVENT) + with self.assertRaises(psutil.NoSuchProcess): + p.send_signal(signal.CTRL_BREAK_EVENT) + + excluded_names = ['pid', 'is_running', 'wait', 'create_time', + 'oneshot', 'memory_info_ex'] + if LINUX and not HAS_RLIMIT: + excluded_names.append('rlimit') + for name in dir(p): + if (name.startswith('_') or + name in excluded_names): + continue + try: + meth = getattr(p, name) + # get/set methods + if name == 'nice': + if POSIX: + ret = meth(1) + else: + ret = meth(psutil.NORMAL_PRIORITY_CLASS) + elif name == 'ionice': + ret = meth() + ret = meth(2) + elif name == 'rlimit': + ret = meth(psutil.RLIMIT_NOFILE) + ret = meth(psutil.RLIMIT_NOFILE, (5, 5)) + elif name == 'cpu_affinity': + ret = meth() + ret = meth([0]) + elif name == 'send_signal': + ret = meth(signal.SIGTERM) + else: + ret = meth() + except psutil.ZombieProcess: + self.fail("ZombieProcess for %r was not supposed to happen" % + name) + except psutil.NoSuchProcess: + pass + except psutil.AccessDenied: + if OPENBSD and name in ('threads', 'num_threads'): + pass + else: + raise + except NotImplementedError: + pass + else: + self.fail( + "NoSuchProcess exception not raised for %r, retval=%s" % ( + name, ret)) + + @unittest.skipIf(not POSIX, 'POSIX only') + def test_zombie_process(self): + def succeed_or_zombie_p_exc(fun, *args, **kwargs): + try: + return fun(*args, **kwargs) + except (psutil.ZombieProcess, psutil.AccessDenied): + pass + + zpid = create_zombie_proc() + self.addCleanup(reap_children, recursive=True) + # A zombie process should always be instantiable + zproc = psutil.Process(zpid) + # ...and at least its status always be querable + self.assertEqual(zproc.status(), psutil.STATUS_ZOMBIE) + # ...and it should be considered 'running' + self.assertTrue(zproc.is_running()) + # ...and as_dict() shouldn't crash + zproc.as_dict() + # if cmdline succeeds it should be an empty list + ret = succeed_or_zombie_p_exc(zproc.suspend) + if ret is not None: + self.assertEqual(ret, []) + + if hasattr(zproc, "rlimit"): + succeed_or_zombie_p_exc(zproc.rlimit, psutil.RLIMIT_NOFILE) + succeed_or_zombie_p_exc(zproc.rlimit, psutil.RLIMIT_NOFILE, + (5, 5)) + # set methods + succeed_or_zombie_p_exc(zproc.parent) + if hasattr(zproc, 'cpu_affinity'): + try: + succeed_or_zombie_p_exc(zproc.cpu_affinity, [0]) + except ValueError as err: + if TRAVIS and LINUX and "not eligible" in str(err): + # https://travis-ci.org/giampaolo/psutil/jobs/279890461 + pass + else: + raise + + succeed_or_zombie_p_exc(zproc.nice, 0) + if hasattr(zproc, 'ionice'): + if LINUX: + succeed_or_zombie_p_exc(zproc.ionice, 2, 0) + else: + succeed_or_zombie_p_exc(zproc.ionice, 0) # Windows + if hasattr(zproc, 'rlimit'): + succeed_or_zombie_p_exc(zproc.rlimit, + psutil.RLIMIT_NOFILE, (5, 5)) + succeed_or_zombie_p_exc(zproc.suspend) + succeed_or_zombie_p_exc(zproc.resume) + succeed_or_zombie_p_exc(zproc.terminate) + succeed_or_zombie_p_exc(zproc.kill) + + # ...its parent should 'see' it + # edit: not true on BSD and MACOS + # descendants = [x.pid for x in psutil.Process().children( + # recursive=True)] + # self.assertIn(zpid, descendants) + # XXX should we also assume ppid be usable? Note: this + # would be an important use case as the only way to get + # rid of a zombie is to kill its parent. + # self.assertEqual(zpid.ppid(), os.getpid()) + # ...and all other APIs should be able to deal with it + self.assertTrue(psutil.pid_exists(zpid)) + if not TRAVIS and MACOS: + # For some reason this started failing all of the sudden. + # Maybe they upgraded MACOS version? + # https://travis-ci.org/giampaolo/psutil/jobs/310896404 + self.assertIn(zpid, psutil.pids()) + self.assertIn(zpid, [x.pid for x in psutil.process_iter()]) + psutil._pmap = {} + self.assertIn(zpid, [x.pid for x in psutil.process_iter()]) + + @unittest.skipIf(not POSIX, 'POSIX only') + def test_zombie_process_is_running_w_exc(self): + # Emulate a case where internally is_running() raises + # ZombieProcess. + p = psutil.Process() + with mock.patch("psutil.Process", + side_effect=psutil.ZombieProcess(0)) as m: + assert p.is_running() + assert m.called + + @unittest.skipIf(not POSIX, 'POSIX only') + def test_zombie_process_status_w_exc(self): + # Emulate a case where internally status() raises + # ZombieProcess. + p = psutil.Process() + with mock.patch("psutil._psplatform.Process.status", + side_effect=psutil.ZombieProcess(0)) as m: + self.assertEqual(p.status(), psutil.STATUS_ZOMBIE) + assert m.called + + def test_pid_0(self): + # Process(0) is supposed to work on all platforms except Linux + if 0 not in psutil.pids(): + self.assertRaises(psutil.NoSuchProcess, psutil.Process, 0) + return + + # test all methods + p = psutil.Process(0) + for name in psutil._as_dict_attrnames: + if name == 'pid': + continue + meth = getattr(p, name) + try: + ret = meth() + except psutil.AccessDenied: + pass + else: + if name in ("uids", "gids"): + self.assertEqual(ret.real, 0) + elif name == "username": + if POSIX: + self.assertEqual(p.username(), 'root') + elif WINDOWS: + self.assertEqual(p.username(), 'NT AUTHORITY\\SYSTEM') + elif name == "name": + assert name, name + + if hasattr(p, 'rlimit'): + try: + p.rlimit(psutil.RLIMIT_FSIZE) + except psutil.AccessDenied: + pass + + p.as_dict() + + if not OPENBSD: + self.assertIn(0, psutil.pids()) + self.assertTrue(psutil.pid_exists(0)) + + @unittest.skipIf(not HAS_ENVIRON, "not supported") + def test_environ(self): + def clean_dict(d): + # Most of these are problematic on Travis. + d.pop("PSUTIL_TESTING", None) + d.pop("PLAT", None) + d.pop("HOME", None) + if MACOS: + d.pop("__CF_USER_TEXT_ENCODING", None) + d.pop("VERSIONER_PYTHON_PREFER_32_BIT", None) + d.pop("VERSIONER_PYTHON_VERSION", None) + return dict( + [(k.replace("\r", "").replace("\n", ""), + v.replace("\r", "").replace("\n", "")) + for k, v in d.items()]) + + self.maxDiff = None + p = psutil.Process() + d1 = clean_dict(p.environ()) + d2 = clean_dict(os.environ.copy()) + self.assertEqual(d1, d2) + + @unittest.skipIf(not HAS_ENVIRON, "not supported") + @unittest.skipIf(not POSIX, "POSIX only") + def test_weird_environ(self): + # environment variables can contain values without an equals sign + code = textwrap.dedent(""" + #include + #include + char * const argv[] = {"cat", 0}; + char * const envp[] = {"A=1", "X", "C=3", 0}; + int main(void) { + /* Close stderr on exec so parent can wait for the execve to + * finish. */ + if (fcntl(2, F_SETFD, FD_CLOEXEC) != 0) + return 0; + return execve("/bin/cat", argv, envp); + } + """) + path = TESTFN + create_exe(path, c_code=code) + self.addCleanup(safe_rmpath, path) + sproc = get_test_subprocess([path], + stdin=subprocess.PIPE, + stderr=subprocess.PIPE) + p = psutil.Process(sproc.pid) + wait_for_pid(p.pid) + self.assertTrue(p.is_running()) + # Wait for process to exec or exit. + self.assertEqual(sproc.stderr.read(), b"") + self.assertEqual(p.environ(), {"A": "1", "C": "3"}) + sproc.communicate() + self.assertEqual(sproc.returncode, 0) + + +# =================================================================== +# --- Limited user tests +# =================================================================== + + +if POSIX and os.getuid() == 0: + class LimitedUserTestCase(TestProcess): + """Repeat the previous tests by using a limited user. + Executed only on UNIX and only if the user who run the test script + is root. + """ + # the uid/gid the test suite runs under + if hasattr(os, 'getuid'): + PROCESS_UID = os.getuid() + PROCESS_GID = os.getgid() + + def __init__(self, *args, **kwargs): + TestProcess.__init__(self, *args, **kwargs) + # re-define all existent test methods in order to + # ignore AccessDenied exceptions + for attr in [x for x in dir(self) if x.startswith('test')]: + meth = getattr(self, attr) + + def test_(self): + try: + meth() + except psutil.AccessDenied: + pass + setattr(self, attr, types.MethodType(test_, self)) + + def setUp(self): + safe_rmpath(TESTFN) + TestProcess.setUp(self) + os.setegid(1000) + os.seteuid(1000) + + def tearDown(self): + os.setegid(self.PROCESS_UID) + os.seteuid(self.PROCESS_GID) + TestProcess.tearDown(self) + + def test_nice(self): + try: + psutil.Process().nice(-1) + except psutil.AccessDenied: + pass + else: + self.fail("exception not raised") + + def test_zombie_process(self): + # causes problems if test test suite is run as root + pass + + +# =================================================================== +# --- psutil.Popen tests +# =================================================================== + + +class TestPopen(unittest.TestCase): + """Tests for psutil.Popen class.""" + + def tearDown(self): + reap_children() + + def test_misc(self): + # XXX this test causes a ResourceWarning on Python 3 because + # psutil.__subproc instance doesn't get propertly freed. + # Not sure what to do though. + cmd = [PYTHON_EXE, "-c", "import time; time.sleep(60);"] + with psutil.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) as proc: + proc.name() + proc.cpu_times() + proc.stdin + self.assertTrue(dir(proc)) + self.assertRaises(AttributeError, getattr, proc, 'foo') + proc.terminate() + + def test_ctx_manager(self): + with psutil.Popen([PYTHON_EXE, "-V"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + stdin=subprocess.PIPE) as proc: + proc.communicate() + assert proc.stdout.closed + assert proc.stderr.closed + assert proc.stdin.closed + self.assertEqual(proc.returncode, 0) + + def test_kill_terminate(self): + # subprocess.Popen()'s terminate(), kill() and send_signal() do + # not raise exception after the process is gone. psutil.Popen + # diverges from that. + cmd = [PYTHON_EXE, "-c", "import time; time.sleep(60);"] + with psutil.Popen(cmd, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) as proc: + proc.terminate() + proc.wait() + self.assertRaises(psutil.NoSuchProcess, proc.terminate) + self.assertRaises(psutil.NoSuchProcess, proc.kill) + self.assertRaises(psutil.NoSuchProcess, proc.send_signal, + signal.SIGTERM) + if WINDOWS and sys.version_info >= (2, 7): + self.assertRaises(psutil.NoSuchProcess, proc.send_signal, + signal.CTRL_C_EVENT) + self.assertRaises(psutil.NoSuchProcess, proc.send_signal, + signal.CTRL_BREAK_EVENT) + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_sunos.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_sunos.py new file mode 100644 index 00000000..ea9afcde --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_sunos.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python + +# 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. + +"""Sun OS specific tests.""" + +import os + +import psutil +from psutil import SUNOS +from psutil.tests import run_test_module_by_name +from psutil.tests import sh +from psutil.tests import unittest + + +@unittest.skipIf(not SUNOS, "SUNOS only") +class SunOSSpecificTestCase(unittest.TestCase): + + def test_swap_memory(self): + out = sh('env PATH=/usr/sbin:/sbin:%s swap -l' % os.environ['PATH']) + lines = out.strip().split('\n')[1:] + if not lines: + raise ValueError('no swap device(s) configured') + total = free = 0 + for line in lines: + line = line.split() + t, f = line[-2:] + total += int(int(t) * 512) + free += int(int(f) * 512) + used = total - free + + psutil_swap = psutil.swap_memory() + self.assertEqual(psutil_swap.total, total) + self.assertEqual(psutil_swap.used, used) + self.assertEqual(psutil_swap.free, free) + + def test_cpu_count(self): + out = sh("/usr/sbin/psrinfo") + self.assertEqual(psutil.cpu_count(), len(out.split('\n'))) + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_system.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_system.py new file mode 100644 index 00000000..51223fb0 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_system.py @@ -0,0 +1,871 @@ +#!/usr/bin/env python + +# 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. + +"""Tests for system APIS.""" + +import contextlib +import datetime +import errno +import os +import pprint +import shutil +import signal +import socket +import sys +import tempfile +import time + +import psutil +from psutil import AIX +from psutil import BSD +from psutil import FREEBSD +from psutil import LINUX +from psutil import MACOS +from psutil import NETBSD +from psutil import OPENBSD +from psutil import POSIX +from psutil import SUNOS +from psutil import WINDOWS +from psutil._compat import long +from psutil.tests import APPVEYOR +from psutil.tests import ASCII_FS +from psutil.tests import check_net_address +from psutil.tests import DEVNULL +from psutil.tests import enum +from psutil.tests import get_test_subprocess +from psutil.tests import HAS_BATTERY +from psutil.tests import HAS_CPU_FREQ +from psutil.tests import HAS_NET_IO_COUNTERS +from psutil.tests import HAS_SENSORS_BATTERY +from psutil.tests import HAS_SENSORS_FANS +from psutil.tests import HAS_SENSORS_TEMPERATURES +from psutil.tests import mock +from psutil.tests import reap_children +from psutil.tests import retry_before_failing +from psutil.tests import run_test_module_by_name +from psutil.tests import safe_rmpath +from psutil.tests import TESTFN +from psutil.tests import TESTFN_UNICODE +from psutil.tests import TRAVIS +from psutil.tests import unittest + + +# =================================================================== +# --- System-related API tests +# =================================================================== + + +class TestSystemAPIs(unittest.TestCase): + """Tests for system-related APIs.""" + + def setUp(self): + safe_rmpath(TESTFN) + + def tearDown(self): + reap_children() + + def test_process_iter(self): + self.assertIn(os.getpid(), [x.pid for x in psutil.process_iter()]) + sproc = get_test_subprocess() + self.assertIn(sproc.pid, [x.pid for x in psutil.process_iter()]) + p = psutil.Process(sproc.pid) + p.kill() + p.wait() + self.assertNotIn(sproc.pid, [x.pid for x in psutil.process_iter()]) + + with mock.patch('psutil.Process', + side_effect=psutil.NoSuchProcess(os.getpid())): + self.assertEqual(list(psutil.process_iter()), []) + with mock.patch('psutil.Process', + side_effect=psutil.AccessDenied(os.getpid())): + with self.assertRaises(psutil.AccessDenied): + list(psutil.process_iter()) + + def test_prcess_iter_w_params(self): + for p in psutil.process_iter(attrs=['pid']): + self.assertEqual(list(p.info.keys()), ['pid']) + with self.assertRaises(ValueError): + list(psutil.process_iter(attrs=['foo'])) + with mock.patch("psutil._psplatform.Process.cpu_times", + side_effect=psutil.AccessDenied(0, "")) as m: + for p in psutil.process_iter(attrs=["pid", "cpu_times"]): + self.assertIsNone(p.info['cpu_times']) + self.assertGreaterEqual(p.info['pid'], 0) + assert m.called + with mock.patch("psutil._psplatform.Process.cpu_times", + side_effect=psutil.AccessDenied(0, "")) as m: + flag = object() + for p in psutil.process_iter( + attrs=["pid", "cpu_times"], ad_value=flag): + self.assertIs(p.info['cpu_times'], flag) + self.assertGreaterEqual(p.info['pid'], 0) + assert m.called + + def test_wait_procs(self): + def callback(p): + pids.append(p.pid) + + pids = [] + sproc1 = get_test_subprocess() + sproc2 = get_test_subprocess() + sproc3 = get_test_subprocess() + procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)] + self.assertRaises(ValueError, psutil.wait_procs, procs, timeout=-1) + self.assertRaises(TypeError, psutil.wait_procs, procs, callback=1) + t = time.time() + gone, alive = psutil.wait_procs(procs, timeout=0.01, callback=callback) + + self.assertLess(time.time() - t, 0.5) + self.assertEqual(gone, []) + self.assertEqual(len(alive), 3) + self.assertEqual(pids, []) + for p in alive: + self.assertFalse(hasattr(p, 'returncode')) + + @retry_before_failing(30) + def test(procs, callback): + gone, alive = psutil.wait_procs(procs, timeout=0.03, + callback=callback) + self.assertEqual(len(gone), 1) + self.assertEqual(len(alive), 2) + return gone, alive + + sproc3.terminate() + gone, alive = test(procs, callback) + self.assertIn(sproc3.pid, [x.pid for x in gone]) + if POSIX: + self.assertEqual(gone.pop().returncode, -signal.SIGTERM) + else: + self.assertEqual(gone.pop().returncode, 1) + self.assertEqual(pids, [sproc3.pid]) + for p in alive: + self.assertFalse(hasattr(p, 'returncode')) + + @retry_before_failing(30) + def test(procs, callback): + gone, alive = psutil.wait_procs(procs, timeout=0.03, + callback=callback) + self.assertEqual(len(gone), 3) + self.assertEqual(len(alive), 0) + return gone, alive + + sproc1.terminate() + sproc2.terminate() + gone, alive = test(procs, callback) + self.assertEqual(set(pids), set([sproc1.pid, sproc2.pid, sproc3.pid])) + for p in gone: + self.assertTrue(hasattr(p, 'returncode')) + + def test_wait_procs_no_timeout(self): + sproc1 = get_test_subprocess() + sproc2 = get_test_subprocess() + sproc3 = get_test_subprocess() + procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)] + for p in procs: + p.terminate() + gone, alive = psutil.wait_procs(procs) + + def test_boot_time(self): + bt = psutil.boot_time() + self.assertIsInstance(bt, float) + self.assertGreater(bt, 0) + self.assertLess(bt, time.time()) + + @unittest.skipIf(not POSIX, 'POSIX only') + def test_PAGESIZE(self): + # pagesize is used internally to perform different calculations + # and it's determined by using SC_PAGE_SIZE; make sure + # getpagesize() returns the same value. + import resource + self.assertEqual(os.sysconf("SC_PAGE_SIZE"), resource.getpagesize()) + + def test_virtual_memory(self): + mem = psutil.virtual_memory() + assert mem.total > 0, mem + assert mem.available > 0, mem + assert 0 <= mem.percent <= 100, mem + assert mem.used > 0, mem + assert mem.free >= 0, mem + for name in mem._fields: + value = getattr(mem, name) + if name != 'percent': + self.assertIsInstance(value, (int, long)) + if name != 'total': + if not value >= 0: + self.fail("%r < 0 (%s)" % (name, value)) + if value > mem.total: + self.fail("%r > total (total=%s, %s=%s)" + % (name, mem.total, name, value)) + + def test_swap_memory(self): + mem = psutil.swap_memory() + self.assertEqual( + mem._fields, ('total', 'used', 'free', 'percent', 'sin', 'sout')) + + assert mem.total >= 0, mem + assert mem.used >= 0, mem + if mem.total > 0: + # likely a system with no swap partition + assert mem.free > 0, mem + else: + assert mem.free == 0, mem + assert 0 <= mem.percent <= 100, mem + assert mem.sin >= 0, mem + assert mem.sout >= 0, mem + + def test_pid_exists(self): + sproc = get_test_subprocess() + self.assertTrue(psutil.pid_exists(sproc.pid)) + p = psutil.Process(sproc.pid) + p.kill() + p.wait() + self.assertFalse(psutil.pid_exists(sproc.pid)) + self.assertFalse(psutil.pid_exists(-1)) + self.assertEqual(psutil.pid_exists(0), 0 in psutil.pids()) + + def test_pid_exists_2(self): + reap_children() + pids = psutil.pids() + for pid in pids: + try: + assert psutil.pid_exists(pid) + except AssertionError: + # in case the process disappeared in meantime fail only + # if it is no longer in psutil.pids() + time.sleep(.1) + if pid in psutil.pids(): + self.fail(pid) + pids = range(max(pids) + 5000, max(pids) + 6000) + for pid in pids: + self.assertFalse(psutil.pid_exists(pid), msg=pid) + + def test_pids(self): + pidslist = psutil.pids() + procslist = [x.pid for x in psutil.process_iter()] + # make sure every pid is unique + self.assertEqual(sorted(set(pidslist)), pidslist) + self.assertEqual(pidslist, procslist) + + def test_test(self): + # test for psutil.test() function + stdout = sys.stdout + sys.stdout = DEVNULL + try: + psutil.test() + finally: + sys.stdout = stdout + + def test_cpu_count(self): + logical = psutil.cpu_count() + self.assertEqual(logical, len(psutil.cpu_times(percpu=True))) + self.assertGreaterEqual(logical, 1) + # + if os.path.exists("/proc/cpuinfo"): + with open("/proc/cpuinfo") as fd: + cpuinfo_data = fd.read() + if "physical id" not in cpuinfo_data: + raise unittest.SkipTest("cpuinfo doesn't include physical id") + physical = psutil.cpu_count(logical=False) + if WINDOWS and sys.getwindowsversion()[:2] <= (6, 1): # <= Vista + self.assertIsNone(physical) + else: + self.assertGreaterEqual(physical, 1) + self.assertGreaterEqual(logical, physical) + + def test_cpu_count_none(self): + # https://github.com/giampaolo/psutil/issues/1085 + for val in (-1, 0, None): + with mock.patch('psutil._psplatform.cpu_count_logical', + return_value=val) as m: + self.assertIsNone(psutil.cpu_count()) + assert m.called + with mock.patch('psutil._psplatform.cpu_count_physical', + return_value=val) as m: + self.assertIsNone(psutil.cpu_count(logical=False)) + assert m.called + + def test_cpu_times(self): + # Check type, value >= 0, str(). + total = 0 + times = psutil.cpu_times() + sum(times) + for cp_time in times: + self.assertIsInstance(cp_time, float) + self.assertGreaterEqual(cp_time, 0.0) + total += cp_time + self.assertEqual(total, sum(times)) + str(times) + # CPU times are always supposed to increase over time + # or at least remain the same and that's because time + # cannot go backwards. + # Surprisingly sometimes this might not be the case (at + # least on Windows and Linux), see: + # https://github.com/giampaolo/psutil/issues/392 + # https://github.com/giampaolo/psutil/issues/645 + # if not WINDOWS: + # last = psutil.cpu_times() + # for x in range(100): + # new = psutil.cpu_times() + # for field in new._fields: + # new_t = getattr(new, field) + # last_t = getattr(last, field) + # self.assertGreaterEqual(new_t, last_t, + # msg="%s %s" % (new_t, last_t)) + # last = new + + def test_cpu_times_time_increases(self): + # Make sure time increases between calls. + t1 = sum(psutil.cpu_times()) + stop_at = time.time() + 1 + while time.time() < stop_at: + t2 = sum(psutil.cpu_times()) + if t2 > t1: + return + self.fail("time remained the same") + + def test_per_cpu_times(self): + # Check type, value >= 0, str(). + for times in psutil.cpu_times(percpu=True): + total = 0 + sum(times) + for cp_time in times: + self.assertIsInstance(cp_time, float) + self.assertGreaterEqual(cp_time, 0.0) + total += cp_time + self.assertEqual(total, sum(times)) + str(times) + self.assertEqual(len(psutil.cpu_times(percpu=True)[0]), + len(psutil.cpu_times(percpu=False))) + + # Note: in theory CPU times are always supposed to increase over + # time or remain the same but never go backwards. In practice + # sometimes this is not the case. + # This issue seemd to be afflict Windows: + # https://github.com/giampaolo/psutil/issues/392 + # ...but it turns out also Linux (rarely) behaves the same. + # last = psutil.cpu_times(percpu=True) + # for x in range(100): + # new = psutil.cpu_times(percpu=True) + # for index in range(len(new)): + # newcpu = new[index] + # lastcpu = last[index] + # for field in newcpu._fields: + # new_t = getattr(newcpu, field) + # last_t = getattr(lastcpu, field) + # self.assertGreaterEqual( + # new_t, last_t, msg="%s %s" % (lastcpu, newcpu)) + # last = new + + def test_per_cpu_times_2(self): + # Simulate some work load then make sure time have increased + # between calls. + tot1 = psutil.cpu_times(percpu=True) + stop_at = time.time() + 0.1 + while True: + if time.time() >= stop_at: + break + tot2 = psutil.cpu_times(percpu=True) + for t1, t2 in zip(tot1, tot2): + t1, t2 = sum(t1), sum(t2) + difference = t2 - t1 + if difference >= 0.05: + return + self.fail() + + def test_cpu_times_comparison(self): + # Make sure the sum of all per cpu times is almost equal to + # base "one cpu" times. + base = psutil.cpu_times() + per_cpu = psutil.cpu_times(percpu=True) + summed_values = base._make([sum(num) for num in zip(*per_cpu)]) + for field in base._fields: + self.assertAlmostEqual( + getattr(base, field), getattr(summed_values, field), delta=1) + + def _test_cpu_percent(self, percent, last_ret, new_ret): + try: + self.assertIsInstance(percent, float) + self.assertGreaterEqual(percent, 0.0) + self.assertIsNot(percent, -0.0) + self.assertLessEqual(percent, 100.0 * psutil.cpu_count()) + except AssertionError as err: + raise AssertionError("\n%s\nlast=%s\nnew=%s" % ( + err, pprint.pformat(last_ret), pprint.pformat(new_ret))) + + def test_cpu_percent(self): + last = psutil.cpu_percent(interval=0.001) + for x in range(100): + new = psutil.cpu_percent(interval=None) + self._test_cpu_percent(new, last, new) + last = new + with self.assertRaises(ValueError): + psutil.cpu_percent(interval=-1) + + 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): + new = psutil.cpu_percent(interval=None, percpu=True) + for percent in new: + self._test_cpu_percent(percent, last, new) + last = new + with self.assertRaises(ValueError): + psutil.cpu_percent(interval=-1, percpu=True) + + def test_cpu_times_percent(self): + last = psutil.cpu_times_percent(interval=0.001) + for x in range(100): + new = psutil.cpu_times_percent(interval=None) + for percent in new: + self._test_cpu_percent(percent, last, new) + self._test_cpu_percent(sum(new), last, new) + last = new + + 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): + new = psutil.cpu_times_percent(interval=None, percpu=True) + for cpu in new: + for percent in cpu: + self._test_cpu_percent(percent, last, new) + self._test_cpu_percent(sum(cpu), last, new) + last = new + + def test_per_cpu_times_percent_negative(self): + # see: https://github.com/giampaolo/psutil/issues/645 + psutil.cpu_times_percent(percpu=True) + zero_times = [x._make([0 for x in range(len(x._fields))]) + for x in psutil.cpu_times(percpu=True)] + with mock.patch('psutil.cpu_times', return_value=zero_times): + for cpu in psutil.cpu_times_percent(percpu=True): + for percent in cpu: + self._test_cpu_percent(percent, None, None) + + def test_disk_usage(self): + usage = psutil.disk_usage(os.getcwd()) + self.assertEqual(usage._fields, ('total', 'used', 'free', 'percent')) + + assert usage.total > 0, usage + assert usage.used > 0, usage + assert usage.free > 0, usage + assert usage.total > usage.used, usage + assert usage.total > usage.free, usage + assert 0 <= usage.percent <= 100, usage.percent + if hasattr(shutil, 'disk_usage'): + # py >= 3.3, see: http://bugs.python.org/issue12442 + shutil_usage = shutil.disk_usage(os.getcwd()) + tolerance = 5 * 1024 * 1024 # 5MB + self.assertEqual(usage.total, shutil_usage.total) + self.assertAlmostEqual(usage.free, shutil_usage.free, + delta=tolerance) + self.assertAlmostEqual(usage.used, shutil_usage.used, + delta=tolerance) + + # if path does not exist OSError ENOENT is expected across + # all platforms + fname = tempfile.mktemp() + with self.assertRaises(OSError) as exc: + psutil.disk_usage(fname) + self.assertEqual(exc.exception.errno, errno.ENOENT) + + def test_disk_usage_unicode(self): + # See: https://github.com/giampaolo/psutil/issues/416 + if ASCII_FS: + with self.assertRaises(UnicodeEncodeError): + psutil.disk_usage(TESTFN_UNICODE) + + def test_disk_usage_bytes(self): + psutil.disk_usage(b'.') + + def test_disk_partitions(self): + # all = False + ls = psutil.disk_partitions(all=False) + # on travis we get: + # self.assertEqual(p.cpu_affinity(), [n]) + # AssertionError: Lists differ: [0, 1, 2, 3, 4, 5, 6, 7,... != [0] + self.assertTrue(ls, msg=ls) + for disk in ls: + self.assertIsInstance(disk.device, str) + self.assertIsInstance(disk.mountpoint, str) + self.assertIsInstance(disk.fstype, str) + self.assertIsInstance(disk.opts, str) + if WINDOWS and 'cdrom' in disk.opts: + continue + if not POSIX: + assert os.path.exists(disk.device), disk + else: + # we cannot make any assumption about this, see: + # http://goo.gl/p9c43 + disk.device + if SUNOS or TRAVIS: + # on solaris apparently mount points can also be files + assert os.path.exists(disk.mountpoint), disk + else: + assert os.path.isdir(disk.mountpoint), disk + assert disk.fstype, disk + + # all = True + ls = psutil.disk_partitions(all=True) + self.assertTrue(ls, msg=ls) + for disk in psutil.disk_partitions(all=True): + if not WINDOWS: + try: + os.stat(disk.mountpoint) + except OSError as err: + if TRAVIS and MACOS and err.errno == errno.EIO: + continue + # http://mail.python.org/pipermail/python-dev/ + # 2012-June/120787.html + if err.errno not in (errno.EPERM, errno.EACCES): + raise + else: + assert os.path.exists(disk.mountpoint), disk + self.assertIsInstance(disk.fstype, str) + self.assertIsInstance(disk.opts, str) + + def find_mount_point(path): + path = os.path.abspath(path) + while not os.path.ismount(path): + path = os.path.dirname(path) + return path.lower() + + mount = find_mount_point(__file__) + mounts = [x.mountpoint.lower() for x in + psutil.disk_partitions(all=True)] + self.assertIn(mount, mounts) + psutil.disk_usage(mount) + + @unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported') + def test_net_io_counters(self): + def check_ntuple(nt): + self.assertEqual(nt[0], nt.bytes_sent) + self.assertEqual(nt[1], nt.bytes_recv) + self.assertEqual(nt[2], nt.packets_sent) + self.assertEqual(nt[3], nt.packets_recv) + self.assertEqual(nt[4], nt.errin) + self.assertEqual(nt[5], nt.errout) + self.assertEqual(nt[6], nt.dropin) + self.assertEqual(nt[7], nt.dropout) + assert nt.bytes_sent >= 0, nt + assert nt.bytes_recv >= 0, nt + assert nt.packets_sent >= 0, nt + assert nt.packets_recv >= 0, nt + assert nt.errin >= 0, nt + assert nt.errout >= 0, nt + assert nt.dropin >= 0, nt + assert nt.dropout >= 0, nt + + ret = psutil.net_io_counters(pernic=False) + check_ntuple(ret) + ret = psutil.net_io_counters(pernic=True) + self.assertNotEqual(ret, []) + for key in ret: + self.assertTrue(key) + self.assertIsInstance(key, str) + check_ntuple(ret[key]) + + @unittest.skipIf(not HAS_NET_IO_COUNTERS, 'not supported') + def test_net_io_counters_no_nics(self): + # Emulate a case where no NICs are installed, see: + # https://github.com/giampaolo/psutil/issues/1062 + with mock.patch('psutil._psplatform.net_io_counters', + return_value={}) as m: + self.assertIsNone(psutil.net_io_counters(pernic=False)) + self.assertEqual(psutil.net_io_counters(pernic=True), {}) + assert m.called + + def test_net_if_addrs(self): + nics = psutil.net_if_addrs() + assert nics, nics + + nic_stats = psutil.net_if_stats() + + # Not reliable on all platforms (net_if_addrs() reports more + # interfaces). + # self.assertEqual(sorted(nics.keys()), + # sorted(psutil.net_io_counters(pernic=True).keys())) + + families = set([socket.AF_INET, socket.AF_INET6, psutil.AF_LINK]) + for nic, addrs in nics.items(): + self.assertIsInstance(nic, str) + self.assertEqual(len(set(addrs)), len(addrs)) + for addr in addrs: + self.assertIsInstance(addr.family, int) + self.assertIsInstance(addr.address, str) + self.assertIsInstance(addr.netmask, (str, type(None))) + self.assertIsInstance(addr.broadcast, (str, type(None))) + self.assertIn(addr.family, families) + if sys.version_info >= (3, 4): + self.assertIsInstance(addr.family, enum.IntEnum) + if nic_stats[nic].isup: + # Do not test binding to addresses of interfaces + # that are down + if addr.family == socket.AF_INET: + s = socket.socket(addr.family) + with contextlib.closing(s): + s.bind((addr.address, 0)) + elif addr.family == socket.AF_INET6: + info = socket.getaddrinfo( + addr.address, 0, socket.AF_INET6, + socket.SOCK_STREAM, 0, socket.AI_PASSIVE)[0] + af, socktype, proto, canonname, sa = info + s = socket.socket(af, socktype, proto) + with contextlib.closing(s): + s.bind(sa) + for ip in (addr.address, addr.netmask, addr.broadcast, + addr.ptp): + if ip is not None: + # TODO: skip AF_INET6 for now because I get: + # AddressValueError: Only hex digits permitted in + # u'c6f3%lxcbr0' in u'fe80::c8e0:fff:fe54:c6f3%lxcbr0' + if addr.family != socket.AF_INET6: + check_net_address(ip, addr.family) + # broadcast and ptp addresses are mutually exclusive + if addr.broadcast: + self.assertIsNone(addr.ptp) + elif addr.ptp: + self.assertIsNone(addr.broadcast) + + if BSD or MACOS or SUNOS: + if hasattr(socket, "AF_LINK"): + self.assertEqual(psutil.AF_LINK, socket.AF_LINK) + elif LINUX: + self.assertEqual(psutil.AF_LINK, socket.AF_PACKET) + elif WINDOWS: + self.assertEqual(psutil.AF_LINK, -1) + + def test_net_if_addrs_mac_null_bytes(self): + # Simulate that the underlying C function returns an incomplete + # MAC address. psutil is supposed to fill it with null bytes. + # https://github.com/giampaolo/psutil/issues/786 + if POSIX: + ret = [('em1', psutil.AF_LINK, '06:3d:29', None, None, None)] + else: + ret = [('em1', -1, '06-3d-29', None, None, None)] + with mock.patch('psutil._psplatform.net_if_addrs', + return_value=ret) as m: + addr = psutil.net_if_addrs()['em1'][0] + assert m.called + if POSIX: + self.assertEqual(addr.address, '06:3d:29:00:00:00') + else: + self.assertEqual(addr.address, '06-3d-29-00-00-00') + + @unittest.skipIf(TRAVIS, "unreliable on TRAVIS") # raises EPERM + def test_net_if_stats(self): + nics = psutil.net_if_stats() + assert nics, nics + all_duplexes = (psutil.NIC_DUPLEX_FULL, + psutil.NIC_DUPLEX_HALF, + psutil.NIC_DUPLEX_UNKNOWN) + for name, stats in nics.items(): + self.assertIsInstance(name, str) + isup, duplex, speed, mtu = stats + self.assertIsInstance(isup, bool) + self.assertIn(duplex, all_duplexes) + self.assertIn(duplex, all_duplexes) + self.assertGreaterEqual(speed, 0) + self.assertGreaterEqual(mtu, 0) + + @unittest.skipIf(not (LINUX or BSD or MACOS), + "LINUX or BSD or MACOS specific") + def test_net_if_stats_enodev(self): + # See: https://github.com/giampaolo/psutil/issues/1279 + with mock.patch('psutil._psutil_posix.net_if_mtu', + side_effect=OSError(errno.ENODEV, "")) as m: + ret = psutil.net_if_stats() + self.assertEqual(ret, {}) + assert m.called + + @unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'), + '/proc/diskstats not available on this linux version') + @unittest.skipIf(APPVEYOR and psutil.disk_io_counters() is None, + "unreliable on APPVEYOR") # no visible disks + def test_disk_io_counters(self): + def check_ntuple(nt): + self.assertEqual(nt[0], nt.read_count) + self.assertEqual(nt[1], nt.write_count) + self.assertEqual(nt[2], nt.read_bytes) + self.assertEqual(nt[3], nt.write_bytes) + if not (OPENBSD or NETBSD): + self.assertEqual(nt[4], nt.read_time) + self.assertEqual(nt[5], nt.write_time) + if LINUX: + self.assertEqual(nt[6], nt.read_merged_count) + self.assertEqual(nt[7], nt.write_merged_count) + self.assertEqual(nt[8], nt.busy_time) + elif FREEBSD: + self.assertEqual(nt[6], nt.busy_time) + for name in nt._fields: + assert getattr(nt, name) >= 0, nt + + ret = psutil.disk_io_counters(perdisk=False) + assert ret is not None, "no disks on this system?" + check_ntuple(ret) + ret = psutil.disk_io_counters(perdisk=True) + # make sure there are no duplicates + self.assertEqual(len(ret), len(set(ret))) + for key in ret: + assert key, key + check_ntuple(ret[key]) + + def test_disk_io_counters_no_disks(self): + # Emulate a case where no disks are installed, see: + # https://github.com/giampaolo/psutil/issues/1062 + with mock.patch('psutil._psplatform.disk_io_counters', + return_value={}) as m: + self.assertIsNone(psutil.disk_io_counters(perdisk=False)) + self.assertEqual(psutil.disk_io_counters(perdisk=True), {}) + assert m.called + + # can't find users on APPVEYOR or TRAVIS + @unittest.skipIf(APPVEYOR or TRAVIS and not psutil.users(), + "unreliable on APPVEYOR or TRAVIS") + def test_users(self): + users = psutil.users() + self.assertNotEqual(users, []) + for user in users: + assert user.name, user + self.assertIsInstance(user.name, str) + self.assertIsInstance(user.terminal, (str, type(None))) + if user.host is not None: + self.assertIsInstance(user.host, (str, type(None))) + user.terminal + user.host + assert user.started > 0.0, user + datetime.datetime.fromtimestamp(user.started) + if WINDOWS or OPENBSD: + self.assertIsNone(user.pid) + else: + psutil.Process(user.pid) + + def test_cpu_stats(self): + # Tested more extensively in per-platform test modules. + infos = psutil.cpu_stats() + self.assertEqual( + infos._fields, + ('ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls')) + for name in infos._fields: + value = getattr(infos, name) + self.assertGreaterEqual(value, 0) + # on AIX, ctx_switches is always 0 + if not AIX and name in ('ctx_switches', 'interrupts'): + self.assertGreater(value, 0) + + @unittest.skipIf(not HAS_CPU_FREQ, "not suported") + def test_cpu_freq(self): + def check_ls(ls): + for nt in ls: + self.assertEqual(nt._fields, ('current', 'min', 'max')) + self.assertLessEqual(nt.current, nt.max) + for name in nt._fields: + value = getattr(nt, name) + self.assertIsInstance(value, (int, long, float)) + self.assertGreaterEqual(value, 0) + + ls = psutil.cpu_freq(percpu=True) + if TRAVIS and not ls: + raise self.skipTest("skipped on Travis") + if FREEBSD and not ls: + raise self.skipTest("returns empty list on FreeBSD") + + assert ls, ls + check_ls([psutil.cpu_freq(percpu=False)]) + + if LINUX: + self.assertEqual(len(ls), psutil.cpu_count()) + + def test_os_constants(self): + names = ["POSIX", "WINDOWS", "LINUX", "MACOS", "FREEBSD", "OPENBSD", + "NETBSD", "BSD", "SUNOS"] + for name in names: + self.assertIsInstance(getattr(psutil, name), bool, msg=name) + + if os.name == 'posix': + assert psutil.POSIX + assert not psutil.WINDOWS + names.remove("POSIX") + if "linux" in sys.platform.lower(): + assert psutil.LINUX + names.remove("LINUX") + elif "bsd" in sys.platform.lower(): + assert psutil.BSD + self.assertEqual([psutil.FREEBSD, psutil.OPENBSD, + psutil.NETBSD].count(True), 1) + names.remove("BSD") + names.remove("FREEBSD") + names.remove("OPENBSD") + names.remove("NETBSD") + elif "sunos" in sys.platform.lower() or \ + "solaris" in sys.platform.lower(): + assert psutil.SUNOS + names.remove("SUNOS") + elif "darwin" in sys.platform.lower(): + assert psutil.MACOS + names.remove("MACOS") + else: + assert psutil.WINDOWS + assert not psutil.POSIX + names.remove("WINDOWS") + + # assert all other constants are set to False + for name in names: + self.assertIs(getattr(psutil, name), False, msg=name) + + @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") + def test_sensors_temperatures(self): + temps = psutil.sensors_temperatures() + for name, entries in temps.items(): + self.assertIsInstance(name, str) + for entry in entries: + self.assertIsInstance(entry.label, str) + if entry.current is not None: + self.assertGreaterEqual(entry.current, 0) + if entry.high is not None: + self.assertGreaterEqual(entry.high, 0) + if entry.critical is not None: + self.assertGreaterEqual(entry.critical, 0) + + @unittest.skipIf(not HAS_SENSORS_TEMPERATURES, "not supported") + def test_sensors_temperatures_fahreneit(self): + d = {'coretemp': [('label', 50.0, 60.0, 70.0)]} + with mock.patch("psutil._psplatform.sensors_temperatures", + return_value=d) as m: + temps = psutil.sensors_temperatures( + fahrenheit=True)['coretemp'][0] + assert m.called + self.assertEqual(temps.current, 122.0) + self.assertEqual(temps.high, 140.0) + self.assertEqual(temps.critical, 158.0) + + @unittest.skipIf(not HAS_SENSORS_BATTERY, "not supported") + @unittest.skipIf(not HAS_BATTERY, "no battery") + def test_sensors_battery(self): + ret = psutil.sensors_battery() + self.assertGreaterEqual(ret.percent, 0) + self.assertLessEqual(ret.percent, 100) + if ret.secsleft not in (psutil.POWER_TIME_UNKNOWN, + psutil.POWER_TIME_UNLIMITED): + self.assertGreaterEqual(ret.secsleft, 0) + else: + if ret.secsleft == psutil.POWER_TIME_UNLIMITED: + self.assertTrue(ret.power_plugged) + self.assertIsInstance(ret.power_plugged, bool) + + @unittest.skipIf(not HAS_SENSORS_FANS, "not supported") + def test_sensors_fans(self): + fans = psutil.sensors_fans() + for name, entries in fans.items(): + self.assertIsInstance(name, str) + for entry in entries: + self.assertIsInstance(entry.label, str) + self.assertIsInstance(entry.current, (int, long)) + self.assertGreaterEqual(entry.current, 0) + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_unicode.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_unicode.py new file mode 100644 index 00000000..cfa8dd92 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_unicode.py @@ -0,0 +1,370 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# 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. + +""" +Notes about unicode handling in psutil +====================================== + +In psutil these are the APIs returning or dealing with a string +('not tested' means they are not tested to deal with non-ASCII strings): + +* Process.cmdline() +* Process.connections('unix') +* Process.cwd() +* Process.environ() +* Process.exe() +* Process.memory_maps() +* Process.name() +* Process.open_files() +* Process.username() (not tested) + +* disk_io_counters() (not tested) +* disk_partitions() (not tested) +* disk_usage(str) +* net_connections('unix') +* net_if_addrs() (not tested) +* net_if_stats() (not tested) +* net_io_counters() (not tested) +* sensors_fans() (not tested) +* sensors_temperatures() (not tested) +* users() (not tested) + +* WindowsService.binpath() (not tested) +* WindowsService.description() (not tested) +* WindowsService.display_name() (not tested) +* WindowsService.name() (not tested) +* WindowsService.status() (not tested) +* WindowsService.username() (not tested) + +In here we create a unicode path with a funky non-ASCII name and (where +possible) make psutil return it back (e.g. on name(), exe(), open_files(), +etc.) and make sure that: + +* psutil never crashes with UnicodeDecodeError +* the returned path matches + +For a detailed explanation of how psutil handles unicode see: +- https://github.com/giampaolo/psutil/issues/1040 +- http://psutil.readthedocs.io/#unicode +""" + +import os +import traceback +import warnings +from contextlib import closing + +from psutil import BSD +from psutil import MACOS +from psutil import OPENBSD +from psutil import POSIX +from psutil import WINDOWS +from psutil._compat import PY3 +from psutil._compat import u +from psutil.tests import APPVEYOR +from psutil.tests import ASCII_FS +from psutil.tests import bind_unix_socket +from psutil.tests import chdir +from psutil.tests import copyload_shared_lib +from psutil.tests import create_exe +from psutil.tests import get_test_subprocess +from psutil.tests import HAS_CONNECTIONS_UNIX +from psutil.tests import HAS_ENVIRON +from psutil.tests import HAS_MEMORY_MAPS +from psutil.tests import mock +from psutil.tests import PYPY +from psutil.tests import reap_children +from psutil.tests import run_test_module_by_name +from psutil.tests import safe_mkdir +from psutil.tests import safe_rmpath as _safe_rmpath +from psutil.tests import skip_on_access_denied +from psutil.tests import TESTFILE_PREFIX +from psutil.tests import TESTFN +from psutil.tests import TESTFN_UNICODE +from psutil.tests import TRAVIS +from psutil.tests import unittest +from psutil.tests import unix_socket_path +import psutil + + +def safe_rmpath(path): + if APPVEYOR: + # TODO - this is quite random and I'm not sure why it happens, + # nor I can reproduce it locally: + # https://ci.appveyor.com/project/giampaolo/psutil/build/job/ + # jiq2cgd6stsbtn60 + # safe_rmpath() happens after reap_children() so this is weird + # Perhaps wait_procs() on Windows is broken? Maybe because + # of STILL_ACTIVE? + # https://github.com/giampaolo/psutil/blob/ + # 68c7a70728a31d8b8b58f4be6c4c0baa2f449eda/psutil/arch/ + # windows/process_info.c#L146 + try: + return _safe_rmpath(path) + except WindowsError: + traceback.print_exc() + else: + return _safe_rmpath(path) + + +def subprocess_supports_unicode(name): + """Return True if both the fs and the subprocess module can + deal with a unicode file name. + """ + if PY3: + return True + try: + safe_rmpath(name) + create_exe(name) + get_test_subprocess(cmd=[name]) + except UnicodeEncodeError: + return False + else: + return True + finally: + reap_children() + + +# An invalid unicode string. +if PY3: + INVALID_NAME = (TESTFN.encode('utf8') + b"f\xc0\x80").decode( + 'utf8', 'surrogateescape') +else: + INVALID_NAME = TESTFN + "f\xc0\x80" + + +# =================================================================== +# FS APIs +# =================================================================== + + +class _BaseFSAPIsTests(object): + funky_name = None + + @classmethod + def setUpClass(cls): + safe_rmpath(cls.funky_name) + create_exe(cls.funky_name) + + @classmethod + def tearDownClass(cls): + reap_children() + safe_rmpath(cls.funky_name) + + def tearDown(self): + reap_children() + + def expect_exact_path_match(self): + raise NotImplementedError("must be implemented in subclass") + + def test_proc_exe(self): + subp = get_test_subprocess(cmd=[self.funky_name]) + p = psutil.Process(subp.pid) + exe = p.exe() + self.assertIsInstance(exe, str) + if self.expect_exact_path_match(): + self.assertEqual(exe, self.funky_name) + + def test_proc_name(self): + subp = get_test_subprocess(cmd=[self.funky_name]) + if WINDOWS: + # On Windows name() is determined from exe() first, because + # it's faster; we want to overcome the internal optimization + # and test name() instead of exe(). + with mock.patch("psutil._psplatform.cext.proc_exe", + side_effect=psutil.AccessDenied(os.getpid())) as m: + name = psutil.Process(subp.pid).name() + assert m.called + else: + name = psutil.Process(subp.pid).name() + self.assertIsInstance(name, str) + if self.expect_exact_path_match(): + self.assertEqual(name, os.path.basename(self.funky_name)) + + def test_proc_cmdline(self): + subp = get_test_subprocess(cmd=[self.funky_name]) + p = psutil.Process(subp.pid) + cmdline = p.cmdline() + for part in cmdline: + self.assertIsInstance(part, str) + if self.expect_exact_path_match(): + self.assertEqual(cmdline, [self.funky_name]) + + def test_proc_cwd(self): + dname = self.funky_name + "2" + self.addCleanup(safe_rmpath, dname) + safe_mkdir(dname) + with chdir(dname): + p = psutil.Process() + cwd = p.cwd() + self.assertIsInstance(p.cwd(), str) + if self.expect_exact_path_match(): + self.assertEqual(cwd, dname) + + def test_proc_open_files(self): + p = psutil.Process() + start = set(p.open_files()) + with open(self.funky_name, 'rb'): + new = set(p.open_files()) + path = (new - start).pop().path + self.assertIsInstance(path, str) + if BSD and not path: + # XXX - see https://github.com/giampaolo/psutil/issues/595 + return self.skipTest("open_files on BSD is broken") + if self.expect_exact_path_match(): + self.assertEqual(os.path.normcase(path), + os.path.normcase(self.funky_name)) + + @unittest.skipIf(not POSIX, "POSIX only") + def test_proc_connections(self): + suffix = os.path.basename(self.funky_name) + with unix_socket_path(suffix=suffix) as name: + try: + sock = bind_unix_socket(name) + except UnicodeEncodeError: + if PY3: + raise + else: + raise unittest.SkipTest("not supported") + with closing(sock): + conn = psutil.Process().connections('unix')[0] + self.assertIsInstance(conn.laddr, str) + # AF_UNIX addr not set on OpenBSD + if not OPENBSD: + self.assertEqual(conn.laddr, name) + + @unittest.skipIf(not POSIX, "POSIX only") + @unittest.skipIf(not HAS_CONNECTIONS_UNIX, "can't list UNIX sockets") + @skip_on_access_denied() + def test_net_connections(self): + def find_sock(cons): + for conn in cons: + if os.path.basename(conn.laddr).startswith(TESTFILE_PREFIX): + return conn + raise ValueError("connection not found") + + suffix = os.path.basename(self.funky_name) + with unix_socket_path(suffix=suffix) as name: + try: + sock = bind_unix_socket(name) + except UnicodeEncodeError: + if PY3: + raise + else: + raise unittest.SkipTest("not supported") + with closing(sock): + cons = psutil.net_connections(kind='unix') + # AF_UNIX addr not set on OpenBSD + if not OPENBSD: + conn = find_sock(cons) + self.assertIsInstance(conn.laddr, str) + self.assertEqual(conn.laddr, name) + + def test_disk_usage(self): + dname = self.funky_name + "2" + self.addCleanup(safe_rmpath, dname) + safe_mkdir(dname) + psutil.disk_usage(dname) + + @unittest.skipIf(not HAS_MEMORY_MAPS, "not supported") + @unittest.skipIf(not PY3, "ctypes does not support unicode on PY2") + def test_memory_maps(self): + # XXX: on Python 2, using ctypes.CDLL with a unicode path + # opens a message box which blocks the test run. + with copyload_shared_lib(dst_prefix=self.funky_name) as funky_path: + def normpath(p): + return os.path.realpath(os.path.normcase(p)) + libpaths = [normpath(x.path) + for x in psutil.Process().memory_maps()] + # ...just to have a clearer msg in case of failure + libpaths = [x for x in libpaths if TESTFILE_PREFIX in x] + self.assertIn(normpath(funky_path), libpaths) + for path in libpaths: + self.assertIsInstance(path, str) + + +# https://travis-ci.org/giampaolo/psutil/jobs/440073249 +@unittest.skipIf(PYPY and TRAVIS, "unreliable on PYPY + TRAVIS") +@unittest.skipIf(MACOS and TRAVIS, "unreliable on TRAVIS") # TODO +@unittest.skipIf(ASCII_FS, "ASCII fs") +@unittest.skipIf(not subprocess_supports_unicode(TESTFN_UNICODE), + "subprocess can't deal with unicode") +class TestFSAPIs(_BaseFSAPIsTests, unittest.TestCase): + """Test FS APIs with a funky, valid, UTF8 path name.""" + funky_name = TESTFN_UNICODE + + @classmethod + def expect_exact_path_match(cls): + # Do not expect psutil to correctly handle unicode paths on + # Python 2 if os.listdir() is not able either. + if PY3: + return True + else: + here = '.' if isinstance(cls.funky_name, str) else u('.') + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + return cls.funky_name in os.listdir(here) + + +@unittest.skipIf(PYPY and TRAVIS, "unreliable on PYPY + TRAVIS") +@unittest.skipIf(MACOS and TRAVIS, "unreliable on TRAVIS") # TODO +@unittest.skipIf(not subprocess_supports_unicode(INVALID_NAME), + "subprocess can't deal with invalid unicode") +class TestFSAPIsWithInvalidPath(_BaseFSAPIsTests, unittest.TestCase): + """Test FS APIs with a funky, invalid path name.""" + funky_name = INVALID_NAME + + @classmethod + def expect_exact_path_match(cls): + # Invalid unicode names are supposed to work on Python 2. + return True + + +@unittest.skipIf(not WINDOWS, "WINDOWS only") +class TestWinProcessName(unittest.TestCase): + + def test_name_type(self): + # On Windows name() is determined from exe() first, because + # it's faster; we want to overcome the internal optimization + # and test name() instead of exe(). + with mock.patch("psutil._psplatform.cext.proc_exe", + side_effect=psutil.AccessDenied(os.getpid())) as m: + self.assertIsInstance(psutil.Process().name(), str) + assert m.called + + +# =================================================================== +# Non fs APIs +# =================================================================== + + +class TestNonFSAPIS(unittest.TestCase): + """Unicode tests for non fs-related APIs.""" + + def tearDown(self): + reap_children() + + @unittest.skipIf(not HAS_ENVIRON, "not supported") + def test_proc_environ(self): + # Note: differently from others, this test does not deal + # with fs paths. On Python 2 subprocess module is broken as + # it's not able to handle with non-ASCII env vars, so + # we use "è", which is part of the extended ASCII table + # (unicode point <= 255). + env = os.environ.copy() + funky_str = TESTFN_UNICODE if PY3 else 'è' + env['FUNNY_ARG'] = funky_str + sproc = get_test_subprocess(env=env) + p = psutil.Process(sproc.pid) + env = p.environ() + for k, v in env.items(): + self.assertIsInstance(k, str) + self.assertIsInstance(v, str) + self.assertEqual(env['FUNNY_ARG'], funky_str) + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_windows.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_windows.py new file mode 100644 index 00000000..222d8636 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/test_windows.py @@ -0,0 +1,868 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -* + +# 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. + +"""Windows specific tests.""" + +import datetime +import errno +import glob +import os +import platform +import re +import signal +import subprocess +import sys +import time +import warnings + +import psutil +from psutil import WINDOWS +from psutil.tests import APPVEYOR +from psutil.tests import get_test_subprocess +from psutil.tests import HAS_BATTERY +from psutil.tests import mock +from psutil.tests import reap_children +from psutil.tests import retry_before_failing +from psutil.tests import run_test_module_by_name +from psutil.tests import sh +from psutil.tests import unittest + +with warnings.catch_warnings(): + warnings.simplefilter("ignore") + try: + import win32api # requires "pip install pypiwin32" + import win32con + import win32process + import wmi # requires "pip install wmi" / "make setup-dev-env" + except ImportError: + if os.name == 'nt': + raise + + +cext = psutil._psplatform.cext + +# are we a 64 bit process +IS_64_BIT = sys.maxsize > 2**32 + + +def wrap_exceptions(fun): + def wrapper(self, *args, **kwargs): + try: + return fun(self, *args, **kwargs) + except OSError as err: + from psutil._pswindows import ACCESS_DENIED_SET + if err.errno in ACCESS_DENIED_SET: + raise psutil.AccessDenied(None, None) + if err.errno == errno.ESRCH: + raise psutil.NoSuchProcess(None, None) + raise + return wrapper + + +# =================================================================== +# System APIs +# =================================================================== + + +@unittest.skipIf(not WINDOWS, "WINDOWS only") +class TestCpuAPIs(unittest.TestCase): + + @unittest.skipIf('NUMBER_OF_PROCESSORS' not in os.environ, + 'NUMBER_OF_PROCESSORS env var is not available') + def test_cpu_count_vs_NUMBER_OF_PROCESSORS(self): + # Will likely fail on many-cores systems: + # https://stackoverflow.com/questions/31209256 + num_cpus = int(os.environ['NUMBER_OF_PROCESSORS']) + self.assertEqual(num_cpus, psutil.cpu_count()) + + def test_cpu_count_vs_GetSystemInfo(self): + # Will likely fail on many-cores systems: + # https://stackoverflow.com/questions/31209256 + sys_value = win32api.GetSystemInfo()[5] + psutil_value = psutil.cpu_count() + self.assertEqual(sys_value, psutil_value) + + def test_cpu_count_logical_vs_wmi(self): + w = wmi.WMI() + proc = w.Win32_Processor()[0] + self.assertEqual(psutil.cpu_count(), proc.NumberOfLogicalProcessors) + + def test_cpu_count_phys_vs_wmi(self): + w = wmi.WMI() + proc = w.Win32_Processor()[0] + self.assertEqual(psutil.cpu_count(logical=False), proc.NumberOfCores) + + def test_cpu_count_vs_cpu_times(self): + self.assertEqual(psutil.cpu_count(), + len(psutil.cpu_times(percpu=True))) + + def test_cpu_freq(self): + w = wmi.WMI() + proc = w.Win32_Processor()[0] + self.assertEqual(proc.CurrentClockSpeed, psutil.cpu_freq().current) + self.assertEqual(proc.MaxClockSpeed, psutil.cpu_freq().max) + + +@unittest.skipIf(not WINDOWS, "WINDOWS only") +class TestSystemAPIs(unittest.TestCase): + + def test_nic_names(self): + out = sh('ipconfig /all') + nics = psutil.net_io_counters(pernic=True).keys() + for nic in nics: + if "pseudo-interface" in nic.replace(' ', '-').lower(): + continue + if nic not in out: + self.fail( + "%r nic wasn't found in 'ipconfig /all' output" % nic) + + def test_total_phymem(self): + w = wmi.WMI().Win32_ComputerSystem()[0] + self.assertEqual(int(w.TotalPhysicalMemory), + psutil.virtual_memory().total) + + # @unittest.skipIf(wmi is None, "wmi module is not installed") + # def test__UPTIME(self): + # # _UPTIME constant is not public but it is used internally + # # as value to return for pid 0 creation time. + # # WMI behaves the same. + # w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + # p = psutil.Process(0) + # wmic_create = str(w.CreationDate.split('.')[0]) + # psutil_create = time.strftime("%Y%m%d%H%M%S", + # time.localtime(p.create_time())) + + # Note: this test is not very reliable + @unittest.skipIf(APPVEYOR, "test not relieable on appveyor") + @retry_before_failing() + def test_pids(self): + # Note: this test might fail if the OS is starting/killing + # other processes in the meantime + w = wmi.WMI().Win32_Process() + wmi_pids = set([x.ProcessId for x in w]) + psutil_pids = set(psutil.pids()) + self.assertEqual(wmi_pids, psutil_pids) + + @retry_before_failing() + def test_disks(self): + ps_parts = psutil.disk_partitions(all=True) + wmi_parts = wmi.WMI().Win32_LogicalDisk() + for ps_part in ps_parts: + for wmi_part in wmi_parts: + if ps_part.device.replace('\\', '') == wmi_part.DeviceID: + if not ps_part.mountpoint: + # this is usually a CD-ROM with no disk inserted + break + if 'cdrom' in ps_part.opts: + break + try: + usage = psutil.disk_usage(ps_part.mountpoint) + except OSError as err: + if err.errno == errno.ENOENT: + # usually this is the floppy + break + else: + raise + self.assertEqual(usage.total, int(wmi_part.Size)) + wmi_free = int(wmi_part.FreeSpace) + self.assertEqual(usage.free, wmi_free) + # 10 MB tollerance + if abs(usage.free - wmi_free) > 10 * 1024 * 1024: + self.fail("psutil=%s, wmi=%s" % ( + usage.free, wmi_free)) + break + else: + self.fail("can't find partition %s" % repr(ps_part)) + + def test_disk_usage(self): + for disk in psutil.disk_partitions(): + if 'cdrom' in disk.opts: + continue + sys_value = win32api.GetDiskFreeSpaceEx(disk.mountpoint) + psutil_value = psutil.disk_usage(disk.mountpoint) + self.assertAlmostEqual(sys_value[0], psutil_value.free, + delta=1024 * 1024) + self.assertAlmostEqual(sys_value[1], psutil_value.total, + delta=1024 * 1024) + self.assertEqual(psutil_value.used, + psutil_value.total - psutil_value.free) + + def test_disk_partitions(self): + sys_value = [ + x + '\\' for x in win32api.GetLogicalDriveStrings().split("\\\x00") + if x and not x.startswith('A:')] + psutil_value = [x.mountpoint for x in psutil.disk_partitions(all=True)] + self.assertEqual(sys_value, psutil_value) + + def test_net_if_stats(self): + ps_names = set(cext.net_if_stats()) + wmi_adapters = wmi.WMI().Win32_NetworkAdapter() + wmi_names = set() + for wmi_adapter in wmi_adapters: + wmi_names.add(wmi_adapter.Name) + wmi_names.add(wmi_adapter.NetConnectionID) + self.assertTrue(ps_names & wmi_names, + "no common entries in %s, %s" % (ps_names, wmi_names)) + + def test_boot_time(self): + wmi_os = wmi.WMI().Win32_OperatingSystem() + wmi_btime_str = wmi_os[0].LastBootUpTime.split('.')[0] + wmi_btime_dt = datetime.datetime.strptime( + wmi_btime_str, "%Y%m%d%H%M%S") + psutil_dt = datetime.datetime.fromtimestamp(psutil.boot_time()) + diff = abs((wmi_btime_dt - psutil_dt).total_seconds()) + # Wmic time is 2-3 secs lower for some reason; that's OK. + self.assertLessEqual(diff, 3) + + def test_boot_time_fluctuation(self): + # https://github.com/giampaolo/psutil/issues/1007 + with mock.patch('psutil._pswindows.cext.boot_time', return_value=5): + self.assertEqual(psutil.boot_time(), 5) + with mock.patch('psutil._pswindows.cext.boot_time', return_value=4): + self.assertEqual(psutil.boot_time(), 5) + with mock.patch('psutil._pswindows.cext.boot_time', return_value=6): + self.assertEqual(psutil.boot_time(), 5) + with mock.patch('psutil._pswindows.cext.boot_time', return_value=333): + self.assertEqual(psutil.boot_time(), 333) + + +# =================================================================== +# sensors_battery() +# =================================================================== + + +@unittest.skipIf(not WINDOWS, "WINDOWS only") +class TestSensorsBattery(unittest.TestCase): + + def test_has_battery(self): + if win32api.GetPwrCapabilities()['SystemBatteriesPresent']: + self.assertIsNotNone(psutil.sensors_battery()) + else: + self.assertIsNone(psutil.sensors_battery()) + + @unittest.skipIf(not HAS_BATTERY, "no battery") + def test_percent(self): + w = wmi.WMI() + battery_wmi = w.query('select * from Win32_Battery')[0] + battery_psutil = psutil.sensors_battery() + self.assertAlmostEqual( + battery_psutil.percent, battery_wmi.EstimatedChargeRemaining, + delta=1) + + @unittest.skipIf(not HAS_BATTERY, "no battery") + def test_power_plugged(self): + w = wmi.WMI() + battery_wmi = w.query('select * from Win32_Battery')[0] + battery_psutil = psutil.sensors_battery() + # Status codes: + # https://msdn.microsoft.com/en-us/library/aa394074(v=vs.85).aspx + self.assertEqual(battery_psutil.power_plugged, + battery_wmi.BatteryStatus == 2) + + def test_emulate_no_battery(self): + with mock.patch("psutil._pswindows.cext.sensors_battery", + return_value=(0, 128, 0, 0)) as m: + self.assertIsNone(psutil.sensors_battery()) + assert m.called + + def test_emulate_power_connected(self): + with mock.patch("psutil._pswindows.cext.sensors_battery", + return_value=(1, 0, 0, 0)) as m: + self.assertEqual(psutil.sensors_battery().secsleft, + psutil.POWER_TIME_UNLIMITED) + assert m.called + + def test_emulate_power_charging(self): + with mock.patch("psutil._pswindows.cext.sensors_battery", + return_value=(0, 8, 0, 0)) as m: + self.assertEqual(psutil.sensors_battery().secsleft, + psutil.POWER_TIME_UNLIMITED) + assert m.called + + def test_emulate_secs_left_unknown(self): + with mock.patch("psutil._pswindows.cext.sensors_battery", + return_value=(0, 0, 0, -1)) as m: + self.assertEqual(psutil.sensors_battery().secsleft, + psutil.POWER_TIME_UNKNOWN) + assert m.called + + +# =================================================================== +# Process APIs +# =================================================================== + + +@unittest.skipIf(not WINDOWS, "WINDOWS only") +class TestProcess(unittest.TestCase): + + @classmethod + def setUpClass(cls): + cls.pid = get_test_subprocess().pid + + @classmethod + def tearDownClass(cls): + reap_children() + + def test_issue_24(self): + p = psutil.Process(0) + self.assertRaises(psutil.AccessDenied, p.kill) + + def test_special_pid(self): + p = psutil.Process(4) + self.assertEqual(p.name(), 'System') + # use __str__ to access all common Process properties to check + # that nothing strange happens + str(p) + p.username() + self.assertTrue(p.create_time() >= 0.0) + try: + rss, vms = p.memory_info()[:2] + except psutil.AccessDenied: + # expected on Windows Vista and Windows 7 + if not platform.uname()[1] in ('vista', 'win-7', 'win7'): + raise + else: + self.assertTrue(rss > 0) + + def test_send_signal(self): + p = psutil.Process(self.pid) + self.assertRaises(ValueError, p.send_signal, signal.SIGINT) + + def test_exe_and_name(self): + for p in psutil.process_iter(): + # On Windows name() is never supposed to raise AccessDenied, + # see https://github.com/giampaolo/psutil/issues/627 + try: + name = p.name() + except psutil.NoSuchProcess: + pass + else: + try: + self.assertEqual(os.path.basename(p.exe()), name) + except psutil.Error: + continue + + def test_num_handles_increment(self): + p = psutil.Process(os.getpid()) + before = p.num_handles() + handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, + win32con.FALSE, os.getpid()) + after = p.num_handles() + self.assertEqual(after, before + 1) + win32api.CloseHandle(handle) + self.assertEqual(p.num_handles(), before) + + def test_handles_leak(self): + # Call all Process methods and make sure no handles are left + # open. This is here mainly to make sure functions using + # OpenProcess() always call CloseHandle(). + def call(p, attr): + attr = getattr(p, name, None) + if attr is not None and callable(attr): + attr() + else: + attr + + p = psutil.Process(self.pid) + failures = [] + for name in dir(psutil.Process): + if name.startswith('_') \ + or name in ('terminate', 'kill', 'suspend', 'resume', + 'nice', 'send_signal', 'wait', 'children', + 'as_dict', 'memory_info_ex'): + continue + else: + try: + call(p, name) + num1 = p.num_handles() + call(p, name) + num2 = p.num_handles() + except (psutil.NoSuchProcess, psutil.AccessDenied): + pass + else: + if num2 > num1: + fail = \ + "failure while processing Process.%s method " \ + "(before=%s, after=%s)" % (name, num1, num2) + failures.append(fail) + if failures: + self.fail('\n' + '\n'.join(failures)) + + @unittest.skipIf(not sys.version_info >= (2, 7), + "CTRL_* signals not supported") + def test_ctrl_signals(self): + p = psutil.Process(get_test_subprocess().pid) + p.send_signal(signal.CTRL_C_EVENT) + p.send_signal(signal.CTRL_BREAK_EVENT) + p.kill() + p.wait() + self.assertRaises(psutil.NoSuchProcess, + p.send_signal, signal.CTRL_C_EVENT) + self.assertRaises(psutil.NoSuchProcess, + p.send_signal, signal.CTRL_BREAK_EVENT) + + def test_username(self): + self.assertEqual(psutil.Process().username(), + win32api.GetUserNameEx(win32con.NameSamCompatible)) + + def test_cmdline(self): + sys_value = re.sub(' +', ' ', win32api.GetCommandLine()).strip() + psutil_value = ' '.join(psutil.Process().cmdline()) + self.assertEqual(sys_value, psutil_value) + + # XXX - occasional failures + + # def test_cpu_times(self): + # handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, + # win32con.FALSE, os.getpid()) + # self.addCleanup(win32api.CloseHandle, handle) + # sys_value = win32process.GetProcessTimes(handle) + # psutil_value = psutil.Process().cpu_times() + # self.assertAlmostEqual( + # psutil_value.user, sys_value['UserTime'] / 10000000.0, + # delta=0.2) + # self.assertAlmostEqual( + # psutil_value.user, sys_value['KernelTime'] / 10000000.0, + # delta=0.2) + + def test_nice(self): + handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, + win32con.FALSE, os.getpid()) + self.addCleanup(win32api.CloseHandle, handle) + sys_value = win32process.GetPriorityClass(handle) + psutil_value = psutil.Process().nice() + self.assertEqual(psutil_value, sys_value) + + def test_memory_info(self): + handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, + win32con.FALSE, self.pid) + self.addCleanup(win32api.CloseHandle, handle) + sys_value = win32process.GetProcessMemoryInfo(handle) + psutil_value = psutil.Process(self.pid).memory_info() + self.assertEqual( + sys_value['PeakWorkingSetSize'], psutil_value.peak_wset) + self.assertEqual( + sys_value['WorkingSetSize'], psutil_value.wset) + self.assertEqual( + sys_value['QuotaPeakPagedPoolUsage'], psutil_value.peak_paged_pool) + self.assertEqual( + sys_value['QuotaPagedPoolUsage'], psutil_value.paged_pool) + self.assertEqual( + sys_value['QuotaPeakNonPagedPoolUsage'], + psutil_value.peak_nonpaged_pool) + self.assertEqual( + sys_value['QuotaNonPagedPoolUsage'], psutil_value.nonpaged_pool) + self.assertEqual( + sys_value['PagefileUsage'], psutil_value.pagefile) + self.assertEqual( + sys_value['PeakPagefileUsage'], psutil_value.peak_pagefile) + + self.assertEqual(psutil_value.rss, psutil_value.wset) + self.assertEqual(psutil_value.vms, psutil_value.pagefile) + + def test_wait(self): + handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, + win32con.FALSE, self.pid) + self.addCleanup(win32api.CloseHandle, handle) + p = psutil.Process(self.pid) + p.terminate() + psutil_value = p.wait() + sys_value = win32process.GetExitCodeProcess(handle) + self.assertEqual(psutil_value, sys_value) + + def test_cpu_affinity(self): + def from_bitmask(x): + return [i for i in range(64) if (1 << i) & x] + + handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, + win32con.FALSE, self.pid) + self.addCleanup(win32api.CloseHandle, handle) + sys_value = from_bitmask( + win32process.GetProcessAffinityMask(handle)[0]) + psutil_value = psutil.Process(self.pid).cpu_affinity() + self.assertEqual(psutil_value, sys_value) + + def test_io_counters(self): + handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, + win32con.FALSE, os.getpid()) + self.addCleanup(win32api.CloseHandle, handle) + sys_value = win32process.GetProcessIoCounters(handle) + psutil_value = psutil.Process().io_counters() + self.assertEqual( + psutil_value.read_count, sys_value['ReadOperationCount']) + self.assertEqual( + psutil_value.write_count, sys_value['WriteOperationCount']) + self.assertEqual( + psutil_value.read_bytes, sys_value['ReadTransferCount']) + self.assertEqual( + psutil_value.write_bytes, sys_value['WriteTransferCount']) + self.assertEqual( + psutil_value.other_count, sys_value['OtherOperationCount']) + self.assertEqual( + psutil_value.other_bytes, sys_value['OtherTransferCount']) + + def test_num_handles(self): + import ctypes + import ctypes.wintypes + PROCESS_QUERY_INFORMATION = 0x400 + handle = ctypes.windll.kernel32.OpenProcess( + PROCESS_QUERY_INFORMATION, 0, self.pid) + self.addCleanup(ctypes.windll.kernel32.CloseHandle, handle) + + hndcnt = ctypes.wintypes.DWORD() + ctypes.windll.kernel32.GetProcessHandleCount( + handle, ctypes.byref(hndcnt)) + sys_value = hndcnt.value + psutil_value = psutil.Process(self.pid).num_handles() + self.assertEqual(psutil_value, sys_value) + + +@unittest.skipIf(not WINDOWS, "WINDOWS only") +class TestProcessWMI(unittest.TestCase): + """Compare Process API results with WMI.""" + + @classmethod + def setUpClass(cls): + cls.pid = get_test_subprocess().pid + + @classmethod + def tearDownClass(cls): + reap_children() + + def test_name(self): + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + self.assertEqual(p.name(), w.Caption) + + def test_exe(self): + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + # Note: wmi reports the exe as a lower case string. + # Being Windows paths case-insensitive we ignore that. + self.assertEqual(p.exe().lower(), w.ExecutablePath.lower()) + + def test_cmdline(self): + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + self.assertEqual(' '.join(p.cmdline()), + w.CommandLine.replace('"', '')) + + def test_username(self): + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + domain, _, username = w.GetOwner() + username = "%s\\%s" % (domain, username) + self.assertEqual(p.username(), username) + + def test_memory_rss(self): + time.sleep(0.1) + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + rss = p.memory_info().rss + self.assertEqual(rss, int(w.WorkingSetSize)) + + def test_memory_vms(self): + time.sleep(0.1) + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + vms = p.memory_info().vms + # http://msdn.microsoft.com/en-us/library/aa394372(VS.85).aspx + # ...claims that PageFileUsage is represented in Kilo + # bytes but funnily enough on certain platforms bytes are + # returned instead. + wmi_usage = int(w.PageFileUsage) + if (vms != wmi_usage) and (vms != wmi_usage * 1024): + self.fail("wmi=%s, psutil=%s" % (wmi_usage, vms)) + + def test_create_time(self): + w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] + p = psutil.Process(self.pid) + wmic_create = str(w.CreationDate.split('.')[0]) + psutil_create = time.strftime("%Y%m%d%H%M%S", + time.localtime(p.create_time())) + self.assertEqual(wmic_create, psutil_create) + + +@unittest.skipIf(not WINDOWS, "WINDOWS only") +class TestDualProcessImplementation(unittest.TestCase): + """ + Certain APIs on Windows have 2 internal implementations, one + based on documented Windows APIs, another one based + NtQuerySystemInformation() which gets called as fallback in + case the first fails because of limited permission error. + Here we test that the two methods return the exact same value, + see: + https://github.com/giampaolo/psutil/issues/304 + """ + + @classmethod + def setUpClass(cls): + cls.pid = get_test_subprocess().pid + + @classmethod + def tearDownClass(cls): + reap_children() + # --- + # same tests as above but mimicks the AccessDenied failure of + # the first (fast) method failing with AD. + + def test_name(self): + name = psutil.Process(self.pid).name() + with mock.patch("psutil._psplatform.cext.proc_exe", + side_effect=psutil.AccessDenied(os.getpid())) as fun: + self.assertEqual(psutil.Process(self.pid).name(), name) + assert fun.called + + def test_memory_info(self): + mem_1 = psutil.Process(self.pid).memory_info() + with mock.patch("psutil._psplatform.cext.proc_memory_info", + side_effect=OSError(errno.EPERM, "msg")) as fun: + mem_2 = psutil.Process(self.pid).memory_info() + self.assertEqual(len(mem_1), len(mem_2)) + for i in range(len(mem_1)): + self.assertGreaterEqual(mem_1[i], 0) + self.assertGreaterEqual(mem_2[i], 0) + self.assertAlmostEqual(mem_1[i], mem_2[i], delta=512) + assert fun.called + + def test_create_time(self): + ctime = psutil.Process(self.pid).create_time() + with mock.patch("psutil._psplatform.cext.proc_create_time", + side_effect=OSError(errno.EPERM, "msg")) as fun: + self.assertEqual(psutil.Process(self.pid).create_time(), ctime) + assert fun.called + + def test_cpu_times(self): + cpu_times_1 = psutil.Process(self.pid).cpu_times() + with mock.patch("psutil._psplatform.cext.proc_cpu_times", + side_effect=OSError(errno.EPERM, "msg")) as fun: + cpu_times_2 = psutil.Process(self.pid).cpu_times() + assert fun.called + self.assertAlmostEqual( + cpu_times_1.user, cpu_times_2.user, delta=0.01) + self.assertAlmostEqual( + cpu_times_1.system, cpu_times_2.system, delta=0.01) + + def test_io_counters(self): + io_counters_1 = psutil.Process(self.pid).io_counters() + with mock.patch("psutil._psplatform.cext.proc_io_counters", + side_effect=OSError(errno.EPERM, "msg")) as fun: + io_counters_2 = psutil.Process(self.pid).io_counters() + for i in range(len(io_counters_1)): + self.assertAlmostEqual( + io_counters_1[i], io_counters_2[i], delta=5) + assert fun.called + + def test_num_handles(self): + num_handles = psutil.Process(self.pid).num_handles() + with mock.patch("psutil._psplatform.cext.proc_num_handles", + side_effect=OSError(errno.EPERM, "msg")) as fun: + self.assertEqual(psutil.Process(self.pid).num_handles(), + num_handles) + assert fun.called + + def test_cmdline(self): + from psutil._pswindows import ACCESS_DENIED_ERRSET + for pid in psutil.pids(): + try: + a = cext.proc_cmdline(pid, use_peb=True) + b = cext.proc_cmdline(pid, use_peb=False) + except OSError as err: + if err.errno in ACCESS_DENIED_ERRSET: + pass + elif err.errno == errno.ESRCH: + pass # NSP + else: + raise + else: + self.assertEqual(a, b) + + +@unittest.skipIf(not WINDOWS, "WINDOWS only") +class RemoteProcessTestCase(unittest.TestCase): + """Certain functions require calling ReadProcessMemory. + This trivially works when called on the current process. + Check that this works on other processes, especially when they + have a different bitness. + """ + + @staticmethod + def find_other_interpreter(): + # find a python interpreter that is of the opposite bitness from us + code = "import sys; sys.stdout.write(str(sys.maxsize > 2**32))" + + # XXX: a different and probably more stable approach might be to access + # the registry but accessing 64 bit paths from a 32 bit process + for filename in glob.glob(r"C:\Python*\python.exe"): + proc = subprocess.Popen(args=[filename, "-c", code], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + output, _ = proc.communicate() + if output == str(not IS_64_BIT): + return filename + + @classmethod + def setUpClass(cls): + other_python = cls.find_other_interpreter() + + if other_python is None: + raise unittest.SkipTest( + "could not find interpreter with opposite bitness") + + if IS_64_BIT: + cls.python64 = sys.executable + cls.python32 = other_python + else: + cls.python64 = other_python + cls.python32 = sys.executable + + test_args = ["-c", "import sys; sys.stdin.read()"] + + def setUp(self): + env = os.environ.copy() + env["THINK_OF_A_NUMBER"] = str(os.getpid()) + self.proc32 = get_test_subprocess([self.python32] + self.test_args, + env=env, + stdin=subprocess.PIPE) + self.proc64 = get_test_subprocess([self.python64] + self.test_args, + env=env, + stdin=subprocess.PIPE) + + def tearDown(self): + self.proc32.communicate() + self.proc64.communicate() + reap_children() + + @classmethod + def tearDownClass(cls): + reap_children() + + def test_cmdline_32(self): + p = psutil.Process(self.proc32.pid) + self.assertEqual(len(p.cmdline()), 3) + self.assertEqual(p.cmdline()[1:], self.test_args) + + def test_cmdline_64(self): + p = psutil.Process(self.proc64.pid) + self.assertEqual(len(p.cmdline()), 3) + self.assertEqual(p.cmdline()[1:], self.test_args) + + def test_cwd_32(self): + p = psutil.Process(self.proc32.pid) + self.assertEqual(p.cwd(), os.getcwd()) + + def test_cwd_64(self): + p = psutil.Process(self.proc64.pid) + self.assertEqual(p.cwd(), os.getcwd()) + + def test_environ_32(self): + p = psutil.Process(self.proc32.pid) + e = p.environ() + self.assertIn("THINK_OF_A_NUMBER", e) + self.assertEquals(e["THINK_OF_A_NUMBER"], str(os.getpid())) + + def test_environ_64(self): + p = psutil.Process(self.proc64.pid) + try: + p.environ() + except psutil.AccessDenied: + pass + + +# =================================================================== +# Windows services +# =================================================================== + + +@unittest.skipIf(not WINDOWS, "WINDOWS only") +class TestServices(unittest.TestCase): + + def test_win_service_iter(self): + valid_statuses = set([ + "running", + "paused", + "start", + "pause", + "continue", + "stop", + "stopped", + ]) + valid_start_types = set([ + "automatic", + "manual", + "disabled", + ]) + valid_statuses = set([ + "running", + "paused", + "start_pending", + "pause_pending", + "continue_pending", + "stop_pending", + "stopped" + ]) + for serv in psutil.win_service_iter(): + data = serv.as_dict() + self.assertIsInstance(data['name'], str) + self.assertNotEqual(data['name'].strip(), "") + self.assertIsInstance(data['display_name'], str) + self.assertIsInstance(data['username'], str) + self.assertIn(data['status'], valid_statuses) + if data['pid'] is not None: + psutil.Process(data['pid']) + self.assertIsInstance(data['binpath'], str) + self.assertIsInstance(data['username'], str) + self.assertIsInstance(data['start_type'], str) + self.assertIn(data['start_type'], valid_start_types) + self.assertIn(data['status'], valid_statuses) + self.assertIsInstance(data['description'], str) + pid = serv.pid() + if pid is not None: + p = psutil.Process(pid) + self.assertTrue(p.is_running()) + # win_service_get + s = psutil.win_service_get(serv.name()) + # test __eq__ + self.assertEqual(serv, s) + + def test_win_service_get(self): + name = next(psutil.win_service_iter()).name() + + with self.assertRaises(psutil.NoSuchProcess) as cm: + psutil.win_service_get(name + '???') + self.assertEqual(cm.exception.name, name + '???') + + # test NoSuchProcess + service = psutil.win_service_get(name) + exc = WindowsError( + psutil._psplatform.cext.ERROR_SERVICE_DOES_NOT_EXIST, "") + with mock.patch("psutil._psplatform.cext.winservice_query_status", + side_effect=exc): + self.assertRaises(psutil.NoSuchProcess, service.status) + with mock.patch("psutil._psplatform.cext.winservice_query_config", + side_effect=exc): + self.assertRaises(psutil.NoSuchProcess, service.username) + + # test AccessDenied + exc = WindowsError( + psutil._psplatform.cext.ERROR_ACCESS_DENIED, "") + with mock.patch("psutil._psplatform.cext.winservice_query_status", + side_effect=exc): + self.assertRaises(psutil.AccessDenied, service.status) + with mock.patch("psutil._psplatform.cext.winservice_query_config", + side_effect=exc): + self.assertRaises(psutil.AccessDenied, service.username) + + # test __str__ and __repr__ + self.assertIn(service.name(), str(service)) + self.assertIn(service.display_name(), str(service)) + self.assertIn(service.name(), repr(service)) + self.assertIn(service.display_name(), repr(service)) + + +if __name__ == '__main__': + run_test_module_by_name(__file__) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/wheel/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/wheel/__pycache__/__init__.cpython-37.pyc index 2d91388c2b088d1507aee7a30aebda7b54e1f0a1..019159f2d4de59e878b434f38b7e0d4e0ff540b8 100644 GIT binary patch delta 21 bcmX@bc#4tNiI_L(jF2f delta 47 zcmZ3^IG2&ziI)K28KkZ^OhiU}=FEh>(2OinF|amg>w%gIknDV~_>1OO=$ B4w3)> diff --git a/WPy32-3720/python-3.7.2/Lib/urllib/__pycache__/error.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/urllib/__pycache__/error.cpython-37.pyc index 233592bb17ccd33d0c7ba75c2662861e30254912..74620c0de0232ce6e5eb96af384ed08a2487d4ef 100644 GIT binary patch delta 20 acmew;`cahIiI)NbT{#svU8Jq6JK diff --git a/WPy32-3720/python-3.7.2/Lib/urllib/__pycache__/parse.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/urllib/__pycache__/parse.cpython-37.pyc index b9f2b3b7e1cb75c77d8731809599242305741863..09d5689f708a96687066a35df16a401ba31aa948 100644 GIT binary patch delta 3912 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 PhLD;eqUB1Cs1o}x>61OQ diff --git a/WPy32-3720/python-3.7.2/Lib/urllib/__pycache__/request.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/urllib/__pycache__/request.cpython-37.pyc index 1b6dad4b7f241d5094c8f8fb392bc4f3ba349695..9bbf0293298465c11a6f6cadde5a4792a2d40670 100644 GIT binary patch delta 25 fcmeC&%F?-&h1-djmx}=irj>1Mlc}kMoiIlc}kMoiI)NbV7&jSE9w*_VZ diff --git a/WPy32-3720/python-3.7.2/Lib/xml/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/xml/__pycache__/__init__.cpython-37.pyc index 8699bec82723b0e91e6e76f62891e8457af97a48..0dc1e3c27291fe9bdc183c6c9b73d1bdd50d2de4 100644 GIT binary patch delta 59 zcmcb}dYhHoiIoL`U{T$CK@6XRcy Nnimw{IC%n-BLEN=6CwZr delta 49 zcmcc3dXbgeiIk7?OGCT=HQUM>b8m|nJVBe(Q=08vo}!Tk7?OGCT=HQUM>b8c;ZpJkz0B_08vy1tpET3 diff --git a/WPy32-3720/python-3.7.2/Lib/xml/etree/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/xml/etree/__pycache__/__init__.cpython-37.pyc index e07cdfdb5e2d3cb51a6b7402fbe9f29889e0c256..0ecde883985dd577476374e43d00b2a098491f14 100644 GIT binary patch delta 19 ZcmZ3*xQdb6iI>rY1u6gl diff --git a/WPy32-3720/python-3.7.2/Lib/xml/parsers/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/xml/parsers/__pycache__/__init__.cpython-37.pyc index 8c0c6633df77facbfd9f82ac57e266bf07add731..860cf43a615eb1bd5b5a64bba5ef140dc35500e4 100644 GIT binary patch delta 58 zcmX@dbc2c8iIm2 i{PJ+NiU}=FEh>(2OinF|amg>w%gIknDW0s!=mP+~*&L?; diff --git a/WPy32-3720/python-3.7.2/Lib/xml/sax/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/xml/sax/__pycache__/__init__.cpython-37.pyc index 133422c9098f55f2fc38bbcd35cc315f02c21523..b5dc74bbab9e50055f90d875a6d10a3e934d21ad 100644 GIT binary patch delta 20 acmZpcY?kD9;^pOH0D|dd8#i)S@BjcSssyM2 delta 20 ZcmZpcY?kD9;^pOH0D>nTwHvuBcmOM{1d{*& diff --git a/WPy32-3720/python-3.7.2/Lib/xml/sax/__pycache__/_exceptions.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/xml/sax/__pycache__/_exceptions.cpython-37.pyc index 5a1aef3cf7b2576258dacaacd0ec1cd6b72df222..2317b3e69b0e4b96b42bd54d2fb81bde32e897a7 100644 GIT binary patch delta 20 acmeCs?$G9T;^pOH0D|dd8#i*-iUI&H0|ev% delta 20 ZcmeCs?$G9T;^pOH0D>nTwHvu>MFB4c1kV5f diff --git a/WPy32-3720/python-3.7.2/Lib/xml/sax/__pycache__/handler.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/xml/sax/__pycache__/handler.cpython-37.pyc index a81143ee63a2b093762a203339daf6adf90ba955..df035114643dc85a9191651855a9a97ee5135e7e 100644 GIT binary patch delta 20 acmaEo@FaoTiI delta 20 acmaEo@FaoTiI)K27{0{|$p1fc)` diff --git a/WPy32-3720/python-3.7.2/Lib/xmlrpc/__pycache__/client.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/xmlrpc/__pycache__/client.cpython-37.pyc index a1428f2f5bb204d566d89572905bd1c60a11d169..557ed6ab2409113275c3922a3376ba9b86141ac5 100644 GIT binary patch delta 22 ccmeC}W9sc=;&$TY17)?ax=9906@kCuK)l5 delta 22 bcmeC}W9sc=;&$TY

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 literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_pslinux.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_pslinux.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..623e239df22bf4a13ef9775c7070627b632f127d GIT binary patch literal 48476 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 YDLsFWb%@JB>ps*DSp%TsVBh`!2ZI!2K>z>% literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_psposix.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_psposix.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..02f08085758a1bac3598d487b3f4fbd648e24e72 GIT binary patch literal 3685 zcmZu!&2JmW72nwp?(##jtf+SCy3SUB5!0<@q(y=zFq|r~VheC+L!v8Xp_W*2htf*R zU3z9Hi3({HmH{h34fLFo74%XdD9}s)f}$wU|6tKe+mq2-k3IGGW+_>2y2Q-Bee>qc z*YEx2@so*(ih<{^yMI`J|GS3qPx?4{YzRL?kzb>VjKGLkWF{Ft>jo|}AUlw~z|(RGayck#*-a|lYEad(2e}s1AeW;`RE=tzb}$i{!DKWM zm7f{Gx#)Z}8C9OKU@AHnRiQc0-DoPRJu?njFddmIMt%C=>T=dsamuCN&br+!^;PDF zN#gf18SndYAQkV*xmQ?@(RjsB*IDj%c{hs>IK+yKV!6|o;U;}eXra~PqRmqUh4t|B zpHPQ>8n?5E=apU@wfKH4mCU`pFjg%n@(THA>Av~YCRZ)RMK?~vq}2_3Z5osw6NPqu z0YxULhS=R5Q`BfBgDGXaWTZJZnXzi5pW22pcPe6o86(DwgKI;!Z7FNpMvvQ(wPK9F z9eg*)!;n2?t43r;_J}=UYsTkBT3R!xC9<(o&cO!@TfDvF?`?6l#f6WF`^8H97`wK` z{dQjnEZgsitj(qLRk)GxIYIMpe%h#)ax;^;y%Q%%?mk#q6e1J3!-Yt*z*$^bUbu(X z!^P##>Sk`ywpeKUogt>t|342FK3abyxsdDgZ7$a5d%ZiM3fJ#v?J!wy@@{Xv7x!+& zsZ=<;8=XD5FLpkZ>ph9XO-^2|p47)W*Bb~AUN57_3#bg!E7{CsQ~1?Pn@Z_|*|w+& zPZ@=Fp1$Q}tmnD$oIN+6ThHx|LkNE6jVxs-7FmjIvqS4k`v`d6DT_~@8yyxoQ3)3I zk$q?!Sr?5j&9tWVZlRC7k+c7&!Q>F_>*lC5a&dm0@%jA)=Z82rxHt4p&+pemYv>%Z zk+auKe>B$9IsS3~iYgre-Qt@Qi^pHl={^1m9?hq~g+5>JiAU%AxVdHwOHmm;|8{EM zRPIY}=pHliZ%Ad5s>X@|xkB=9nD8K1Nrtu-L3;rsK4p)a1j}$9OSh?#JCOkK$1AWH9c!9LAFS&A7|KJ&XIj zSn$Xv>M1mErB!o!f~WCMapa)9MJW6!Dqze2#(a${bH@?Bg6_yT0^7c@o-)N=nnU9l z(XT8pgE<3cJw!a$?MB@cQ}B@6Y1rkjh*>tjnECzPzaRYeJZek+a;DD(kgEmAm8RT(zoYE8Z!I;Q=uV?sSrD3B4$IA zA`XF?#1E(0{mh;7UK;NwdB5G{(*b%~esK$X$d$ zsFV;FX$;yEaSj!TcB#=^4oZs)_m=M8(PUWcOm%hX)0L&WjrseFcXDsF2|C7SUWR&c zZK(-mb(Msb=6v(fN?!SSnDn`(@_M=0z34$DTsdw@EY|-b;g|pQfelC7O}Po%z(F{19Q73p~$S5Gp1*H%(N=3 zX4P25I*lV@{wj*b-Jc;SLrk5-%7~@WVDj}Bc(Vy6ws4bT&*`V^p`n~ZQzV1wq4Bar ze0hv08_}&hGq(L@VT(J|T*JLk#36ixg9{yQ-!e*N#u%A+SI4r2cWo@&Lvv`oZH%0u zGqf)nqmr6{RHFOlg*9^3B-+t3bR+8p@va@tfg+X*8l{ZF*BJ$fQ)X@ApU5vbI8<8& zwKOutKk^?nmeyd}2Yv@2E?ly^ptSd|`r3!=g>8;YKW=aNCp_Dx>pjNht_f;mfZm{F ze~Hon*mU}7TgBkBS(V{Bp49|83!7-x-zB_A4AV(?TM^@GAKFmck=dIgbHTy=vmL?t z*wr|{nuVJlO*k#6oN|z}X4=)MEzR+a<6;K{#dMtkn^`}NTHroMPbIghb8ge1xqFh& zof9RP>p%%WbD`Sp$b9-yk=re%bWQ0{$SbkbsYr@k#YLCA#C2c$W}| zo~>ii^eoSwMEfZV(kxFS?N|7SjS(>+WvNWR&0_{+v;B=ByJP$!KrGDcR6JWNUSMIi1=>Y<~NYa-ni}4X6iHpFlnm-Add)+K={KVig;o_!JgX;$sE%ubWdA&hrvzcTY`Q*IBR#P-+WE3Q86L#pLYzg#!P0M*{vGHKB z(F6=FkY!*dQp{l6UQ^}kyGhW-euE;(!fPe4F8#Y1H4!-Bv5Y-Q3c| zFFu5AaqGNC5?u>{+baJ02#Zv7Xc}bb2|YHYK)uE>oPj3bjI!q9+8}ZkgcCiZGXOe8 lQSRO9W>G)kw+Xw_M`eSW$3L?M>efH2=Gc~Zxw7EB_g|SWuJ8Z= literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_pssunos.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_pssunos.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..15392b5402309990dba2365f8319dd3cc6a72f74 GIT binary patch literal 18022 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 L%NW^U_R#+WK3Lri literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_pswindows.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/__pycache__/_pswindows.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0827cba748f670589540b37feb065876657c4b25 GIT binary patch literal 26945 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 literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_common.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_common.py new file mode 100644 index 00000000..6d430388 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_common.py @@ -0,0 +1,600 @@ +# 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. + +"""Common objects shared by __init__.py and _ps*.py modules.""" + +# Note: this module is imported by setup.py so it should not import +# psutil or third-party modules. + +from __future__ import division + +import contextlib +import errno +import functools +import os +import socket +import stat +import sys +import threading +import warnings +from collections import defaultdict +from collections import namedtuple +from socket import AF_INET +from socket import SOCK_DGRAM +from socket import SOCK_STREAM +try: + from socket import AF_INET6 +except ImportError: + AF_INET6 = None +try: + from socket import AF_UNIX +except ImportError: + AF_UNIX = None + +if sys.version_info >= (3, 4): + import enum +else: + enum = None + +# can't take it from _common.py as this script is imported by setup.py +PY3 = sys.version_info[0] == 3 + +__all__ = [ + # constants + 'FREEBSD', 'BSD', 'LINUX', 'NETBSD', 'OPENBSD', 'MACOS', 'OSX', 'POSIX', + 'SUNOS', 'WINDOWS', + 'ENCODING', 'ENCODING_ERRS', 'AF_INET6', + # connection constants + 'CONN_CLOSE', 'CONN_CLOSE_WAIT', 'CONN_CLOSING', 'CONN_ESTABLISHED', + 'CONN_FIN_WAIT1', 'CONN_FIN_WAIT2', 'CONN_LAST_ACK', 'CONN_LISTEN', + 'CONN_NONE', 'CONN_SYN_RECV', 'CONN_SYN_SENT', 'CONN_TIME_WAIT', + # net constants + 'NIC_DUPLEX_FULL', 'NIC_DUPLEX_HALF', 'NIC_DUPLEX_UNKNOWN', + # process status constants + 'STATUS_DEAD', 'STATUS_DISK_SLEEP', 'STATUS_IDLE', 'STATUS_LOCKED', + 'STATUS_RUNNING', 'STATUS_SLEEPING', 'STATUS_STOPPED', 'STATUS_SUSPENDED', + 'STATUS_TRACING_STOP', 'STATUS_WAITING', 'STATUS_WAKE_KILL', + 'STATUS_WAKING', 'STATUS_ZOMBIE', 'STATUS_PARKED', + # named tuples + 'pconn', 'pcputimes', 'pctxsw', 'pgids', 'pio', 'pionice', 'popenfile', + 'pthread', 'puids', 'sconn', 'scpustats', 'sdiskio', 'sdiskpart', + 'sdiskusage', 'snetio', 'snicaddr', 'snicstats', 'sswap', 'suser', + # utility functions + 'conn_tmap', 'deprecated_method', 'isfile_strict', 'memoize', + 'parse_environ_block', 'path_exists_strict', 'usage_percent', + 'supports_ipv6', 'sockfam_to_enum', 'socktype_to_enum', "wrap_numbers", +] + + +# =================================================================== +# --- OS constants +# =================================================================== + + +POSIX = os.name == "posix" +WINDOWS = os.name == "nt" +LINUX = sys.platform.startswith("linux") +MACOS = sys.platform.startswith("darwin") +OSX = MACOS # deprecated alias +FREEBSD = sys.platform.startswith("freebsd") +OPENBSD = sys.platform.startswith("openbsd") +NETBSD = sys.platform.startswith("netbsd") +BSD = FREEBSD or OPENBSD or NETBSD +SUNOS = sys.platform.startswith(("sunos", "solaris")) +AIX = sys.platform.startswith("aix") + + +# =================================================================== +# --- API constants +# =================================================================== + + +# Process.status() +STATUS_RUNNING = "running" +STATUS_SLEEPING = "sleeping" +STATUS_DISK_SLEEP = "disk-sleep" +STATUS_STOPPED = "stopped" +STATUS_TRACING_STOP = "tracing-stop" +STATUS_ZOMBIE = "zombie" +STATUS_DEAD = "dead" +STATUS_WAKE_KILL = "wake-kill" +STATUS_WAKING = "waking" +STATUS_IDLE = "idle" # Linux, macOS, FreeBSD +STATUS_LOCKED = "locked" # FreeBSD +STATUS_WAITING = "waiting" # FreeBSD +STATUS_SUSPENDED = "suspended" # NetBSD +STATUS_PARKED = "parked" # Linux + +# Process.connections() and psutil.net_connections() +CONN_ESTABLISHED = "ESTABLISHED" +CONN_SYN_SENT = "SYN_SENT" +CONN_SYN_RECV = "SYN_RECV" +CONN_FIN_WAIT1 = "FIN_WAIT1" +CONN_FIN_WAIT2 = "FIN_WAIT2" +CONN_TIME_WAIT = "TIME_WAIT" +CONN_CLOSE = "CLOSE" +CONN_CLOSE_WAIT = "CLOSE_WAIT" +CONN_LAST_ACK = "LAST_ACK" +CONN_LISTEN = "LISTEN" +CONN_CLOSING = "CLOSING" +CONN_NONE = "NONE" + +# net_if_stats() +if enum is None: + NIC_DUPLEX_FULL = 2 + NIC_DUPLEX_HALF = 1 + NIC_DUPLEX_UNKNOWN = 0 +else: + class NicDuplex(enum.IntEnum): + NIC_DUPLEX_FULL = 2 + NIC_DUPLEX_HALF = 1 + NIC_DUPLEX_UNKNOWN = 0 + + globals().update(NicDuplex.__members__) + +# sensors_battery() +if enum is None: + POWER_TIME_UNKNOWN = -1 + POWER_TIME_UNLIMITED = -2 +else: + class BatteryTime(enum.IntEnum): + POWER_TIME_UNKNOWN = -1 + POWER_TIME_UNLIMITED = -2 + + globals().update(BatteryTime.__members__) + +# --- others + +ENCODING = sys.getfilesystemencoding() +if not PY3: + ENCODING_ERRS = "replace" +else: + try: + ENCODING_ERRS = sys.getfilesystemencodeerrors() # py 3.6 + except AttributeError: + ENCODING_ERRS = "surrogateescape" if POSIX else "replace" + + +# =================================================================== +# --- namedtuples +# =================================================================== + +# --- for system functions + +# psutil.swap_memory() +sswap = namedtuple('sswap', ['total', 'used', 'free', 'percent', 'sin', + 'sout']) +# psutil.disk_usage() +sdiskusage = namedtuple('sdiskusage', ['total', 'used', 'free', 'percent']) +# psutil.disk_io_counters() +sdiskio = namedtuple('sdiskio', ['read_count', 'write_count', + 'read_bytes', 'write_bytes', + 'read_time', 'write_time']) +# psutil.disk_partitions() +sdiskpart = namedtuple('sdiskpart', ['device', 'mountpoint', 'fstype', 'opts']) +# psutil.net_io_counters() +snetio = namedtuple('snetio', ['bytes_sent', 'bytes_recv', + 'packets_sent', 'packets_recv', + 'errin', 'errout', + 'dropin', 'dropout']) +# psutil.users() +suser = namedtuple('suser', ['name', 'terminal', 'host', 'started', 'pid']) +# psutil.net_connections() +sconn = namedtuple('sconn', ['fd', 'family', 'type', 'laddr', 'raddr', + 'status', 'pid']) +# psutil.net_if_addrs() +snicaddr = namedtuple('snicaddr', + ['family', 'address', 'netmask', 'broadcast', 'ptp']) +# psutil.net_if_stats() +snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu']) +# psutil.cpu_stats() +scpustats = namedtuple( + 'scpustats', ['ctx_switches', 'interrupts', 'soft_interrupts', 'syscalls']) +# psutil.cpu_freq() +scpufreq = namedtuple('scpufreq', ['current', 'min', 'max']) +# psutil.sensors_temperatures() +shwtemp = namedtuple( + 'shwtemp', ['label', 'current', 'high', 'critical']) +# psutil.sensors_battery() +sbattery = namedtuple('sbattery', ['percent', 'secsleft', 'power_plugged']) +# psutil.sensors_fans() +sfan = namedtuple('sfan', ['label', 'current']) + +# --- for Process methods + +# psutil.Process.cpu_times() +pcputimes = namedtuple('pcputimes', + ['user', 'system', 'children_user', 'children_system']) +# psutil.Process.open_files() +popenfile = namedtuple('popenfile', ['path', 'fd']) +# psutil.Process.threads() +pthread = namedtuple('pthread', ['id', 'user_time', 'system_time']) +# psutil.Process.uids() +puids = namedtuple('puids', ['real', 'effective', 'saved']) +# psutil.Process.gids() +pgids = namedtuple('pgids', ['real', 'effective', 'saved']) +# psutil.Process.io_counters() +pio = namedtuple('pio', ['read_count', 'write_count', + 'read_bytes', 'write_bytes']) +# psutil.Process.ionice() +pionice = namedtuple('pionice', ['ioclass', 'value']) +# psutil.Process.ctx_switches() +pctxsw = namedtuple('pctxsw', ['voluntary', 'involuntary']) +# psutil.Process.connections() +pconn = namedtuple('pconn', ['fd', 'family', 'type', 'laddr', 'raddr', + 'status']) + +# psutil.connections() and psutil.Process.connections() +addr = namedtuple('addr', ['ip', 'port']) + + +# =================================================================== +# --- Process.connections() 'kind' parameter mapping +# =================================================================== + + +conn_tmap = { + "all": ([AF_INET, AF_INET6, AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]), + "tcp": ([AF_INET, AF_INET6], [SOCK_STREAM]), + "tcp4": ([AF_INET], [SOCK_STREAM]), + "udp": ([AF_INET, AF_INET6], [SOCK_DGRAM]), + "udp4": ([AF_INET], [SOCK_DGRAM]), + "inet": ([AF_INET, AF_INET6], [SOCK_STREAM, SOCK_DGRAM]), + "inet4": ([AF_INET], [SOCK_STREAM, SOCK_DGRAM]), + "inet6": ([AF_INET6], [SOCK_STREAM, SOCK_DGRAM]), +} + +if AF_INET6 is not None: + conn_tmap.update({ + "tcp6": ([AF_INET6], [SOCK_STREAM]), + "udp6": ([AF_INET6], [SOCK_DGRAM]), + }) + +if AF_UNIX is not None: + conn_tmap.update({ + "unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]), + }) + +del AF_INET, AF_UNIX, SOCK_STREAM, SOCK_DGRAM + + +# =================================================================== +# --- utils +# =================================================================== + + +def usage_percent(used, total, round_=None): + """Calculate percentage usage of 'used' against 'total'.""" + try: + ret = (used / total) * 100 + except ZeroDivisionError: + ret = 0.0 if isinstance(used, float) or isinstance(total, float) else 0 + if round_ is not None: + return round(ret, round_) + else: + return ret + + +def memoize(fun): + """A simple memoize decorator for functions supporting (hashable) + positional arguments. + It also provides a cache_clear() function for clearing the cache: + + >>> @memoize + ... def foo() + ... return 1 + ... + >>> foo() + 1 + >>> foo.cache_clear() + >>> + """ + @functools.wraps(fun) + def wrapper(*args, **kwargs): + key = (args, frozenset(sorted(kwargs.items()))) + try: + return cache[key] + except KeyError: + ret = cache[key] = fun(*args, **kwargs) + return ret + + def cache_clear(): + """Clear cache.""" + cache.clear() + + cache = {} + wrapper.cache_clear = cache_clear + return wrapper + + +def memoize_when_activated(fun): + """A memoize decorator which is disabled by default. It can be + activated and deactivated on request. + For efficiency reasons it can be used only against class methods + accepting no arguments. + + >>> class Foo: + ... @memoize + ... def foo() + ... print(1) + ... + >>> f = Foo() + >>> # deactivated (default) + >>> foo() + 1 + >>> foo() + 1 + >>> + >>> # activated + >>> foo.cache_activate(self) + >>> foo() + 1 + >>> foo() + >>> foo() + >>> + """ + @functools.wraps(fun) + def wrapper(self): + try: + # case 1: we previously entered oneshot() ctx + ret = self._cache[fun] + except AttributeError: + # case 2: we never entered oneshot() ctx + return fun(self) + except KeyError: + # case 3: we entered oneshot() ctx but there's no cache + # for this entry yet + ret = self._cache[fun] = fun(self) + return ret + + def cache_activate(proc): + """Activate cache. Expects a Process instance. Cache will be + stored as a "_cache" instance attribute.""" + proc._cache = {} + + def cache_deactivate(proc): + """Deactivate and clear cache.""" + try: + del proc._cache + except AttributeError: + pass + + wrapper.cache_activate = cache_activate + wrapper.cache_deactivate = cache_deactivate + return wrapper + + +def isfile_strict(path): + """Same as os.path.isfile() but does not swallow EACCES / EPERM + exceptions, see: + http://mail.python.org/pipermail/python-dev/2012-June/120787.html + """ + try: + st = os.stat(path) + except OSError as err: + if err.errno in (errno.EPERM, errno.EACCES): + raise + return False + else: + return stat.S_ISREG(st.st_mode) + + +def path_exists_strict(path): + """Same as os.path.exists() but does not swallow EACCES / EPERM + exceptions, see: + http://mail.python.org/pipermail/python-dev/2012-June/120787.html + """ + try: + os.stat(path) + except OSError as err: + if err.errno in (errno.EPERM, errno.EACCES): + raise + return False + else: + return True + + +@memoize +def supports_ipv6(): + """Return True if IPv6 is supported on this platform.""" + if not socket.has_ipv6 or AF_INET6 is None: + return False + try: + sock = socket.socket(AF_INET6, socket.SOCK_STREAM) + with contextlib.closing(sock): + sock.bind(("::1", 0)) + return True + except socket.error: + return False + + +def parse_environ_block(data): + """Parse a C environ block of environment variables into a dictionary.""" + # The block is usually raw data from the target process. It might contain + # trailing garbage and lines that do not look like assignments. + ret = {} + pos = 0 + + # localize global variable to speed up access. + WINDOWS_ = WINDOWS + while True: + next_pos = data.find("\0", pos) + # nul byte at the beginning or double nul byte means finish + if next_pos <= pos: + break + # there might not be an equals sign + equal_pos = data.find("=", pos, next_pos) + if equal_pos > pos: + key = data[pos:equal_pos] + value = data[equal_pos + 1:next_pos] + # Windows expects environment variables to be uppercase only + if WINDOWS_: + key = key.upper() + ret[key] = value + pos = next_pos + 1 + + return ret + + +def sockfam_to_enum(num): + """Convert a numeric socket family value to an IntEnum member. + If it's not a known member, return the numeric value itself. + """ + if enum is None: + return num + else: # pragma: no cover + try: + return socket.AddressFamily(num) + except (ValueError, AttributeError): + return num + + +def socktype_to_enum(num): + """Convert a numeric socket type value to an IntEnum member. + If it's not a known member, return the numeric value itself. + """ + if enum is None: + return num + else: # pragma: no cover + try: + return socket.AddressType(num) + except (ValueError, AttributeError): + return num + + +def deprecated_method(replacement): + """A decorator which can be used to mark a method as deprecated + 'replcement' is the method name which will be called instead. + """ + def outer(fun): + msg = "%s() is deprecated and will be removed; use %s() instead" % ( + fun.__name__, replacement) + if fun.__doc__ is None: + fun.__doc__ = msg + + @functools.wraps(fun) + def inner(self, *args, **kwargs): + warnings.warn(msg, category=DeprecationWarning, stacklevel=2) + return getattr(self, replacement)(*args, **kwargs) + return inner + return outer + + +class _WrapNumbers: + """Watches numbers so that they don't overflow and wrap + (reset to zero). + """ + + def __init__(self): + self.lock = threading.Lock() + self.cache = {} + self.reminders = {} + self.reminder_keys = {} + + def _add_dict(self, input_dict, name): + assert name not in self.cache + assert name not in self.reminders + assert name not in self.reminder_keys + self.cache[name] = input_dict + self.reminders[name] = defaultdict(int) + self.reminder_keys[name] = defaultdict(set) + + def _remove_dead_reminders(self, input_dict, name): + """In case the number of keys changed between calls (e.g. a + disk disappears) this removes the entry from self.reminders. + """ + old_dict = self.cache[name] + gone_keys = set(old_dict.keys()) - set(input_dict.keys()) + for gone_key in gone_keys: + for remkey in self.reminder_keys[name][gone_key]: + del self.reminders[name][remkey] + del self.reminder_keys[name][gone_key] + + def run(self, input_dict, name): + """Cache dict and sum numbers which overflow and wrap. + Return an updated copy of `input_dict` + """ + if name not in self.cache: + # This was the first call. + self._add_dict(input_dict, name) + return input_dict + + self._remove_dead_reminders(input_dict, name) + + old_dict = self.cache[name] + new_dict = {} + for key in input_dict.keys(): + input_tuple = input_dict[key] + try: + old_tuple = old_dict[key] + except KeyError: + # The input dict has a new key (e.g. a new disk or NIC) + # which didn't exist in the previous call. + new_dict[key] = input_tuple + continue + + bits = [] + for i in range(len(input_tuple)): + input_value = input_tuple[i] + old_value = old_tuple[i] + remkey = (key, i) + if input_value < old_value: + # it wrapped! + self.reminders[name][remkey] += old_value + self.reminder_keys[name][key].add(remkey) + bits.append(input_value + self.reminders[name][remkey]) + + new_dict[key] = tuple(bits) + + self.cache[name] = input_dict + return new_dict + + def cache_clear(self, name=None): + """Clear the internal cache, optionally only for function 'name'.""" + with self.lock: + if name is None: + self.cache.clear() + self.reminders.clear() + self.reminder_keys.clear() + else: + self.cache.pop(name, None) + self.reminders.pop(name, None) + self.reminder_keys.pop(name, None) + + def cache_info(self): + """Return internal cache dicts as a tuple of 3 elements.""" + with self.lock: + return (self.cache, self.reminders, self.reminder_keys) + + +def wrap_numbers(input_dict, name): + """Given an `input_dict` and a function `name`, adjust the numbers + which "wrap" (restart from zero) across different calls by adding + "old value" to "new value" and return an updated dict. + """ + with _wn.lock: + return _wn.run(input_dict, name) + + +_wn = _WrapNumbers() +wrap_numbers.cache_clear = _wn.cache_clear +wrap_numbers.cache_info = _wn.cache_info + + +def open_binary(fname, **kwargs): + return open(fname, "rb", **kwargs) + + +def open_text(fname, **kwargs): + """On Python 3 opens a file in text mode by using fs encoding and + a proper en/decoding errors handler. + On Python 2 this is just an alias for open(name, 'rt'). + """ + if PY3: + # See: + # https://github.com/giampaolo/psutil/issues/675 + # https://github.com/giampaolo/psutil/pull/733 + kwargs.setdefault('encoding', ENCODING) + kwargs.setdefault('errors', ENCODING_ERRS) + return open(fname, "rt", **kwargs) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_compat.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_compat.py new file mode 100644 index 00000000..08aefe4b --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_compat.py @@ -0,0 +1,241 @@ +# 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. + +"""Module which provides compatibility with older Python versions.""" + +import collections +import functools +import os +import sys + +__all__ = ["PY3", "long", "xrange", "unicode", "basestring", "u", "b", + "lru_cache", "which"] + +PY3 = sys.version_info[0] == 3 + +if PY3: + long = int + xrange = range + unicode = str + basestring = str + + def u(s): + return s + + def b(s): + return s.encode("latin-1") +else: + long = long + xrange = xrange + unicode = unicode + basestring = basestring + + def u(s): + return unicode(s, "unicode_escape") + + def b(s): + return s + + +# --- stdlib additions + + +# py 3.2 functools.lru_cache +# Taken from: http://code.activestate.com/recipes/578078 +# Credit: Raymond Hettinger +try: + from functools import lru_cache +except ImportError: + try: + from threading import RLock + except ImportError: + from dummy_threading import RLock + + _CacheInfo = collections.namedtuple( + "CacheInfo", ["hits", "misses", "maxsize", "currsize"]) + + class _HashedSeq(list): + __slots__ = 'hashvalue' + + def __init__(self, tup, hash=hash): + self[:] = tup + self.hashvalue = hash(tup) + + def __hash__(self): + return self.hashvalue + + def _make_key(args, kwds, typed, + kwd_mark=(object(), ), + fasttypes=set((int, str, frozenset, type(None))), + sorted=sorted, tuple=tuple, type=type, len=len): + key = args + if kwds: + sorted_items = sorted(kwds.items()) + key += kwd_mark + for item in sorted_items: + key += item + if typed: + key += tuple(type(v) for v in args) + if kwds: + key += tuple(type(v) for k, v in sorted_items) + elif len(key) == 1 and type(key[0]) in fasttypes: + return key[0] + return _HashedSeq(key) + + def lru_cache(maxsize=100, typed=False): + """Least-recently-used cache decorator, see: + http://docs.python.org/3/library/functools.html#functools.lru_cache + """ + def decorating_function(user_function): + cache = dict() + stats = [0, 0] + HITS, MISSES = 0, 1 + make_key = _make_key + cache_get = cache.get + _len = len + lock = RLock() + root = [] + root[:] = [root, root, None, None] + nonlocal_root = [root] + PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 + if maxsize == 0: + def wrapper(*args, **kwds): + result = user_function(*args, **kwds) + stats[MISSES] += 1 + return result + elif maxsize is None: + def wrapper(*args, **kwds): + key = make_key(args, kwds, typed) + result = cache_get(key, root) + if result is not root: + stats[HITS] += 1 + return result + result = user_function(*args, **kwds) + cache[key] = result + stats[MISSES] += 1 + return result + else: + def wrapper(*args, **kwds): + if kwds or typed: + key = make_key(args, kwds, typed) + else: + key = args + lock.acquire() + try: + link = cache_get(key) + if link is not None: + root, = nonlocal_root + link_prev, link_next, key, result = link + link_prev[NEXT] = link_next + link_next[PREV] = link_prev + last = root[PREV] + last[NEXT] = root[PREV] = link + link[PREV] = last + link[NEXT] = root + stats[HITS] += 1 + return result + finally: + lock.release() + result = user_function(*args, **kwds) + lock.acquire() + try: + root, = nonlocal_root + if key in cache: + pass + elif _len(cache) >= maxsize: + oldroot = root + oldroot[KEY] = key + oldroot[RESULT] = result + root = nonlocal_root[0] = oldroot[NEXT] + oldkey = root[KEY] + root[KEY] = root[RESULT] = None + del cache[oldkey] + cache[key] = oldroot + else: + last = root[PREV] + link = [last, root, key, result] + last[NEXT] = root[PREV] = cache[key] = link + stats[MISSES] += 1 + finally: + lock.release() + return result + + def cache_info(): + """Report cache statistics""" + lock.acquire() + try: + return _CacheInfo(stats[HITS], stats[MISSES], maxsize, + len(cache)) + finally: + lock.release() + + def cache_clear(): + """Clear the cache and cache statistics""" + lock.acquire() + try: + cache.clear() + root = nonlocal_root[0] + root[:] = [root, root, None, None] + stats[:] = [0, 0] + finally: + lock.release() + + wrapper.__wrapped__ = user_function + wrapper.cache_info = cache_info + wrapper.cache_clear = cache_clear + return functools.update_wrapper(wrapper, user_function) + + return decorating_function + + +# python 3.3 +try: + from shutil import which +except ImportError: + def which(cmd, mode=os.F_OK | os.X_OK, path=None): + """Given a command, mode, and a PATH string, return the path which + conforms to the given mode on the PATH, or None if there is no such + file. + + `mode` defaults to os.F_OK | os.X_OK. `path` defaults to the result + of os.environ.get("PATH"), or can be overridden with a custom search + path. + """ + def _access_check(fn, mode): + return (os.path.exists(fn) and os.access(fn, mode) and + not os.path.isdir(fn)) + + if os.path.dirname(cmd): + if _access_check(cmd, mode): + return cmd + return None + + if path is None: + path = os.environ.get("PATH", os.defpath) + if not path: + return None + path = path.split(os.pathsep) + + if sys.platform == "win32": + if os.curdir not in path: + path.insert(0, os.curdir) + + pathext = os.environ.get("PATHEXT", "").split(os.pathsep) + if any(cmd.lower().endswith(ext.lower()) for ext in pathext): + files = [cmd] + else: + files = [cmd + ext for ext in pathext] + else: + files = [cmd] + + seen = set() + for dir in path: + normdir = os.path.normcase(dir) + if normdir not in seen: + seen.add(normdir) + for thefile in files: + name = os.path.join(dir, thefile) + if _access_check(name, mode): + return name + return None diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psaix.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psaix.py new file mode 100644 index 00000000..ff086b90 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psaix.py @@ -0,0 +1,581 @@ +# Copyright (c) 2009, Giampaolo Rodola' +# Copyright (c) 2017, Arnon Yaari +# All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""AIX platform implementation.""" + +import errno +import glob +import os +import re +import subprocess +import sys +from collections import namedtuple +from socket import AF_INET + +from . import _common +from . import _psposix +from . import _psutil_aix as cext +from . import _psutil_posix as cext_posix +from ._common import AF_INET6 +from ._common import memoize_when_activated +from ._common import NIC_DUPLEX_FULL +from ._common import NIC_DUPLEX_HALF +from ._common import NIC_DUPLEX_UNKNOWN +from ._common import sockfam_to_enum +from ._common import socktype_to_enum +from ._common import usage_percent +from ._compat import PY3 + + +__extra__all__ = ["PROCFS_PATH"] + + +# ===================================================================== +# --- globals +# ===================================================================== + + +HAS_THREADS = hasattr(cext, "proc_threads") +HAS_NET_IO_COUNTERS = hasattr(cext, "net_io_counters") +HAS_PROC_IO_COUNTERS = hasattr(cext, "proc_io_counters") + +PAGE_SIZE = os.sysconf('SC_PAGE_SIZE') +AF_LINK = cext_posix.AF_LINK + +PROC_STATUSES = { + cext.SIDL: _common.STATUS_IDLE, + cext.SZOMB: _common.STATUS_ZOMBIE, + cext.SACTIVE: _common.STATUS_RUNNING, + cext.SSWAP: _common.STATUS_RUNNING, # TODO what status is this? + cext.SSTOP: _common.STATUS_STOPPED, +} + +TCP_STATUSES = { + cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, + cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, + cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV, + cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, + cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, + cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, + cext.TCPS_CLOSED: _common.CONN_CLOSE, + cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, + cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, + cext.TCPS_LISTEN: _common.CONN_LISTEN, + cext.TCPS_CLOSING: _common.CONN_CLOSING, + cext.PSUTIL_CONN_NONE: _common.CONN_NONE, +} + +proc_info_map = dict( + ppid=0, + rss=1, + vms=2, + create_time=3, + nice=4, + num_threads=5, + status=6, + ttynr=7) + +# These objects get set on "import psutil" from the __init__.py +# file, see: https://github.com/giampaolo/psutil/issues/1402 +NoSuchProcess = None +ZombieProcess = None +AccessDenied = None +TimeoutExpired = None + + +# ===================================================================== +# --- named tuples +# ===================================================================== + + +# psutil.Process.memory_info() +pmem = namedtuple('pmem', ['rss', 'vms']) +# psutil.Process.memory_full_info() +pfullmem = pmem +# psutil.Process.cpu_times() +scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait']) +# psutil.virtual_memory() +svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) + + +# ===================================================================== +# --- utils +# ===================================================================== + + +def get_procfs_path(): + """Return updated psutil.PROCFS_PATH constant.""" + return sys.modules['psutil'].PROCFS_PATH + + +# ===================================================================== +# --- memory +# ===================================================================== + + +def virtual_memory(): + total, avail, free, pinned, inuse = cext.virtual_mem() + percent = usage_percent((total - avail), total, round_=1) + return svmem(total, avail, percent, inuse, free) + + +def swap_memory(): + """Swap system memory as a (total, used, free, sin, sout) tuple.""" + total, free, sin, sout = cext.swap_mem() + used = total - free + percent = usage_percent(used, total, round_=1) + return _common.sswap(total, used, free, percent, sin, sout) + + +# ===================================================================== +# --- CPU +# ===================================================================== + + +def cpu_times(): + """Return system-wide CPU times as a named tuple""" + ret = cext.per_cpu_times() + return scputimes(*[sum(x) for x in zip(*ret)]) + + +def per_cpu_times(): + """Return system per-CPU times as a list of named tuples""" + ret = cext.per_cpu_times() + return [scputimes(*x) for x in ret] + + +def cpu_count_logical(): + """Return the number of logical CPUs in the system.""" + try: + return os.sysconf("SC_NPROCESSORS_ONLN") + except ValueError: + # mimic os.cpu_count() behavior + return None + + +def cpu_count_physical(): + cmd = "lsdev -Cc processor" + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + if PY3: + stdout, stderr = [x.decode(sys.stdout.encoding) + for x in (stdout, stderr)] + if p.returncode != 0: + raise RuntimeError("%r command error\n%s" % (cmd, stderr)) + processors = stdout.strip().splitlines() + return len(processors) or None + + +def cpu_stats(): + """Return various CPU stats as a named tuple.""" + ctx_switches, interrupts, soft_interrupts, syscalls = cext.cpu_stats() + return _common.scpustats( + ctx_switches, interrupts, soft_interrupts, syscalls) + + +# ===================================================================== +# --- disks +# ===================================================================== + + +disk_io_counters = cext.disk_io_counters +disk_usage = _psposix.disk_usage + + +def disk_partitions(all=False): + """Return system disk partitions.""" + # TODO - the filtering logic should be better checked so that + # it tries to reflect 'df' as much as possible + retlist = [] + partitions = cext.disk_partitions() + for partition in partitions: + device, mountpoint, fstype, opts = partition + if device == 'none': + device = '' + if not all: + # Differently from, say, Linux, we don't have a list of + # common fs types so the best we can do, AFAIK, is to + # filter by filesystem having a total size > 0. + if not disk_usage(mountpoint).total: + continue + ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) + retlist.append(ntuple) + return retlist + + +# ===================================================================== +# --- network +# ===================================================================== + + +net_if_addrs = cext_posix.net_if_addrs + +if HAS_NET_IO_COUNTERS: + net_io_counters = cext.net_io_counters + + +def net_connections(kind, _pid=-1): + """Return socket connections. If pid == -1 return system-wide + connections (as opposed to connections opened by one process only). + """ + cmap = _common.conn_tmap + if kind not in cmap: + raise ValueError("invalid %r kind argument; choose between %s" + % (kind, ', '.join([repr(x) for x in cmap]))) + families, types = _common.conn_tmap[kind] + rawlist = cext.net_connections(_pid) + ret = set() + for item in rawlist: + fd, fam, type_, laddr, raddr, status, pid = item + if fam not in families: + continue + if type_ not in types: + continue + status = TCP_STATUSES[status] + if fam in (AF_INET, AF_INET6): + if laddr: + laddr = _common.addr(*laddr) + if raddr: + raddr = _common.addr(*raddr) + fam = sockfam_to_enum(fam) + type_ = socktype_to_enum(type_) + if _pid == -1: + nt = _common.sconn(fd, fam, type_, laddr, raddr, status, pid) + else: + nt = _common.pconn(fd, fam, type_, laddr, raddr, status) + ret.add(nt) + return list(ret) + + +def net_if_stats(): + """Get NIC stats (isup, duplex, speed, mtu).""" + duplex_map = {"Full": NIC_DUPLEX_FULL, + "Half": NIC_DUPLEX_HALF} + names = set([x[0] for x in net_if_addrs()]) + ret = {} + for name in names: + isup, mtu = cext.net_if_stats(name) + + # try to get speed and duplex + # TODO: rewrite this in C (entstat forks, so use truss -f to follow. + # looks like it is using an undocumented ioctl?) + duplex = "" + speed = 0 + p = subprocess.Popen(["/usr/bin/entstat", "-d", name], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + if PY3: + stdout, stderr = [x.decode(sys.stdout.encoding) + for x in (stdout, stderr)] + if p.returncode == 0: + re_result = re.search( + r"Running: (\d+) Mbps.*?(\w+) Duplex", stdout) + if re_result is not None: + speed = int(re_result.group(1)) + duplex = re_result.group(2) + + duplex = duplex_map.get(duplex, NIC_DUPLEX_UNKNOWN) + ret[name] = _common.snicstats(isup, duplex, speed, mtu) + return ret + + +# ===================================================================== +# --- other system functions +# ===================================================================== + + +def boot_time(): + """The system boot time expressed in seconds since the epoch.""" + return cext.boot_time() + + +def users(): + """Return currently connected users as a list of namedtuples.""" + retlist = [] + rawlist = cext.users() + localhost = (':0.0', ':0') + for item in rawlist: + user, tty, hostname, tstamp, user_process, pid = item + # note: the underlying C function includes entries about + # system boot, run level and others. We might want + # to use them in the future. + if not user_process: + continue + if hostname in localhost: + hostname = 'localhost' + nt = _common.suser(user, tty, hostname, tstamp, pid) + retlist.append(nt) + return retlist + + +# ===================================================================== +# --- processes +# ===================================================================== + + +def pids(): + """Returns a list of PIDs currently running on the system.""" + return [int(x) for x in os.listdir(get_procfs_path()) if x.isdigit()] + + +def pid_exists(pid): + """Check for the existence of a unix pid.""" + return os.path.exists(os.path.join(get_procfs_path(), str(pid), "psinfo")) + + +def wrap_exceptions(fun): + """Call callable into a try/except clause and translate ENOENT, + EACCES and EPERM in NoSuchProcess or AccessDenied exceptions. + """ + + def wrapper(self, *args, **kwargs): + try: + return fun(self, *args, **kwargs) + except EnvironmentError as err: + # support for private module import + if (NoSuchProcess is None or AccessDenied is None or + ZombieProcess is None): + raise + # ENOENT (no such file or directory) gets raised on open(). + # ESRCH (no such process) can get raised on read() if + # process is gone in meantime. + if err.errno in (errno.ENOENT, errno.ESRCH): + if not pid_exists(self.pid): + raise NoSuchProcess(self.pid, self._name) + else: + raise ZombieProcess(self.pid, self._name, self._ppid) + if err.errno in (errno.EPERM, errno.EACCES): + raise AccessDenied(self.pid, self._name) + raise + return wrapper + + +class Process(object): + """Wrapper class around underlying C implementation.""" + + __slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"] + + def __init__(self, pid): + self.pid = pid + self._name = None + self._ppid = None + self._procfs_path = get_procfs_path() + + def oneshot_enter(self): + self._proc_name_and_args.cache_activate(self) + self._proc_basic_info.cache_activate(self) + self._proc_cred.cache_activate(self) + + def oneshot_exit(self): + self._proc_name_and_args.cache_deactivate(self) + self._proc_basic_info.cache_deactivate(self) + self._proc_cred.cache_deactivate(self) + + @wrap_exceptions + @memoize_when_activated + def _proc_name_and_args(self): + return cext.proc_name_and_args(self.pid, self._procfs_path) + + @wrap_exceptions + @memoize_when_activated + def _proc_basic_info(self): + return cext.proc_basic_info(self.pid, self._procfs_path) + + @wrap_exceptions + @memoize_when_activated + def _proc_cred(self): + return cext.proc_cred(self.pid, self._procfs_path) + + @wrap_exceptions + def name(self): + if self.pid == 0: + return "swapper" + # note: this is limited to 15 characters + return self._proc_name_and_args()[0].rstrip("\x00") + + @wrap_exceptions + def exe(self): + # there is no way to get executable path in AIX other than to guess, + # and guessing is more complex than what's in the wrapping class + exe = self.cmdline()[0] + if os.path.sep in exe: + # relative or absolute path + if not os.path.isabs(exe): + # if cwd has changed, we're out of luck - this may be wrong! + exe = os.path.abspath(os.path.join(self.cwd(), exe)) + if (os.path.isabs(exe) and + os.path.isfile(exe) and + os.access(exe, os.X_OK)): + return exe + # not found, move to search in PATH using basename only + exe = os.path.basename(exe) + # search for exe name PATH + for path in os.environ["PATH"].split(":"): + possible_exe = os.path.abspath(os.path.join(path, exe)) + if (os.path.isfile(possible_exe) and + os.access(possible_exe, os.X_OK)): + return possible_exe + return '' + + @wrap_exceptions + def cmdline(self): + return self._proc_name_and_args()[1].split(' ') + + @wrap_exceptions + def create_time(self): + return self._proc_basic_info()[proc_info_map['create_time']] + + @wrap_exceptions + def num_threads(self): + return self._proc_basic_info()[proc_info_map['num_threads']] + + if HAS_THREADS: + @wrap_exceptions + def threads(self): + rawlist = cext.proc_threads(self.pid) + retlist = [] + for thread_id, utime, stime in rawlist: + ntuple = _common.pthread(thread_id, utime, stime) + retlist.append(ntuple) + # The underlying C implementation retrieves all OS threads + # and filters them by PID. At this point we can't tell whether + # an empty list means there were no connections for process or + # process is no longer active so we force NSP in case the PID + # is no longer there. + if not retlist: + # will raise NSP if process is gone + os.stat('%s/%s' % (self._procfs_path, self.pid)) + return retlist + + @wrap_exceptions + def connections(self, kind='inet'): + ret = net_connections(kind, _pid=self.pid) + # The underlying C implementation retrieves all OS connections + # and filters them by PID. At this point we can't tell whether + # an empty list means there were no connections for process or + # process is no longer active so we force NSP in case the PID + # is no longer there. + if not ret: + # will raise NSP if process is gone + os.stat('%s/%s' % (self._procfs_path, self.pid)) + return ret + + @wrap_exceptions + def nice_get(self): + return cext_posix.getpriority(self.pid) + + @wrap_exceptions + def nice_set(self, value): + return cext_posix.setpriority(self.pid, value) + + @wrap_exceptions + def ppid(self): + self._ppid = self._proc_basic_info()[proc_info_map['ppid']] + return self._ppid + + @wrap_exceptions + def uids(self): + real, effective, saved, _, _, _ = self._proc_cred() + return _common.puids(real, effective, saved) + + @wrap_exceptions + def gids(self): + _, _, _, real, effective, saved = self._proc_cred() + return _common.puids(real, effective, saved) + + @wrap_exceptions + def cpu_times(self): + cpu_times = cext.proc_cpu_times(self.pid, self._procfs_path) + return _common.pcputimes(*cpu_times) + + @wrap_exceptions + def terminal(self): + ttydev = self._proc_basic_info()[proc_info_map['ttynr']] + # convert from 64-bit dev_t to 32-bit dev_t and then map the device + ttydev = (((ttydev & 0x0000FFFF00000000) >> 16) | (ttydev & 0xFFFF)) + # try to match rdev of /dev/pts/* files ttydev + for dev in glob.glob("/dev/**/*"): + if os.stat(dev).st_rdev == ttydev: + return dev + return None + + @wrap_exceptions + def cwd(self): + procfs_path = self._procfs_path + try: + result = os.readlink("%s/%s/cwd" % (procfs_path, self.pid)) + return result.rstrip('/') + except OSError as err: + if err.errno == errno.ENOENT: + os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD + return None + raise + + @wrap_exceptions + def memory_info(self): + ret = self._proc_basic_info() + rss = ret[proc_info_map['rss']] * 1024 + vms = ret[proc_info_map['vms']] * 1024 + return pmem(rss, vms) + + memory_full_info = memory_info + + @wrap_exceptions + def status(self): + code = self._proc_basic_info()[proc_info_map['status']] + # XXX is '?' legit? (we're not supposed to return it anyway) + return PROC_STATUSES.get(code, '?') + + def open_files(self): + # TODO rewrite without using procfiles (stat /proc/pid/fd/* and then + # find matching name of the inode) + p = subprocess.Popen(["/usr/bin/procfiles", "-n", str(self.pid)], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + if PY3: + stdout, stderr = [x.decode(sys.stdout.encoding) + for x in (stdout, stderr)] + if "no such process" in stderr.lower(): + raise NoSuchProcess(self.pid, self._name) + procfiles = re.findall(r"(\d+): S_IFREG.*\s*.*name:(.*)\n", stdout) + retlist = [] + for fd, path in procfiles: + path = path.strip() + if path.startswith("//"): + path = path[1:] + if path.lower() == "cannot be retrieved": + continue + retlist.append(_common.popenfile(path, int(fd))) + return retlist + + @wrap_exceptions + def num_fds(self): + if self.pid == 0: # no /proc/0/fd + return 0 + return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid))) + + @wrap_exceptions + def num_ctx_switches(self): + return _common.pctxsw( + *cext.proc_num_ctx_switches(self.pid)) + + @wrap_exceptions + def wait(self, timeout=None): + return _psposix.wait_pid(self.pid, timeout, self._name) + + if HAS_PROC_IO_COUNTERS: + @wrap_exceptions + def io_counters(self): + try: + rc, wc, rb, wb = cext.proc_io_counters(self.pid) + except OSError: + # if process is terminated, proc_io_counters returns OSError + # instead of NSP + if not pid_exists(self.pid): + raise NoSuchProcess(self.pid, self._name) + raise + return _common.pio(rc, wc, rb, wb) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psbsd.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psbsd.py new file mode 100644 index 00000000..3d9dfdab --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psbsd.py @@ -0,0 +1,926 @@ +# 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. + +"""FreeBSD, OpenBSD and NetBSD platforms implementation.""" + +import contextlib +import errno +import functools +import os +import xml.etree.ElementTree as ET +from collections import namedtuple +from socket import AF_INET +from collections import defaultdict + +from . import _common +from . import _psposix +from . import _psutil_bsd as cext +from . import _psutil_posix as cext_posix +from ._common import AF_INET6 +from ._common import conn_tmap +from ._common import FREEBSD +from ._common import memoize +from ._common import memoize_when_activated +from ._common import NETBSD +from ._common import OPENBSD +from ._common import sockfam_to_enum +from ._common import socktype_to_enum +from ._common import usage_percent +from ._compat import which + +__extra__all__ = [] + + +# ===================================================================== +# --- globals +# ===================================================================== + + +if FREEBSD: + PROC_STATUSES = { + cext.SIDL: _common.STATUS_IDLE, + cext.SRUN: _common.STATUS_RUNNING, + cext.SSLEEP: _common.STATUS_SLEEPING, + cext.SSTOP: _common.STATUS_STOPPED, + cext.SZOMB: _common.STATUS_ZOMBIE, + cext.SWAIT: _common.STATUS_WAITING, + cext.SLOCK: _common.STATUS_LOCKED, + } +elif OPENBSD or NETBSD: + PROC_STATUSES = { + cext.SIDL: _common.STATUS_IDLE, + cext.SSLEEP: _common.STATUS_SLEEPING, + cext.SSTOP: _common.STATUS_STOPPED, + # According to /usr/include/sys/proc.h SZOMB is unused. + # test_zombie_process() shows that SDEAD is the right + # equivalent. Also it appears there's no equivalent of + # psutil.STATUS_DEAD. SDEAD really means STATUS_ZOMBIE. + # cext.SZOMB: _common.STATUS_ZOMBIE, + cext.SDEAD: _common.STATUS_ZOMBIE, + cext.SZOMB: _common.STATUS_ZOMBIE, + # From http://www.eecs.harvard.edu/~margo/cs161/videos/proc.h.txt + # OpenBSD has SRUN and SONPROC: SRUN indicates that a process + # is runnable but *not* yet running, i.e. is on a run queue. + # SONPROC indicates that the process is actually executing on + # a CPU, i.e. it is no longer on a run queue. + # As such we'll map SRUN to STATUS_WAKING and SONPROC to + # STATUS_RUNNING + cext.SRUN: _common.STATUS_WAKING, + cext.SONPROC: _common.STATUS_RUNNING, + } +elif NETBSD: + PROC_STATUSES = { + cext.SIDL: _common.STATUS_IDLE, + cext.SACTIVE: _common.STATUS_RUNNING, + cext.SDYING: _common.STATUS_ZOMBIE, + cext.SSTOP: _common.STATUS_STOPPED, + cext.SZOMB: _common.STATUS_ZOMBIE, + cext.SDEAD: _common.STATUS_DEAD, + cext.SSUSPENDED: _common.STATUS_SUSPENDED, # unique to NetBSD + } + +TCP_STATUSES = { + cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, + cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, + cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV, + cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, + cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, + cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, + cext.TCPS_CLOSED: _common.CONN_CLOSE, + cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, + cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, + cext.TCPS_LISTEN: _common.CONN_LISTEN, + cext.TCPS_CLOSING: _common.CONN_CLOSING, + cext.PSUTIL_CONN_NONE: _common.CONN_NONE, +} + +if NETBSD: + PAGESIZE = os.sysconf("SC_PAGESIZE") +else: + PAGESIZE = os.sysconf("SC_PAGE_SIZE") +AF_LINK = cext_posix.AF_LINK + +HAS_PER_CPU_TIMES = hasattr(cext, "per_cpu_times") +HAS_PROC_NUM_THREADS = hasattr(cext, "proc_num_threads") +HAS_PROC_OPEN_FILES = hasattr(cext, 'proc_open_files') +HAS_PROC_NUM_FDS = hasattr(cext, 'proc_num_fds') + +kinfo_proc_map = dict( + ppid=0, + status=1, + real_uid=2, + effective_uid=3, + saved_uid=4, + real_gid=5, + effective_gid=6, + saved_gid=7, + ttynr=8, + create_time=9, + ctx_switches_vol=10, + ctx_switches_unvol=11, + read_io_count=12, + write_io_count=13, + user_time=14, + sys_time=15, + ch_user_time=16, + ch_sys_time=17, + rss=18, + vms=19, + memtext=20, + memdata=21, + memstack=22, + cpunum=23, + name=24, +) + +# These objects get set on "import psutil" from the __init__.py +# file, see: https://github.com/giampaolo/psutil/issues/1402 +NoSuchProcess = None +ZombieProcess = None +AccessDenied = None +TimeoutExpired = None + + +# ===================================================================== +# --- named tuples +# ===================================================================== + + +# psutil.virtual_memory() +svmem = namedtuple( + 'svmem', ['total', 'available', 'percent', 'used', 'free', + 'active', 'inactive', 'buffers', 'cached', 'shared', 'wired']) +# psutil.cpu_times() +scputimes = namedtuple( + 'scputimes', ['user', 'nice', 'system', 'idle', 'irq']) +# psutil.Process.memory_info() +pmem = namedtuple('pmem', ['rss', 'vms', 'text', 'data', 'stack']) +# psutil.Process.memory_full_info() +pfullmem = pmem +# psutil.Process.cpu_times() +pcputimes = namedtuple('pcputimes', + ['user', 'system', 'children_user', 'children_system']) +# psutil.Process.memory_maps(grouped=True) +pmmap_grouped = namedtuple( + 'pmmap_grouped', 'path rss, private, ref_count, shadow_count') +# psutil.Process.memory_maps(grouped=False) +pmmap_ext = namedtuple( + 'pmmap_ext', 'addr, perms path rss, private, ref_count, shadow_count') +# psutil.disk_io_counters() +if FREEBSD: + sdiskio = namedtuple('sdiskio', ['read_count', 'write_count', + 'read_bytes', 'write_bytes', + 'read_time', 'write_time', + 'busy_time']) +else: + sdiskio = namedtuple('sdiskio', ['read_count', 'write_count', + 'read_bytes', 'write_bytes']) + + +# ===================================================================== +# --- memory +# ===================================================================== + + +def virtual_memory(): + """System virtual memory as a namedtuple.""" + mem = cext.virtual_mem() + total, free, active, inactive, wired, cached, buffers, shared = mem + if NETBSD: + # On NetBSD buffers and shared mem is determined via /proc. + # The C ext set them to 0. + with open('/proc/meminfo', 'rb') as f: + for line in f: + if line.startswith(b'Buffers:'): + buffers = int(line.split()[1]) * 1024 + elif line.startswith(b'MemShared:'): + shared = int(line.split()[1]) * 1024 + avail = inactive + cached + free + used = active + wired + cached + percent = usage_percent((total - avail), total, round_=1) + return svmem(total, avail, percent, used, free, + active, inactive, buffers, cached, shared, wired) + + +def swap_memory(): + """System swap memory as (total, used, free, sin, sout) namedtuple.""" + total, used, free, sin, sout = cext.swap_mem() + percent = usage_percent(used, total, round_=1) + return _common.sswap(total, used, free, percent, sin, sout) + + +# ===================================================================== +# --- CPU +# ===================================================================== + + +def cpu_times(): + """Return system per-CPU times as a namedtuple""" + user, nice, system, idle, irq = cext.cpu_times() + return scputimes(user, nice, system, idle, irq) + + +if HAS_PER_CPU_TIMES: + def per_cpu_times(): + """Return system CPU times as a namedtuple""" + ret = [] + for cpu_t in cext.per_cpu_times(): + user, nice, system, idle, irq = cpu_t + item = scputimes(user, nice, system, idle, irq) + ret.append(item) + return ret +else: + # XXX + # Ok, this is very dirty. + # On FreeBSD < 8 we cannot gather per-cpu information, see: + # https://github.com/giampaolo/psutil/issues/226 + # If num cpus > 1, on first call we return single cpu times to avoid a + # crash at psutil import time. + # Next calls will fail with NotImplementedError + def per_cpu_times(): + """Return system CPU times as a namedtuple""" + if cpu_count_logical() == 1: + return [cpu_times()] + if per_cpu_times.__called__: + raise NotImplementedError("supported only starting from FreeBSD 8") + per_cpu_times.__called__ = True + return [cpu_times()] + + per_cpu_times.__called__ = False + + +def cpu_count_logical(): + """Return the number of logical CPUs in the system.""" + return cext.cpu_count_logical() + + +if OPENBSD or NETBSD: + def cpu_count_physical(): + # OpenBSD and NetBSD do not implement this. + return 1 if cpu_count_logical() == 1 else None +else: + def cpu_count_physical(): + """Return the number of physical CPUs in the system.""" + # From the C module we'll get an XML string similar to this: + # http://manpages.ubuntu.com/manpages/precise/man4/smp.4freebsd.html + # We may get None in case "sysctl kern.sched.topology_spec" + # is not supported on this BSD version, in which case we'll mimic + # os.cpu_count() and return None. + ret = None + s = cext.cpu_count_phys() + if s is not None: + # get rid of padding chars appended at the end of the string + index = s.rfind("") + if index != -1: + s = s[:index + 9] + root = ET.fromstring(s) + try: + ret = len(root.findall('group/children/group/cpu')) or None + finally: + # needed otherwise it will memleak + root.clear() + if not ret: + # If logical CPUs are 1 it's obvious we'll have only 1 + # physical CPU. + if cpu_count_logical() == 1: + return 1 + return ret + + +def cpu_stats(): + """Return various CPU stats as a named tuple.""" + if FREEBSD: + # Note: the C ext is returning some metrics we are not exposing: + # traps. + ctxsw, intrs, soft_intrs, syscalls, traps = cext.cpu_stats() + elif NETBSD: + # XXX + # Note about intrs: the C extension returns 0. intrs + # can be determined via /proc/stat; it has the same value as + # soft_intrs thought so the kernel is faking it (?). + # + # Note about syscalls: the C extension always sets it to 0 (?). + # + # Note: the C ext is returning some metrics we are not exposing: + # traps, faults and forks. + ctxsw, intrs, soft_intrs, syscalls, traps, faults, forks = \ + cext.cpu_stats() + with open('/proc/stat', 'rb') as f: + for line in f: + if line.startswith(b'intr'): + intrs = int(line.split()[1]) + elif OPENBSD: + # Note: the C ext is returning some metrics we are not exposing: + # traps, faults and forks. + ctxsw, intrs, soft_intrs, syscalls, traps, faults, forks = \ + cext.cpu_stats() + return _common.scpustats(ctxsw, intrs, soft_intrs, syscalls) + + +# ===================================================================== +# --- disks +# ===================================================================== + + +def disk_partitions(all=False): + """Return mounted disk partitions as a list of namedtuples. + 'all' argument is ignored, see: + https://github.com/giampaolo/psutil/issues/906 + """ + retlist = [] + partitions = cext.disk_partitions() + for partition in partitions: + device, mountpoint, fstype, opts = partition + ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) + retlist.append(ntuple) + return retlist + + +disk_usage = _psposix.disk_usage +disk_io_counters = cext.disk_io_counters + + +# ===================================================================== +# --- network +# ===================================================================== + + +net_io_counters = cext.net_io_counters +net_if_addrs = cext_posix.net_if_addrs + + +def net_if_stats(): + """Get NIC stats (isup, duplex, speed, mtu).""" + names = net_io_counters().keys() + ret = {} + for name in names: + try: + mtu = cext_posix.net_if_mtu(name) + isup = cext_posix.net_if_flags(name) + duplex, speed = cext_posix.net_if_duplex_speed(name) + except OSError as err: + # https://github.com/giampaolo/psutil/issues/1279 + if err.errno != errno.ENODEV: + raise + else: + if hasattr(_common, 'NicDuplex'): + duplex = _common.NicDuplex(duplex) + ret[name] = _common.snicstats(isup, duplex, speed, mtu) + return ret + + +def net_connections(kind): + """System-wide network connections.""" + if OPENBSD: + ret = [] + for pid in pids(): + try: + cons = Process(pid).connections(kind) + except (NoSuchProcess, ZombieProcess): + continue + else: + for conn in cons: + conn = list(conn) + conn.append(pid) + ret.append(_common.sconn(*conn)) + return ret + + if kind not in _common.conn_tmap: + raise ValueError("invalid %r kind argument; choose between %s" + % (kind, ', '.join([repr(x) for x in conn_tmap]))) + families, types = conn_tmap[kind] + ret = set() + if NETBSD: + rawlist = cext.net_connections(-1) + else: + rawlist = cext.net_connections() + for item in rawlist: + fd, fam, type, laddr, raddr, status, pid = item + # TODO: apply filter at C level + if fam in families and type in types: + try: + status = TCP_STATUSES[status] + except KeyError: + # XXX: Not sure why this happens. I saw this occurring + # with IPv6 sockets opened by 'vim'. Those sockets + # have a very short lifetime so maybe the kernel + # can't initialize their status? + status = TCP_STATUSES[cext.PSUTIL_CONN_NONE] + if fam in (AF_INET, AF_INET6): + if laddr: + laddr = _common.addr(*laddr) + if raddr: + raddr = _common.addr(*raddr) + fam = sockfam_to_enum(fam) + type = socktype_to_enum(type) + nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid) + ret.add(nt) + return list(ret) + + +# ===================================================================== +# --- sensors +# ===================================================================== + + +if FREEBSD: + + def sensors_battery(): + """Return battery info.""" + try: + percent, minsleft, power_plugged = cext.sensors_battery() + except NotImplementedError: + # See: https://github.com/giampaolo/psutil/issues/1074 + return None + power_plugged = power_plugged == 1 + if power_plugged: + secsleft = _common.POWER_TIME_UNLIMITED + elif minsleft == -1: + secsleft = _common.POWER_TIME_UNKNOWN + else: + secsleft = minsleft * 60 + return _common.sbattery(percent, secsleft, power_plugged) + + def sensors_temperatures(): + "Return CPU cores temperatures if available, else an empty dict." + ret = defaultdict(list) + num_cpus = cpu_count_logical() + for cpu in range(num_cpus): + try: + current, high = cext.sensors_cpu_temperature(cpu) + if high <= 0: + high = None + name = "Core %s" % cpu + ret["coretemp"].append( + _common.shwtemp(name, current, high, high)) + except NotImplementedError: + pass + + return ret + + def cpu_freq(): + """Return frequency metrics for CPUs. As of Dec 2018 only + CPU 0 appears to be supported by FreeBSD and all other cores + match the frequency of CPU 0. + """ + ret = [] + num_cpus = cpu_count_logical() + for cpu in range(num_cpus): + try: + current, available_freq = cext.cpu_frequency(cpu) + except NotImplementedError: + continue + if available_freq: + try: + min_freq = int(available_freq.split(" ")[-1].split("/")[0]) + except(IndexError, ValueError): + min_freq = None + try: + max_freq = int(available_freq.split(" ")[0].split("/")[0]) + except(IndexError, ValueError): + max_freq = None + ret.append(_common.scpufreq(current, min_freq, max_freq)) + return ret + + +# ===================================================================== +# --- other system functions +# ===================================================================== + + +def boot_time(): + """The system boot time expressed in seconds since the epoch.""" + return cext.boot_time() + + +def users(): + """Return currently connected users as a list of namedtuples.""" + retlist = [] + rawlist = cext.users() + for item in rawlist: + user, tty, hostname, tstamp, pid = item + if pid == -1: + assert OPENBSD + pid = None + if tty == '~': + continue # reboot or shutdown + nt = _common.suser(user, tty or None, hostname, tstamp, pid) + retlist.append(nt) + return retlist + + +# ===================================================================== +# --- processes +# ===================================================================== + + +@memoize +def _pid_0_exists(): + try: + Process(0).name() + except NoSuchProcess: + return False + except AccessDenied: + return True + else: + return True + + +def pids(): + """Returns a list of PIDs currently running on the system.""" + ret = cext.pids() + if OPENBSD and (0 not in ret) and _pid_0_exists(): + # On OpenBSD the kernel does not return PID 0 (neither does + # ps) but it's actually querable (Process(0) will succeed). + ret.insert(0, 0) + return ret + + +if OPENBSD or NETBSD: + def pid_exists(pid): + """Return True if pid exists.""" + exists = _psposix.pid_exists(pid) + if not exists: + # We do this because _psposix.pid_exists() lies in case of + # zombie processes. + return pid in pids() + else: + return True +else: + pid_exists = _psposix.pid_exists + + +def wrap_exceptions(fun): + """Decorator which translates bare OSError exceptions into + NoSuchProcess and AccessDenied. + """ + @functools.wraps(fun) + def wrapper(self, *args, **kwargs): + try: + return fun(self, *args, **kwargs) + except OSError as err: + if self.pid == 0: + if 0 in pids(): + raise AccessDenied(self.pid, self._name) + else: + raise + if err.errno == errno.ESRCH: + if not pid_exists(self.pid): + raise NoSuchProcess(self.pid, self._name) + else: + raise ZombieProcess(self.pid, self._name, self._ppid) + if err.errno in (errno.EPERM, errno.EACCES): + raise AccessDenied(self.pid, self._name) + raise + return wrapper + + +@contextlib.contextmanager +def wrap_exceptions_procfs(inst): + """Same as above, for routines relying on reading /proc fs.""" + try: + yield + except EnvironmentError as err: + # ENOENT (no such file or directory) gets raised on open(). + # ESRCH (no such process) can get raised on read() if + # process is gone in meantime. + if err.errno in (errno.ENOENT, errno.ESRCH): + if not pid_exists(inst.pid): + raise NoSuchProcess(inst.pid, inst._name) + else: + raise ZombieProcess(inst.pid, inst._name, inst._ppid) + if err.errno in (errno.EPERM, errno.EACCES): + raise AccessDenied(inst.pid, inst._name) + raise + + +class Process(object): + """Wrapper class around underlying C implementation.""" + + __slots__ = ["pid", "_name", "_ppid", "_cache"] + + def __init__(self, pid): + self.pid = pid + self._name = None + self._ppid = None + + def _assert_alive(self): + """Raise NSP if the process disappeared on us.""" + # For those C function who do not raise NSP, possibly returning + # incorrect or incomplete result. + cext.proc_name(self.pid) + + @wrap_exceptions + @memoize_when_activated + def oneshot(self): + """Retrieves multiple process info in one shot as a raw tuple.""" + ret = cext.proc_oneshot_info(self.pid) + assert len(ret) == len(kinfo_proc_map) + return ret + + def oneshot_enter(self): + self.oneshot.cache_activate(self) + + def oneshot_exit(self): + self.oneshot.cache_deactivate(self) + + @wrap_exceptions + def name(self): + name = self.oneshot()[kinfo_proc_map['name']] + return name if name is not None else cext.proc_name(self.pid) + + @wrap_exceptions + def exe(self): + if FREEBSD: + return cext.proc_exe(self.pid) + elif NETBSD: + if self.pid == 0: + # /proc/0 dir exists but /proc/0/exe doesn't + return "" + with wrap_exceptions_procfs(self): + return os.readlink("/proc/%s/exe" % self.pid) + else: + # OpenBSD: exe cannot be determined; references: + # https://chromium.googlesource.com/chromium/src/base/+/ + # master/base_paths_posix.cc + # We try our best guess by using which against the first + # cmdline arg (may return None). + cmdline = self.cmdline() + if cmdline: + return which(cmdline[0]) + else: + return "" + + @wrap_exceptions + def cmdline(self): + if OPENBSD and self.pid == 0: + return [] # ...else it crashes + elif NETBSD: + # XXX - most of the times the underlying sysctl() call on Net + # and Open BSD returns a truncated string. + # Also /proc/pid/cmdline behaves the same so it looks + # like this is a kernel bug. + try: + return cext.proc_cmdline(self.pid) + except OSError as err: + if err.errno == errno.EINVAL: + if not pid_exists(self.pid): + raise NoSuchProcess(self.pid, self._name) + else: + raise ZombieProcess(self.pid, self._name, self._ppid) + else: + raise + else: + return cext.proc_cmdline(self.pid) + + @wrap_exceptions + def terminal(self): + tty_nr = self.oneshot()[kinfo_proc_map['ttynr']] + tmap = _psposix.get_terminal_map() + try: + return tmap[tty_nr] + except KeyError: + return None + + @wrap_exceptions + def ppid(self): + self._ppid = self.oneshot()[kinfo_proc_map['ppid']] + return self._ppid + + @wrap_exceptions + def uids(self): + rawtuple = self.oneshot() + return _common.puids( + rawtuple[kinfo_proc_map['real_uid']], + rawtuple[kinfo_proc_map['effective_uid']], + rawtuple[kinfo_proc_map['saved_uid']]) + + @wrap_exceptions + def gids(self): + rawtuple = self.oneshot() + return _common.pgids( + rawtuple[kinfo_proc_map['real_gid']], + rawtuple[kinfo_proc_map['effective_gid']], + rawtuple[kinfo_proc_map['saved_gid']]) + + @wrap_exceptions + def cpu_times(self): + rawtuple = self.oneshot() + return _common.pcputimes( + rawtuple[kinfo_proc_map['user_time']], + rawtuple[kinfo_proc_map['sys_time']], + rawtuple[kinfo_proc_map['ch_user_time']], + rawtuple[kinfo_proc_map['ch_sys_time']]) + + if FREEBSD: + @wrap_exceptions + def cpu_num(self): + return self.oneshot()[kinfo_proc_map['cpunum']] + + @wrap_exceptions + def memory_info(self): + rawtuple = self.oneshot() + return pmem( + rawtuple[kinfo_proc_map['rss']], + rawtuple[kinfo_proc_map['vms']], + rawtuple[kinfo_proc_map['memtext']], + rawtuple[kinfo_proc_map['memdata']], + rawtuple[kinfo_proc_map['memstack']]) + + memory_full_info = memory_info + + @wrap_exceptions + def create_time(self): + return self.oneshot()[kinfo_proc_map['create_time']] + + @wrap_exceptions + def num_threads(self): + if HAS_PROC_NUM_THREADS: + # FreeBSD + return cext.proc_num_threads(self.pid) + else: + return len(self.threads()) + + @wrap_exceptions + def num_ctx_switches(self): + rawtuple = self.oneshot() + return _common.pctxsw( + rawtuple[kinfo_proc_map['ctx_switches_vol']], + rawtuple[kinfo_proc_map['ctx_switches_unvol']]) + + @wrap_exceptions + def threads(self): + # Note: on OpenSBD this (/dev/mem) requires root access. + rawlist = cext.proc_threads(self.pid) + retlist = [] + for thread_id, utime, stime in rawlist: + ntuple = _common.pthread(thread_id, utime, stime) + retlist.append(ntuple) + if OPENBSD: + self._assert_alive() + return retlist + + @wrap_exceptions + def connections(self, kind='inet'): + if kind not in conn_tmap: + raise ValueError("invalid %r kind argument; choose between %s" + % (kind, ', '.join([repr(x) for x in conn_tmap]))) + + if NETBSD: + families, types = conn_tmap[kind] + ret = set() + rawlist = cext.net_connections(self.pid) + for item in rawlist: + fd, fam, type, laddr, raddr, status, pid = item + assert pid == self.pid + if fam in families and type in types: + try: + status = TCP_STATUSES[status] + except KeyError: + status = TCP_STATUSES[cext.PSUTIL_CONN_NONE] + if fam in (AF_INET, AF_INET6): + if laddr: + laddr = _common.addr(*laddr) + if raddr: + raddr = _common.addr(*raddr) + fam = sockfam_to_enum(fam) + type = socktype_to_enum(type) + nt = _common.pconn(fd, fam, type, laddr, raddr, status) + ret.add(nt) + self._assert_alive() + return list(ret) + + families, types = conn_tmap[kind] + rawlist = cext.proc_connections(self.pid, families, types) + ret = [] + for item in rawlist: + fd, fam, type, laddr, raddr, status = item + if fam in (AF_INET, AF_INET6): + if laddr: + laddr = _common.addr(*laddr) + if raddr: + raddr = _common.addr(*raddr) + fam = sockfam_to_enum(fam) + type = socktype_to_enum(type) + status = TCP_STATUSES[status] + nt = _common.pconn(fd, fam, type, laddr, raddr, status) + ret.append(nt) + if OPENBSD: + self._assert_alive() + return ret + + @wrap_exceptions + def wait(self, timeout=None): + return _psposix.wait_pid(self.pid, timeout, self._name) + + @wrap_exceptions + def nice_get(self): + return cext_posix.getpriority(self.pid) + + @wrap_exceptions + def nice_set(self, value): + return cext_posix.setpriority(self.pid, value) + + @wrap_exceptions + def status(self): + code = self.oneshot()[kinfo_proc_map['status']] + # XXX is '?' legit? (we're not supposed to return it anyway) + return PROC_STATUSES.get(code, '?') + + @wrap_exceptions + def io_counters(self): + rawtuple = self.oneshot() + return _common.pio( + rawtuple[kinfo_proc_map['read_io_count']], + rawtuple[kinfo_proc_map['write_io_count']], + -1, + -1) + + @wrap_exceptions + def cwd(self): + """Return process current working directory.""" + # sometimes we get an empty string, in which case we turn + # it into None + if OPENBSD and self.pid == 0: + return None # ...else it would raise EINVAL + elif NETBSD: + with wrap_exceptions_procfs(self): + return os.readlink("/proc/%s/cwd" % self.pid) + elif HAS_PROC_OPEN_FILES: + # FreeBSD < 8 does not support functions based on + # kinfo_getfile() and kinfo_getvmmap() + return cext.proc_cwd(self.pid) or None + else: + raise NotImplementedError( + "supported only starting from FreeBSD 8" if + FREEBSD else "") + + nt_mmap_grouped = namedtuple( + 'mmap', 'path rss, private, ref_count, shadow_count') + nt_mmap_ext = namedtuple( + 'mmap', 'addr, perms path rss, private, ref_count, shadow_count') + + def _not_implemented(self): + raise NotImplementedError + + # FreeBSD < 8 does not support functions based on kinfo_getfile() + # and kinfo_getvmmap() + if HAS_PROC_OPEN_FILES: + @wrap_exceptions + def open_files(self): + """Return files opened by process as a list of namedtuples.""" + rawlist = cext.proc_open_files(self.pid) + return [_common.popenfile(path, fd) for path, fd in rawlist] + else: + open_files = _not_implemented + + # FreeBSD < 8 does not support functions based on kinfo_getfile() + # and kinfo_getvmmap() + if HAS_PROC_NUM_FDS: + @wrap_exceptions + def num_fds(self): + """Return the number of file descriptors opened by this process.""" + ret = cext.proc_num_fds(self.pid) + if NETBSD: + self._assert_alive() + return ret + else: + num_fds = _not_implemented + + # --- FreeBSD only APIs + + if FREEBSD: + + @wrap_exceptions + def cpu_affinity_get(self): + return cext.proc_cpu_affinity_get(self.pid) + + @wrap_exceptions + def cpu_affinity_set(self, cpus): + # Pre-emptively check if CPUs are valid because the C + # function has a weird behavior in case of invalid CPUs, + # see: https://github.com/giampaolo/psutil/issues/586 + allcpus = tuple(range(len(per_cpu_times()))) + for cpu in cpus: + if cpu not in allcpus: + raise ValueError("invalid CPU #%i (choose between %s)" + % (cpu, allcpus)) + try: + cext.proc_cpu_affinity_set(self.pid, cpus) + except OSError as err: + # 'man cpuset_setaffinity' about EDEADLK: + # <> + if err.errno in (errno.EINVAL, errno.EDEADLK): + for cpu in cpus: + if cpu not in allcpus: + raise ValueError( + "invalid CPU #%i (choose between %s)" % ( + cpu, allcpus)) + raise + + @wrap_exceptions + def memory_maps(self): + return cext.proc_memory_maps(self.pid) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_pslinux.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_pslinux.py new file mode 100644 index 00000000..41be6665 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_pslinux.py @@ -0,0 +1,2119 @@ +# 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. + +"""Linux platform implementation.""" + +from __future__ import division + +import base64 +import collections +import errno +import functools +import glob +import os +import re +import socket +import struct +import sys +import traceback +import warnings +from collections import defaultdict +from collections import namedtuple + +from . import _common +from . import _psposix +from . import _psutil_linux as cext +from . import _psutil_posix as cext_posix +from ._common import ENCODING +from ._common import ENCODING_ERRS +from ._common import isfile_strict +from ._common import memoize +from ._common import memoize_when_activated +from ._common import NIC_DUPLEX_FULL +from ._common import NIC_DUPLEX_HALF +from ._common import NIC_DUPLEX_UNKNOWN +from ._common import open_binary +from ._common import open_text +from ._common import parse_environ_block +from ._common import path_exists_strict +from ._common import supports_ipv6 +from ._common import usage_percent +from ._compat import b +from ._compat import basestring +from ._compat import long +from ._compat import PY3 + +if sys.version_info >= (3, 4): + import enum +else: + enum = None + + +__extra__all__ = [ + # + 'PROCFS_PATH', + # io prio constants + "IOPRIO_CLASS_NONE", "IOPRIO_CLASS_RT", "IOPRIO_CLASS_BE", + "IOPRIO_CLASS_IDLE", + # connection status constants + "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1", + "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT", + "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", ] + + +# ===================================================================== +# --- globals +# ===================================================================== + + +POWER_SUPPLY_PATH = "/sys/class/power_supply" +HAS_SMAPS = os.path.exists('/proc/%s/smaps' % os.getpid()) +HAS_PRLIMIT = hasattr(cext, "linux_prlimit") +HAS_PROC_IO_PRIORITY = hasattr(cext, "proc_ioprio_get") +_DEFAULT = object() + +# RLIMIT_* constants, not guaranteed to be present on all kernels +if HAS_PRLIMIT: + for name in dir(cext): + if name.startswith('RLIM'): + __extra__all__.append(name) + +# Number of clock ticks per second +CLOCK_TICKS = os.sysconf("SC_CLK_TCK") +PAGESIZE = os.sysconf("SC_PAGE_SIZE") +BOOT_TIME = None # set later +# Used when reading "big" files, namely /proc/{pid}/smaps and /proc/net/*. +# On Python 2, using a buffer with open() for such files may result in a +# speedup, see: https://github.com/giampaolo/psutil/issues/708 +BIGFILE_BUFFERING = -1 if PY3 else 8192 +LITTLE_ENDIAN = sys.byteorder == 'little' + +# "man iostat" states that sectors are equivalent with blocks and have +# a size of 512 bytes. Despite this value can be queried at runtime +# via /sys/block/{DISK}/queue/hw_sector_size and results may vary +# between 1k, 2k, or 4k... 512 appears to be a magic constant used +# throughout Linux source code: +# * https://stackoverflow.com/a/38136179/376587 +# * https://lists.gt.net/linux/kernel/2241060 +# * https://github.com/giampaolo/psutil/issues/1305 +# * https://github.com/torvalds/linux/blob/ +# 4f671fe2f9523a1ea206f63fe60a7c7b3a56d5c7/include/linux/bio.h#L99 +# * https://lkml.org/lkml/2015/8/17/234 +DISK_SECTOR_SIZE = 512 + +if enum is None: + AF_LINK = socket.AF_PACKET +else: + AddressFamily = enum.IntEnum('AddressFamily', + {'AF_LINK': int(socket.AF_PACKET)}) + AF_LINK = AddressFamily.AF_LINK + +# ioprio_* constants http://linux.die.net/man/2/ioprio_get +if enum is None: + IOPRIO_CLASS_NONE = 0 + IOPRIO_CLASS_RT = 1 + IOPRIO_CLASS_BE = 2 + IOPRIO_CLASS_IDLE = 3 +else: + class IOPriority(enum.IntEnum): + IOPRIO_CLASS_NONE = 0 + IOPRIO_CLASS_RT = 1 + IOPRIO_CLASS_BE = 2 + IOPRIO_CLASS_IDLE = 3 + + globals().update(IOPriority.__members__) + +# See: +# https://github.com/torvalds/linux/blame/master/fs/proc/array.c +# ...and (TASK_* constants): +# https://github.com/torvalds/linux/blob/master/include/linux/sched.h +PROC_STATUSES = { + "R": _common.STATUS_RUNNING, + "S": _common.STATUS_SLEEPING, + "D": _common.STATUS_DISK_SLEEP, + "T": _common.STATUS_STOPPED, + "t": _common.STATUS_TRACING_STOP, + "Z": _common.STATUS_ZOMBIE, + "X": _common.STATUS_DEAD, + "x": _common.STATUS_DEAD, + "K": _common.STATUS_WAKE_KILL, + "W": _common.STATUS_WAKING, + "I": _common.STATUS_IDLE, + "P": _common.STATUS_PARKED, +} + +# https://github.com/torvalds/linux/blob/master/include/net/tcp_states.h +TCP_STATUSES = { + "01": _common.CONN_ESTABLISHED, + "02": _common.CONN_SYN_SENT, + "03": _common.CONN_SYN_RECV, + "04": _common.CONN_FIN_WAIT1, + "05": _common.CONN_FIN_WAIT2, + "06": _common.CONN_TIME_WAIT, + "07": _common.CONN_CLOSE, + "08": _common.CONN_CLOSE_WAIT, + "09": _common.CONN_LAST_ACK, + "0A": _common.CONN_LISTEN, + "0B": _common.CONN_CLOSING +} + +# These objects get set on "import psutil" from the __init__.py +# file, see: https://github.com/giampaolo/psutil/issues/1402 +NoSuchProcess = None +ZombieProcess = None +AccessDenied = None +TimeoutExpired = None + + +# ===================================================================== +# --- named tuples +# ===================================================================== + + +# psutil.virtual_memory() +svmem = namedtuple( + 'svmem', ['total', 'available', 'percent', 'used', 'free', + 'active', 'inactive', 'buffers', 'cached', 'shared', 'slab']) +# psutil.disk_io_counters() +sdiskio = namedtuple( + 'sdiskio', ['read_count', 'write_count', + 'read_bytes', 'write_bytes', + 'read_time', 'write_time', + 'read_merged_count', 'write_merged_count', + 'busy_time']) +# psutil.Process().open_files() +popenfile = namedtuple( + 'popenfile', ['path', 'fd', 'position', 'mode', 'flags']) +# psutil.Process().memory_info() +pmem = namedtuple('pmem', 'rss vms shared text lib data dirty') +# psutil.Process().memory_full_info() +pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', 'pss', 'swap')) +# psutil.Process().memory_maps(grouped=True) +pmmap_grouped = namedtuple( + 'pmmap_grouped', + ['path', 'rss', 'size', 'pss', 'shared_clean', 'shared_dirty', + 'private_clean', 'private_dirty', 'referenced', 'anonymous', 'swap']) +# psutil.Process().memory_maps(grouped=False) +pmmap_ext = namedtuple( + 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) +# psutil.Process.io_counters() +pio = namedtuple('pio', ['read_count', 'write_count', + 'read_bytes', 'write_bytes', + 'read_chars', 'write_chars']) + + +# ===================================================================== +# --- utils +# ===================================================================== + + +if PY3: + def decode(s): + return s.decode(encoding=ENCODING, errors=ENCODING_ERRS) +else: + def decode(s): + return s + + +def get_procfs_path(): + """Return updated psutil.PROCFS_PATH constant.""" + return sys.modules['psutil'].PROCFS_PATH + + +def readlink(path): + """Wrapper around os.readlink().""" + assert isinstance(path, basestring), path + path = os.readlink(path) + # readlink() might return paths containing null bytes ('\x00') + # resulting in "TypeError: must be encoded string without NULL + # bytes, not str" errors when the string is passed to other + # fs-related functions (os.*, open(), ...). + # Apparently everything after '\x00' is garbage (we can have + # ' (deleted)', 'new' and possibly others), see: + # https://github.com/giampaolo/psutil/issues/717 + path = path.split('\x00')[0] + # Certain paths have ' (deleted)' appended. Usually this is + # bogus as the file actually exists. Even if it doesn't we + # don't care. + if path.endswith(' (deleted)') and not path_exists_strict(path): + path = path[:-10] + return path + + +def file_flags_to_mode(flags): + """Convert file's open() flags into a readable string. + Used by Process.open_files(). + """ + modes_map = {os.O_RDONLY: 'r', os.O_WRONLY: 'w', os.O_RDWR: 'w+'} + mode = modes_map[flags & (os.O_RDONLY | os.O_WRONLY | os.O_RDWR)] + if flags & os.O_APPEND: + mode = mode.replace('w', 'a', 1) + mode = mode.replace('w+', 'r+') + # possible values: r, w, a, r+, a+ + return mode + + +def is_storage_device(name): + """Return True if the given name refers to a root device (e.g. + "sda", "nvme0n1") as opposed to a logical partition (e.g. "sda1", + "nvme0n1p1"). If name is a virtual device (e.g. "loop1", "ram") + return True. + """ + # Readapted from iostat source code, see: + # https://github.com/sysstat/sysstat/blob/ + # 97912938cd476645b267280069e83b1c8dc0e1c7/common.c#L208 + # Some devices may have a slash in their name (e.g. cciss/c0d0...). + name = name.replace('/', '!') + including_virtual = True + if including_virtual: + path = "/sys/block/%s" % name + else: + path = "/sys/block/%s/device" % name + return os.access(path, os.F_OK) + + +@memoize +def set_scputimes_ntuple(procfs_path): + """Set a namedtuple of variable fields depending on the CPU times + available on this Linux kernel version which may be: + (user, nice, system, idle, iowait, irq, softirq, [steal, [guest, + [guest_nice]]]) + Used by cpu_times() function. + """ + global scputimes + with open_binary('%s/stat' % procfs_path) as f: + values = f.readline().split()[1:] + fields = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq'] + vlen = len(values) + if vlen >= 8: + # Linux >= 2.6.11 + fields.append('steal') + if vlen >= 9: + # Linux >= 2.6.24 + fields.append('guest') + if vlen >= 10: + # Linux >= 3.2.0 + fields.append('guest_nice') + scputimes = namedtuple('scputimes', fields) + + +def cat(fname, fallback=_DEFAULT, binary=True): + """Return file content. + fallback: the value returned in case the file does not exist or + cannot be read + binary: whether to open the file in binary or text mode. + """ + try: + with open_binary(fname) if binary else open_text(fname) as f: + return f.read().strip() + except (IOError, OSError): + if fallback is not _DEFAULT: + return fallback + else: + raise + + +try: + set_scputimes_ntuple("/proc") +except Exception: + # Don't want to crash at import time. + traceback.print_exc() + scputimes = namedtuple('scputimes', 'user system idle')(0.0, 0.0, 0.0) + + +# ===================================================================== +# --- system memory +# ===================================================================== + + +def calculate_avail_vmem(mems): + """Fallback for kernels < 3.14 where /proc/meminfo does not provide + "MemAvailable:" column, see: + https://blog.famzah.net/2014/09/24/ + This code reimplements the algorithm outlined here: + https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/ + commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 + + XXX: on recent kernels this calculation differs by ~1.5% than + "MemAvailable:" as it's calculated slightly differently, see: + https://gitlab.com/procps-ng/procps/issues/42 + https://github.com/famzah/linux-memavailable-procfs/issues/2 + It is still way more realistic than doing (free + cached) though. + """ + # Fallback for very old distros. According to + # https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/ + # commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773 + # ...long ago "avail" was calculated as (free + cached). + # We might fallback in such cases: + # "Active(file)" not available: 2.6.28 / Dec 2008 + # "Inactive(file)" not available: 2.6.28 / Dec 2008 + # "SReclaimable:" not available: 2.6.19 / Nov 2006 + # /proc/zoneinfo not available: 2.6.13 / Aug 2005 + free = mems[b'MemFree:'] + fallback = free + mems.get(b"Cached:", 0) + try: + lru_active_file = mems[b'Active(file):'] + lru_inactive_file = mems[b'Inactive(file):'] + slab_reclaimable = mems[b'SReclaimable:'] + except KeyError: + return fallback + try: + f = open_binary('%s/zoneinfo' % get_procfs_path()) + except IOError: + return fallback # kernel 2.6.13 + + watermark_low = 0 + with f: + for line in f: + line = line.strip() + if line.startswith(b'low'): + watermark_low += int(line.split()[1]) + watermark_low *= PAGESIZE + watermark_low = watermark_low + + avail = free - watermark_low + pagecache = lru_active_file + lru_inactive_file + pagecache -= min(pagecache / 2, watermark_low) + avail += pagecache + avail += slab_reclaimable - min(slab_reclaimable / 2.0, watermark_low) + return int(avail) + + +def virtual_memory(): + """Report virtual memory stats. + This implementation matches "free" and "vmstat -s" cmdline + utility values and procps-ng-3.3.12 source was used as a reference + (2016-09-18): + https://gitlab.com/procps-ng/procps/blob/ + 24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c + For reference, procps-ng-3.3.10 is the version available on Ubuntu + 16.04. + + Note about "available" memory: up until psutil 4.3 it was + calculated as "avail = (free + buffers + cached)". Now + "MemAvailable:" column (kernel 3.14) from /proc/meminfo is used as + it's more accurate. + That matches "available" column in newer versions of "free". + """ + missing_fields = [] + mems = {} + with open_binary('%s/meminfo' % get_procfs_path()) as f: + for line in f: + fields = line.split() + mems[fields[0]] = int(fields[1]) * 1024 + + # /proc doc states that the available fields in /proc/meminfo vary + # by architecture and compile options, but these 3 values are also + # returned by sysinfo(2); as such we assume they are always there. + total = mems[b'MemTotal:'] + free = mems[b'MemFree:'] + try: + buffers = mems[b'Buffers:'] + except KeyError: + # https://github.com/giampaolo/psutil/issues/1010 + buffers = 0 + missing_fields.append('buffers') + try: + cached = mems[b"Cached:"] + except KeyError: + cached = 0 + missing_fields.append('cached') + else: + # "free" cmdline utility sums reclaimable to cached. + # Older versions of procps used to add slab memory instead. + # This got changed in: + # https://gitlab.com/procps-ng/procps/commit/ + # 05d751c4f076a2f0118b914c5e51cfbb4762ad8e + cached += mems.get(b"SReclaimable:", 0) # since kernel 2.6.19 + + try: + shared = mems[b'Shmem:'] # since kernel 2.6.32 + except KeyError: + try: + shared = mems[b'MemShared:'] # kernels 2.4 + except KeyError: + shared = 0 + missing_fields.append('shared') + + try: + active = mems[b"Active:"] + except KeyError: + active = 0 + missing_fields.append('active') + + try: + inactive = mems[b"Inactive:"] + except KeyError: + try: + inactive = \ + mems[b"Inact_dirty:"] + \ + mems[b"Inact_clean:"] + \ + mems[b"Inact_laundry:"] + except KeyError: + inactive = 0 + missing_fields.append('inactive') + + try: + slab = mems[b"Slab:"] + except KeyError: + slab = 0 + + used = total - free - cached - buffers + if used < 0: + # May be symptomatic of running within a LCX container where such + # values will be dramatically distorted over those of the host. + used = total - free + + # - starting from 4.4.0 we match free's "available" column. + # Before 4.4.0 we calculated it as (free + buffers + cached) + # which matched htop. + # - free and htop available memory differs as per: + # http://askubuntu.com/a/369589 + # http://unix.stackexchange.com/a/65852/168884 + # - MemAvailable has been introduced in kernel 3.14 + try: + avail = mems[b'MemAvailable:'] + except KeyError: + avail = calculate_avail_vmem(mems) + + if avail < 0: + avail = 0 + missing_fields.append('available') + + # If avail is greater than total or our calculation overflows, + # that's symptomatic of running within a LCX container where such + # values will be dramatically distorted over those of the host. + # https://gitlab.com/procps-ng/procps/blob/ + # 24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c#L764 + if avail > total: + avail = free + + percent = usage_percent((total - avail), total, round_=1) + + # Warn about missing metrics which are set to 0. + if missing_fields: + msg = "%s memory stats couldn't be determined and %s set to 0" % ( + ", ".join(missing_fields), + "was" if len(missing_fields) == 1 else "were") + warnings.warn(msg, RuntimeWarning) + + return svmem(total, avail, percent, used, free, + active, inactive, buffers, cached, shared, slab) + + +def swap_memory(): + """Return swap memory metrics.""" + mems = {} + with open_binary('%s/meminfo' % get_procfs_path()) as f: + for line in f: + fields = line.split() + mems[fields[0]] = int(fields[1]) * 1024 + # We prefer /proc/meminfo over sysinfo() syscall so that + # psutil.PROCFS_PATH can be used in order to allow retrieval + # for linux containers, see: + # https://github.com/giampaolo/psutil/issues/1015 + try: + total = mems[b'SwapTotal:'] + free = mems[b'SwapFree:'] + except KeyError: + _, _, _, _, total, free, unit_multiplier = cext.linux_sysinfo() + total *= unit_multiplier + free *= unit_multiplier + + used = total - free + percent = usage_percent(used, total, round_=1) + # get pgin/pgouts + try: + f = open_binary("%s/vmstat" % get_procfs_path()) + except IOError as err: + # see https://github.com/giampaolo/psutil/issues/722 + msg = "'sin' and 'sout' swap memory stats couldn't " \ + "be determined and were set to 0 (%s)" % str(err) + warnings.warn(msg, RuntimeWarning) + sin = sout = 0 + else: + with f: + sin = sout = None + for line in f: + # values are expressed in 4 kilo bytes, we want + # bytes instead + if line.startswith(b'pswpin'): + sin = int(line.split(b' ')[1]) * 4 * 1024 + elif line.startswith(b'pswpout'): + sout = int(line.split(b' ')[1]) * 4 * 1024 + if sin is not None and sout is not None: + break + else: + # we might get here when dealing with exotic Linux + # flavors, see: + # https://github.com/giampaolo/psutil/issues/313 + msg = "'sin' and 'sout' swap memory stats couldn't " \ + "be determined and were set to 0" + warnings.warn(msg, RuntimeWarning) + sin = sout = 0 + return _common.sswap(total, used, free, percent, sin, sout) + + +# ===================================================================== +# --- CPU +# ===================================================================== + + +def cpu_times(): + """Return a named tuple representing the following system-wide + CPU times: + (user, nice, system, idle, iowait, irq, softirq [steal, [guest, + [guest_nice]]]) + Last 3 fields may not be available on all Linux kernel versions. + """ + procfs_path = get_procfs_path() + set_scputimes_ntuple(procfs_path) + with open_binary('%s/stat' % procfs_path) as f: + values = f.readline().split() + fields = values[1:len(scputimes._fields) + 1] + fields = [float(x) / CLOCK_TICKS for x in fields] + return scputimes(*fields) + + +def per_cpu_times(): + """Return a list of namedtuple representing the CPU times + for every CPU available on the system. + """ + procfs_path = get_procfs_path() + set_scputimes_ntuple(procfs_path) + cpus = [] + with open_binary('%s/stat' % procfs_path) as f: + # get rid of the first line which refers to system wide CPU stats + f.readline() + for line in f: + if line.startswith(b'cpu'): + values = line.split() + fields = values[1:len(scputimes._fields) + 1] + fields = [float(x) / CLOCK_TICKS for x in fields] + entry = scputimes(*fields) + cpus.append(entry) + return cpus + + +def cpu_count_logical(): + """Return the number of logical CPUs in the system.""" + try: + return os.sysconf("SC_NPROCESSORS_ONLN") + except ValueError: + # as a second fallback we try to parse /proc/cpuinfo + num = 0 + with open_binary('%s/cpuinfo' % get_procfs_path()) as f: + for line in f: + if line.lower().startswith(b'processor'): + num += 1 + + # unknown format (e.g. amrel/sparc architectures), see: + # https://github.com/giampaolo/psutil/issues/200 + # try to parse /proc/stat as a last resort + if num == 0: + search = re.compile(r'cpu\d') + with open_text('%s/stat' % get_procfs_path()) as f: + for line in f: + line = line.split(' ')[0] + if search.match(line): + num += 1 + + if num == 0: + # mimic os.cpu_count() + return None + return num + + +def cpu_count_physical(): + """Return the number of physical cores in the system.""" + mapping = {} + current_info = {} + with open_binary('%s/cpuinfo' % get_procfs_path()) as f: + for line in f: + line = line.strip().lower() + if not line: + # new section + if (b'physical id' in current_info and + b'cpu cores' in current_info): + mapping[current_info[b'physical id']] = \ + current_info[b'cpu cores'] + current_info = {} + else: + # ongoing section + if (line.startswith(b'physical id') or + line.startswith(b'cpu cores')): + key, value = line.split(b'\t:', 1) + current_info[key] = int(value) + + # mimic os.cpu_count() + return sum(mapping.values()) or None + + +def cpu_stats(): + """Return various CPU stats as a named tuple.""" + with open_binary('%s/stat' % get_procfs_path()) as f: + ctx_switches = None + interrupts = None + soft_interrupts = None + for line in f: + if line.startswith(b'ctxt'): + ctx_switches = int(line.split()[1]) + elif line.startswith(b'intr'): + interrupts = int(line.split()[1]) + elif line.startswith(b'softirq'): + soft_interrupts = int(line.split()[1]) + if ctx_switches is not None and soft_interrupts is not None \ + and interrupts is not None: + break + syscalls = 0 + return _common.scpustats( + ctx_switches, interrupts, soft_interrupts, syscalls) + + +if os.path.exists("/sys/devices/system/cpu/cpufreq") or \ + os.path.exists("/sys/devices/system/cpu/cpu0/cpufreq"): + def cpu_freq(): + """Return frequency metrics for all CPUs. + Contrarily to other OSes, Linux updates these values in + real-time. + """ + # scaling_* files seem preferable to cpuinfo_*, see: + # http://unix.stackexchange.com/a/87537/168884 + ret = [] + ls = glob.glob("/sys/devices/system/cpu/cpufreq/policy*") + if ls: + # Sort the list so that '10' comes after '2'. This should + # ensure the CPU order is consistent with other CPU functions + # having a 'percpu' argument and returning results for multiple + # CPUs (cpu_times(), cpu_percent(), cpu_times_percent()). + ls.sort(key=lambda x: int(os.path.basename(x)[6:])) + else: + # https://github.com/giampaolo/psutil/issues/981 + ls = glob.glob("/sys/devices/system/cpu/cpu[0-9]*/cpufreq") + ls.sort(key=lambda x: int(re.search('[0-9]+', x).group(0))) + + pjoin = os.path.join + for path in ls: + curr = cat(pjoin(path, "scaling_cur_freq"), fallback=None) + if curr is None: + # Likely an old RedHat, see: + # https://github.com/giampaolo/psutil/issues/1071 + curr = cat(pjoin(path, "cpuinfo_cur_freq"), fallback=None) + if curr is None: + raise NotImplementedError( + "can't find current frequency file") + curr = int(curr) / 1000 + max_ = int(cat(pjoin(path, "scaling_max_freq"))) / 1000 + min_ = int(cat(pjoin(path, "scaling_min_freq"))) / 1000 + ret.append(_common.scpufreq(curr, min_, max_)) + return ret + +elif os.path.exists("/proc/cpuinfo"): + def cpu_freq(): + """Alternate implementation using /proc/cpuinfo. + min and max frequencies are not available and are set to None. + """ + ret = [] + with open_binary('%s/cpuinfo' % get_procfs_path()) as f: + for line in f: + if line.lower().startswith(b'cpu mhz'): + key, value = line.split(b'\t:', 1) + ret.append(_common.scpufreq(float(value), None, None)) + return ret + + +# ===================================================================== +# --- network +# ===================================================================== + + +net_if_addrs = cext_posix.net_if_addrs + + +class _Ipv6UnsupportedError(Exception): + pass + + +class Connections: + """A wrapper on top of /proc/net/* files, retrieving per-process + and system-wide open connections (TCP, UDP, UNIX) similarly to + "netstat -an". + + Note: in case of UNIX sockets we're only able to determine the + local endpoint/path, not the one it's connected to. + According to [1] it would be possible but not easily. + + [1] http://serverfault.com/a/417946 + """ + + def __init__(self): + tcp4 = ("tcp", socket.AF_INET, socket.SOCK_STREAM) + tcp6 = ("tcp6", socket.AF_INET6, socket.SOCK_STREAM) + udp4 = ("udp", socket.AF_INET, socket.SOCK_DGRAM) + udp6 = ("udp6", socket.AF_INET6, socket.SOCK_DGRAM) + unix = ("unix", socket.AF_UNIX, None) + self.tmap = { + "all": (tcp4, tcp6, udp4, udp6, unix), + "tcp": (tcp4, tcp6), + "tcp4": (tcp4,), + "tcp6": (tcp6,), + "udp": (udp4, udp6), + "udp4": (udp4,), + "udp6": (udp6,), + "unix": (unix,), + "inet": (tcp4, tcp6, udp4, udp6), + "inet4": (tcp4, udp4), + "inet6": (tcp6, udp6), + } + self._procfs_path = None + + def get_proc_inodes(self, pid): + inodes = defaultdict(list) + for fd in os.listdir("%s/%s/fd" % (self._procfs_path, pid)): + try: + inode = readlink("%s/%s/fd/%s" % (self._procfs_path, pid, fd)) + except OSError as err: + # ENOENT == file which is gone in the meantime; + # os.stat('/proc/%s' % self.pid) will be done later + # to force NSP (if it's the case) + if err.errno in (errno.ENOENT, errno.ESRCH): + continue + elif err.errno == errno.EINVAL: + # not a link + continue + else: + raise + else: + if inode.startswith('socket:['): + # the process is using a socket + inode = inode[8:][:-1] + inodes[inode].append((pid, int(fd))) + return inodes + + def get_all_inodes(self): + inodes = {} + for pid in pids(): + try: + inodes.update(self.get_proc_inodes(pid)) + except OSError as err: + # os.listdir() is gonna raise a lot of access denied + # exceptions in case of unprivileged user; that's fine + # as we'll just end up returning a connection with PID + # and fd set to None anyway. + # Both netstat -an and lsof does the same so it's + # unlikely we can do any better. + # ENOENT just means a PID disappeared on us. + if err.errno not in ( + errno.ENOENT, errno.ESRCH, errno.EPERM, errno.EACCES): + raise + return inodes + + @staticmethod + def decode_address(addr, family): + """Accept an "ip:port" address as displayed in /proc/net/* + and convert it into a human readable form, like: + + "0500000A:0016" -> ("10.0.0.5", 22) + "0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521) + + The IP address portion is a little or big endian four-byte + hexadecimal number; that is, the least significant byte is listed + first, so we need to reverse the order of the bytes to convert it + to an IP address. + The port is represented as a two-byte hexadecimal number. + + Reference: + http://linuxdevcenter.com/pub/a/linux/2000/11/16/LinuxAdmin.html + """ + ip, port = addr.split(':') + port = int(port, 16) + # this usually refers to a local socket in listen mode with + # no end-points connected + if not port: + return () + if PY3: + ip = ip.encode('ascii') + if family == socket.AF_INET: + # see: https://github.com/giampaolo/psutil/issues/201 + if LITTLE_ENDIAN: + ip = socket.inet_ntop(family, base64.b16decode(ip)[::-1]) + else: + ip = socket.inet_ntop(family, base64.b16decode(ip)) + else: # IPv6 + # old version - let's keep it, just in case... + # ip = ip.decode('hex') + # return socket.inet_ntop(socket.AF_INET6, + # ''.join(ip[i:i+4][::-1] for i in xrange(0, 16, 4))) + ip = base64.b16decode(ip) + try: + # see: https://github.com/giampaolo/psutil/issues/201 + if LITTLE_ENDIAN: + ip = socket.inet_ntop( + socket.AF_INET6, + struct.pack('>4I', *struct.unpack('<4I', ip))) + else: + ip = socket.inet_ntop( + socket.AF_INET6, + struct.pack('<4I', *struct.unpack('<4I', ip))) + except ValueError: + # see: https://github.com/giampaolo/psutil/issues/623 + if not supports_ipv6(): + raise _Ipv6UnsupportedError + else: + raise + return _common.addr(ip, port) + + @staticmethod + def process_inet(file, family, type_, inodes, filter_pid=None): + """Parse /proc/net/tcp* and /proc/net/udp* files.""" + if file.endswith('6') and not os.path.exists(file): + # IPv6 not supported + return + with open_text(file, buffering=BIGFILE_BUFFERING) as f: + f.readline() # skip the first line + for lineno, line in enumerate(f, 1): + try: + _, laddr, raddr, status, _, _, _, _, _, inode = \ + line.split()[:10] + except ValueError: + raise RuntimeError( + "error while parsing %s; malformed line %s %r" % ( + file, lineno, line)) + if inode in inodes: + # # We assume inet sockets are unique, so we error + # # out if there are multiple references to the + # # same inode. We won't do this for UNIX sockets. + # if len(inodes[inode]) > 1 and family != socket.AF_UNIX: + # raise ValueError("ambiguos inode with multiple " + # "PIDs references") + pid, fd = inodes[inode][0] + else: + pid, fd = None, -1 + if filter_pid is not None and filter_pid != pid: + continue + else: + if type_ == socket.SOCK_STREAM: + status = TCP_STATUSES[status] + else: + status = _common.CONN_NONE + try: + laddr = Connections.decode_address(laddr, family) + raddr = Connections.decode_address(raddr, family) + except _Ipv6UnsupportedError: + continue + yield (fd, family, type_, laddr, raddr, status, pid) + + @staticmethod + def process_unix(file, family, inodes, filter_pid=None): + """Parse /proc/net/unix files.""" + with open_text(file, buffering=BIGFILE_BUFFERING) as f: + f.readline() # skip the first line + for line in f: + tokens = line.split() + try: + _, _, _, _, type_, _, inode = tokens[0:7] + except ValueError: + if ' ' not in line: + # see: https://github.com/giampaolo/psutil/issues/766 + continue + raise RuntimeError( + "error while parsing %s; malformed line %r" % ( + file, line)) + if inode in inodes: + # With UNIX sockets we can have a single inode + # referencing many file descriptors. + pairs = inodes[inode] + else: + pairs = [(None, -1)] + for pid, fd in pairs: + if filter_pid is not None and filter_pid != pid: + continue + else: + if len(tokens) == 8: + path = tokens[-1] + else: + path = "" + type_ = int(type_) + # XXX: determining the remote endpoint of a + # UNIX socket on Linux is not possible, see: + # https://serverfault.com/questions/252723/ + raddr = "" + status = _common.CONN_NONE + yield (fd, family, type_, path, raddr, status, pid) + + def retrieve(self, kind, pid=None): + if kind not in self.tmap: + raise ValueError("invalid %r kind argument; choose between %s" + % (kind, ', '.join([repr(x) for x in self.tmap]))) + self._procfs_path = get_procfs_path() + if pid is not None: + inodes = self.get_proc_inodes(pid) + if not inodes: + # no connections for this process + return [] + else: + inodes = self.get_all_inodes() + ret = set() + for f, family, type_ in self.tmap[kind]: + if family in (socket.AF_INET, socket.AF_INET6): + ls = self.process_inet( + "%s/net/%s" % (self._procfs_path, f), + family, type_, inodes, filter_pid=pid) + else: + ls = self.process_unix( + "%s/net/%s" % (self._procfs_path, f), + family, inodes, filter_pid=pid) + for fd, family, type_, laddr, raddr, status, bound_pid in ls: + if pid: + conn = _common.pconn(fd, family, type_, laddr, raddr, + status) + else: + conn = _common.sconn(fd, family, type_, laddr, raddr, + status, bound_pid) + ret.add(conn) + return list(ret) + + +_connections = Connections() + + +def net_connections(kind='inet'): + """Return system-wide open connections.""" + return _connections.retrieve(kind) + + +def net_io_counters(): + """Return network I/O statistics for every network interface + installed on the system as a dict of raw tuples. + """ + with open_text("%s/net/dev" % get_procfs_path()) as f: + lines = f.readlines() + retdict = {} + for line in lines[2:]: + colon = line.rfind(':') + assert colon > 0, repr(line) + name = line[:colon].strip() + fields = line[colon + 1:].strip().split() + + # in + (bytes_recv, + packets_recv, + errin, + dropin, + fifoin, # unused + framein, # unused + compressedin, # unused + multicastin, # unused + # out + bytes_sent, + packets_sent, + errout, + dropout, + fifoout, # unused + collisionsout, # unused + carrierout, # unused + compressedout) = map(int, fields) + + retdict[name] = (bytes_sent, bytes_recv, packets_sent, packets_recv, + errin, errout, dropin, dropout) + return retdict + + +def net_if_stats(): + """Get NIC stats (isup, duplex, speed, mtu).""" + duplex_map = {cext.DUPLEX_FULL: NIC_DUPLEX_FULL, + cext.DUPLEX_HALF: NIC_DUPLEX_HALF, + cext.DUPLEX_UNKNOWN: NIC_DUPLEX_UNKNOWN} + names = net_io_counters().keys() + ret = {} + for name in names: + try: + mtu = cext_posix.net_if_mtu(name) + isup = cext_posix.net_if_flags(name) + duplex, speed = cext.net_if_duplex_speed(name) + except OSError as err: + # https://github.com/giampaolo/psutil/issues/1279 + if err.errno != errno.ENODEV: + raise + else: + ret[name] = _common.snicstats(isup, duplex_map[duplex], speed, mtu) + return ret + + +# ===================================================================== +# --- disks +# ===================================================================== + + +disk_usage = _psposix.disk_usage + + +def disk_io_counters(perdisk=False): + """Return disk I/O statistics for every disk installed on the + system as a dict of raw tuples. + """ + def read_procfs(): + # OK, this is a bit confusing. The format of /proc/diskstats can + # have 3 variations. + # On Linux 2.4 each line has always 15 fields, e.g.: + # "3 0 8 hda 8 8 8 8 8 8 8 8 8 8 8" + # On Linux 2.6+ each line *usually* has 14 fields, and the disk + # name is in another position, like this: + # "3 0 hda 8 8 8 8 8 8 8 8 8 8 8" + # ...unless (Linux 2.6) the line refers to a partition instead + # of a disk, in which case the line has less fields (7): + # "3 1 hda1 8 8 8 8" + # 4.18+ has 4 fields added: + # "3 0 hda 8 8 8 8 8 8 8 8 8 8 8 0 0 0 0" + # See: + # https://www.kernel.org/doc/Documentation/iostats.txt + # https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats + with open_text("%s/diskstats" % get_procfs_path()) as f: + lines = f.readlines() + for line in lines: + fields = line.split() + flen = len(fields) + if flen == 15: + # Linux 2.4 + name = fields[3] + reads = int(fields[2]) + (reads_merged, rbytes, rtime, writes, writes_merged, + wbytes, wtime, _, busy_time, _) = map(int, fields[4:14]) + elif flen == 14 or flen == 18: + # Linux 2.6+, line referring to a disk + name = fields[2] + (reads, reads_merged, rbytes, rtime, writes, writes_merged, + wbytes, wtime, _, busy_time, _) = map(int, fields[3:14]) + elif flen == 7: + # Linux 2.6+, line referring to a partition + name = fields[2] + reads, rbytes, writes, wbytes = map(int, fields[3:]) + rtime = wtime = reads_merged = writes_merged = busy_time = 0 + else: + raise ValueError("not sure how to interpret line %r" % line) + yield (name, reads, writes, rbytes, wbytes, rtime, wtime, + reads_merged, writes_merged, busy_time) + + def read_sysfs(): + for block in os.listdir('/sys/block'): + for root, _, files in os.walk(os.path.join('/sys/block', block)): + if 'stat' not in files: + continue + with open_text(os.path.join(root, 'stat')) as f: + fields = f.read().strip().split() + name = os.path.basename(root) + (reads, reads_merged, rbytes, rtime, writes, writes_merged, + wbytes, wtime, _, busy_time, _) = map(int, fields) + yield (name, reads, writes, rbytes, wbytes, rtime, + wtime, reads_merged, writes_merged, busy_time) + + if os.path.exists('%s/diskstats' % get_procfs_path()): + gen = read_procfs() + elif os.path.exists('/sys/block'): + gen = read_sysfs() + else: + raise NotImplementedError( + "%s/diskstats nor /sys/block filesystem are available on this " + "system" % get_procfs_path()) + + retdict = {} + for entry in gen: + (name, reads, writes, rbytes, wbytes, rtime, wtime, reads_merged, + writes_merged, busy_time) = entry + if not perdisk and not is_storage_device(name): + # perdisk=False means we want to calculate totals so we skip + # partitions (e.g. 'sda1', 'nvme0n1p1') and only include + # base disk devices (e.g. 'sda', 'nvme0n1'). Base disks + # include a total of all their partitions + some extra size + # of their own: + # $ cat /proc/diskstats + # 259 0 sda 10485760 ... + # 259 1 sda1 5186039 ... + # 259 1 sda2 5082039 ... + # See: + # https://github.com/giampaolo/psutil/pull/1313 + continue + + rbytes *= DISK_SECTOR_SIZE + wbytes *= DISK_SECTOR_SIZE + retdict[name] = (reads, writes, rbytes, wbytes, rtime, wtime, + reads_merged, writes_merged, busy_time) + + return retdict + + +def disk_partitions(all=False): + """Return mounted disk partitions as a list of namedtuples.""" + fstypes = set() + procfs_path = get_procfs_path() + with open_text("%s/filesystems" % procfs_path) as f: + for line in f: + line = line.strip() + if not line.startswith("nodev"): + fstypes.add(line.strip()) + else: + # ignore all lines starting with "nodev" except "nodev zfs" + fstype = line.split("\t")[1] + if fstype == "zfs": + fstypes.add("zfs") + + # See: https://github.com/giampaolo/psutil/issues/1307 + if procfs_path == "/proc": + mtab_path = os.path.realpath("/etc/mtab") + else: + mtab_path = os.path.realpath("%s/self/mounts" % procfs_path) + + retlist = [] + partitions = cext.disk_partitions(mtab_path) + for partition in partitions: + device, mountpoint, fstype, opts = partition + if device == 'none': + device = '' + if not all: + if device == '' or fstype not in fstypes: + continue + ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) + retlist.append(ntuple) + return retlist + + +# ===================================================================== +# --- sensors +# ===================================================================== + + +def sensors_temperatures(): + """Return hardware (CPU and others) temperatures as a dict + including hardware name, label, current, max and critical + temperatures. + + Implementation notes: + - /sys/class/hwmon looks like the most recent interface to + retrieve this info, and this implementation relies on it + only (old distros will probably use something else) + - lm-sensors on Ubuntu 16.04 relies on /sys/class/hwmon + - /sys/class/thermal/thermal_zone* is another one but it's more + difficult to parse + """ + ret = collections.defaultdict(list) + basenames = glob.glob('/sys/class/hwmon/hwmon*/temp*_*') + # CentOS has an intermediate /device directory: + # https://github.com/giampaolo/psutil/issues/971 + # https://github.com/nicolargo/glances/issues/1060 + basenames.extend(glob.glob('/sys/class/hwmon/hwmon*/device/temp*_*')) + basenames = sorted(set([x.split('_')[0] for x in basenames])) + + for base in basenames: + try: + path = base + '_input' + current = float(cat(path)) / 1000.0 + path = os.path.join(os.path.dirname(base), 'name') + unit_name = cat(path, binary=False) + except (IOError, OSError, ValueError) as err: + # A lot of things can go wrong here, so let's just skip the + # whole entry. Sure thing is Linux's /sys/class/hwmon really + # is a stinky broken mess. + # https://github.com/giampaolo/psutil/issues/1009 + # https://github.com/giampaolo/psutil/issues/1101 + # https://github.com/giampaolo/psutil/issues/1129 + # https://github.com/giampaolo/psutil/issues/1245 + # https://github.com/giampaolo/psutil/issues/1323 + warnings.warn("ignoring %r for file %r" % (err, path), + RuntimeWarning) + continue + + high = cat(base + '_max', fallback=None) + critical = cat(base + '_crit', fallback=None) + label = cat(base + '_label', fallback='', binary=False) + + if high is not None: + try: + high = float(high) / 1000.0 + except ValueError: + high = None + if critical is not None: + try: + critical = float(critical) / 1000.0 + except ValueError: + critical = None + + ret[unit_name].append((label, current, high, critical)) + + # Indication that no sensors were detected in /sys/class/hwmon/ + if not basenames: + basenames = glob.glob('/sys/class/thermal/thermal_zone*') + basenames = sorted(set(basenames)) + + for base in basenames: + try: + path = os.path.join(base, 'temp') + current = float(cat(path)) / 1000.0 + path = os.path.join(base, 'type') + unit_name = cat(path, binary=False) + except (IOError, OSError, ValueError) as err: + warnings.warn("ignoring %r for file %r" % (err, path), + RuntimeWarning) + continue + + trip_paths = glob.glob(base + '/trip_point*') + trip_points = set(['_'.join( + os.path.basename(p).split('_')[0:3]) for p in trip_paths]) + critical = None + high = None + for trip_point in trip_points: + path = os.path.join(base, trip_point + "_type") + trip_type = cat(path, fallback='', binary=False) + if trip_type == 'critical': + critical = cat(os.path.join(base, trip_point + "_temp"), + fallback=None) + elif trip_type == 'high': + high = cat(os.path.join(base, trip_point + "_temp"), + fallback=None) + + if high is not None: + try: + high = float(high) / 1000.0 + except ValueError: + high = None + if critical is not None: + try: + critical = float(critical) / 1000.0 + except ValueError: + critical = None + + ret[unit_name].append(('', current, high, critical)) + + return dict(ret) + + +def sensors_fans(): + """Return hardware fans info (for CPU and other peripherals) as a + dict including hardware label and current speed. + + Implementation notes: + - /sys/class/hwmon looks like the most recent interface to + retrieve this info, and this implementation relies on it + only (old distros will probably use something else) + - lm-sensors on Ubuntu 16.04 relies on /sys/class/hwmon + """ + ret = collections.defaultdict(list) + basenames = glob.glob('/sys/class/hwmon/hwmon*/fan*_*') + if not basenames: + # CentOS has an intermediate /device directory: + # https://github.com/giampaolo/psutil/issues/971 + basenames = glob.glob('/sys/class/hwmon/hwmon*/device/fan*_*') + + basenames = sorted(set([x.split('_')[0] for x in basenames])) + for base in basenames: + try: + current = int(cat(base + '_input')) + except (IOError, OSError) as err: + warnings.warn("ignoring %r" % err, RuntimeWarning) + continue + unit_name = cat(os.path.join(os.path.dirname(base), 'name'), + binary=False) + label = cat(base + '_label', fallback='', binary=False) + ret[unit_name].append(_common.sfan(label, current)) + + return dict(ret) + + +def sensors_battery(): + """Return battery information. + Implementation note: it appears /sys/class/power_supply/BAT0/ + directory structure may vary and provide files with the same + meaning but under different names, see: + https://github.com/giampaolo/psutil/issues/966 + """ + null = object() + + def multi_cat(*paths): + """Attempt to read the content of multiple files which may + not exist. If none of them exist return None. + """ + for path in paths: + ret = cat(path, fallback=null) + if ret != null: + return int(ret) if ret.isdigit() else ret + return None + + bats = [x for x in os.listdir(POWER_SUPPLY_PATH) if x.startswith('BAT')] + if not bats: + return None + # Get the first available battery. Usually this is "BAT0", except + # some rare exceptions: + # https://github.com/giampaolo/psutil/issues/1238 + root = os.path.join(POWER_SUPPLY_PATH, sorted(bats)[0]) + + # Base metrics. + energy_now = multi_cat( + root + "/energy_now", + root + "/charge_now") + power_now = multi_cat( + root + "/power_now", + root + "/current_now") + energy_full = multi_cat( + root + "/energy_full", + root + "/charge_full") + if energy_now is None or power_now is None: + return None + + # Percent. If we have energy_full the percentage will be more + # accurate compared to reading /capacity file (float vs. int). + if energy_full is not None: + try: + percent = 100.0 * energy_now / energy_full + except ZeroDivisionError: + percent = 0.0 + else: + percent = int(cat(root + "/capacity", fallback=-1)) + if percent == -1: + return None + + # Is AC power cable plugged in? + # Note: AC0 is not always available and sometimes (e.g. CentOS7) + # it's called "AC". + power_plugged = None + online = multi_cat( + os.path.join(POWER_SUPPLY_PATH, "AC0/online"), + os.path.join(POWER_SUPPLY_PATH, "AC/online")) + if online is not None: + power_plugged = online == 1 + else: + status = cat(root + "/status", fallback="", binary=False).lower() + if status == "discharging": + power_plugged = False + elif status in ("charging", "full"): + power_plugged = True + + # Seconds left. + # Note to self: we may also calculate the charging ETA as per: + # https://github.com/thialfihar/dotfiles/blob/ + # 013937745fd9050c30146290e8f963d65c0179e6/bin/battery.py#L55 + if power_plugged: + secsleft = _common.POWER_TIME_UNLIMITED + else: + try: + secsleft = int(energy_now / power_now * 3600) + except ZeroDivisionError: + secsleft = _common.POWER_TIME_UNKNOWN + + return _common.sbattery(percent, secsleft, power_plugged) + + +# ===================================================================== +# --- other system functions +# ===================================================================== + + +def users(): + """Return currently connected users as a list of namedtuples.""" + retlist = [] + rawlist = cext.users() + for item in rawlist: + user, tty, hostname, tstamp, user_process, pid = item + # note: the underlying C function includes entries about + # system boot, run level and others. We might want + # to use them in the future. + if not user_process: + continue + if hostname in (':0.0', ':0'): + hostname = 'localhost' + nt = _common.suser(user, tty or None, hostname, tstamp, pid) + retlist.append(nt) + return retlist + + +def boot_time(): + """Return the system boot time expressed in seconds since the epoch.""" + global BOOT_TIME + path = '%s/stat' % get_procfs_path() + with open_binary(path) as f: + for line in f: + if line.startswith(b'btime'): + ret = float(line.strip().split()[1]) + BOOT_TIME = ret + return ret + raise RuntimeError( + "line 'btime' not found in %s" % path) + + +# ===================================================================== +# --- processes +# ===================================================================== + + +def pids(): + """Returns a list of PIDs currently running on the system.""" + return [int(x) for x in os.listdir(b(get_procfs_path())) if x.isdigit()] + + +def pid_exists(pid): + """Check for the existence of a unix PID. Linux TIDs are not + supported (always return False). + """ + if not _psposix.pid_exists(pid): + return False + else: + # Linux's apparently does not distinguish between PIDs and TIDs + # (thread IDs). + # listdir("/proc") won't show any TID (only PIDs) but + # os.stat("/proc/{tid}") will succeed if {tid} exists. + # os.kill() can also be passed a TID. This is quite confusing. + # In here we want to enforce this distinction and support PIDs + # only, see: + # https://github.com/giampaolo/psutil/issues/687 + try: + # Note: already checked that this is faster than using a + # regular expr. Also (a lot) faster than doing + # 'return pid in pids()' + path = "%s/%s/status" % (get_procfs_path(), pid) + with open_binary(path) as f: + for line in f: + if line.startswith(b"Tgid:"): + tgid = int(line.split()[1]) + # If tgid and pid are the same then we're + # dealing with a process PID. + return tgid == pid + raise ValueError("'Tgid' line not found in %s" % path) + except (EnvironmentError, ValueError): + return pid in pids() + + +def ppid_map(): + """Obtain a {pid: ppid, ...} dict for all running processes in + one shot. Used to speed up Process.children(). + """ + ret = {} + procfs_path = get_procfs_path() + for pid in pids(): + try: + with open_binary("%s/%s/stat" % (procfs_path, pid)) as f: + data = f.read() + except EnvironmentError as err: + # Note: we should be able to access /stat for all processes + # aka it's unlikely we'll bump into EPERM, which is good. + if err.errno not in (errno.ENOENT, errno.ESRCH): + raise + else: + rpar = data.rfind(b')') + dset = data[rpar + 2:].split() + ppid = int(dset[1]) + ret[pid] = ppid + return ret + + +def wrap_exceptions(fun): + """Decorator which translates bare OSError and IOError exceptions + into NoSuchProcess and AccessDenied. + """ + @functools.wraps(fun) + def wrapper(self, *args, **kwargs): + try: + return fun(self, *args, **kwargs) + except EnvironmentError as err: + if err.errno in (errno.EPERM, errno.EACCES): + raise AccessDenied(self.pid, self._name) + # ESRCH (no such process) can be raised on read() if + # process is gone in the meantime. + if err.errno == errno.ESRCH: + raise NoSuchProcess(self.pid, self._name) + # ENOENT (no such file or directory) can be raised on open(). + if err.errno == errno.ENOENT and not os.path.exists("%s/%s" % ( + self._procfs_path, self.pid)): + raise NoSuchProcess(self.pid, self._name) + # Note: zombies will keep existing under /proc until they're + # gone so there's no way to distinguish them in here. + raise + return wrapper + + +class Process(object): + """Linux process implementation.""" + + __slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"] + + def __init__(self, pid): + self.pid = pid + self._name = None + self._ppid = None + self._procfs_path = get_procfs_path() + + def _assert_alive(self): + """Raise NSP if the process disappeared on us.""" + # For those C function who do not raise NSP, possibly returning + # incorrect or incomplete result. + os.stat('%s/%s' % (self._procfs_path, self.pid)) + + @wrap_exceptions + @memoize_when_activated + def _parse_stat_file(self): + """Parse /proc/{pid}/stat file and return a dict with various + process info. + Using "man proc" as a reference: where "man proc" refers to + position N always substract 3 (e.g ppid position 4 in + 'man proc' == position 1 in here). + The return value is cached in case oneshot() ctx manager is + in use. + """ + with open_binary("%s/%s/stat" % (self._procfs_path, self.pid)) as f: + data = f.read() + # Process name is between parentheses. It can contain spaces and + # other parentheses. This is taken into account by looking for + # the first occurrence of "(" and the last occurence of ")". + rpar = data.rfind(b')') + name = data[data.find(b'(') + 1:rpar] + fields = data[rpar + 2:].split() + + ret = {} + ret['name'] = name + ret['status'] = fields[0] + ret['ppid'] = fields[1] + ret['ttynr'] = fields[4] + ret['utime'] = fields[11] + ret['stime'] = fields[12] + ret['children_utime'] = fields[13] + ret['children_stime'] = fields[14] + ret['create_time'] = fields[19] + ret['cpu_num'] = fields[36] + + return ret + + @wrap_exceptions + @memoize_when_activated + def _read_status_file(self): + """Read /proc/{pid}/stat file and return its content. + The return value is cached in case oneshot() ctx manager is + in use. + """ + with open_binary("%s/%s/status" % (self._procfs_path, self.pid)) as f: + return f.read() + + @wrap_exceptions + @memoize_when_activated + def _read_smaps_file(self): + with open_binary("%s/%s/smaps" % (self._procfs_path, self.pid), + buffering=BIGFILE_BUFFERING) as f: + return f.read().strip() + + def oneshot_enter(self): + self._parse_stat_file.cache_activate(self) + self._read_status_file.cache_activate(self) + self._read_smaps_file.cache_activate(self) + + def oneshot_exit(self): + self._parse_stat_file.cache_deactivate(self) + self._read_status_file.cache_deactivate(self) + self._read_smaps_file.cache_deactivate(self) + + @wrap_exceptions + def name(self): + name = self._parse_stat_file()['name'] + if PY3: + name = decode(name) + # XXX - gets changed later and probably needs refactoring + return name + + def exe(self): + try: + return readlink("%s/%s/exe" % (self._procfs_path, self.pid)) + except OSError as err: + if err.errno in (errno.ENOENT, errno.ESRCH): + # no such file error; might be raised also if the + # path actually exists for system processes with + # low pids (about 0-20) + if os.path.lexists("%s/%s" % (self._procfs_path, self.pid)): + return "" + else: + if not pid_exists(self.pid): + raise NoSuchProcess(self.pid, self._name) + else: + raise ZombieProcess(self.pid, self._name, self._ppid) + if err.errno in (errno.EPERM, errno.EACCES): + raise AccessDenied(self.pid, self._name) + raise + + @wrap_exceptions + def cmdline(self): + with open_text("%s/%s/cmdline" % (self._procfs_path, self.pid)) as f: + data = f.read() + if not data: + # may happen in case of zombie process + return [] + # 'man proc' states that args are separated by null bytes '\0' + # and last char is supposed to be a null byte. Nevertheless + # some processes may change their cmdline after being started + # (via setproctitle() or similar), they are usually not + # compliant with this rule and use spaces instead. Google + # Chrome process is an example. See: + # https://github.com/giampaolo/psutil/issues/1179 + sep = '\x00' if data.endswith('\x00') else ' ' + if data.endswith(sep): + data = data[:-1] + return [x for x in data.split(sep)] + + @wrap_exceptions + def environ(self): + with open_text("%s/%s/environ" % (self._procfs_path, self.pid)) as f: + data = f.read() + return parse_environ_block(data) + + @wrap_exceptions + def terminal(self): + tty_nr = int(self._parse_stat_file()['ttynr']) + tmap = _psposix.get_terminal_map() + try: + return tmap[tty_nr] + except KeyError: + return None + + # May not be available on old kernels. + if os.path.exists('/proc/%s/io' % os.getpid()): + @wrap_exceptions + def io_counters(self): + fname = "%s/%s/io" % (self._procfs_path, self.pid) + fields = {} + with open_binary(fname) as f: + for line in f: + # https://github.com/giampaolo/psutil/issues/1004 + line = line.strip() + if line: + try: + name, value = line.split(b': ') + except ValueError: + # https://github.com/giampaolo/psutil/issues/1004 + continue + else: + fields[name] = int(value) + if not fields: + raise RuntimeError("%s file was empty" % fname) + try: + return pio( + fields[b'syscr'], # read syscalls + fields[b'syscw'], # write syscalls + fields[b'read_bytes'], # read bytes + fields[b'write_bytes'], # write bytes + fields[b'rchar'], # read chars + fields[b'wchar'], # write chars + ) + except KeyError as err: + raise ValueError("%r field was not found in %s; found fields " + "are %r" % (err[0], fname, fields)) + + @wrap_exceptions + def cpu_times(self): + values = self._parse_stat_file() + utime = float(values['utime']) / CLOCK_TICKS + stime = float(values['stime']) / CLOCK_TICKS + children_utime = float(values['children_utime']) / CLOCK_TICKS + children_stime = float(values['children_stime']) / CLOCK_TICKS + return _common.pcputimes(utime, stime, children_utime, children_stime) + + @wrap_exceptions + def cpu_num(self): + """What CPU the process is on.""" + return int(self._parse_stat_file()['cpu_num']) + + @wrap_exceptions + def wait(self, timeout=None): + return _psposix.wait_pid(self.pid, timeout, self._name) + + @wrap_exceptions + def create_time(self): + ctime = float(self._parse_stat_file()['create_time']) + # According to documentation, starttime is in field 21 and the + # unit is jiffies (clock ticks). + # We first divide it for clock ticks and then add uptime returning + # seconds since the epoch, in UTC. + # Also use cached value if available. + bt = BOOT_TIME or boot_time() + return (ctime / CLOCK_TICKS) + bt + + @wrap_exceptions + def memory_info(self): + # ============================================================ + # | FIELD | DESCRIPTION | AKA | TOP | + # ============================================================ + # | rss | resident set size | | RES | + # | vms | total program size | size | VIRT | + # | shared | shared pages (from shared mappings) | | SHR | + # | text | text ('code') | trs | CODE | + # | lib | library (unused in Linux 2.6) | lrs | | + # | data | data + stack | drs | DATA | + # | dirty | dirty pages (unused in Linux 2.6) | dt | | + # ============================================================ + with open_binary("%s/%s/statm" % (self._procfs_path, self.pid)) as f: + vms, rss, shared, text, lib, data, dirty = \ + [int(x) * PAGESIZE for x in f.readline().split()[:7]] + return pmem(rss, vms, shared, text, lib, data, dirty) + + # /proc/pid/smaps does not exist on kernels < 2.6.14 or if + # CONFIG_MMU kernel configuration option is not enabled. + if HAS_SMAPS: + + @wrap_exceptions + def memory_full_info( + self, + # Gets Private_Clean, Private_Dirty, Private_Hugetlb. + _private_re=re.compile(br"\nPrivate.*:\s+(\d+)"), + _pss_re=re.compile(br"\nPss\:\s+(\d+)"), + _swap_re=re.compile(br"\nSwap\:\s+(\d+)")): + basic_mem = self.memory_info() + # Note: using 3 regexes is faster than reading the file + # line by line. + # XXX: on Python 3 the 2 regexes are 30% slower than on + # Python 2 though. Figure out why. + # + # You might be tempted to calculate USS by subtracting + # the "shared" value from the "resident" value in + # /proc//statm. But at least on Linux, statm's "shared" + # value actually counts pages backed by files, which has + # little to do with whether the pages are actually shared. + # /proc/self/smaps on the other hand appears to give us the + # correct information. + smaps_data = self._read_smaps_file() + # Note: smaps file can be empty for certain processes. + # The code below will not crash though and will result to 0. + uss = sum(map(int, _private_re.findall(smaps_data))) * 1024 + pss = sum(map(int, _pss_re.findall(smaps_data))) * 1024 + swap = sum(map(int, _swap_re.findall(smaps_data))) * 1024 + return pfullmem(*basic_mem + (uss, pss, swap)) + + else: + memory_full_info = memory_info + + if HAS_SMAPS: + + @wrap_exceptions + def memory_maps(self): + """Return process's mapped memory regions as a list of named + tuples. Fields are explained in 'man proc'; here is an updated + (Apr 2012) version: http://goo.gl/fmebo + + /proc/{PID}/smaps does not exist on kernels < 2.6.14 or if + CONFIG_MMU kernel configuration option is not enabled. + """ + def get_blocks(lines, current_block): + data = {} + for line in lines: + fields = line.split(None, 5) + if not fields[0].endswith(b':'): + # new block section + yield (current_block.pop(), data) + current_block.append(line) + else: + try: + data[fields[0]] = int(fields[1]) * 1024 + except ValueError: + if fields[0].startswith(b'VmFlags:'): + # see issue #369 + continue + else: + raise ValueError("don't know how to inte" + "rpret line %r" % line) + yield (current_block.pop(), data) + + data = self._read_smaps_file() + # Note: smaps file can be empty for certain processes. + if not data: + return [] + lines = data.split(b'\n') + ls = [] + first_line = lines.pop(0) + current_block = [first_line] + for header, data in get_blocks(lines, current_block): + hfields = header.split(None, 5) + try: + addr, perms, offset, dev, inode, path = hfields + except ValueError: + addr, perms, offset, dev, inode, path = \ + hfields + [''] + if not path: + path = '[anon]' + else: + if PY3: + path = decode(path) + path = path.strip() + if (path.endswith(' (deleted)') and not + path_exists_strict(path)): + path = path[:-10] + ls.append(( + decode(addr), decode(perms), path, + data[b'Rss:'], + data.get(b'Size:', 0), + data.get(b'Pss:', 0), + data.get(b'Shared_Clean:', 0), + data.get(b'Shared_Dirty:', 0), + data.get(b'Private_Clean:', 0), + data.get(b'Private_Dirty:', 0), + data.get(b'Referenced:', 0), + data.get(b'Anonymous:', 0), + data.get(b'Swap:', 0) + )) + return ls + + @wrap_exceptions + def cwd(self): + try: + return readlink("%s/%s/cwd" % (self._procfs_path, self.pid)) + except OSError as err: + # https://github.com/giampaolo/psutil/issues/986 + if err.errno in (errno.ENOENT, errno.ESRCH): + if not pid_exists(self.pid): + raise NoSuchProcess(self.pid, self._name) + else: + raise ZombieProcess(self.pid, self._name, self._ppid) + raise + + @wrap_exceptions + def num_ctx_switches(self, + _ctxsw_re=re.compile(br'ctxt_switches:\t(\d+)')): + data = self._read_status_file() + ctxsw = _ctxsw_re.findall(data) + if not ctxsw: + raise NotImplementedError( + "'voluntary_ctxt_switches' and 'nonvoluntary_ctxt_switches'" + "lines were not found in %s/%s/status; the kernel is " + "probably older than 2.6.23" % ( + self._procfs_path, self.pid)) + else: + return _common.pctxsw(int(ctxsw[0]), int(ctxsw[1])) + + @wrap_exceptions + def num_threads(self, _num_threads_re=re.compile(br'Threads:\t(\d+)')): + # Note: on Python 3 using a re is faster than iterating over file + # line by line. On Python 2 is the exact opposite, and iterating + # over a file on Python 3 is slower than on Python 2. + data = self._read_status_file() + return int(_num_threads_re.findall(data)[0]) + + @wrap_exceptions + def threads(self): + thread_ids = os.listdir("%s/%s/task" % (self._procfs_path, self.pid)) + thread_ids.sort() + retlist = [] + hit_enoent = False + for thread_id in thread_ids: + fname = "%s/%s/task/%s/stat" % ( + self._procfs_path, self.pid, thread_id) + try: + with open_binary(fname) as f: + st = f.read().strip() + except IOError as err: + if err.errno == errno.ENOENT: + # no such file or directory; it means thread + # disappeared on us + hit_enoent = True + continue + raise + # ignore the first two values ("pid (exe)") + st = st[st.find(b')') + 2:] + values = st.split(b' ') + utime = float(values[11]) / CLOCK_TICKS + stime = float(values[12]) / CLOCK_TICKS + ntuple = _common.pthread(int(thread_id), utime, stime) + retlist.append(ntuple) + if hit_enoent: + self._assert_alive() + return retlist + + @wrap_exceptions + def nice_get(self): + # with open_text('%s/%s/stat' % (self._procfs_path, self.pid)) as f: + # data = f.read() + # return int(data.split()[18]) + + # Use C implementation + return cext_posix.getpriority(self.pid) + + @wrap_exceptions + def nice_set(self, value): + return cext_posix.setpriority(self.pid, value) + + @wrap_exceptions + def cpu_affinity_get(self): + return cext.proc_cpu_affinity_get(self.pid) + + def _get_eligible_cpus( + self, _re=re.compile(br"Cpus_allowed_list:\t(\d+)-(\d+)")): + # See: https://github.com/giampaolo/psutil/issues/956 + data = self._read_status_file() + match = _re.findall(data) + if match: + return list(range(int(match[0][0]), int(match[0][1]) + 1)) + else: + return list(range(len(per_cpu_times()))) + + @wrap_exceptions + def cpu_affinity_set(self, cpus): + try: + cext.proc_cpu_affinity_set(self.pid, cpus) + except (OSError, ValueError) as err: + if isinstance(err, ValueError) or err.errno == errno.EINVAL: + eligible_cpus = self._get_eligible_cpus() + all_cpus = tuple(range(len(per_cpu_times()))) + for cpu in cpus: + if cpu not in all_cpus: + raise ValueError( + "invalid CPU number %r; choose between %s" % ( + cpu, eligible_cpus)) + if cpu not in eligible_cpus: + raise ValueError( + "CPU number %r is not eligible; choose " + "between %s" % (cpu, eligible_cpus)) + raise + + # only starting from kernel 2.6.13 + if HAS_PROC_IO_PRIORITY: + + @wrap_exceptions + def ionice_get(self): + ioclass, value = cext.proc_ioprio_get(self.pid) + if enum is not None: + ioclass = IOPriority(ioclass) + return _common.pionice(ioclass, value) + + @wrap_exceptions + def ionice_set(self, ioclass, value): + if value is not None: + if not PY3 and not isinstance(value, (int, long)): + msg = "value argument is not an integer (gor %r)" % value + raise TypeError(msg) + if not 0 <= value <= 7: + raise ValueError( + "value argument range expected is between 0 and 7") + + if ioclass in (IOPRIO_CLASS_NONE, None): + if value: + msg = "can't specify value with IOPRIO_CLASS_NONE " \ + "(got %r)" % value + raise ValueError(msg) + ioclass = IOPRIO_CLASS_NONE + value = 0 + elif ioclass == IOPRIO_CLASS_IDLE: + if value: + msg = "can't specify value with IOPRIO_CLASS_IDLE " \ + "(got %r)" % value + raise ValueError(msg) + value = 0 + elif ioclass in (IOPRIO_CLASS_RT, IOPRIO_CLASS_BE): + if value is None: + # TODO: add comment explaining why this is 4 (?) + value = 4 + else: + # otherwise we would get OSError(EVINAL) + raise ValueError("invalid ioclass argument %r" % ioclass) + + return cext.proc_ioprio_set(self.pid, ioclass, value) + + if HAS_PRLIMIT: + + @wrap_exceptions + def rlimit(self, resource, limits=None): + # If pid is 0 prlimit() applies to the calling process and + # we don't want that. We should never get here though as + # PID 0 is not supported on Linux. + if self.pid == 0: + raise ValueError("can't use prlimit() against PID 0 process") + try: + if limits is None: + # get + return cext.linux_prlimit(self.pid, resource) + else: + # set + if len(limits) != 2: + raise ValueError( + "second argument must be a (soft, hard) tuple, " + "got %s" % repr(limits)) + soft, hard = limits + cext.linux_prlimit(self.pid, resource, soft, hard) + except OSError as err: + if err.errno == errno.ENOSYS and pid_exists(self.pid): + # I saw this happening on Travis: + # https://travis-ci.org/giampaolo/psutil/jobs/51368273 + raise ZombieProcess(self.pid, self._name, self._ppid) + else: + raise + + @wrap_exceptions + def status(self): + letter = self._parse_stat_file()['status'] + if PY3: + letter = letter.decode() + # XXX is '?' legit? (we're not supposed to return it anyway) + return PROC_STATUSES.get(letter, '?') + + @wrap_exceptions + def open_files(self): + retlist = [] + files = os.listdir("%s/%s/fd" % (self._procfs_path, self.pid)) + hit_enoent = False + for fd in files: + file = "%s/%s/fd/%s" % (self._procfs_path, self.pid, fd) + try: + path = readlink(file) + except OSError as err: + # ENOENT == file which is gone in the meantime + if err.errno in (errno.ENOENT, errno.ESRCH): + hit_enoent = True + continue + elif err.errno == errno.EINVAL: + # not a link + continue + else: + raise + else: + # If path is not an absolute there's no way to tell + # whether it's a regular file or not, so we skip it. + # A regular file is always supposed to be have an + # absolute path though. + if path.startswith('/') and isfile_strict(path): + # Get file position and flags. + file = "%s/%s/fdinfo/%s" % ( + self._procfs_path, self.pid, fd) + try: + with open_binary(file) as f: + pos = int(f.readline().split()[1]) + flags = int(f.readline().split()[1], 8) + except IOError as err: + if err.errno == errno.ENOENT: + # fd gone in the meantime; process may + # still be alive + hit_enoent = True + else: + raise + else: + mode = file_flags_to_mode(flags) + ntuple = popenfile( + path, int(fd), int(pos), mode, flags) + retlist.append(ntuple) + if hit_enoent: + self._assert_alive() + return retlist + + @wrap_exceptions + def connections(self, kind='inet'): + ret = _connections.retrieve(kind, self.pid) + self._assert_alive() + return ret + + @wrap_exceptions + def num_fds(self): + return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid))) + + @wrap_exceptions + def ppid(self): + return int(self._parse_stat_file()['ppid']) + + @wrap_exceptions + def uids(self, _uids_re=re.compile(br'Uid:\t(\d+)\t(\d+)\t(\d+)')): + data = self._read_status_file() + real, effective, saved = _uids_re.findall(data)[0] + return _common.puids(int(real), int(effective), int(saved)) + + @wrap_exceptions + def gids(self, _gids_re=re.compile(br'Gid:\t(\d+)\t(\d+)\t(\d+)')): + data = self._read_status_file() + real, effective, saved = _gids_re.findall(data)[0] + return _common.pgids(int(real), int(effective), int(saved)) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psosx.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psosx.py new file mode 100644 index 00000000..7459a0f3 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psosx.py @@ -0,0 +1,578 @@ +# 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. + +"""macOS platform implementation.""" + +import contextlib +import errno +import functools +import os +from socket import AF_INET +from collections import namedtuple + +from . import _common +from . import _psposix +from . import _psutil_osx as cext +from . import _psutil_posix as cext_posix +from ._common import AF_INET6 +from ._common import conn_tmap +from ._common import isfile_strict +from ._common import memoize_when_activated +from ._common import parse_environ_block +from ._common import sockfam_to_enum +from ._common import socktype_to_enum +from ._common import usage_percent + + +__extra__all__ = [] + + +# ===================================================================== +# --- globals +# ===================================================================== + + +PAGESIZE = os.sysconf("SC_PAGE_SIZE") +AF_LINK = cext_posix.AF_LINK + +TCP_STATUSES = { + cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, + cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, + cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV, + cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, + cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, + cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, + cext.TCPS_CLOSED: _common.CONN_CLOSE, + cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, + cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, + cext.TCPS_LISTEN: _common.CONN_LISTEN, + cext.TCPS_CLOSING: _common.CONN_CLOSING, + cext.PSUTIL_CONN_NONE: _common.CONN_NONE, +} + +PROC_STATUSES = { + cext.SIDL: _common.STATUS_IDLE, + cext.SRUN: _common.STATUS_RUNNING, + cext.SSLEEP: _common.STATUS_SLEEPING, + cext.SSTOP: _common.STATUS_STOPPED, + cext.SZOMB: _common.STATUS_ZOMBIE, +} + +kinfo_proc_map = dict( + ppid=0, + ruid=1, + euid=2, + suid=3, + rgid=4, + egid=5, + sgid=6, + ttynr=7, + ctime=8, + status=9, + name=10, +) + +pidtaskinfo_map = dict( + cpuutime=0, + cpustime=1, + rss=2, + vms=3, + pfaults=4, + pageins=5, + numthreads=6, + volctxsw=7, +) + +# These objects get set on "import psutil" from the __init__.py +# file, see: https://github.com/giampaolo/psutil/issues/1402 +NoSuchProcess = None +ZombieProcess = None +AccessDenied = None +TimeoutExpired = None + + +# ===================================================================== +# --- named tuples +# ===================================================================== + + +# psutil.cpu_times() +scputimes = namedtuple('scputimes', ['user', 'nice', 'system', 'idle']) +# psutil.virtual_memory() +svmem = namedtuple( + 'svmem', ['total', 'available', 'percent', 'used', 'free', + 'active', 'inactive', 'wired']) +# psutil.Process.memory_info() +pmem = namedtuple('pmem', ['rss', 'vms', 'pfaults', 'pageins']) +# psutil.Process.memory_full_info() +pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', )) + + +# ===================================================================== +# --- memory +# ===================================================================== + + +def virtual_memory(): + """System virtual memory as a namedtuple.""" + total, active, inactive, wired, free, speculative = cext.virtual_mem() + # This is how Zabbix calculate avail and used mem: + # https://github.com/zabbix/zabbix/blob/trunk/src/libs/zbxsysinfo/ + # osx/memory.c + # Also see: https://github.com/giampaolo/psutil/issues/1277 + avail = inactive + free + used = active + wired + # This is NOT how Zabbix calculates free mem but it matches "free" + # cmdline utility. + free -= speculative + percent = usage_percent((total - avail), total, round_=1) + return svmem(total, avail, percent, used, free, + active, inactive, wired) + + +def swap_memory(): + """Swap system memory as a (total, used, free, sin, sout) tuple.""" + total, used, free, sin, sout = cext.swap_mem() + percent = usage_percent(used, total, round_=1) + return _common.sswap(total, used, free, percent, sin, sout) + + +# ===================================================================== +# --- CPU +# ===================================================================== + + +def cpu_times(): + """Return system CPU times as a namedtuple.""" + user, nice, system, idle = cext.cpu_times() + return scputimes(user, nice, system, idle) + + +def per_cpu_times(): + """Return system CPU times as a named tuple""" + ret = [] + for cpu_t in cext.per_cpu_times(): + user, nice, system, idle = cpu_t + item = scputimes(user, nice, system, idle) + ret.append(item) + return ret + + +def cpu_count_logical(): + """Return the number of logical CPUs in the system.""" + return cext.cpu_count_logical() + + +def cpu_count_physical(): + """Return the number of physical CPUs in the system.""" + return cext.cpu_count_phys() + + +def cpu_stats(): + ctx_switches, interrupts, soft_interrupts, syscalls, traps = \ + cext.cpu_stats() + return _common.scpustats( + ctx_switches, interrupts, soft_interrupts, syscalls) + + +def cpu_freq(): + """Return CPU frequency. + On macOS per-cpu frequency is not supported. + Also, the returned frequency never changes, see: + https://arstechnica.com/civis/viewtopic.php?f=19&t=465002 + """ + curr, min_, max_ = cext.cpu_freq() + return [_common.scpufreq(curr, min_, max_)] + + +# ===================================================================== +# --- disks +# ===================================================================== + + +disk_usage = _psposix.disk_usage +disk_io_counters = cext.disk_io_counters + + +def disk_partitions(all=False): + """Return mounted disk partitions as a list of namedtuples.""" + retlist = [] + partitions = cext.disk_partitions() + for partition in partitions: + device, mountpoint, fstype, opts = partition + if device == 'none': + device = '' + if not all: + if not os.path.isabs(device) or not os.path.exists(device): + continue + ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) + retlist.append(ntuple) + return retlist + + +# ===================================================================== +# --- sensors +# ===================================================================== + + +def sensors_battery(): + """Return battery information.""" + try: + percent, minsleft, power_plugged = cext.sensors_battery() + except NotImplementedError: + # no power source - return None according to interface + return None + power_plugged = power_plugged == 1 + if power_plugged: + secsleft = _common.POWER_TIME_UNLIMITED + elif minsleft == -1: + secsleft = _common.POWER_TIME_UNKNOWN + else: + secsleft = minsleft * 60 + return _common.sbattery(percent, secsleft, power_plugged) + + +# ===================================================================== +# --- network +# ===================================================================== + + +net_io_counters = cext.net_io_counters +net_if_addrs = cext_posix.net_if_addrs + + +def net_connections(kind='inet'): + """System-wide network connections.""" + # Note: on macOS this will fail with AccessDenied unless + # the process is owned by root. + ret = [] + for pid in pids(): + try: + cons = Process(pid).connections(kind) + except NoSuchProcess: + continue + else: + if cons: + for c in cons: + c = list(c) + [pid] + ret.append(_common.sconn(*c)) + return ret + + +def net_if_stats(): + """Get NIC stats (isup, duplex, speed, mtu).""" + names = net_io_counters().keys() + ret = {} + for name in names: + try: + mtu = cext_posix.net_if_mtu(name) + isup = cext_posix.net_if_flags(name) + duplex, speed = cext_posix.net_if_duplex_speed(name) + except OSError as err: + # https://github.com/giampaolo/psutil/issues/1279 + if err.errno != errno.ENODEV: + raise + else: + if hasattr(_common, 'NicDuplex'): + duplex = _common.NicDuplex(duplex) + ret[name] = _common.snicstats(isup, duplex, speed, mtu) + return ret + + +# ===================================================================== +# --- other system functions +# ===================================================================== + + +def boot_time(): + """The system boot time expressed in seconds since the epoch.""" + return cext.boot_time() + + +def users(): + """Return currently connected users as a list of namedtuples.""" + retlist = [] + rawlist = cext.users() + for item in rawlist: + user, tty, hostname, tstamp, pid = item + if tty == '~': + continue # reboot or shutdown + if not tstamp: + continue + nt = _common.suser(user, tty or None, hostname or None, tstamp, pid) + retlist.append(nt) + return retlist + + +# ===================================================================== +# --- processes +# ===================================================================== + + +def pids(): + ls = cext.pids() + if 0 not in ls: + # On certain macOS versions pids() C doesn't return PID 0 but + # "ps" does and the process is querable via sysctl(): + # https://travis-ci.org/giampaolo/psutil/jobs/309619941 + try: + Process(0).create_time() + ls.insert(0, 0) + except NoSuchProcess: + pass + except AccessDenied: + ls.insert(0, 0) + return ls + + +pid_exists = _psposix.pid_exists + + +def wrap_exceptions(fun): + """Decorator which translates bare OSError exceptions into + NoSuchProcess and AccessDenied. + """ + @functools.wraps(fun) + def wrapper(self, *args, **kwargs): + try: + return fun(self, *args, **kwargs) + except OSError as err: + if err.errno == errno.ESRCH: + raise NoSuchProcess(self.pid, self._name) + if err.errno in (errno.EPERM, errno.EACCES): + raise AccessDenied(self.pid, self._name) + raise + except cext.ZombieProcessError: + raise ZombieProcess(self.pid, self._name, self._ppid) + return wrapper + + +@contextlib.contextmanager +def catch_zombie(proc): + """There are some poor C APIs which incorrectly raise ESRCH when + the process is still alive or it's a zombie, or even RuntimeError + (those who don't set errno). This is here in order to solve: + https://github.com/giampaolo/psutil/issues/1044 + """ + try: + yield + except (OSError, RuntimeError) as err: + if isinstance(err, RuntimeError) or err.errno == errno.ESRCH: + try: + # status() is not supposed to lie and correctly detect + # zombies so if it raises ESRCH it's true. + status = proc.status() + except NoSuchProcess: + raise err + else: + if status == _common.STATUS_ZOMBIE: + raise ZombieProcess(proc.pid, proc._name, proc._ppid) + else: + raise AccessDenied(proc.pid, proc._name) + else: + raise + + +class Process(object): + """Wrapper class around underlying C implementation.""" + + __slots__ = ["pid", "_name", "_ppid", "_cache"] + + def __init__(self, pid): + self.pid = pid + self._name = None + self._ppid = None + + @wrap_exceptions + @memoize_when_activated + def _get_kinfo_proc(self): + # Note: should work with all PIDs without permission issues. + ret = cext.proc_kinfo_oneshot(self.pid) + assert len(ret) == len(kinfo_proc_map) + return ret + + @wrap_exceptions + @memoize_when_activated + def _get_pidtaskinfo(self): + # Note: should work for PIDs owned by user only. + with catch_zombie(self): + ret = cext.proc_pidtaskinfo_oneshot(self.pid) + assert len(ret) == len(pidtaskinfo_map) + return ret + + def oneshot_enter(self): + self._get_kinfo_proc.cache_activate(self) + self._get_pidtaskinfo.cache_activate(self) + + def oneshot_exit(self): + self._get_kinfo_proc.cache_deactivate(self) + self._get_pidtaskinfo.cache_deactivate(self) + + @wrap_exceptions + def name(self): + name = self._get_kinfo_proc()[kinfo_proc_map['name']] + return name if name is not None else cext.proc_name(self.pid) + + @wrap_exceptions + def exe(self): + with catch_zombie(self): + return cext.proc_exe(self.pid) + + @wrap_exceptions + def cmdline(self): + with catch_zombie(self): + return cext.proc_cmdline(self.pid) + + @wrap_exceptions + def environ(self): + with catch_zombie(self): + return parse_environ_block(cext.proc_environ(self.pid)) + + @wrap_exceptions + def ppid(self): + self._ppid = self._get_kinfo_proc()[kinfo_proc_map['ppid']] + return self._ppid + + @wrap_exceptions + def cwd(self): + with catch_zombie(self): + return cext.proc_cwd(self.pid) + + @wrap_exceptions + def uids(self): + rawtuple = self._get_kinfo_proc() + return _common.puids( + rawtuple[kinfo_proc_map['ruid']], + rawtuple[kinfo_proc_map['euid']], + rawtuple[kinfo_proc_map['suid']]) + + @wrap_exceptions + def gids(self): + rawtuple = self._get_kinfo_proc() + return _common.puids( + rawtuple[kinfo_proc_map['rgid']], + rawtuple[kinfo_proc_map['egid']], + rawtuple[kinfo_proc_map['sgid']]) + + @wrap_exceptions + def terminal(self): + tty_nr = self._get_kinfo_proc()[kinfo_proc_map['ttynr']] + tmap = _psposix.get_terminal_map() + try: + return tmap[tty_nr] + except KeyError: + return None + + @wrap_exceptions + def memory_info(self): + rawtuple = self._get_pidtaskinfo() + return pmem( + rawtuple[pidtaskinfo_map['rss']], + rawtuple[pidtaskinfo_map['vms']], + rawtuple[pidtaskinfo_map['pfaults']], + rawtuple[pidtaskinfo_map['pageins']], + ) + + @wrap_exceptions + def memory_full_info(self): + basic_mem = self.memory_info() + uss = cext.proc_memory_uss(self.pid) + return pfullmem(*basic_mem + (uss, )) + + @wrap_exceptions + def cpu_times(self): + rawtuple = self._get_pidtaskinfo() + return _common.pcputimes( + rawtuple[pidtaskinfo_map['cpuutime']], + rawtuple[pidtaskinfo_map['cpustime']], + # children user / system times are not retrievable (set to 0) + 0.0, 0.0) + + @wrap_exceptions + def create_time(self): + return self._get_kinfo_proc()[kinfo_proc_map['ctime']] + + @wrap_exceptions + def num_ctx_switches(self): + # Unvoluntary value seems not to be available; + # getrusage() numbers seems to confirm this theory. + # We set it to 0. + vol = self._get_pidtaskinfo()[pidtaskinfo_map['volctxsw']] + return _common.pctxsw(vol, 0) + + @wrap_exceptions + def num_threads(self): + return self._get_pidtaskinfo()[pidtaskinfo_map['numthreads']] + + @wrap_exceptions + def open_files(self): + if self.pid == 0: + return [] + files = [] + with catch_zombie(self): + rawlist = cext.proc_open_files(self.pid) + for path, fd in rawlist: + if isfile_strict(path): + ntuple = _common.popenfile(path, fd) + files.append(ntuple) + return files + + @wrap_exceptions + def connections(self, kind='inet'): + if kind not in conn_tmap: + raise ValueError("invalid %r kind argument; choose between %s" + % (kind, ', '.join([repr(x) for x in conn_tmap]))) + families, types = conn_tmap[kind] + with catch_zombie(self): + rawlist = cext.proc_connections(self.pid, families, types) + ret = [] + for item in rawlist: + fd, fam, type, laddr, raddr, status = item + status = TCP_STATUSES[status] + fam = sockfam_to_enum(fam) + type = socktype_to_enum(type) + if fam in (AF_INET, AF_INET6): + if laddr: + laddr = _common.addr(*laddr) + if raddr: + raddr = _common.addr(*raddr) + nt = _common.pconn(fd, fam, type, laddr, raddr, status) + ret.append(nt) + return ret + + @wrap_exceptions + def num_fds(self): + if self.pid == 0: + return 0 + with catch_zombie(self): + return cext.proc_num_fds(self.pid) + + @wrap_exceptions + def wait(self, timeout=None): + return _psposix.wait_pid(self.pid, timeout, self._name) + + @wrap_exceptions + def nice_get(self): + with catch_zombie(self): + return cext_posix.getpriority(self.pid) + + @wrap_exceptions + def nice_set(self, value): + with catch_zombie(self): + return cext_posix.setpriority(self.pid, value) + + @wrap_exceptions + def status(self): + code = self._get_kinfo_proc()[kinfo_proc_map['status']] + # XXX is '?' legit? (we're not supposed to return it anyway) + return PROC_STATUSES.get(code, '?') + + @wrap_exceptions + def threads(self): + rawlist = cext.proc_threads(self.pid) + retlist = [] + for thread_id, utime, stime in rawlist: + ntuple = _common.pthread(thread_id, utime, stime) + retlist.append(ntuple) + return retlist diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psposix.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psposix.py new file mode 100644 index 00000000..d362143f --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psposix.py @@ -0,0 +1,186 @@ +# 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. + +"""Routines common to all posix systems.""" + +import errno +import glob +import os +import sys +import time + +from ._common import memoize +from ._common import sdiskusage +from ._common import usage_percent +from ._compat import PY3 +from ._compat import unicode + + +__all__ = ['pid_exists', 'wait_pid', 'disk_usage', 'get_terminal_map'] + + +# This object gets set on "import psutil" from the __init__.py +# file, see: https://github.com/giampaolo/psutil/issues/1402 +TimeoutExpired = None + + +def pid_exists(pid): + """Check whether pid exists in the current process table.""" + if pid == 0: + # According to "man 2 kill" PID 0 has a special meaning: + # it refers to <> so we don't want to go any further. + # If we get here it means this UNIX platform *does* have + # a process with id 0. + return True + try: + os.kill(pid, 0) + except OSError as err: + if err.errno == errno.ESRCH: + # ESRCH == No such process + return False + elif err.errno == errno.EPERM: + # EPERM clearly means there's a process to deny access to + return True + else: + # According to "man 2 kill" possible error values are + # (EINVAL, EPERM, ESRCH) therefore we should never get + # here. If we do let's be explicit in considering this + # an error. + raise err + else: + return True + + +def wait_pid(pid, timeout=None, proc_name=None): + """Wait for process with pid 'pid' to terminate and return its + exit status code as an integer. + + If pid is not a children of os.getpid() (current process) just + waits until the process disappears and return None. + + If pid does not exist at all return None immediately. + + Raise TimeoutExpired on timeout expired. + """ + def check_timeout(delay): + if timeout is not None: + if timer() >= stop_at: + raise TimeoutExpired(timeout, pid=pid, name=proc_name) + time.sleep(delay) + return min(delay * 2, 0.04) + + timer = getattr(time, 'monotonic', time.time) + if timeout is not None: + def waitcall(): + return os.waitpid(pid, os.WNOHANG) + stop_at = timer() + timeout + else: + def waitcall(): + return os.waitpid(pid, 0) + + delay = 0.0001 + while True: + try: + retpid, status = waitcall() + except OSError as err: + if err.errno == errno.EINTR: + delay = check_timeout(delay) + continue + elif err.errno == errno.ECHILD: + # This has two meanings: + # - pid is not a child of os.getpid() in which case + # we keep polling until it's gone + # - pid never existed in the first place + # In both cases we'll eventually return None as we + # can't determine its exit status code. + while True: + if pid_exists(pid): + delay = check_timeout(delay) + else: + return + else: + raise + else: + if retpid == 0: + # WNOHANG was used, pid is still running + delay = check_timeout(delay) + continue + # process exited due to a signal; return the integer of + # that signal + if os.WIFSIGNALED(status): + return -os.WTERMSIG(status) + # process exited using exit(2) system call; return the + # integer exit(2) system call has been called with + elif os.WIFEXITED(status): + return os.WEXITSTATUS(status) + else: + # should never happen + raise ValueError("unknown process exit status %r" % status) + + +def disk_usage(path): + """Return disk usage associated with path. + Note: UNIX usually reserves 5% disk space which is not accessible + by user. In this function "total" and "used" values reflect the + total and used disk space whereas "free" and "percent" represent + the "free" and "used percent" user disk space. + """ + if PY3: + st = os.statvfs(path) + else: + # os.statvfs() does not support unicode on Python 2: + # - https://github.com/giampaolo/psutil/issues/416 + # - http://bugs.python.org/issue18695 + try: + st = os.statvfs(path) + except UnicodeEncodeError: + if isinstance(path, unicode): + try: + path = path.encode(sys.getfilesystemencoding()) + except UnicodeEncodeError: + pass + st = os.statvfs(path) + else: + raise + + # Total space which is only available to root (unless changed + # at system level). + total = (st.f_blocks * st.f_frsize) + # Remaining free space usable by root. + avail_to_root = (st.f_bfree * st.f_frsize) + # Remaining free space usable by user. + avail_to_user = (st.f_bavail * st.f_frsize) + # Total space being used in general. + used = (total - avail_to_root) + # Total space which is available to user (same as 'total' but + # for the user). + total_user = used + avail_to_user + # User usage percent compared to the total amount of space + # the user can use. This number would be higher if compared + # to root's because the user has less space (usually -5%). + usage_percent_user = usage_percent(used, total_user, round_=1) + + # NB: the percentage is -5% than what shown by df due to + # reserved blocks that we are currently not considering: + # https://github.com/giampaolo/psutil/issues/829#issuecomment-223750462 + return sdiskusage( + total=total, used=used, free=avail_to_user, percent=usage_percent_user) + + +@memoize +def get_terminal_map(): + """Get a map of device-id -> path as a dict. + Used by Process.terminal() + """ + ret = {} + ls = glob.glob('/dev/tty*') + glob.glob('/dev/pts/*') + for name in ls: + assert name not in ret, name + try: + ret[os.stat(name).st_rdev] = name + except OSError as err: + if err.errno != errno.ENOENT: + raise + return ret diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_pssunos.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_pssunos.py new file mode 100644 index 00000000..67166e46 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_pssunos.py @@ -0,0 +1,731 @@ +# 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. + +"""Sun OS Solaris platform implementation.""" + +import errno +import os +import socket +import subprocess +import sys +from collections import namedtuple +from socket import AF_INET + +from . import _common +from . import _psposix +from . import _psutil_posix as cext_posix +from . import _psutil_sunos as cext +from ._common import AF_INET6 +from ._common import isfile_strict +from ._common import memoize_when_activated +from ._common import sockfam_to_enum +from ._common import socktype_to_enum +from ._common import usage_percent +from ._compat import b +from ._compat import PY3 + + +__extra__all__ = ["CONN_IDLE", "CONN_BOUND", "PROCFS_PATH"] + + +# ===================================================================== +# --- globals +# ===================================================================== + + +PAGE_SIZE = os.sysconf('SC_PAGE_SIZE') +AF_LINK = cext_posix.AF_LINK +IS_64_BIT = sys.maxsize > 2**32 + +CONN_IDLE = "IDLE" +CONN_BOUND = "BOUND" + +PROC_STATUSES = { + cext.SSLEEP: _common.STATUS_SLEEPING, + cext.SRUN: _common.STATUS_RUNNING, + cext.SZOMB: _common.STATUS_ZOMBIE, + cext.SSTOP: _common.STATUS_STOPPED, + cext.SIDL: _common.STATUS_IDLE, + cext.SONPROC: _common.STATUS_RUNNING, # same as run + cext.SWAIT: _common.STATUS_WAITING, +} + +TCP_STATUSES = { + cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, + cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, + cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV, + cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, + cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, + cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, + cext.TCPS_CLOSED: _common.CONN_CLOSE, + cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, + cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, + cext.TCPS_LISTEN: _common.CONN_LISTEN, + cext.TCPS_CLOSING: _common.CONN_CLOSING, + cext.PSUTIL_CONN_NONE: _common.CONN_NONE, + cext.TCPS_IDLE: CONN_IDLE, # sunos specific + cext.TCPS_BOUND: CONN_BOUND, # sunos specific +} + +proc_info_map = dict( + ppid=0, + rss=1, + vms=2, + create_time=3, + nice=4, + num_threads=5, + status=6, + ttynr=7, + uid=8, + euid=9, + gid=10, + egid=11) + +# These objects get set on "import psutil" from the __init__.py +# file, see: https://github.com/giampaolo/psutil/issues/1402 +NoSuchProcess = None +ZombieProcess = None +AccessDenied = None +TimeoutExpired = None + + +# ===================================================================== +# --- named tuples +# ===================================================================== + + +# psutil.cpu_times() +scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait']) +# psutil.cpu_times(percpu=True) +pcputimes = namedtuple('pcputimes', + ['user', 'system', 'children_user', 'children_system']) +# psutil.virtual_memory() +svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) +# psutil.Process.memory_info() +pmem = namedtuple('pmem', ['rss', 'vms']) +pfullmem = pmem +# psutil.Process.memory_maps(grouped=True) +pmmap_grouped = namedtuple('pmmap_grouped', + ['path', 'rss', 'anonymous', 'locked']) +# psutil.Process.memory_maps(grouped=False) +pmmap_ext = namedtuple( + 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) + + +# ===================================================================== +# --- utils +# ===================================================================== + + +def get_procfs_path(): + """Return updated psutil.PROCFS_PATH constant.""" + return sys.modules['psutil'].PROCFS_PATH + + +# ===================================================================== +# --- memory +# ===================================================================== + + +def virtual_memory(): + """Report virtual memory metrics.""" + # we could have done this with kstat, but IMHO this is good enough + total = os.sysconf('SC_PHYS_PAGES') * PAGE_SIZE + # note: there's no difference on Solaris + free = avail = os.sysconf('SC_AVPHYS_PAGES') * PAGE_SIZE + used = total - free + percent = usage_percent(used, total, round_=1) + return svmem(total, avail, percent, used, free) + + +def swap_memory(): + """Report swap memory metrics.""" + sin, sout = cext.swap_mem() + # XXX + # we are supposed to get total/free by doing so: + # http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/ + # usr/src/cmd/swap/swap.c + # ...nevertheless I can't manage to obtain the same numbers as 'swap' + # cmdline utility, so let's parse its output (sigh!) + p = subprocess.Popen(['/usr/bin/env', 'PATH=/usr/sbin:/sbin:%s' % + os.environ['PATH'], 'swap', '-l'], + stdout=subprocess.PIPE) + stdout, stderr = p.communicate() + if PY3: + stdout = stdout.decode(sys.stdout.encoding) + if p.returncode != 0: + raise RuntimeError("'swap -l' failed (retcode=%s)" % p.returncode) + + lines = stdout.strip().split('\n')[1:] + if not lines: + raise RuntimeError('no swap device(s) configured') + total = free = 0 + for line in lines: + line = line.split() + t, f = line[-2:] + total += int(int(t) * 512) + free += int(int(f) * 512) + used = total - free + percent = usage_percent(used, total, round_=1) + return _common.sswap(total, used, free, percent, + sin * PAGE_SIZE, sout * PAGE_SIZE) + + +# ===================================================================== +# --- CPU +# ===================================================================== + + +def cpu_times(): + """Return system-wide CPU times as a named tuple""" + ret = cext.per_cpu_times() + return scputimes(*[sum(x) for x in zip(*ret)]) + + +def per_cpu_times(): + """Return system per-CPU times as a list of named tuples""" + ret = cext.per_cpu_times() + return [scputimes(*x) for x in ret] + + +def cpu_count_logical(): + """Return the number of logical CPUs in the system.""" + try: + return os.sysconf("SC_NPROCESSORS_ONLN") + except ValueError: + # mimic os.cpu_count() behavior + return None + + +def cpu_count_physical(): + """Return the number of physical CPUs in the system.""" + return cext.cpu_count_phys() + + +def cpu_stats(): + """Return various CPU stats as a named tuple.""" + ctx_switches, interrupts, syscalls, traps = cext.cpu_stats() + soft_interrupts = 0 + return _common.scpustats(ctx_switches, interrupts, soft_interrupts, + syscalls) + + +# ===================================================================== +# --- disks +# ===================================================================== + + +disk_io_counters = cext.disk_io_counters +disk_usage = _psposix.disk_usage + + +def disk_partitions(all=False): + """Return system disk partitions.""" + # TODO - the filtering logic should be better checked so that + # it tries to reflect 'df' as much as possible + retlist = [] + partitions = cext.disk_partitions() + for partition in partitions: + device, mountpoint, fstype, opts = partition + if device == 'none': + device = '' + if not all: + # Differently from, say, Linux, we don't have a list of + # common fs types so the best we can do, AFAIK, is to + # filter by filesystem having a total size > 0. + if not disk_usage(mountpoint).total: + continue + ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) + retlist.append(ntuple) + return retlist + + +# ===================================================================== +# --- network +# ===================================================================== + + +net_io_counters = cext.net_io_counters +net_if_addrs = cext_posix.net_if_addrs + + +def net_connections(kind, _pid=-1): + """Return socket connections. If pid == -1 return system-wide + connections (as opposed to connections opened by one process only). + Only INET sockets are returned (UNIX are not). + """ + cmap = _common.conn_tmap.copy() + if _pid == -1: + cmap.pop('unix', 0) + if kind not in cmap: + raise ValueError("invalid %r kind argument; choose between %s" + % (kind, ', '.join([repr(x) for x in cmap]))) + families, types = _common.conn_tmap[kind] + rawlist = cext.net_connections(_pid) + ret = set() + for item in rawlist: + fd, fam, type_, laddr, raddr, status, pid = item + if fam not in families: + continue + if type_ not in types: + continue + if fam in (AF_INET, AF_INET6): + if laddr: + laddr = _common.addr(*laddr) + if raddr: + raddr = _common.addr(*raddr) + status = TCP_STATUSES[status] + fam = sockfam_to_enum(fam) + type_ = socktype_to_enum(type_) + if _pid == -1: + nt = _common.sconn(fd, fam, type_, laddr, raddr, status, pid) + else: + nt = _common.pconn(fd, fam, type_, laddr, raddr, status) + ret.add(nt) + return list(ret) + + +def net_if_stats(): + """Get NIC stats (isup, duplex, speed, mtu).""" + ret = cext.net_if_stats() + for name, items in ret.items(): + isup, duplex, speed, mtu = items + if hasattr(_common, 'NicDuplex'): + duplex = _common.NicDuplex(duplex) + ret[name] = _common.snicstats(isup, duplex, speed, mtu) + return ret + + +# ===================================================================== +# --- other system functions +# ===================================================================== + + +def boot_time(): + """The system boot time expressed in seconds since the epoch.""" + return cext.boot_time() + + +def users(): + """Return currently connected users as a list of namedtuples.""" + retlist = [] + rawlist = cext.users() + localhost = (':0.0', ':0') + for item in rawlist: + user, tty, hostname, tstamp, user_process, pid = item + # note: the underlying C function includes entries about + # system boot, run level and others. We might want + # to use them in the future. + if not user_process: + continue + if hostname in localhost: + hostname = 'localhost' + nt = _common.suser(user, tty, hostname, tstamp, pid) + retlist.append(nt) + return retlist + + +# ===================================================================== +# --- processes +# ===================================================================== + + +def pids(): + """Returns a list of PIDs currently running on the system.""" + return [int(x) for x in os.listdir(b(get_procfs_path())) if x.isdigit()] + + +def pid_exists(pid): + """Check for the existence of a unix pid.""" + return _psposix.pid_exists(pid) + + +def wrap_exceptions(fun): + """Call callable into a try/except clause and translate ENOENT, + EACCES and EPERM in NoSuchProcess or AccessDenied exceptions. + """ + + def wrapper(self, *args, **kwargs): + try: + return fun(self, *args, **kwargs) + except EnvironmentError as err: + if self.pid == 0: + if 0 in pids(): + raise AccessDenied(self.pid, self._name) + else: + raise + # ENOENT (no such file or directory) gets raised on open(). + # ESRCH (no such process) can get raised on read() if + # process is gone in meantime. + if err.errno in (errno.ENOENT, errno.ESRCH): + if not pid_exists(self.pid): + raise NoSuchProcess(self.pid, self._name) + else: + raise ZombieProcess(self.pid, self._name, self._ppid) + if err.errno in (errno.EPERM, errno.EACCES): + raise AccessDenied(self.pid, self._name) + raise + return wrapper + + +class Process(object): + """Wrapper class around underlying C implementation.""" + + __slots__ = ["pid", "_name", "_ppid", "_procfs_path", "_cache"] + + def __init__(self, pid): + self.pid = pid + self._name = None + self._ppid = None + self._procfs_path = get_procfs_path() + + def _assert_alive(self): + """Raise NSP if the process disappeared on us.""" + # For those C function who do not raise NSP, possibly returning + # incorrect or incomplete result. + os.stat('%s/%s' % (self._procfs_path, self.pid)) + + def oneshot_enter(self): + self._proc_name_and_args.cache_activate(self) + self._proc_basic_info.cache_activate(self) + self._proc_cred.cache_activate(self) + + def oneshot_exit(self): + self._proc_name_and_args.cache_deactivate(self) + self._proc_basic_info.cache_deactivate(self) + self._proc_cred.cache_deactivate(self) + + @wrap_exceptions + @memoize_when_activated + def _proc_name_and_args(self): + return cext.proc_name_and_args(self.pid, self._procfs_path) + + @wrap_exceptions + @memoize_when_activated + def _proc_basic_info(self): + ret = cext.proc_basic_info(self.pid, self._procfs_path) + assert len(ret) == len(proc_info_map) + return ret + + @wrap_exceptions + @memoize_when_activated + def _proc_cred(self): + return cext.proc_cred(self.pid, self._procfs_path) + + @wrap_exceptions + def name(self): + # note: max len == 15 + return self._proc_name_and_args()[0] + + @wrap_exceptions + def exe(self): + try: + return os.readlink( + "%s/%s/path/a.out" % (self._procfs_path, self.pid)) + except OSError: + pass # continue and guess the exe name from the cmdline + # Will be guessed later from cmdline but we want to explicitly + # invoke cmdline here in order to get an AccessDenied + # exception if the user has not enough privileges. + self.cmdline() + return "" + + @wrap_exceptions + def cmdline(self): + return self._proc_name_and_args()[1].split(' ') + + @wrap_exceptions + def environ(self): + return cext.proc_environ(self.pid, self._procfs_path) + + @wrap_exceptions + def create_time(self): + return self._proc_basic_info()[proc_info_map['create_time']] + + @wrap_exceptions + def num_threads(self): + return self._proc_basic_info()[proc_info_map['num_threads']] + + @wrap_exceptions + def nice_get(self): + # Note #1: getpriority(3) doesn't work for realtime processes. + # Psinfo is what ps uses, see: + # https://github.com/giampaolo/psutil/issues/1194 + return self._proc_basic_info()[proc_info_map['nice']] + + @wrap_exceptions + def nice_set(self, value): + if self.pid in (2, 3): + # Special case PIDs: internally setpriority(3) return ESRCH + # (no such process), no matter what. + # The process actually exists though, as it has a name, + # creation time, etc. + raise AccessDenied(self.pid, self._name) + return cext_posix.setpriority(self.pid, value) + + @wrap_exceptions + def ppid(self): + self._ppid = self._proc_basic_info()[proc_info_map['ppid']] + return self._ppid + + @wrap_exceptions + def uids(self): + try: + real, effective, saved, _, _, _ = self._proc_cred() + except AccessDenied: + real = self._proc_basic_info()[proc_info_map['uid']] + effective = self._proc_basic_info()[proc_info_map['euid']] + saved = None + return _common.puids(real, effective, saved) + + @wrap_exceptions + def gids(self): + try: + _, _, _, real, effective, saved = self._proc_cred() + except AccessDenied: + real = self._proc_basic_info()[proc_info_map['gid']] + effective = self._proc_basic_info()[proc_info_map['egid']] + saved = None + return _common.puids(real, effective, saved) + + @wrap_exceptions + def cpu_times(self): + try: + times = cext.proc_cpu_times(self.pid, self._procfs_path) + except OSError as err: + if err.errno == errno.EOVERFLOW and not IS_64_BIT: + # We may get here if we attempt to query a 64bit process + # with a 32bit python. + # Error originates from read() and also tools like "cat" + # fail in the same way (!). + # Since there simply is no way to determine CPU times we + # return 0.0 as a fallback. See: + # https://github.com/giampaolo/psutil/issues/857 + times = (0.0, 0.0, 0.0, 0.0) + else: + raise + return _common.pcputimes(*times) + + @wrap_exceptions + def cpu_num(self): + return cext.proc_cpu_num(self.pid, self._procfs_path) + + @wrap_exceptions + def terminal(self): + procfs_path = self._procfs_path + hit_enoent = False + tty = wrap_exceptions( + self._proc_basic_info()[proc_info_map['ttynr']]) + if tty != cext.PRNODEV: + for x in (0, 1, 2, 255): + try: + return os.readlink( + '%s/%d/path/%d' % (procfs_path, self.pid, x)) + except OSError as err: + if err.errno == errno.ENOENT: + hit_enoent = True + continue + raise + if hit_enoent: + self._assert_alive() + + @wrap_exceptions + def cwd(self): + # /proc/PID/path/cwd may not be resolved by readlink() even if + # it exists (ls shows it). If that's the case and the process + # is still alive return None (we can return None also on BSD). + # Reference: http://goo.gl/55XgO + procfs_path = self._procfs_path + try: + return os.readlink("%s/%s/path/cwd" % (procfs_path, self.pid)) + except OSError as err: + if err.errno == errno.ENOENT: + os.stat("%s/%s" % (procfs_path, self.pid)) # raise NSP or AD + return None + raise + + @wrap_exceptions + def memory_info(self): + ret = self._proc_basic_info() + rss = ret[proc_info_map['rss']] * 1024 + vms = ret[proc_info_map['vms']] * 1024 + return pmem(rss, vms) + + memory_full_info = memory_info + + @wrap_exceptions + def status(self): + code = self._proc_basic_info()[proc_info_map['status']] + # XXX is '?' legit? (we're not supposed to return it anyway) + return PROC_STATUSES.get(code, '?') + + @wrap_exceptions + def threads(self): + procfs_path = self._procfs_path + ret = [] + tids = os.listdir('%s/%d/lwp' % (procfs_path, self.pid)) + hit_enoent = False + for tid in tids: + tid = int(tid) + try: + utime, stime = cext.query_process_thread( + self.pid, tid, procfs_path) + except EnvironmentError as err: + if err.errno == errno.EOVERFLOW and not IS_64_BIT: + # We may get here if we attempt to query a 64bit process + # with a 32bit python. + # Error originates from read() and also tools like "cat" + # fail in the same way (!). + # Since there simply is no way to determine CPU times we + # return 0.0 as a fallback. See: + # https://github.com/giampaolo/psutil/issues/857 + continue + # ENOENT == thread gone in meantime + if err.errno == errno.ENOENT: + hit_enoent = True + continue + raise + else: + nt = _common.pthread(tid, utime, stime) + ret.append(nt) + if hit_enoent: + self._assert_alive() + return ret + + @wrap_exceptions + def open_files(self): + retlist = [] + hit_enoent = False + procfs_path = self._procfs_path + pathdir = '%s/%d/path' % (procfs_path, self.pid) + for fd in os.listdir('%s/%d/fd' % (procfs_path, self.pid)): + path = os.path.join(pathdir, fd) + if os.path.islink(path): + try: + file = os.readlink(path) + except OSError as err: + # ENOENT == file which is gone in the meantime + if err.errno == errno.ENOENT: + hit_enoent = True + continue + raise + else: + if isfile_strict(file): + retlist.append(_common.popenfile(file, int(fd))) + if hit_enoent: + self._assert_alive() + return retlist + + def _get_unix_sockets(self, pid): + """Get UNIX sockets used by process by parsing 'pfiles' output.""" + # TODO: rewrite this in C (...but the damn netstat source code + # does not include this part! Argh!!) + cmd = "pfiles %s" % pid + p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + stdout, stderr = p.communicate() + if PY3: + stdout, stderr = [x.decode(sys.stdout.encoding) + for x in (stdout, stderr)] + if p.returncode != 0: + if 'permission denied' in stderr.lower(): + raise AccessDenied(self.pid, self._name) + if 'no such process' in stderr.lower(): + raise NoSuchProcess(self.pid, self._name) + raise RuntimeError("%r command error\n%s" % (cmd, stderr)) + + lines = stdout.split('\n')[2:] + for i, line in enumerate(lines): + line = line.lstrip() + if line.startswith('sockname: AF_UNIX'): + path = line.split(' ', 2)[2] + type = lines[i - 2].strip() + if type == 'SOCK_STREAM': + type = socket.SOCK_STREAM + elif type == 'SOCK_DGRAM': + type = socket.SOCK_DGRAM + else: + type = -1 + yield (-1, socket.AF_UNIX, type, path, "", _common.CONN_NONE) + + @wrap_exceptions + def connections(self, kind='inet'): + ret = net_connections(kind, _pid=self.pid) + # The underlying C implementation retrieves all OS connections + # and filters them by PID. At this point we can't tell whether + # an empty list means there were no connections for process or + # process is no longer active so we force NSP in case the PID + # is no longer there. + if not ret: + # will raise NSP if process is gone + os.stat('%s/%s' % (self._procfs_path, self.pid)) + + # UNIX sockets + if kind in ('all', 'unix'): + ret.extend([_common.pconn(*conn) for conn in + self._get_unix_sockets(self.pid)]) + return ret + + nt_mmap_grouped = namedtuple('mmap', 'path rss anon locked') + nt_mmap_ext = namedtuple('mmap', 'addr perms path rss anon locked') + + @wrap_exceptions + def memory_maps(self): + def toaddr(start, end): + return '%s-%s' % (hex(start)[2:].strip('L'), + hex(end)[2:].strip('L')) + + procfs_path = self._procfs_path + retlist = [] + try: + rawlist = cext.proc_memory_maps(self.pid, procfs_path) + except OSError as err: + if err.errno == errno.EOVERFLOW and not IS_64_BIT: + # We may get here if we attempt to query a 64bit process + # with a 32bit python. + # Error originates from read() and also tools like "cat" + # fail in the same way (!). + # Since there simply is no way to determine CPU times we + # return 0.0 as a fallback. See: + # https://github.com/giampaolo/psutil/issues/857 + return [] + else: + raise + hit_enoent = False + for item in rawlist: + addr, addrsize, perm, name, rss, anon, locked = item + addr = toaddr(addr, addrsize) + if not name.startswith('['): + try: + name = os.readlink( + '%s/%s/path/%s' % (procfs_path, self.pid, name)) + except OSError as err: + if err.errno == errno.ENOENT: + # sometimes the link may not be resolved by + # readlink() even if it exists (ls shows it). + # If that's the case we just return the + # unresolved link path. + # This seems an incosistency with /proc similar + # to: http://goo.gl/55XgO + name = '%s/%s/path/%s' % (procfs_path, self.pid, name) + hit_enoent = True + else: + raise + retlist.append((addr, perm, name, rss, anon, locked)) + if hit_enoent: + self._assert_alive() + return retlist + + @wrap_exceptions + def num_fds(self): + return len(os.listdir("%s/%s/fd" % (self._procfs_path, self.pid))) + + @wrap_exceptions + def num_ctx_switches(self): + return _common.pctxsw( + *cext.proc_num_ctx_switches(self.pid, self._procfs_path)) + + @wrap_exceptions + def wait(self, timeout=None): + return _psposix.wait_pid(self.pid, timeout, self._name) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psutil_windows.cp37-win32.pyd b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_psutil_windows.cp37-win32.pyd new file mode 100644 index 0000000000000000000000000000000000000000..46608d7ab1d0771e8c0bfb726a4968c258aaa818 GIT binary patch literal 61952 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 literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_pswindows.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_pswindows.py new file mode 100644 index 00000000..6687770c --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/_pswindows.py @@ -0,0 +1,1066 @@ +# 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. + +"""Windows platform implementation.""" + +import contextlib +import errno +import functools +import os +import sys +import time +from collections import namedtuple + +from . import _common +try: + from . import _psutil_windows as cext +except ImportError as err: + if str(err).lower().startswith("dll load failed") and \ + sys.getwindowsversion()[0] < 6: + # We may get here if: + # 1) we are on an old Windows version + # 2) psutil was installed via pip + wheel + # See: https://github.com/giampaolo/psutil/issues/811 + # It must be noted that psutil can still (kind of) work + # on outdated systems if compiled / installed from sources, + # but if we get here it means this this was a wheel (or exe). + msg = "this Windows version is too old (< Windows Vista); " + msg += "psutil 3.4.2 is the latest version which supports Windows " + msg += "2000, XP and 2003 server" + raise RuntimeError(msg) + else: + raise + +from ._common import conn_tmap +from ._common import ENCODING +from ._common import ENCODING_ERRS +from ._common import isfile_strict +from ._common import memoize +from ._common import memoize_when_activated +from ._common import parse_environ_block +from ._common import sockfam_to_enum +from ._common import socktype_to_enum +from ._common import usage_percent +from ._compat import long +from ._compat import lru_cache +from ._compat import PY3 +from ._compat import unicode +from ._compat import xrange +from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS +from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS +from ._psutil_windows import HIGH_PRIORITY_CLASS +from ._psutil_windows import IDLE_PRIORITY_CLASS +from ._psutil_windows import NORMAL_PRIORITY_CLASS +from ._psutil_windows import REALTIME_PRIORITY_CLASS + +if sys.version_info >= (3, 4): + import enum +else: + enum = None + +# process priority constants, import from __init__.py: +# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx +__extra__all__ = [ + "win_service_iter", "win_service_get", + "ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS", + "HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS", + "NORMAL_PRIORITY_CLASS", "REALTIME_PRIORITY_CLASS", + "CONN_DELETE_TCB", + "AF_LINK", +] + + +# ===================================================================== +# --- globals +# ===================================================================== + +CONN_DELETE_TCB = "DELETE_TCB" +ACCESS_DENIED_ERRSET = frozenset([errno.EPERM, errno.EACCES, + cext.ERROR_ACCESS_DENIED]) +NO_SUCH_SERVICE_ERRSET = frozenset([cext.ERROR_INVALID_NAME, + cext.ERROR_SERVICE_DOES_NOT_EXIST]) +HAS_PROC_IO_PRIORITY = hasattr(cext, "proc_io_priority_get") + + +if enum is None: + AF_LINK = -1 +else: + AddressFamily = enum.IntEnum('AddressFamily', {'AF_LINK': -1}) + AF_LINK = AddressFamily.AF_LINK + +TCP_STATUSES = { + cext.MIB_TCP_STATE_ESTAB: _common.CONN_ESTABLISHED, + cext.MIB_TCP_STATE_SYN_SENT: _common.CONN_SYN_SENT, + cext.MIB_TCP_STATE_SYN_RCVD: _common.CONN_SYN_RECV, + cext.MIB_TCP_STATE_FIN_WAIT1: _common.CONN_FIN_WAIT1, + cext.MIB_TCP_STATE_FIN_WAIT2: _common.CONN_FIN_WAIT2, + cext.MIB_TCP_STATE_TIME_WAIT: _common.CONN_TIME_WAIT, + cext.MIB_TCP_STATE_CLOSED: _common.CONN_CLOSE, + cext.MIB_TCP_STATE_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, + cext.MIB_TCP_STATE_LAST_ACK: _common.CONN_LAST_ACK, + cext.MIB_TCP_STATE_LISTEN: _common.CONN_LISTEN, + cext.MIB_TCP_STATE_CLOSING: _common.CONN_CLOSING, + cext.MIB_TCP_STATE_DELETE_TCB: CONN_DELETE_TCB, + cext.PSUTIL_CONN_NONE: _common.CONN_NONE, +} + +if enum is not None: + class Priority(enum.IntEnum): + ABOVE_NORMAL_PRIORITY_CLASS = ABOVE_NORMAL_PRIORITY_CLASS + BELOW_NORMAL_PRIORITY_CLASS = BELOW_NORMAL_PRIORITY_CLASS + HIGH_PRIORITY_CLASS = HIGH_PRIORITY_CLASS + IDLE_PRIORITY_CLASS = IDLE_PRIORITY_CLASS + NORMAL_PRIORITY_CLASS = NORMAL_PRIORITY_CLASS + REALTIME_PRIORITY_CLASS = REALTIME_PRIORITY_CLASS + + globals().update(Priority.__members__) + +pinfo_map = dict( + num_handles=0, + ctx_switches=1, + user_time=2, + kernel_time=3, + create_time=4, + num_threads=5, + io_rcount=6, + io_wcount=7, + io_rbytes=8, + io_wbytes=9, + io_count_others=10, + io_bytes_others=11, + num_page_faults=12, + peak_wset=13, + wset=14, + peak_paged_pool=15, + paged_pool=16, + peak_non_paged_pool=17, + non_paged_pool=18, + pagefile=19, + peak_pagefile=20, + mem_private=21, +) + +# These objects get set on "import psutil" from the __init__.py +# file, see: https://github.com/giampaolo/psutil/issues/1402 +NoSuchProcess = None +ZombieProcess = None +AccessDenied = None +TimeoutExpired = None + +# More values at: https://stackoverflow.com/a/20804735/376587 +WIN_10 = (10, 0) +WIN_8 = (6, 2) +WIN_7 = (6, 1) +WIN_SERVER_2008 = (6, 0) +WIN_VISTA = (6, 0) +WIN_SERVER_2003 = (5, 2) +WIN_XP = (5, 1) + + +@lru_cache() +def get_winver(): + """Usage: + >>> if get_winver() <= WIN_VISTA: + ... ... + """ + wv = sys.getwindowsversion() + return (wv.major, wv.minor) + + +IS_WIN_XP = get_winver() < WIN_VISTA + + +# ===================================================================== +# --- named tuples +# ===================================================================== + + +# psutil.cpu_times() +scputimes = namedtuple('scputimes', + ['user', 'system', 'idle', 'interrupt', 'dpc']) +# psutil.virtual_memory() +svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) +# psutil.Process.memory_info() +pmem = namedtuple( + 'pmem', ['rss', 'vms', + 'num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool', + 'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool', + 'pagefile', 'peak_pagefile', 'private']) +# psutil.Process.memory_full_info() +pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', )) +# psutil.Process.memory_maps(grouped=True) +pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss']) +# psutil.Process.memory_maps(grouped=False) +pmmap_ext = namedtuple( + 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) +# psutil.Process.io_counters() +pio = namedtuple('pio', ['read_count', 'write_count', + 'read_bytes', 'write_bytes', + 'other_count', 'other_bytes']) + + +# ===================================================================== +# --- utils +# ===================================================================== + + +@lru_cache(maxsize=512) +def convert_dos_path(s): + r"""Convert paths using native DOS format like: + "\Device\HarddiskVolume1\Windows\systemew\file.txt" + into: + "C:\Windows\systemew\file.txt" + """ + rawdrive = '\\'.join(s.split('\\')[:3]) + driveletter = cext.win32_QueryDosDevice(rawdrive) + return os.path.join(driveletter, s[len(rawdrive):]) + + +def py2_strencode(s): + """Encode a unicode string to a byte string by using the default fs + encoding + "replace" error handler. + """ + if PY3: + return s + else: + if isinstance(s, str): + return s + else: + return s.encode(ENCODING, ENCODING_ERRS) + + +@memoize +def getpagesize(): + return cext.getpagesize() + + +# ===================================================================== +# --- memory +# ===================================================================== + + +def virtual_memory(): + """System virtual memory as a namedtuple.""" + mem = cext.virtual_mem() + totphys, availphys, totpagef, availpagef, totvirt, freevirt = mem + # + total = totphys + avail = availphys + free = availphys + used = total - avail + percent = usage_percent((total - avail), total, round_=1) + return svmem(total, avail, percent, used, free) + + +def swap_memory(): + """Swap system memory as a (total, used, free, sin, sout) tuple.""" + mem = cext.virtual_mem() + total = mem[2] + free = mem[3] + used = total - free + percent = usage_percent(used, total, round_=1) + return _common.sswap(total, used, free, percent, 0, 0) + + +# ===================================================================== +# --- disk +# ===================================================================== + + +disk_io_counters = cext.disk_io_counters + + +def disk_usage(path): + """Return disk usage associated with path.""" + if PY3 and isinstance(path, bytes): + # XXX: do we want to use "strict"? Probably yes, in order + # to fail immediately. After all we are accepting input here... + path = path.decode(ENCODING, errors="strict") + total, free = cext.disk_usage(path) + used = total - free + percent = usage_percent(used, total, round_=1) + return _common.sdiskusage(total, used, free, percent) + + +def disk_partitions(all): + """Return disk partitions.""" + rawlist = cext.disk_partitions(all) + return [_common.sdiskpart(*x) for x in rawlist] + + +# ===================================================================== +# --- CPU +# ===================================================================== + + +def cpu_times(): + """Return system CPU times as a named tuple.""" + user, system, idle = cext.cpu_times() + # Internally, GetSystemTimes() is used, and it doesn't return + # interrupt and dpc times. cext.per_cpu_times() does, so we + # rely on it to get those only. + percpu_summed = scputimes(*[sum(n) for n in zip(*cext.per_cpu_times())]) + return scputimes(user, system, idle, + percpu_summed.interrupt, percpu_summed.dpc) + + +def per_cpu_times(): + """Return system per-CPU times as a list of named tuples.""" + ret = [] + for user, system, idle, interrupt, dpc in cext.per_cpu_times(): + item = scputimes(user, system, idle, interrupt, dpc) + ret.append(item) + return ret + + +def cpu_count_logical(): + """Return the number of logical CPUs in the system.""" + return cext.cpu_count_logical() + + +def cpu_count_physical(): + """Return the number of physical CPU cores in the system.""" + return cext.cpu_count_phys() + + +def cpu_stats(): + """Return CPU statistics.""" + ctx_switches, interrupts, dpcs, syscalls = cext.cpu_stats() + soft_interrupts = 0 + return _common.scpustats(ctx_switches, interrupts, soft_interrupts, + syscalls) + + +def cpu_freq(): + """Return CPU frequency. + On Windows per-cpu frequency is not supported. + """ + curr, max_ = cext.cpu_freq() + min_ = 0.0 + return [_common.scpufreq(float(curr), min_, float(max_))] + + +# ===================================================================== +# --- network +# ===================================================================== + + +def net_connections(kind, _pid=-1): + """Return socket connections. If pid == -1 return system-wide + connections (as opposed to connections opened by one process only). + """ + if kind not in conn_tmap: + raise ValueError("invalid %r kind argument; choose between %s" + % (kind, ', '.join([repr(x) for x in conn_tmap]))) + families, types = conn_tmap[kind] + rawlist = cext.net_connections(_pid, families, types) + ret = set() + for item in rawlist: + fd, fam, type, laddr, raddr, status, pid = item + if laddr: + laddr = _common.addr(*laddr) + if raddr: + raddr = _common.addr(*raddr) + status = TCP_STATUSES[status] + fam = sockfam_to_enum(fam) + type = socktype_to_enum(type) + if _pid == -1: + nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid) + else: + nt = _common.pconn(fd, fam, type, laddr, raddr, status) + ret.add(nt) + return list(ret) + + +def net_if_stats(): + """Get NIC stats (isup, duplex, speed, mtu).""" + ret = {} + rawdict = cext.net_if_stats() + for name, items in rawdict.items(): + if not PY3: + assert isinstance(name, unicode), type(name) + name = py2_strencode(name) + isup, duplex, speed, mtu = items + if hasattr(_common, 'NicDuplex'): + duplex = _common.NicDuplex(duplex) + ret[name] = _common.snicstats(isup, duplex, speed, mtu) + return ret + + +def net_io_counters(): + """Return network I/O statistics for every network interface + installed on the system as a dict of raw tuples. + """ + ret = cext.net_io_counters() + return dict([(py2_strencode(k), v) for k, v in ret.items()]) + + +def net_if_addrs(): + """Return the addresses associated to each NIC.""" + ret = [] + for items in cext.net_if_addrs(): + items = list(items) + items[0] = py2_strencode(items[0]) + ret.append(items) + return ret + + +# ===================================================================== +# --- sensors +# ===================================================================== + + +def sensors_battery(): + """Return battery information.""" + # For constants meaning see: + # https://msdn.microsoft.com/en-us/library/windows/desktop/ + # aa373232(v=vs.85).aspx + acline_status, flags, percent, secsleft = cext.sensors_battery() + power_plugged = acline_status == 1 + no_battery = bool(flags & 128) + charging = bool(flags & 8) + + if no_battery: + return None + if power_plugged or charging: + secsleft = _common.POWER_TIME_UNLIMITED + elif secsleft == -1: + secsleft = _common.POWER_TIME_UNKNOWN + + return _common.sbattery(percent, secsleft, power_plugged) + + +# ===================================================================== +# --- other system functions +# ===================================================================== + + +_last_btime = 0 + + +def boot_time(): + """The system boot time expressed in seconds since the epoch.""" + # This dirty hack is to adjust the precision of the returned + # value which may have a 1 second fluctuation, see: + # https://github.com/giampaolo/psutil/issues/1007 + global _last_btime + ret = float(cext.boot_time()) + if abs(ret - _last_btime) <= 1: + return _last_btime + else: + _last_btime = ret + return ret + + +def users(): + """Return currently connected users as a list of namedtuples.""" + retlist = [] + rawlist = cext.users() + for item in rawlist: + user, hostname, tstamp = item + user = py2_strencode(user) + nt = _common.suser(user, None, hostname, tstamp, None) + retlist.append(nt) + return retlist + + +# ===================================================================== +# --- Windows services +# ===================================================================== + + +def win_service_iter(): + """Yields a list of WindowsService instances.""" + for name, display_name in cext.winservice_enumerate(): + yield WindowsService(py2_strencode(name), py2_strencode(display_name)) + + +def win_service_get(name): + """Open a Windows service and return it as a WindowsService instance.""" + service = WindowsService(name, None) + service._display_name = service._query_config()['display_name'] + return service + + +class WindowsService(object): + """Represents an installed Windows service.""" + + def __init__(self, name, display_name): + self._name = name + self._display_name = display_name + + def __str__(self): + details = "(name=%r, display_name=%r)" % ( + self._name, self._display_name) + return "%s%s" % (self.__class__.__name__, details) + + def __repr__(self): + return "<%s at %s>" % (self.__str__(), id(self)) + + def __eq__(self, other): + # Test for equality with another WindosService object based + # on name. + if not isinstance(other, WindowsService): + return NotImplemented + return self._name == other._name + + def __ne__(self, other): + return not self == other + + def _query_config(self): + with self._wrap_exceptions(): + display_name, binpath, username, start_type = \ + cext.winservice_query_config(self._name) + # XXX - update _self.display_name? + return dict( + display_name=py2_strencode(display_name), + binpath=py2_strencode(binpath), + username=py2_strencode(username), + start_type=py2_strencode(start_type)) + + def _query_status(self): + with self._wrap_exceptions(): + status, pid = cext.winservice_query_status(self._name) + if pid == 0: + pid = None + return dict(status=status, pid=pid) + + @contextlib.contextmanager + def _wrap_exceptions(self): + """Ctx manager which translates bare OSError and WindowsError + exceptions into NoSuchProcess and AccessDenied. + """ + try: + yield + except WindowsError as err: + if err.errno in ACCESS_DENIED_ERRSET: + raise AccessDenied( + pid=None, name=self._name, + msg="service %r is not querable (not enough privileges)" % + self._name) + elif err.errno in NO_SUCH_SERVICE_ERRSET or \ + err.winerror in NO_SUCH_SERVICE_ERRSET: + raise NoSuchProcess( + pid=None, name=self._name, + msg="service %r does not exist)" % self._name) + else: + raise + + # config query + + def name(self): + """The service name. This string is how a service is referenced + and can be passed to win_service_get() to get a new + WindowsService instance. + """ + return self._name + + def display_name(self): + """The service display name. The value is cached when this class + is instantiated. + """ + return self._display_name + + def binpath(self): + """The fully qualified path to the service binary/exe file as + a string, including command line arguments. + """ + return self._query_config()['binpath'] + + def username(self): + """The name of the user that owns this service.""" + return self._query_config()['username'] + + def start_type(self): + """A string which can either be "automatic", "manual" or + "disabled". + """ + return self._query_config()['start_type'] + + # status query + + def pid(self): + """The process PID, if any, else None. This can be passed + to Process class to control the service's process. + """ + return self._query_status()['pid'] + + def status(self): + """Service status as a string.""" + return self._query_status()['status'] + + def description(self): + """Service long description.""" + return py2_strencode(cext.winservice_query_descr(self.name())) + + # utils + + def as_dict(self): + """Utility method retrieving all the information above as a + dictionary. + """ + d = self._query_config() + d.update(self._query_status()) + d['name'] = self.name() + d['display_name'] = self.display_name() + d['description'] = self.description() + return d + + # actions + # XXX: the necessary C bindings for start() and stop() are + # implemented but for now I prefer not to expose them. + # I may change my mind in the future. Reasons: + # - they require Administrator privileges + # - can't implement a timeout for stop() (unless by using a thread, + # which sucks) + # - would require adding ServiceAlreadyStarted and + # ServiceAlreadyStopped exceptions, adding two new APIs. + # - we might also want to have modify(), which would basically mean + # rewriting win32serviceutil.ChangeServiceConfig, which involves a + # lot of stuff (and API constants which would pollute the API), see: + # http://pyxr.sourceforge.net/PyXR/c/python24/lib/site-packages/ + # win32/lib/win32serviceutil.py.html#0175 + # - psutil is typically about "read only" monitoring stuff; + # win_service_* APIs should only be used to retrieve a service and + # check whether it's running + + # def start(self, timeout=None): + # with self._wrap_exceptions(): + # cext.winservice_start(self.name()) + # if timeout: + # giveup_at = time.time() + timeout + # while True: + # if self.status() == "running": + # return + # else: + # if time.time() > giveup_at: + # raise TimeoutExpired(timeout) + # else: + # time.sleep(.1) + + # def stop(self): + # # Note: timeout is not implemented because it's just not + # # possible, see: + # # http://stackoverflow.com/questions/11973228/ + # with self._wrap_exceptions(): + # return cext.winservice_stop(self.name()) + + +# ===================================================================== +# --- processes +# ===================================================================== + + +pids = cext.pids +pid_exists = cext.pid_exists +ppid_map = cext.ppid_map # used internally by Process.children() + + +def wrap_exceptions(fun): + """Decorator which translates bare OSError and WindowsError + exceptions into NoSuchProcess and AccessDenied. + """ + @functools.wraps(fun) + def wrapper(self, *args, **kwargs): + try: + return fun(self, *args, **kwargs) + except OSError as err: + if err.errno in ACCESS_DENIED_ERRSET: + raise AccessDenied(self.pid, self._name) + if err.errno == errno.ESRCH: + raise NoSuchProcess(self.pid, self._name) + raise + return wrapper + + +class Process(object): + """Wrapper class around underlying C implementation.""" + + __slots__ = ["pid", "_name", "_ppid", "_cache"] + + def __init__(self, pid): + self.pid = pid + self._name = None + self._ppid = None + + # --- oneshot() stuff + + def oneshot_enter(self): + self.oneshot_info.cache_activate(self) + + def oneshot_exit(self): + self.oneshot_info.cache_deactivate(self) + + @wrap_exceptions + @memoize_when_activated + def oneshot_info(self): + """Return multiple information about this process as a + raw tuple. + """ + ret = cext.proc_info(self.pid) + assert len(ret) == len(pinfo_map) + return ret + + @wrap_exceptions + def name(self): + """Return process name, which on Windows is always the final + part of the executable. + """ + # This is how PIDs 0 and 4 are always represented in taskmgr + # and process-hacker. + if self.pid == 0: + return "System Idle Process" + elif self.pid == 4: + return "System" + else: + try: + # Note: this will fail with AD for most PIDs owned + # by another user but it's faster. + return py2_strencode(os.path.basename(self.exe())) + except AccessDenied: + return py2_strencode(cext.proc_name(self.pid)) + + @wrap_exceptions + def exe(self): + # Dual implementation, see: + # https://github.com/giampaolo/psutil/pull/1413 + if not IS_WIN_XP: + exe = cext.proc_exe(self.pid) + else: + if self.pid in (0, 4): + # https://github.com/giampaolo/psutil/issues/414 + # https://github.com/giampaolo/psutil/issues/528 + raise AccessDenied(self.pid, self._name) + exe = cext.proc_exe(self.pid) + exe = convert_dos_path(exe) + return py2_strencode(exe) + + @wrap_exceptions + def cmdline(self): + if cext.WINVER >= cext.WINDOWS_8_1: + # PEB method detects cmdline changes but requires more + # privileges: https://github.com/giampaolo/psutil/pull/1398 + try: + ret = cext.proc_cmdline(self.pid, use_peb=True) + except OSError as err: + if err.errno in ACCESS_DENIED_ERRSET: + ret = cext.proc_cmdline(self.pid, use_peb=False) + else: + raise + else: + ret = cext.proc_cmdline(self.pid, use_peb=True) + if PY3: + return ret + else: + return [py2_strencode(s) for s in ret] + + @wrap_exceptions + def environ(self): + ustr = cext.proc_environ(self.pid) + if ustr and not PY3: + assert isinstance(ustr, unicode), type(ustr) + return parse_environ_block(py2_strencode(ustr)) + + def ppid(self): + try: + return ppid_map()[self.pid] + except KeyError: + raise NoSuchProcess(self.pid, self._name) + + def _get_raw_meminfo(self): + try: + return cext.proc_memory_info(self.pid) + except OSError as err: + if err.errno in ACCESS_DENIED_ERRSET: + # TODO: the C ext can probably be refactored in order + # to get this from cext.proc_info() + info = self.oneshot_info() + return ( + info[pinfo_map['num_page_faults']], + info[pinfo_map['peak_wset']], + info[pinfo_map['wset']], + info[pinfo_map['peak_paged_pool']], + info[pinfo_map['paged_pool']], + info[pinfo_map['peak_non_paged_pool']], + info[pinfo_map['non_paged_pool']], + info[pinfo_map['pagefile']], + info[pinfo_map['peak_pagefile']], + info[pinfo_map['mem_private']], + ) + raise + + @wrap_exceptions + def memory_info(self): + # on Windows RSS == WorkingSetSize and VSM == PagefileUsage. + # Underlying C function returns fields of PROCESS_MEMORY_COUNTERS + # struct. + t = self._get_raw_meminfo() + rss = t[2] # wset + vms = t[7] # pagefile + return pmem(*(rss, vms, ) + t) + + @wrap_exceptions + def memory_full_info(self): + basic_mem = self.memory_info() + uss = cext.proc_memory_uss(self.pid) + uss *= getpagesize() + return pfullmem(*basic_mem + (uss, )) + + def memory_maps(self): + try: + raw = cext.proc_memory_maps(self.pid) + except OSError as err: + # XXX - can't use wrap_exceptions decorator as we're + # returning a generator; probably needs refactoring. + if err.errno in ACCESS_DENIED_ERRSET: + raise AccessDenied(self.pid, self._name) + if err.errno == errno.ESRCH: + raise NoSuchProcess(self.pid, self._name) + raise + else: + for addr, perm, path, rss in raw: + path = convert_dos_path(path) + if not PY3: + assert isinstance(path, unicode), type(path) + path = py2_strencode(path) + addr = hex(addr) + yield (addr, perm, path, rss) + + @wrap_exceptions + def kill(self): + return cext.proc_kill(self.pid) + + @wrap_exceptions + def send_signal(self, sig): + os.kill(self.pid, sig) + + @wrap_exceptions + def wait(self, timeout=None): + if timeout is None: + cext_timeout = cext.INFINITE + else: + # WaitForSingleObject() expects time in milliseconds. + cext_timeout = int(timeout * 1000) + + timer = getattr(time, 'monotonic', time.time) + stop_at = timer() + timeout if timeout is not None else None + + try: + # Exit code is supposed to come from GetExitCodeProcess(). + # May also be None if OpenProcess() failed with + # ERROR_INVALID_PARAMETER, meaning PID is already gone. + exit_code = cext.proc_wait(self.pid, cext_timeout) + except cext.TimeoutExpired: + # WaitForSingleObject() returned WAIT_TIMEOUT. Just raise. + raise TimeoutExpired(timeout, self.pid, self._name) + except cext.TimeoutAbandoned: + # WaitForSingleObject() returned WAIT_ABANDONED, see: + # https://github.com/giampaolo/psutil/issues/1224 + # We'll just rely on the internal polling and return None + # when the PID disappears. Subprocess module does the same + # (return None): + # https://github.com/python/cpython/blob/ + # be50a7b627d0aa37e08fa8e2d5568891f19903ce/ + # Lib/subprocess.py#L1193-L1194 + exit_code = None + + # At this point WaitForSingleObject() returned WAIT_OBJECT_0, + # meaning the process is gone. Stupidly there are cases where + # its PID may still stick around so we do a further internal + # polling. + delay = 0.0001 + while True: + if not pid_exists(self.pid): + return exit_code + if stop_at and timer() >= stop_at: + raise TimeoutExpired(timeout, pid=self.pid, name=self._name) + time.sleep(delay) + delay = min(delay * 2, 0.04) # incremental delay + + @wrap_exceptions + def username(self): + if self.pid in (0, 4): + return 'NT AUTHORITY\\SYSTEM' + domain, user = cext.proc_username(self.pid) + return py2_strencode(domain) + '\\' + py2_strencode(user) + + @wrap_exceptions + def create_time(self): + # special case for kernel process PIDs; return system boot time + if self.pid in (0, 4): + return boot_time() + try: + return cext.proc_create_time(self.pid) + except OSError as err: + if err.errno in ACCESS_DENIED_ERRSET: + return self.oneshot_info()[pinfo_map['create_time']] + raise + + @wrap_exceptions + def num_threads(self): + return self.oneshot_info()[pinfo_map['num_threads']] + + @wrap_exceptions + def threads(self): + rawlist = cext.proc_threads(self.pid) + retlist = [] + for thread_id, utime, stime in rawlist: + ntuple = _common.pthread(thread_id, utime, stime) + retlist.append(ntuple) + return retlist + + @wrap_exceptions + def cpu_times(self): + try: + user, system = cext.proc_cpu_times(self.pid) + except OSError as err: + if err.errno in ACCESS_DENIED_ERRSET: + info = self.oneshot_info() + user = info[pinfo_map['user_time']] + system = info[pinfo_map['kernel_time']] + else: + raise + # Children user/system times are not retrievable (set to 0). + return _common.pcputimes(user, system, 0.0, 0.0) + + @wrap_exceptions + def suspend(self): + cext.proc_suspend_or_resume(self.pid, True) + + @wrap_exceptions + def resume(self): + cext.proc_suspend_or_resume(self.pid, False) + + @wrap_exceptions + def cwd(self): + if self.pid in (0, 4): + raise AccessDenied(self.pid, self._name) + # return a normalized pathname since the native C function appends + # "\\" at the and of the path + path = cext.proc_cwd(self.pid) + return py2_strencode(os.path.normpath(path)) + + @wrap_exceptions + def open_files(self): + if self.pid in (0, 4): + return [] + ret = set() + # Filenames come in in native format like: + # "\Device\HarddiskVolume1\Windows\systemew\file.txt" + # Convert the first part in the corresponding drive letter + # (e.g. "C:\") by using Windows's QueryDosDevice() + raw_file_names = cext.proc_open_files(self.pid) + for _file in raw_file_names: + _file = convert_dos_path(_file) + if isfile_strict(_file): + if not PY3: + _file = py2_strencode(_file) + ntuple = _common.popenfile(_file, -1) + ret.add(ntuple) + return list(ret) + + @wrap_exceptions + def connections(self, kind='inet'): + return net_connections(kind, _pid=self.pid) + + @wrap_exceptions + def nice_get(self): + value = cext.proc_priority_get(self.pid) + if enum is not None: + value = Priority(value) + return value + + @wrap_exceptions + def nice_set(self, value): + return cext.proc_priority_set(self.pid, value) + + # available on Windows >= Vista + if HAS_PROC_IO_PRIORITY: + @wrap_exceptions + def ionice_get(self): + return cext.proc_io_priority_get(self.pid) + + @wrap_exceptions + def ionice_set(self, value, _): + if _: + raise TypeError("set_proc_ionice() on Windows takes only " + "1 argument (2 given)") + if value not in (2, 1, 0): + raise ValueError("value must be 2 (normal), 1 (low) or 0 " + "(very low); got %r" % value) + return cext.proc_io_priority_set(self.pid, value) + + @wrap_exceptions + def io_counters(self): + try: + ret = cext.proc_io_counters(self.pid) + except OSError as err: + if err.errno in ACCESS_DENIED_ERRSET: + info = self.oneshot_info() + ret = ( + info[pinfo_map['io_rcount']], + info[pinfo_map['io_wcount']], + info[pinfo_map['io_rbytes']], + info[pinfo_map['io_wbytes']], + info[pinfo_map['io_count_others']], + info[pinfo_map['io_bytes_others']], + ) + else: + raise + return pio(*ret) + + @wrap_exceptions + def status(self): + suspended = cext.proc_is_suspended(self.pid) + if suspended: + return _common.STATUS_STOPPED + else: + return _common.STATUS_RUNNING + + @wrap_exceptions + def cpu_affinity_get(self): + def from_bitmask(x): + return [i for i in xrange(64) if (1 << i) & x] + bitmask = cext.proc_cpu_affinity_get(self.pid) + return from_bitmask(bitmask) + + @wrap_exceptions + def cpu_affinity_set(self, value): + def to_bitmask(l): + if not l: + raise ValueError("invalid argument %r" % l) + out = 0 + for b in l: + out |= 2 ** b + return out + + # SetProcessAffinityMask() states that ERROR_INVALID_PARAMETER + # is returned for an invalid CPU but this seems not to be true, + # therefore we check CPUs validy beforehand. + allcpus = list(range(len(per_cpu_times()))) + for cpu in value: + if cpu not in allcpus: + if not isinstance(cpu, (int, long)): + raise TypeError( + "invalid CPU %r; an integer is required" % cpu) + else: + raise ValueError("invalid CPU %r" % cpu) + + bitmask = to_bitmask(value) + cext.proc_cpu_affinity_set(self.pid, bitmask) + + @wrap_exceptions + def num_handles(self): + try: + return cext.proc_num_handles(self.pid) + except OSError as err: + if err.errno in ACCESS_DENIED_ERRSET: + return self.oneshot_info()[pinfo_map['num_handles']] + raise + + @wrap_exceptions + def num_ctx_switches(self): + ctx_switches = self.oneshot_info()[pinfo_map['ctx_switches']] + # only voluntary ctx switches are supported + return _common.pctxsw(ctx_switches, 0) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__init__.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__init__.py new file mode 100644 index 00000000..74b0c969 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__init__.py @@ -0,0 +1,1244 @@ +# -*- coding: utf-8 -*- + +# 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. + +""" +Test utilities. +""" + +from __future__ import print_function + +import atexit +import contextlib +import ctypes +import errno +import functools +import os +import random +import re +import select +import shutil +import socket +import stat +import subprocess +import sys +import tempfile +import textwrap +import threading +import time +import traceback +import warnings +from socket import AF_INET +from socket import AF_INET6 +from socket import SOCK_DGRAM +from socket import SOCK_STREAM + +import psutil +from psutil import MACOS +from psutil import POSIX +from psutil import SUNOS +from psutil import WINDOWS +from psutil._common import supports_ipv6 +from psutil._compat import PY3 +from psutil._compat import u +from psutil._compat import unicode +from psutil._compat import which + +if sys.version_info < (2, 7): + import unittest2 as unittest # requires "pip install unittest2" +else: + import unittest + +try: + from unittest import mock # py3 +except ImportError: + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + import mock # NOQA - requires "pip install mock" + +if sys.version_info >= (3, 4): + import enum +else: + enum = None + + +__all__ = [ + # constants + 'APPVEYOR', 'DEVNULL', 'GLOBAL_TIMEOUT', 'MEMORY_TOLERANCE', 'NO_RETRIES', + 'PYPY', 'PYTHON_EXE', 'ROOT_DIR', 'SCRIPTS_DIR', 'TESTFILE_PREFIX', + 'TESTFN', 'TESTFN_UNICODE', 'TOX', 'TRAVIS', 'VALID_PROC_STATUSES', + 'VERBOSITY', + "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", + # subprocesses + 'pyrun', 'reap_children', 'get_test_subprocess', 'create_zombie_proc', + 'create_proc_children_pair', + # threads + 'ThreadTask' + # test utils + 'unittest', 'skip_on_access_denied', 'skip_on_not_implemented', + 'retry_before_failing', 'run_test_module_by_name', 'get_suite', + 'run_suite', + # install utils + 'install_pip', 'install_test_deps', + # fs utils + 'chdir', 'safe_rmpath', 'create_exe', 'decode_path', 'encode_path', + 'unique_filename', + # os + 'get_winver', 'get_kernel_version', + # sync primitives + 'call_until', 'wait_for_pid', 'wait_for_file', + # network + 'check_connection_ntuple', 'check_net_address', + 'get_free_port', 'unix_socket_path', 'bind_socket', 'bind_unix_socket', + 'tcp_socketpair', 'unix_socketpair', 'create_sockets', + # compat + 'reload_module', 'import_module_by_path', + # others + 'warn', 'copyload_shared_lib', 'is_namedtuple', +] + + +# =================================================================== +# --- constants +# =================================================================== + +# --- platforms + +TOX = os.getenv('TOX') or '' in ('1', 'true') +PYPY = '__pypy__' in sys.builtin_module_names +WIN_VISTA = (6, 0, 0) if WINDOWS else None +# whether we're running this test suite on Travis (https://travis-ci.org/) +TRAVIS = bool(os.environ.get('TRAVIS')) +# whether we're running this test suite on Appveyor for Windows +# (http://www.appveyor.com/) +APPVEYOR = bool(os.environ.get('APPVEYOR')) +PYPY = '__pypy__' in sys.builtin_module_names + +# --- configurable defaults + +# how many times retry_before_failing() decorator will retry +NO_RETRIES = 10 +# bytes tolerance for system-wide memory related tests +MEMORY_TOLERANCE = 500 * 1024 # 500KB +# the timeout used in functions which have to wait +GLOBAL_TIMEOUT = 3 if TRAVIS or APPVEYOR else 0.5 +# test output verbosity +VERBOSITY = 1 if os.getenv('SILENT') or TOX else 2 +# be more tolerant if we're on travis / appveyor in order to avoid +# false positives +if TRAVIS or APPVEYOR: + NO_RETRIES *= 3 + GLOBAL_TIMEOUT *= 3 + +# --- files + +TESTFILE_PREFIX = '$testfn' +if os.name == 'java': + # Jython disallows @ in module names + TESTFILE_PREFIX = '$psutil-test-' +else: + TESTFILE_PREFIX = '@psutil-test-' +TESTFN = os.path.join(os.path.realpath(os.getcwd()), TESTFILE_PREFIX) +# Disambiguate TESTFN for parallel testing, while letting it remain a valid +# module name. +TESTFN = TESTFN + str(os.getpid()) + +_TESTFN = TESTFN + '-internal' +TESTFN_UNICODE = TESTFN + u("-ƒőő") +ASCII_FS = sys.getfilesystemencoding().lower() in ('ascii', 'us-ascii') + +# --- paths + +ROOT_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) +SCRIPTS_DIR = os.path.join(ROOT_DIR, 'scripts') +HERE = os.path.abspath(os.path.dirname(__file__)) + +# --- support + +HAS_CONNECTIONS_UNIX = POSIX and not SUNOS +HAS_CPU_AFFINITY = hasattr(psutil.Process, "cpu_affinity") +HAS_CPU_FREQ = hasattr(psutil, "cpu_freq") +HAS_ENVIRON = hasattr(psutil.Process, "environ") +HAS_IONICE = hasattr(psutil.Process, "ionice") +HAS_MEMORY_MAPS = hasattr(psutil.Process, "memory_maps") +HAS_NET_IO_COUNTERS = hasattr(psutil, "net_io_counters") +HAS_PROC_CPU_NUM = hasattr(psutil.Process, "cpu_num") +HAS_PROC_IO_COUNTERS = hasattr(psutil.Process, "io_counters") +HAS_RLIMIT = hasattr(psutil.Process, "rlimit") +HAS_SENSORS_BATTERY = hasattr(psutil, "sensors_battery") +try: + HAS_BATTERY = HAS_SENSORS_BATTERY and bool(psutil.sensors_battery()) +except Exception: + HAS_BATTERY = True +HAS_SENSORS_FANS = hasattr(psutil, "sensors_fans") +HAS_SENSORS_TEMPERATURES = hasattr(psutil, "sensors_temperatures") +HAS_THREADS = hasattr(psutil.Process, "threads") + +# --- misc + + +def _get_py_exe(): + def attempt(exe): + try: + subprocess.check_call( + [exe, "-V"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + except Exception: + return None + else: + return exe + + if MACOS: + exe = \ + attempt(sys.executable) or \ + attempt(os.path.realpath(sys.executable)) or \ + attempt(which("python%s.%s" % sys.version_info[:2])) or \ + attempt(psutil.Process().exe()) + if not exe: + raise ValueError("can't find python exe real abspath") + return exe + else: + exe = os.path.realpath(sys.executable) + if WINDOWS: + # avoid subprocess warnings + exe = exe.replace('\\', '\\\\') + assert os.path.exists(exe), exe + return exe + + +PYTHON_EXE = _get_py_exe() +DEVNULL = open(os.devnull, 'r+') +VALID_PROC_STATUSES = [getattr(psutil, x) for x in dir(psutil) + if x.startswith('STATUS_')] +AF_UNIX = getattr(socket, "AF_UNIX", object()) +SOCK_SEQPACKET = getattr(socket, "SOCK_SEQPACKET", object()) + +_subprocesses_started = set() +_pids_started = set() +_testfiles_created = set() + + +@atexit.register +def cleanup_test_files(): + DEVNULL.close() + for name in os.listdir(u('.')): + if isinstance(name, unicode): + prefix = u(TESTFILE_PREFIX) + else: + prefix = TESTFILE_PREFIX + if name.startswith(prefix): + try: + safe_rmpath(name) + except Exception: + traceback.print_exc() + for path in _testfiles_created: + try: + safe_rmpath(path) + except Exception: + traceback.print_exc() + + +# this is executed first +@atexit.register +def cleanup_test_procs(): + reap_children(recursive=True) + + +# =================================================================== +# --- threads +# =================================================================== + + +class ThreadTask(threading.Thread): + """A thread task which does nothing expect staying alive.""" + + def __init__(self): + threading.Thread.__init__(self) + self._running = False + self._interval = 0.001 + self._flag = threading.Event() + + def __repr__(self): + name = self.__class__.__name__ + return '<%s running=%s at %#x>' % (name, self._running, id(self)) + + def __enter__(self): + self.start() + return self + + def __exit__(self, *args, **kwargs): + self.stop() + + def start(self): + """Start thread and keep it running until an explicit + stop() request. Polls for shutdown every 'timeout' seconds. + """ + if self._running: + raise ValueError("already started") + threading.Thread.start(self) + self._flag.wait() + + def run(self): + self._running = True + self._flag.set() + while self._running: + time.sleep(self._interval) + + def stop(self): + """Stop thread execution and and waits until it is stopped.""" + if not self._running: + raise ValueError("already stopped") + self._running = False + self.join() + + +# =================================================================== +# --- subprocesses +# =================================================================== + + +def _reap_children_on_err(fun): + @functools.wraps(fun) + def wrapper(*args, **kwargs): + try: + return fun(*args, **kwargs) + except Exception: + reap_children() + raise + return wrapper + + +@_reap_children_on_err +def get_test_subprocess(cmd=None, **kwds): + """Creates a python subprocess which does nothing for 60 secs and + return it as subprocess.Popen instance. + If "cmd" is specified that is used instead of python. + By default stdin and stdout are redirected to /dev/null. + It also attemps to make sure the process is in a reasonably + initialized state. + The process is registered for cleanup on reap_children(). + """ + kwds.setdefault("stdin", DEVNULL) + kwds.setdefault("stdout", DEVNULL) + kwds.setdefault("cwd", os.getcwd()) + kwds.setdefault("env", os.environ) + if WINDOWS: + # Prevents the subprocess to open error dialogs. This will also + # cause stderr to be suppressed, which is suboptimal in order + # to debug broken tests. + CREATE_NO_WINDOW = 0x8000000 + kwds.setdefault("creationflags", CREATE_NO_WINDOW) + if cmd is None: + safe_rmpath(_TESTFN) + pyline = "from time import sleep;" \ + "open(r'%s', 'w').close();" \ + "sleep(60);" % _TESTFN + cmd = [PYTHON_EXE, "-c", pyline] + sproc = subprocess.Popen(cmd, **kwds) + _subprocesses_started.add(sproc) + wait_for_file(_TESTFN, delete=True, empty=True) + else: + sproc = subprocess.Popen(cmd, **kwds) + _subprocesses_started.add(sproc) + wait_for_pid(sproc.pid) + return sproc + + +@_reap_children_on_err +def create_proc_children_pair(): + """Create a subprocess which creates another one as in: + A (us) -> B (child) -> C (grandchild). + Return a (child, grandchild) tuple. + The 2 processes are fully initialized and will live for 60 secs + and are registered for cleanup on reap_children(). + """ + _TESTFN2 = os.path.basename(_TESTFN) + '2' # need to be relative + s = textwrap.dedent("""\ + import subprocess, os, sys, time + s = "import os, time;" + s += "f = open('%s', 'w');" + s += "f.write(str(os.getpid()));" + s += "f.close();" + s += "time.sleep(60);" + p = subprocess.Popen(['%s', '-c', s]) + p.wait() + """ % (_TESTFN2, PYTHON_EXE)) + # On Windows if we create a subprocess with CREATE_NO_WINDOW flag + # set (which is the default) a "conhost.exe" extra process will be + # spawned as a child. We don't want that. + if WINDOWS: + subp = pyrun(s, creationflags=0) + else: + subp = pyrun(s) + child1 = psutil.Process(subp.pid) + data = wait_for_file(_TESTFN2, delete=False, empty=False) + safe_rmpath(_TESTFN2) + child2_pid = int(data) + _pids_started.add(child2_pid) + child2 = psutil.Process(child2_pid) + return (child1, child2) + + +def create_zombie_proc(): + """Create a zombie process and return its PID.""" + assert psutil.POSIX + unix_file = tempfile.mktemp(prefix=TESTFILE_PREFIX) if MACOS else TESTFN + src = textwrap.dedent("""\ + import os, sys, time, socket, contextlib + child_pid = os.fork() + if child_pid > 0: + time.sleep(3000) + else: + # this is the zombie process + s = socket.socket(socket.AF_UNIX) + with contextlib.closing(s): + s.connect('%s') + if sys.version_info < (3, ): + pid = str(os.getpid()) + else: + pid = bytes(str(os.getpid()), 'ascii') + s.sendall(pid) + """ % unix_file) + with contextlib.closing(socket.socket(socket.AF_UNIX)) as sock: + sock.settimeout(GLOBAL_TIMEOUT) + sock.bind(unix_file) + sock.listen(1) + pyrun(src) + conn, _ = sock.accept() + try: + select.select([conn.fileno()], [], [], GLOBAL_TIMEOUT) + zpid = int(conn.recv(1024)) + _pids_started.add(zpid) + zproc = psutil.Process(zpid) + call_until(lambda: zproc.status(), "ret == psutil.STATUS_ZOMBIE") + return zpid + finally: + conn.close() + + +@_reap_children_on_err +def pyrun(src, **kwds): + """Run python 'src' code string in a separate interpreter. + Returns a subprocess.Popen instance. + """ + kwds.setdefault("stdout", None) + kwds.setdefault("stderr", None) + with tempfile.NamedTemporaryFile( + prefix=TESTFILE_PREFIX, mode="wt", delete=False) as f: + _testfiles_created.add(f.name) + f.write(src) + f.flush() + subp = get_test_subprocess([PYTHON_EXE, f.name], **kwds) + wait_for_pid(subp.pid) + return subp + + +@_reap_children_on_err +def sh(cmd, **kwds): + """run cmd in a subprocess and return its output. + raises RuntimeError on error. + """ + shell = True if isinstance(cmd, (str, unicode)) else False + # Prevents subprocess to open error dialogs in case of error. + flags = 0x8000000 if WINDOWS and shell else 0 + kwds.setdefault("shell", shell) + kwds.setdefault("stdout", subprocess.PIPE) + kwds.setdefault("stderr", subprocess.PIPE) + kwds.setdefault("universal_newlines", True) + kwds.setdefault("creationflags", flags) + p = subprocess.Popen(cmd, **kwds) + _subprocesses_started.add(p) + stdout, stderr = p.communicate() + if p.returncode != 0: + raise RuntimeError(stderr) + if stderr: + warn(stderr) + if stdout.endswith('\n'): + stdout = stdout[:-1] + return stdout + + +def reap_children(recursive=False): + """Terminate and wait() any subprocess started by this test suite + and ensure that no zombies stick around to hog resources and + create problems when looking for refleaks. + + If resursive is True it also tries to terminate and wait() + all grandchildren started by this process. + """ + # This is here to make sure wait_procs() behaves properly and + # investigate: + # https://ci.appveyor.com/project/giampaolo/psutil/build/job/ + # jiq2cgd6stsbtn60 + def assert_gone(pid): + assert not psutil.pid_exists(pid), pid + assert pid not in psutil.pids(), pid + try: + p = psutil.Process(pid) + assert not p.is_running(), pid + except psutil.NoSuchProcess: + pass + else: + assert 0, "pid %s is not gone" % pid + + # Get the children here, before terminating the children sub + # processes as we don't want to lose the intermediate reference + # in case of grandchildren. + if recursive: + children = set(psutil.Process().children(recursive=True)) + else: + children = set() + + # Terminate subprocess.Popen instances "cleanly" by closing their + # fds and wiat()ing for them in order to avoid zombies. + while _subprocesses_started: + subp = _subprocesses_started.pop() + _pids_started.add(subp.pid) + try: + subp.terminate() + except OSError as err: + if WINDOWS and err.winerror == 6: # "invalid handle" + pass + elif err.errno != errno.ESRCH: + raise + if subp.stdout: + subp.stdout.close() + if subp.stderr: + subp.stderr.close() + try: + # Flushing a BufferedWriter may raise an error. + if subp.stdin: + subp.stdin.close() + finally: + # Wait for the process to terminate, to avoid zombies. + try: + subp.wait() + except OSError as err: + if err.errno != errno.ECHILD: + raise + + # Terminate started pids. + while _pids_started: + pid = _pids_started.pop() + try: + p = psutil.Process(pid) + except psutil.NoSuchProcess: + assert_gone(pid) + else: + children.add(p) + + # Terminate children. + if children: + for p in children: + try: + p.terminate() + except psutil.NoSuchProcess: + pass + gone, alive = psutil.wait_procs(children, timeout=GLOBAL_TIMEOUT) + for p in alive: + warn("couldn't terminate process %r; attempting kill()" % p) + try: + p.kill() + except psutil.NoSuchProcess: + pass + gone, alive = psutil.wait_procs(alive, timeout=GLOBAL_TIMEOUT) + if alive: + for p in alive: + warn("process %r survived kill()" % p) + + for p in children: + assert_gone(p.pid) + + +# =================================================================== +# --- OS +# =================================================================== + + +def get_kernel_version(): + """Return a tuple such as (2, 6, 36).""" + if not POSIX: + raise NotImplementedError("not POSIX") + s = "" + uname = os.uname()[2] + for c in uname: + if c.isdigit() or c == '.': + s += c + else: + break + if not s: + raise ValueError("can't parse %r" % uname) + minor = 0 + micro = 0 + nums = s.split('.') + major = int(nums[0]) + if len(nums) >= 2: + minor = int(nums[1]) + if len(nums) >= 3: + micro = int(nums[2]) + return (major, minor, micro) + + +def get_winver(): + if not WINDOWS: + raise NotImplementedError("not WINDOWS") + wv = sys.getwindowsversion() + if hasattr(wv, 'service_pack_major'): # python >= 2.7 + sp = wv.service_pack_major or 0 + else: + r = re.search(r"\s\d$", wv[4]) + if r: + sp = int(r.group(0)) + else: + sp = 0 + return (wv[0], wv[1], sp) + + +# =================================================================== +# --- sync primitives +# =================================================================== + + +class retry(object): + """A retry decorator.""" + + def __init__(self, + exception=Exception, + timeout=None, + retries=None, + interval=0.001, + logfun=print, + ): + if timeout and retries: + raise ValueError("timeout and retries args are mutually exclusive") + self.exception = exception + self.timeout = timeout + self.retries = retries + self.interval = interval + self.logfun = logfun + + def __iter__(self): + if self.timeout: + stop_at = time.time() + self.timeout + while time.time() < stop_at: + yield + elif self.retries: + for _ in range(self.retries): + yield + else: + while True: + yield + + def sleep(self): + if self.interval is not None: + time.sleep(self.interval) + + def __call__(self, fun): + @functools.wraps(fun) + def wrapper(*args, **kwargs): + exc = None + for _ in self: + try: + return fun(*args, **kwargs) + except self.exception as _: # NOQA + exc = _ + if self.logfun is not None: + self.logfun(exc) + self.sleep() + continue + if PY3: + raise exc + else: + raise + + # This way the user of the decorated function can change config + # parameters. + wrapper.decorator = self + return wrapper + + +@retry(exception=psutil.NoSuchProcess, logfun=None, timeout=GLOBAL_TIMEOUT, + interval=0.001) +def wait_for_pid(pid): + """Wait for pid to show up in the process list then return. + Used in the test suite to give time the sub process to initialize. + """ + psutil.Process(pid) + if WINDOWS: + # give it some more time to allow better initialization + time.sleep(0.01) + + +@retry(exception=(EnvironmentError, AssertionError), logfun=None, + timeout=GLOBAL_TIMEOUT, interval=0.001) +def wait_for_file(fname, delete=True, empty=False): + """Wait for a file to be written on disk with some content.""" + with open(fname, "rb") as f: + data = f.read() + if not empty: + assert data + if delete: + safe_rmpath(fname) + return data + + +@retry(exception=AssertionError, logfun=None, timeout=GLOBAL_TIMEOUT, + interval=0.001) +def call_until(fun, expr): + """Keep calling function for timeout secs and exit if eval() + expression is True. + """ + ret = fun() + assert eval(expr) + return ret + + +# =================================================================== +# --- fs +# =================================================================== + + +def safe_rmpath(path): + "Convenience function for removing temporary test files or dirs" + def retry_fun(fun): + # On Windows it could happen that the file or directory has + # open handles or references preventing the delete operation + # to succeed immediately, so we retry for a while. See: + # https://bugs.python.org/issue33240 + stop_at = time.time() + 1 + while time.time() < stop_at: + try: + return fun() + except WindowsError as _: + err = _ + if err.errno != errno.ENOENT: + raise + else: + warn("ignoring %s" % (str(err))) + time.sleep(0.01) + raise err + + try: + st = os.stat(path) + if stat.S_ISDIR(st.st_mode): + fun = functools.partial(shutil.rmtree, path) + else: + fun = functools.partial(os.remove, path) + if POSIX: + fun() + else: + retry_fun(fun) + except OSError as err: + if err.errno != errno.ENOENT: + raise + + +def safe_mkdir(dir): + "Convenience function for creating a directory" + try: + os.mkdir(dir) + except OSError as err: + if err.errno != errno.EEXIST: + raise + + +@contextlib.contextmanager +def chdir(dirname): + "Context manager which temporarily changes the current directory." + curdir = os.getcwd() + try: + os.chdir(dirname) + yield + finally: + os.chdir(curdir) + + +def create_exe(outpath, c_code=None): + """Creates an executable file in the given location.""" + assert not os.path.exists(outpath), outpath + if c_code: + if not which("gcc"): + raise ValueError("gcc is not installed") + if isinstance(c_code, bool): # c_code is True + c_code = textwrap.dedent( + """ + #include + int main() { + pause(); + return 1; + } + """) + assert isinstance(c_code, str), c_code + with tempfile.NamedTemporaryFile( + suffix='.c', delete=False, mode='wt') as f: + f.write(c_code) + try: + subprocess.check_call(["gcc", f.name, "-o", outpath]) + finally: + safe_rmpath(f.name) + else: + # copy python executable + shutil.copyfile(PYTHON_EXE, outpath) + if POSIX: + st = os.stat(outpath) + os.chmod(outpath, st.st_mode | stat.S_IEXEC) + + +def unique_filename(prefix=TESTFILE_PREFIX, suffix=""): + return tempfile.mktemp(prefix=prefix, suffix=suffix) + + +# =================================================================== +# --- testing +# =================================================================== + + +class TestCase(unittest.TestCase): + + # Print a full path representation of the single unit tests + # being run. + def __str__(self): + return "%s.%s.%s" % ( + self.__class__.__module__, self.__class__.__name__, + self._testMethodName) + + # assertRaisesRegexp renamed to assertRaisesRegex in 3.3; + # add support for the new name. + if not hasattr(unittest.TestCase, 'assertRaisesRegex'): + assertRaisesRegex = unittest.TestCase.assertRaisesRegexp + + +# override default unittest.TestCase +unittest.TestCase = TestCase + + +def _setup_tests(): + if 'PSUTIL_TESTING' not in os.environ: + # This won't work on Windows but set_testing() below will do it. + os.environ['PSUTIL_TESTING'] = '1' + psutil._psplatform.cext.set_testing() + + +def get_suite(): + testmods = [os.path.splitext(x)[0] for x in os.listdir(HERE) + if x.endswith('.py') and x.startswith('test_') and not + x.startswith('test_memory_leaks')] + if "WHEELHOUSE_UPLOADER_USERNAME" in os.environ: + testmods = [x for x in testmods if not x.endswith(( + "osx", "posix", "linux"))] + suite = unittest.TestSuite() + for tm in testmods: + # ...so that the full test paths are printed on screen + tm = "psutil.tests.%s" % tm + suite.addTest(unittest.defaultTestLoader.loadTestsFromName(tm)) + return suite + + +def run_suite(): + _setup_tests() + result = unittest.TextTestRunner(verbosity=VERBOSITY).run(get_suite()) + success = result.wasSuccessful() + sys.exit(0 if success else 1) + + +def run_test_module_by_name(name): + # testmodules = [os.path.splitext(x)[0] for x in os.listdir(HERE) + # if x.endswith('.py') and x.startswith('test_')] + _setup_tests() + name = os.path.splitext(os.path.basename(name))[0] + suite = unittest.TestSuite() + suite.addTest(unittest.defaultTestLoader.loadTestsFromName(name)) + result = unittest.TextTestRunner(verbosity=VERBOSITY).run(suite) + success = result.wasSuccessful() + sys.exit(0 if success else 1) + + +def retry_before_failing(retries=NO_RETRIES): + """Decorator which runs a test function and retries N times before + actually failing. + """ + return retry(exception=AssertionError, timeout=None, retries=retries) + + +def skip_on_access_denied(only_if=None): + """Decorator to Ignore AccessDenied exceptions.""" + def decorator(fun): + @functools.wraps(fun) + def wrapper(*args, **kwargs): + try: + return fun(*args, **kwargs) + except psutil.AccessDenied: + if only_if is not None: + if not only_if: + raise + raise unittest.SkipTest("raises AccessDenied") + return wrapper + return decorator + + +def skip_on_not_implemented(only_if=None): + """Decorator to Ignore NotImplementedError exceptions.""" + def decorator(fun): + @functools.wraps(fun) + def wrapper(*args, **kwargs): + try: + return fun(*args, **kwargs) + except NotImplementedError: + if only_if is not None: + if not only_if: + raise + msg = "%r was skipped because it raised NotImplementedError" \ + % fun.__name__ + raise unittest.SkipTest(msg) + return wrapper + return decorator + + +# =================================================================== +# --- network +# =================================================================== + + +def get_free_port(host='127.0.0.1'): + """Return an unused TCP port.""" + with contextlib.closing(socket.socket()) as sock: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind((host, 0)) + return sock.getsockname()[1] + + +@contextlib.contextmanager +def unix_socket_path(suffix=""): + """A context manager which returns a non-existent file name + and tries to delete it on exit. + """ + assert psutil.POSIX + path = unique_filename(suffix=suffix) + try: + yield path + finally: + try: + os.unlink(path) + except OSError: + pass + + +def bind_socket(family=AF_INET, type=SOCK_STREAM, addr=None): + """Binds a generic socket.""" + if addr is None and family in (AF_INET, AF_INET6): + addr = ("", 0) + sock = socket.socket(family, type) + try: + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind(addr) + if type == socket.SOCK_STREAM: + sock.listen(10) + return sock + except Exception: + sock.close() + raise + + +def bind_unix_socket(name, type=socket.SOCK_STREAM): + """Bind a UNIX socket.""" + assert psutil.POSIX + assert not os.path.exists(name), name + sock = socket.socket(socket.AF_UNIX, type) + try: + sock.bind(name) + if type == socket.SOCK_STREAM: + sock.listen(10) + except Exception: + sock.close() + raise + return sock + + +def tcp_socketpair(family, addr=("", 0)): + """Build a pair of TCP sockets connected to each other. + Return a (server, client) tuple. + """ + with contextlib.closing(socket.socket(family, SOCK_STREAM)) as ll: + ll.bind(addr) + ll.listen(10) + addr = ll.getsockname() + c = socket.socket(family, SOCK_STREAM) + try: + c.connect(addr) + caddr = c.getsockname() + while True: + a, addr = ll.accept() + # check that we've got the correct client + if addr == caddr: + return (a, c) + a.close() + except OSError: + c.close() + raise + + +def unix_socketpair(name): + """Build a pair of UNIX sockets connected to each other through + the same UNIX file name. + Return a (server, client) tuple. + """ + assert psutil.POSIX + server = client = None + try: + server = bind_unix_socket(name, type=socket.SOCK_STREAM) + server.setblocking(0) + client = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + client.setblocking(0) + client.connect(name) + # new = server.accept() + except Exception: + if server is not None: + server.close() + if client is not None: + client.close() + raise + return (server, client) + + +@contextlib.contextmanager +def create_sockets(): + """Open as many socket families / types as possible.""" + socks = [] + fname1 = fname2 = None + try: + socks.append(bind_socket(socket.AF_INET, socket.SOCK_STREAM)) + socks.append(bind_socket(socket.AF_INET, socket.SOCK_DGRAM)) + if supports_ipv6(): + socks.append(bind_socket(socket.AF_INET6, socket.SOCK_STREAM)) + socks.append(bind_socket(socket.AF_INET6, socket.SOCK_DGRAM)) + if POSIX and HAS_CONNECTIONS_UNIX: + fname1 = unix_socket_path().__enter__() + fname2 = unix_socket_path().__enter__() + s1, s2 = unix_socketpair(fname1) + s3 = bind_unix_socket(fname2, type=socket.SOCK_DGRAM) + # self.addCleanup(safe_rmpath, fname1) + # self.addCleanup(safe_rmpath, fname2) + for s in (s1, s2, s3): + socks.append(s) + yield socks + finally: + for s in socks: + s.close() + if fname1 is not None: + safe_rmpath(fname1) + if fname2 is not None: + safe_rmpath(fname2) + + +def check_net_address(addr, family): + """Check a net address validity. Supported families are IPv4, + IPv6 and MAC addresses. + """ + import ipaddress # python >= 3.3 / requires "pip install ipaddress" + if enum and PY3: + assert isinstance(family, enum.IntEnum), family + if family == socket.AF_INET: + octs = [int(x) for x in addr.split('.')] + assert len(octs) == 4, addr + for num in octs: + assert 0 <= num <= 255, addr + if not PY3: + addr = unicode(addr) + ipaddress.IPv4Address(addr) + elif family == socket.AF_INET6: + assert isinstance(addr, str), addr + if not PY3: + addr = unicode(addr) + ipaddress.IPv6Address(addr) + 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) + + +def check_connection_ntuple(conn): + """Check validity of a connection namedtuple.""" + # check ntuple + assert len(conn) in (6, 7), conn + has_pid = len(conn) == 7 + has_fd = getattr(conn, 'fd', -1) != -1 + assert conn[0] == conn.fd + assert conn[1] == conn.family + assert conn[2] == conn.type + assert conn[3] == conn.laddr + assert conn[4] == conn.raddr + assert conn[5] == conn.status + if has_pid: + assert conn[6] == conn.pid + + # check fd + if has_fd: + assert conn.fd >= 0, conn + if hasattr(socket, 'fromfd') and not WINDOWS: + try: + dupsock = socket.fromfd(conn.fd, conn.family, conn.type) + except (socket.error, OSError) as err: + if err.args[0] != errno.EBADF: + raise + else: + with contextlib.closing(dupsock): + assert dupsock.family == conn.family + assert dupsock.type == conn.type + + # check family + assert conn.family in (AF_INET, AF_INET6, AF_UNIX), repr(conn.family) + if conn.family in (AF_INET, AF_INET6): + # actually try to bind the local socket; ignore IPv6 + # sockets as their address might be represented as + # an IPv4-mapped-address (e.g. "::127.0.0.1") + # and that's rejected by bind() + if conn.family == AF_INET: + s = socket.socket(conn.family, conn.type) + with contextlib.closing(s): + try: + s.bind((conn.laddr[0], 0)) + except socket.error as err: + if err.errno != errno.EADDRNOTAVAIL: + raise + elif conn.family == AF_UNIX: + assert conn.status == psutil.CONN_NONE, conn.status + + # check type (SOCK_SEQPACKET may happen in case of AF_UNIX socks) + assert conn.type in (SOCK_STREAM, SOCK_DGRAM, SOCK_SEQPACKET), \ + repr(conn.type) + if conn.type == SOCK_DGRAM: + assert conn.status == psutil.CONN_NONE, conn.status + + # check laddr (IP address and port sanity) + for addr in (conn.laddr, conn.raddr): + if conn.family in (AF_INET, AF_INET6): + assert isinstance(addr, tuple), addr + if not addr: + continue + assert isinstance(addr.port, int), addr.port + assert 0 <= addr.port <= 65535, addr.port + check_net_address(addr.ip, conn.family) + elif conn.family == AF_UNIX: + assert isinstance(addr, str), addr + + # check status + assert isinstance(conn.status, str), conn + valids = [getattr(psutil, x) for x in dir(psutil) if x.startswith('CONN_')] + assert conn.status in valids, conn + + +# =================================================================== +# --- compatibility +# =================================================================== + + +def reload_module(module): + """Backport of importlib.reload of Python 3.3+.""" + try: + import importlib + if not hasattr(importlib, 'reload'): # python <=3.3 + raise ImportError + except ImportError: + import imp + return imp.reload(module) + else: + return importlib.reload(module) + + +def import_module_by_path(path): + name = os.path.splitext(os.path.basename(path))[0] + if sys.version_info[0] == 2: + import imp + return imp.load_source(name, path) + elif sys.version_info[:2] <= (3, 4): + from importlib.machinery import SourceFileLoader + return SourceFileLoader(name, path).load_module() + else: + import importlib.util + spec = importlib.util.spec_from_file_location(name, path) + mod = importlib.util.module_from_spec(spec) + spec.loader.exec_module(mod) + return mod + + +# =================================================================== +# --- others +# =================================================================== + + +def warn(msg): + """Raise a warning msg.""" + warnings.warn(msg, UserWarning) + + +def is_namedtuple(x): + """Check if object is an instance of namedtuple.""" + t = type(x) + b = t.__bases__ + if len(b) != 1 or b[0] != tuple: + return False + f = getattr(t, '_fields', None) + if not isinstance(f, tuple): + return False + return all(type(n) == str for n in f) + + +if POSIX: + @contextlib.contextmanager + def copyload_shared_lib(dst_prefix=TESTFILE_PREFIX): + """Ctx manager which picks up a random shared CO lib used + by this process, copies it in another location and loads it + in memory via ctypes. Return the new absolutized path. + """ + exe = 'pypy' if PYPY else 'python' + ext = ".so" + dst = tempfile.mktemp(prefix=dst_prefix, suffix=ext) + libs = [x.path for x in psutil.Process().memory_maps() if + os.path.splitext(x.path)[1] == ext and + exe in x.path.lower()] + src = random.choice(libs) + shutil.copyfile(src, dst) + try: + ctypes.CDLL(dst) + yield dst + finally: + safe_rmpath(dst) +else: + @contextlib.contextmanager + def copyload_shared_lib(dst_prefix=TESTFILE_PREFIX): + """Ctx manager which picks up a random shared DLL lib used + by this process, copies it in another location and loads it + in memory via ctypes. + Return the new absolutized, normcased path. + """ + from ctypes import wintypes + from ctypes import WinError + ext = ".dll" + dst = tempfile.mktemp(prefix=dst_prefix, suffix=ext) + libs = [x.path for x in psutil.Process().memory_maps() if + os.path.splitext(x.path)[1].lower() == ext and + 'python' in os.path.basename(x.path).lower() and + 'wow64' not in x.path.lower()] + src = random.choice(libs) + shutil.copyfile(src, dst) + cfile = None + try: + cfile = ctypes.WinDLL(dst) + yield dst + finally: + # Work around OverflowError: + # - https://ci.appveyor.com/project/giampaolo/psutil/build/1207/ + # job/o53330pbnri9bcw7 + # - http://bugs.python.org/issue30286 + # - http://stackoverflow.com/questions/23522055 + if cfile is not None: + FreeLibrary = ctypes.windll.kernel32.FreeLibrary + FreeLibrary.argtypes = [wintypes.HMODULE] + ret = FreeLibrary(cfile._handle) + if ret == 0: + WinError() + safe_rmpath(dst) diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__main__.py b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__main__.py new file mode 100644 index 00000000..36554a12 --- /dev/null +++ b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__main__.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python + +# 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. + +""" +Run unit tests. This is invoked by: + +$ python -m psutil.tests +""" + +import contextlib +import optparse +import os +import sys +import tempfile +try: + from urllib.request import urlopen # py3 +except ImportError: + from urllib2 import urlopen + +from psutil.tests import PYTHON_EXE +from psutil.tests import run_suite + + +HERE = os.path.abspath(os.path.dirname(__file__)) +GET_PIP_URL = "https://bootstrap.pypa.io/get-pip.py" +TEST_DEPS = [] +if sys.version_info[:2] == (2, 6): + TEST_DEPS.extend(["ipaddress", "unittest2", "argparse", "mock==1.0.1"]) +elif sys.version_info[:2] == (2, 7) or sys.version_info[:2] <= (3, 2): + TEST_DEPS.extend(["ipaddress", "mock"]) + + +def install_pip(): + try: + import pip # NOQA + except ImportError: + import ssl + f = tempfile.NamedTemporaryFile(suffix='.py') + with contextlib.closing(f): + print("downloading %s to %s" % (GET_PIP_URL, f.name)) + if hasattr(ssl, '_create_unverified_context'): + ctx = ssl._create_unverified_context() + else: + ctx = None + kwargs = dict(context=ctx) if ctx else {} + req = urlopen(GET_PIP_URL, **kwargs) + data = req.read() + f.write(data) + f.flush() + + print("installing pip") + code = os.system('%s %s --user' % (PYTHON_EXE, f.name)) + return code + + +def install_test_deps(deps=None): + """Install test dependencies via pip.""" + if deps is None: + deps = TEST_DEPS + deps = set(deps) + if deps: + is_venv = hasattr(sys, 'real_prefix') + opts = "--user" if not is_venv else "" + install_pip() + code = os.system('%s -m pip install %s --upgrade %s' % ( + PYTHON_EXE, opts, " ".join(deps))) + return code + + +def main(): + usage = "%s -m psutil.tests [opts]" % PYTHON_EXE + parser = optparse.OptionParser(usage=usage, description="run unit tests") + parser.add_option("-i", "--install-deps", + action="store_true", default=False, + help="don't print status messages to stdout") + + opts, args = parser.parse_args() + if opts.install_deps: + install_pip() + install_test_deps() + else: + for dep in TEST_DEPS: + try: + __import__(dep.split("==")[0]) + except ImportError: + sys.exit("%r lib is not installed; run %s -m psutil.tests " + "--install-deps" % (dep, PYTHON_EXE)) + run_suite() + + +main() diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/__init__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/__init__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d1d00158e7acd7e18ceec68ff9b622c96a910c17 GIT binary patch literal 30549 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�I26>MqxzJuW*hBNw;^U0BQjq(C6MuDcK*wP~`ZyJ$fs zuVGVejhZM2zJv!p!~qkvHV6Y(RZ-+1q=Mi82nJZDdm2D19^|}Vo=1V=l~*^zx)+QMcKluX4RWLtzh*a!B&irxetlMV7o_XPdp41R*aPcoQCfUN}F zuwvX2b`vLMMEV(PL5akq=V@fT$hQ%2;fDZD!+g8asjgH^Grvi(wv9Atg@EJjftj|( z2Dc4mm7@>PNd;;Tg0nzU?UiRCyoj_w<{13HzgW4ES%rU3d7ELE%0DL17E5!rVe;Yf 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 Xse`GDsqWO?R6Ny1eN6A3nEihMmlRKp literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/__main__.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/__main__.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b7b65aec4b945235d058f8bb0b0e693c341bb83f GIT binary patch literal 2541 zcmZuyO>^7E8Qxti2oQv*Ps?^^l0h?eGHgmY_NjI1d^lDbXEKT+$+e9zgMqk92_gs} zyGvQ*kSDuGr~L;Zk3II*Lw`VLI+Gu;lUq*iPspk7E~SjzDM-Bg{bJweefHV=OG^QQ z=ijG)?|cunpG@Q8@uBh&yt0WAVkkxoGm_&N+mgh@mQL*0lE&1QZtRX$pyuSYffsui zJw`=D5%>Fn=wM`icC@}2eToY5#PrZS7&PLB9d)4|#vw-BIa!)DtzG6Tb3DiKDyzk7 zM<`zB^kjn(=KYymN6haN@ejT}yTa-$U=0=?(K*Jbxbxbqr9P2AzSh(1WAUH!b<0P@ ztYIr`^#zJI*(O_K>o0J8m2I#q&~uGndv115_EGEV_`_gtSVY4jQ<36Q$*t(%IFph2 z7pG;Pv*>ViHwbP-)kqzeMbsWdl^m)p-?Gz#R|e*t7S`TSHC)s|o z4XwHu7Kt2YijQv`D^%1rwe0go*rTqs`E!038b zrHlzKWn4EqHDA7?{Zt%PsgQi!7?j=qy?eK}-rKr;vCy+lUO7-$Pcb!x9 zC-BN2z>Gpj9?H?wB>JBeDGZ7J*Dr}iIhkVRoKQ%W^Ab;qa%Z&(0R5L27%7iYx}=tT9JZr=Se%#1Tq`6NlAa;(}yoO4X9`dw4>>!&7(S&YCb6 z{LYpqHIqcBt;``=@CDEMU7f8lU#(w!YmTSh#M?(-p*{2jos$qjV(U8s*p9{y017#% z$ziXTosBnG`K-vxlx4+HbW=vE1gn3QbOlcpPlm-Q7g;akEa{eo;%CYv_Pjc7W`$H~ zo}0Chs&NPo;NNZ!B^Rv??Len)JRDS|P}@S3LOW9C+E;u~^|GAnwViap*#R_5k&4l$ zrY|`6o@a;frM#5jUAvXY3Z)x=+&)NlAMPfP_P)@xfW_K7PGzc;5GHw=vaG9w;ftma z0n_d?0X)-gFCWTdO-c!ok0fkB7$UTM(S$;*m<70}ovu35wf-|8lGKji--5$brJ8n2 z#{Y)IO_=xdqfhR39zlSz^KqAp&c{{t0OoYQD7$IiF|l+Y?Djb{?cOtaCi=gZoy8%! zDC}A3B*`GniX?%Y=*Ibq1XkaG??_`1COE`R?1K&Q8V+zkD3l@e1lT7&-oWA=nAbJQ zH4lZ?aM|+sPf(eF2=#ptDqyn06JX;M`ox|h%3<0i=RCEafk?G9yn z#C3yl*%eu(va%SHb~bLdf1$U*Ob1exf+tE0`KRNXtSsJ9kv*^xq*e`OGytUrPgY)} zV&zb^99>Jh#-sKa@1?_BX?o1_YE16kTPW2BH$?;@U~ZnGR2Mwq?ET1W^#8>1`mS2b z3sU$HoxK%w_@xbD*IW@o2XKQVFlM$8*a?X__HlT@2@~3aW+v_8T`)RGlFZ6kl4w^} zd8Wj&8El(D%Fm!}4q(d_cT7*s`W50mJG@X8aQnYBq(%iE!Wi+!91S? zpaYxGTLUZZ!<-i0XmNgi8>bjbDo0sHw2$(Er1rWW$_)(10%aTQC%k-^GvM6$pI|zzCfUfW-*l2EKut Lj(;_1`d9u7V`Zh) literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_aix.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_aix.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..196334a3b0b210186f5d0dbbb1f6ffacafd0b44a GIT binary patch literal 3326 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 literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_connections.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_connections.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..8f969354caa876a4fe9d2e060b70a012a5789825 GIT binary patch literal 14817 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 HOWyu(enCmV literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_contracts.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_contracts.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..332752b56372ba80d467236eef0aa4aa5c32b21e GIT binary patch literal 23435 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 literal 0 HcmV?d00001 diff --git a/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_linux.cpython-37.pyc b/WPy32-3720/python-3.7.2/Lib/site-packages/psutil/tests/__pycache__/test_linux.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..547bdb47ad203209eb2df0f44ea0a35fad10dc4d GIT binary patch literal 69172 zcmd_T3xFM0S{_*U{p^QYt=7Y`eJx9tTDGKasV&JGkFB>YTWV?4?bk(~>#MHYt=qbN zyIobS$4!eNmSJpmj0_ADhMi1W0ft91Lx2G?2_%HD1IrMGymqq%n;#QjSn za~MDK|4e9_u9Y=CrpFtxxp+AqV?NPHloN7HmXmT!l~Zy|m(z00lrwV7ma}rqm2+~; zm-BKglnZh!mWy)iDfh^+x7;hozH*-&`^)`uTvJ|yW3sVkZlF9MZAdlN&JC6aC7(uq zU3s14Gsq8>ha{hEte@LZ-XQrL@*B$=C7(xrQ+bo*3&`J7zDM#!9x&KU{t|rq!~uk1X$! zba!pf?bz*Dc|_k_9@XzH@73=s@2d^G9W(xget&sPFX<1wu9Y9vx9AVzxL@C@Z^Q9` z{*b;M$AkI~eHh2b^qu;{I3B7cXFsGrqVIZLyBRA#E@!*-J#zNp+Ro)CY6C@0AGsZW zO4CR6y{~Kf-rCODCvPTD`f%j_K79=L$GrPTBKIHF_v8M4@BY!q{R8?z+&}2uKNh+F zn0^TN4|(^GNA7<}e;oH8_wJvF-2brt1nxiK-9H(;FZqr5)+gm#59>!z7GI#g6<_;Q zur#1?R6m9iXrlv-rz7`|>nCs@ZE)_Nirhb`KZX0K)w%ynK zGKArnoz?4C>SleuIgXRm=~Ls+y@*WyV%0=3qu!jsS>oJF`*4UY^3GJX(Wopot$G7z zg{O~9RE{2*oIG*;2nX~6#s!X0eed7F) z@na`&Ejc$ob(zO=FP&ozsfFvtViTDjqgGw0OkJusbfe~6Xv|mj%G|uZ*r=hzpi#4o z>y?YO>3O48nXc9wsbyECXmZ6HtQB&hJ5Pk zr8*kC?oCar4=~xzM2l+x@nZ`5vRR?OI9 z#c?HZGmf*wa>7c?Ch<$%j^Bt|>E+B){C4aXcm(ccmtxDgrTB9Gwq_Nq;&P9kT+(jG zZzuGWo@RZwV-wm(wDa1FcmwDmGj6ak@AM(DQ&n@SUbmBbAKh=hGsw#ukPP?Qsp+Yv z)i6?0=;C#Jpq(~>shVYHj-0HV8b2{<=O@k{d$w}?sq;t9fGXwzvTIhOe$mcMHResA z!p_y3HLKFJ=Bsw9K0jqO?DTZKQESfIg^5#Vk3Dtj;~jx3(~OkjYji+n7AWWCxRBBzBKO-A}(j`ZgZsjYoK+P^ny8tT(KB zvr>^Z+sWDadUH5s>|&V`lie(stT(~bKE!jAuKUjH7_L2}zV%he)}JY%Co! zp1|EH7U5qOKT3hZgDhk$Q0>jw4FG-_vf%C5jo7tkmSV@Xmyh0vgBs&{;&#l~fL!dh zb|HBqaU*#nbt4Vllhl(sc~WL6W2KgoH)BXslBRFQZesL#b;ApqmDbaG96SrOI0TA( zEv9FH&TQ)==c#*93mT&4sfRZ^SI&D~hYQ-RlGj4abc~aWM8W z5#W0mFb?3_5`Hc#k)~AGYS5_9+X8%q?DHLRHon})P(x3KRJ&jh;Q}%U97$HIU?$*-fF!MIdmT@hMI_|2{rF{LLowrdoKNv0|A=#s zvvNF8Kp@|Q92d6|7G$&K)NM$58*$`E-;DEgW2Qx0pH zt2#|51z=bZL`T}Yjst|C@d~6Ru%`+~leh4I4CNa5g;B=Y6nhB&h&Ku`58`K%j6SY? zJofSUG}Qp{*Rv2gwKwAsKsM`%W?aVrV8v$>5HnIsaXtN3;#QG@$n*I67a)o_qNZZ; zA3Fn?u{6I>Ywj2>IYXatd5msTHM3N=z}Q`uUoAndv#Q|3uZT3+v|f>(Ki@=&s*W1! z(2zQ>sQUnyXq~h>VXklo! zVs8LDH{(W$W7-=cF(a2!xmTa|^UeM@K)BPfrPyaNGJYE{Co*+x9LORR?L4MZlt7#K z6fz$>UZ1zK6EcxHb=J-tr6_&sEQyXIhMlY$GZ3vWU*!>3GtQUWS@%oq+`LhrsSt*$ zuc{G&=a}D2UH%*VqFy8jk-9S%9Qt*|9mr zauce66xCT&K5I=|qrU_9Owneg`in`B?m*0F;M!jR@s_(0uTiaIa$I_)c5UjFt~4p6 zdv|oX1>fb+W$zo>Yq74>=7O+7z`eqxiUj17K$8^s1*XCn2v|YH7mzW@o=7R_cDBw3JH1jv zzrIFl=##SneXX4J>x23_=;+qyL;89g2lNg4MjY4boAi5d9Mm`K_u{xtzfZp($05Ch zk>mk;{Up>86W2|vHurqpuokNg2o#W`L(GssIYyv7ghUNfdVCOy2rIT6zpc$CI6^Nc zmts&gP%+FgI5FNTDlrB^4=Suvz5-@B2HI&g(YAZ9sCQOW8Ie8gHB}Qcck4)FZr-#` zyox5tuv=?P+eJ0HRz$3`i>elNrudyl#CBfh?b3puW7CC}lSS~n)|M{cyxV_dIPp#b zPZ?K{yhDc7>Ys18GNl?QJqQsxoF)l`4kBY|H>sqF&Bibq#+MU-Q0zuxNt;bB#g`Hm z6y!YOetJ4FgyH?Iqz|*)HnW8Pm`;G1ru16Fs@jP;b7nXrB9s!$7Vr||RVD@#>WJ*L z5)RR$OkO+8Yk4)Wb8=xU@@i!8&&daKHt{RCtK^kr8gsxr28VR4^}vdN;&ZLR#imhf z)TFHk-XDK^O+Co^Dv%bd^DVCjOrj=KG4pnvgTcU zWKpo|Joh#4JLArGZe0<%&SM|gr&cldy;57%r>0feyZF+Ae5rcu_q`8II3N1piXW<; z`k=nEuim_iFU`88@8Vl~xDoh3bXmQs4d);8(J`aHxSXw6IJ;=;nbVU@P4nI*J2^Nq#1 zW-G}0q?;Qpv}ZV{7~e;bH#Q=HgbWotzcSGOy{>QkH9iwyf(B>e9hrcl8r6tDLm{&t zi54gSQxjO>fh$vwdfI~~d7U>DP_l6+w(hj{2J~ZqDkiU&GsaGVYl?7f9>Q!76C}*^ zF#pptoZMpSlv+*$+8Iolv{~qCmy%Xam*Y}QV4d?|o%iO17iGe0=c-q*$U(lWCcZnm zAi*o<;=wqJcFVl78%FZ}3|TN@d^4Xo!NljtALpru77YBtk$qi5SG4pBfqTu$VV)dN zVijY>_@FyJJ+vaNdsT$c!|8zxM>;AddMLw?xH(SWjK3YbbsTa{au!38o_s5Y^PL#Q zlgnu+FR@H!WtOv;pmX%jna8dCYgmj~#!|`>rsjH@(htxG^ohE?XSr9;-j10Kr(B<& zv-+WiUjtP;OKQt~dcN&Sq3ues?MhGEmEN{1eUU4LrNrz21ygx5&(?;{2194-LT5vv zv-P2~4eAW@d1vX!&xs`1Ki=xuvtZ0m?ZHS+?Lu_{pr<-E_;*AGh#l4Dd~^5^Z|ol( zdvt7cf9dj3nH_Z~%k?2ucJE`4j*RRd>s0oX!;t-&A3ZR3;0|TonnxeqkD>=V)qAEk zcf{>s(q3ucuF)=KPeN|+i|rjjBSuELl%1sd+ATb~e;*dyI=5lsd~K>xt6sd>F- zXQ9q$LOo;Jy;IZ)RJ`+|DGRJX243g07QPe8blvVfA`=D7L`8LO7u3W-rVMrhYll#b za0!vRlWeW2D^+|}l{(e56Bt75%p4Z+sxvj?e_)gSFOU!NJ_Bk$@KTqHaVBcVubOrO z3lMhfYE-UXFD%Uc4z3o@)zMTF1}K_2hKIFeJQj~7bN$c_=4G^@j<6r%XD@UX{=Z(F zyZ>5yR^)c=Z}Zq5Ssqn(!uGxg8O~=L+8owyAZyc#N1MZ1aSY4PU~CwjZpLnn-AG=0 zWGM+X?A9Atry+C1Do%0;DKLV{uo#%9aNb<1wxRKE_O9?1# zKLzC<8DbXeJ(;EK20Xo#xkuBpm_X*h0@F)5E)Y0Ue_qK9Al5-(d1|o%Wl}{rdF2Y| z5!VZ%kh%y-#<(6~EJDyCN1HwP%upA7N5_?S2#Vp1-KWTXw@dEEGOio9nH*ulvCK|X zFPi1NqL$MjlHt4>!WSEj|3=~cq88xoV1U8w_Xg6 zd$)R(@c_rVAZll`=3y%*qh1~(NP$awGUh>ap_qbY=#16FrDiq8`OnH&kZl_aPRF~A z1uh2!V|{FFZ0x|^j(qs*HEtZ0xtSSg#NLAk9(#0eC!T#wcwnID*ul|*qhl+NNB$Ud z;Na-Kj`jY9ja~aO96ffhV|&qwzCL5uC3Kzu$V#P04;*;(U`HI^9W)r4`r(AH5rv!SZ**3RwPb*a6FX-Fy`+ zAynQImb;6zEPpp$*eSni5tQX8?xHKRJVenz7k%aQQ-7tp=)IA#o1z`W*NPhb=e+)@ zM7(^Ye?Gd({u!>->zq{AP~9t{+_xgrVH|H@mYUR|Jh0NU83=P&th_ajYuVWx7b@P0 z-P(_lKEGVR*iOAY=B~3n&WsLbVHn4utH#VVXZ2x(?~jh-{)q19WNe2DA~MgL>@c>I z0KVQG*6HAGcPf=um>;q|f7Ls92L{r0-pcR&%f=AyW_)M+TfIu3(3)>zVSjqQwXr!5 zwc^wz*l2Mb!YJu=Om!_RJAFXBW=%(NfGdf1=G0j={Y+t!3Uk%;iSe^1#wR<<3SA`x zM`5|LaBzPY&f|jNTgZFvLz^7gprE_sk!zsH3*o8W|!B9{5f zNW`F2*?+)d>P;FYZ*c5CumT4Ak2vf=`G26ooeh;O!_r**aB%gNhf1p*V)c54qTgGQL*hXFYfar6(JGBoNs_eVRc ziFmiI8>>e;P9>c39aL7OeVwK>EZ@!+Oat}ewQrFA1B4$mM}le(h$IBWv0 zM;nB1=!)kTjJj332!DX^L!;dh4JGqA==_4SdqSxzrq5It7TSSS+S?V=?IN*!^xm$R zo`8BW+F-?$8lJvrG-P;w@ z<0mI7&(Q+T(_gD^=!)s1^NTQ+3$>q5bk+>xi+az#u9!Z84)pZmOfAxh_I1Uy^oRB*_I1UyJaBGKkMz8K zUHkO0xoQ-o1m3>xn4YV4U`wU3u9)_kUkSZvtShGd2SP6z>)NON2hN*Ud}NPx#kBvx z#G>I7cxTNc!NCU>$ocB6U^g1;ifJ%o2-3j9*#00bjdjJe|GD|1)NB;s#Gdd6C@7235B2J!Fn~R=qDUOJQWHzs zn*P46AM4uNTyjA>>RLY&=oIVPB$LfdN=#m40t2++flii^-PMrK@>>rxku@w?+={Hx z{g1pWYjn=ye2o`onaBcHVy@=c-#S1f{OnCK3F!!t@Au{(@!|nxY)L~3S-^_B%UHd! z*511Z_W1C6J6jRY%u2=1S6pw+ie0Q!Xd=i(KKMy-X+v3wr0J-6YTBR(FBa^^8s=^= z;S!7SjZD6Y$!knrXYwsf-eB^#nEWu4zr*D3GWmN+j=aV!O0$0 z2{7M;8LDq~TF%H>M$d{VC`?ZEJj&$sf?mWiulMM^I2QCiy&uP-z6SQ01NNYg1`2hU zP0;QW@0CBOZu~{VM{uG{S+Fidy9F4j+=yY`6n8B6VGnURJ--t!h&ZD5RBPXP<(oBW zEY@iE9I^l?!5rWU48-BAg*QVX51aQXb9ZE_G~UYl(q=2iyf9Mu-q5zjPSVmJC!doO z9S)uW#0asj0|`?>P`Ok!#U)C-8~%iJD)yj>Jap%+ot*%&yW^v6Gs9zex4A{YbCYJC zGAk4dDX7*wtH#({^sbJ>H`ujb9LFQd)nyJ`D$&~7xe8vBE&$^z+dQ6A>6@mp_`h-P7MNBg5&*TjaHu9Gq7aK#`@tdBD0 zAuB7Ilbn_BXnjPNU|JttbjtNWquUGJNuSc_q8I0=-}Q7ZJX@pAe2s{ob9KCH-L-Qp zAb7ZPz52x!^9 zo$vH<8CjP5F5dkV6Z*gy;RQNag4CNZ@jx@~Vy$kS^e9(Rj~XhhV1QJy3GdKE@fNo3 zh{GoZ17K%{)3G{_-a|CQ;Yexz6{U!dpLFBdtqI+9wpx2)l~!xhU9Hx-T9WzH;^$nt zDXI}bS@5qyW4jt6diFgNkr3Y1no%p6HSsGO86GsK&ow^Jux1ZMm+ zEBF~CcTHc-c^JOX1j`XSA0T~+k~i)ucOx_g1Mih-ELx>UV-Q9CF`wTI9--Za`K8!M z!Xp7Hoquo$hZ{J| zfgaOfT$Gk0yn@wA)RM9&(Pn$GF4eb`w)(*bQH#(~YP|J8SdzfV4y$69d59d*+TyY( z*P3k##%H_5u&rXkcNh|Z*aW!4@fzbF5IPjEWM<-v-EIQ=29jCLP%T`?$9qenBS*{2y- zPSm;PxB(O*{z0IC*lfbQ&q}^Vnb9#56MVL*$Nv!3v6D1#=)}z-?s?#fg5W^`K@BjX z(U{wCihiJYN5(u(NQmqQU!ZKrUV`%F84-e&BhbnfjSu%2Kh8#ek;zXWv5V}c^(nmR z(!8!nO6DW}#6#vB|A-H8reORWlb>heBh$mE@l&|*M-=Y*k;x{CnQXc@)0@fmW!Gl= z<*p~Jqkyba9LCXn9?$qwhvj4q4oA0P;;biRdXTQ63)eEU+2tJk*J6lbgbqjdeYu+t z+=cLfyRgk;j1ak7kh?{_c$0Uqu%bKOY2_a04wj2?XASPSo@u>pcf?Z-lbJrpSFPXi zRa+w^8AEClp1()mEbm+^S5x}E@TgQ=dU(Pj3~5-(F8tFmQh8JB(H;T$({r! zGlgYjxORjYLLA+L%+z6{^zz16C$Rh;w=!1Nk~lrY5WT)3^1+4ra>_UjHd)XaFaZl! z%_5nmdqz7;lxRu`MEVJoaL!O7hZ1i~iF~Mpb0(d#fHkWN`okA?yU9E3xhhOy$c^LiVYjo3->&7qQl0-!*r)Cgt!@~8eyu^p3mU3RMSDN*y8oCi#teu-$ zSgcrem^;}S$Ckp58#Oz_up7{r+VOeQPAzhtZ$K%c880z8!Q==NN_4IT@c6uSs_8m` z`~Ys0^U8Xv0w?!!pP!fMV4(8}CshszUUQx!$DqbQi|1n-V1x;di6PccTbn~Pp_qsF zcj){pc>+vw&(qliAq6mwli*;^n^>=GLDI^hXeH@rK1!Mm|tBJ0Cb zhtqQ7?=zWXA{KByiew1%kqwLTCTT)~)N} z=qBdaT-yqvh!Z&>gssR}FqL3DB_N)TMChWk5U-&IKqn^u7Jf`mSXKM3UEqZD`&Rh6rhx(WGB$bD2VRs3L<&WRYHaYtAWwA9$6)R<+T!Z}Hl9V~@zV zbJB%gPW%#~%z-*tphs-NjRS%D!f+J6;?BgMLZNaNeo?hbT{l$>B+3j?*edHQe;9J3 zP+=Sr_`F8o_ToVez)g!|kFb?pE0RdG77xl9RK$@?SOp@^!tlrm{)o5&YHU}`LY(H~ zxBf`1HX#_QyQ*(Mqn9zCp#D$F0^+d2ir+dUWpi#>;sEeZqqGFB@XipLcO%}5pIBn~ zb2qEVH3rP_dgl+|2}C=WD1PJhKC+>@1;#6^>U?Oz6*7 zXHeR;l|Q6gh}sxLPK74xi-dxbGXR4?WAYl?9iGFHk?76EO^B>86{@AQHA%c3jIZ7sm?5r&+%Mn?q>*VnHr&QVxC17`ndh- z4|$8EgbV+X`TvKBe3#FkI<@sn{8kx?lf79+ap2k_B-w6!s8b!@Kur4djGd_`?nqW3 zsW)S-Z;=5{NDDo#$pt$)VKBZnA~7>?03yMeC+R@>hGvd?j+F7)f-?wXDQ~vO{Iy5$ zWL62f5TrKCkSH#fUde|+7 za&ha(od_7+h@-YoywO@)Xu)n?+^t&R$OxQcrRlu8um}YeC#A+8BZ1R8l`v+23-G@u zGw>k7m4mpVto-RqM9DHkMY1PZWuBCacqs2a^l56&ukhSR4HMMBSz$RlgVocyKa2Lq+ z@9uBATfOGrJs@|Xy!abvvv0qK3l&~?g-I0&=uc-}Mo`j%7_9xS$Iyg%t60AIc}yWu zH@^8Woasebm_mU-Z<3BAeTZT)B3v#S2MZU&Feuy zSWug-7Q^DjJY`oJYH?+rOJP_H+p$`pdOe39;q{!iak5g+AxlR;NjQ;FE$s!zjiBjb6w@GR?jx$rEfyj=W#HJO^H6XRKBDdCSW|!{iD^ofHnmpcFbWwejwhmOPFiwi}(r#*%&h>Tf zs{i7>b=Ccmu8MtvoWU;ARsBxr=Y%yB)s)0>m3t%XD(5hS-I2Gb`5V>+Y2>rwaM{zP zvmeIidc)-g%ds-M8AtfBt=^FN2tS27*Dk{&EHK)KM`H|Ccda1#IP~hj1K0J`ONA^#MO4Zk<}Lb0J`!!Ty6Epo1zha zA|4$_rVGAzc=#R((LsMlkqFZM>T!+{x&xwDiQc_Y^!CPAB`F9)a&>3tCFHWbmdn8Y z4n5+e>neSH@d1;gZZgC}R!9o(MoAmk<`Q77C5xDC7Qv~&tKy1RZAqzXqU9NTFN8Xd z5L!Qu%6&r<6?E?>d2Is|vN3;-V!X@K|AmRogbN?W|IXz9VDj&o{4SHEbEH|4VrWHUo4ESC=q z-8-~?XhS|`@QEq>yuT!Jhw+nuSa-BnQ8p}4*oaL?MyHW^#vTX(bb^7(y6cC4CV$=H zA)NT@7Jd|CWwI?xa0!3;tzV*|UqkFl?B>DX@%29fWH6XsM>U`+uD=J&7^pWkp=-6S z!RTB)Aa>E{1fm|ZSbUL57_9ahMR9@WPLa6MD9Tj@%<2MBTcISAFLsu+0}qAR0fp0J z_yvMDyM|dRaC65`MsWHjqprantn0@bS&~PdiGdf~@$35J>->7pM!qc&mpS}x{v+ID zW#!Jmc#%edi4R-J3Eg4^K|9IUlKMcmX@gg$aN_+DUWf5BiBy*^MTv+A;EwwRY^nn8 z7in5k>6sd0bG{XqJQhc=;1SpTsNQ*HDFr8teo*cjdyP-I<2CE*ym8q>8k?5EPmsnb z&NW?`43SEq3YxqC(;=+0J+lRi2Xz07UB5J3G| zS-h|_&Q@5mb5LNA0@7+G1OqrK^@*8 zenHiS13c9SqEClF>S@L=qPA-nLLfb@KzhC3f~(Dv>^#JN5!G-Rj@*WPSL|_9iC2aC8$f1 ztC;`lxwfkrT+QQZAygKzBlKe1)f}$&;3}fE2I|e@YG2#c0uK*g_xJP5 zXCv1E7{ptQ>3Q#ZAymE?x$c(l@vg%RJ5Yb0cfCJ!ea+)AFaiS^h*167^Dklx7VZUT zh6x|h`_*Nv1x;OPt(|Ny=NB=d18VhQIGQ*7YHS8vsW-(20E$`MT(nyKx-m~*eeY$6 zH;OCJ!e)46kq6PF9Zw!|USC32EImB@r0iShKb4nr)wT!Gw$(nsmZCSZ??(G5w#tRU zql*2;&I$2>Tv7E=>7H4aUo5g$-iMnSR8tfv**Aw^vZ4OD=Rw=H_Fg)#?B%dqfv>i3 zUod%cI9{fL8!fWauwX@GRs(z7f+*2+N3bzyc3`ZRs~D6FhA%a+ajs^3FWZf6b2Z~0 zCYS(gt{rEea2NmG4liRd3JLNOzv4ihk?I_k0`}Jh$7|N-4eaWR^=tP7fEl&(nF~b$ z;GjqtkrtQ)=57KrUR=XqdCCii!Egpv__YGjrB?!Os}x-|ReN9VhHRxgl=*}$^A5A`5KB%p}F!WA_{WH@H5XNxxN#F7S}MrHfGT&Wl4ymKW6LThS-FN zi;vW!3m?^H)8M3s-Jy$o)S{pw=4GC2I~;E%4jmd*cDX6Gc|R9vF2m{;2Ax~*T084( z;<+DNadH>WiOKUPxQ!=<@nelzwYj(eOFV4ji5-d%mQ|O2iAVwqd{)Q-gJ9Fy{LUGv z$~{gLc=hf6?w<<=F%=!Rwt09BR3%Wu=CV#rHU0BMw2Wm*j%0L$>4(xN81JYJkt@~b zjc;)@$rB&;|0_BGq$WUo}w zzDGw8s3uU4b#(8G2QTe^?C3}CuAZ?mgb)eTGxhZKgCj2;JlkH2^HFzqXsZU>9|Cab zEDr*7FnDQ@UOvI(EheNo1H0X7tFzO%rz2%4Qv9dh#TMFwhf-D@Sv<(aryL&S%A>sCc$8yW zBOc{Fjz@W~zD6HF`96KEK8Rz#zD^&)agDwnBEbf`&!6lZubY?6a)$Ebm1(oJiPl*v zk1gA1*3xb?n?=((13t#@_#Px`GKP&uKS5rodL3p$OAw)8LJQFxOMl>v*idE`fvB+? zrEEb8k2CI3L@83#ry8m<*dqk;QbI8$J)aw#(%9}=S?DV1AFd!>fFQn>1t zdUeQ=_X5@-Y&Kc=1e@JLLZ+d%DOB$BFw++^N!kQJzC)wII-DFQbrh4aA8(S|Y6d<6 zf;1*_=k@fBB+U4^gDMQ{B!!(pLW{!`Pu%O&R-2h=ZikCC%|3m)wCh}H*U{2wY0EZq zi?X8xy=d>SmDpkq_GY5Tg+4>Xmq}a}J4!pTFt2tJ#O(Wzc~#~XPcwIl&n94nAK5oD zK)5n8$MxxdNs=8vd3wgGMVJlH<|nZsY3opgLezXt2eH6Bz_9AFacTwIdR7)0tlbxA z^l6Nnu<>j(>KX>eR=*l!KfKL+q@+*d0QI37h$5BQdAT6fmGg7-MUYMBls%sK-F-hl z@Gugr)x+jU_Fi(`^~L}>nlc#JrB&)M_TkDMfS`=RA`S7s>Q_7frLqOC;}5``ZU9qW z7^epUe;;QTx&wf`p^H>Vb-8q&UqyygDDHW1;8czxAtw>Ih`>SQ+_mrHoI}(N{i0yN z;0CH2Ij6lkqKtL9L;w$@CGIe8fnnT)=mCn%!Gx3(GMSNb=x z{!$v`tTdt^xbY+7vmibz4^yf(a?!ymD@Df$3Q}0VYxIK%A`M#qz+?&hZ;x2_a0aJD z@m5L*3sW0^d`=RVnX?loWVdDyalW*nbYeMgmqdTD%PyQdfA$z+o}D`~`LwGoy^IgH z<5O)e8l90tI-fQDAI+Tp2@{%KfDS z2oCvJ334$)GLG(TJrM2fbwrUtR9TEb74&a7^wD$UYk(LhZzXoRvp5kOa^>P1ZkM-`WW)OV{qaYWh(*jwAcUtOUmBvQZ@;j zWIfuMus?9BHl8MtpJMX8Ad1dZZ9K#KBxK`R=1wy?!vv~cbQ>n;m~evw<2;iICX+~3 zBDqIo{??u3_E)AC;WeR#p8GwzgMuKAfvXGMJ>Fd!?MQc_mwf$*&%%~D0rm%>DsTq2 z8o3{3twBcH6Joo5#ALGMK6TG$rhZP?Dg>@Jwz}RWzR@u8eNe;(Dp)09`7|ZuB$On? zCL|`*wJO5eb4S8zFi0r)ucEDe9&M$=v_+0K;Dx_yJ$cu(6@E`=@>&LbB1$Pl19z2D zVx-%^c?x578e@3|OEL5}h2+jh3UD&I?gf3|s?kG!zF0sfUbO}d6IwvZ+ zg!gl-i)1G%DXMxxDp+)Jr&h$xfB|jd)<}nXLG7-wIn_8KjS5@zDb>&Yf0AZFMlW() zrLgLujNFxz08v#@JXK-tp*V_<8!xdqXO0kY{q-tO8)>g;6N=|ZWvow&wI)`_?l4=5 zkgBiZX{(>kMVv1x4$ch_v6}ey$R3M^N1E(!bgp{W8CN zD;|mVulo{N5p|Q&EQ8V_-JoxdMKUkQ|Ow3?M%VRxdFof`h}-9 z4Q=iQ^(gk}gX1+)C{8I{NFN9&HA9rrj~6-{BEX;(PHhQL49p&)(!t3|mwrTfD5T@j zkC?07Al%ZZjt-^CSkSLwB`ySI&vamMQ~Bm_N=6cI-4~s`xs!g!(-h6CPGh?Kfc(`;2P2w$zrhqaw2xPZiZ}5}I3xTNw@wAc( zwo?V;2-*DOeD4>T`~;JYOnwrHok3JGIB*)uY;zs2e~2wV%H$~~&oOzP$qP)%OfE2a znaM|)_#MgbO?zNVbY1WBc3|xo?qjk#;-R&>oa`TIsjTe+P5c(DHgEr@HVL+d#kuVRR7z z&lx=j#*ODlfuBXv+5``YQmKSB{pi2E+{2`&?M`V#-5c$E&m%{YA%FMdC&s?`81yW- zJPrkI{G%5B!*KjpdhXUnqc%%Bjpj_LI)!LuW(k2ZWlKt!Z5&0lk>IH4VImQ}!dq1& z7mqrCZ{8q0 zv;zu1OQdr=!T1@c?QT9c7*8VZKoN2e7L=e75zPoDpV;*}PJf9(L<{N1&c{Ouw>&*F z2k|c%+X0tmxa&O-=E)u2>vacma!)>b1V9VU7`e6yu6z)@+F4e@Trdrz9V{mKL6pH+ zll0o>5i1#vd5_Npyc*$G?9}+vZjIpgtg#iYQ8qtAja<8TYZMO2S*wJbK&NFuZ^+-F zbL`38cAjz6e<*Ji@JvcLRiKu@Rkth*Rk7KlR|aRj>dgNtkqQxVDHsIj+rYF!f1UW4 z^p-ZA3`(|fwXP-GcwFa_ZYOVbX;-Iy8)`mIRJ&GLvI{SW)+tPfTnK+J9qzJ;ut=xV z?8W{v?hH@sOfE5Dr&fZ@FChnuC$nZi)-`#V3x)*xi1Wd=p&t>@b}RgcNrWu6WkEs zA$K91k$dzcbgu}2Cw-qBW^Xv+k@IYNRnIm%KFc5u-QKIVWaN8)IQ*<|jof&9{4KGN zAOV}hX*)Mlug)!0=Nt2_6g-Re>}|yljj+Rf)A~#Q`pBfLoML?W8c_m_AS^7l%BnUl z%_E8|=IFTOK9@W+vb*icP!T&ZJwG3*+hDD*m+)teGRJ3^EW?fmjkJ?|+3H9^xl_nv z4jJT025M!Kid7nF4~mLaa&h-sYg3psf>m@Ti!Y#s?)0MdZA+M9R2W$U3LB_*Tz0O` z99BQ;oN*rK2>^-gCGo}{{A7~BZiu~x(Hg67xnGIH zj-5qv++)*@$h5}b#~C^k;esN|`0~%IL_38b)g8r(^8prK%S7yBddBA`u+i%|*g-%( zwKGme#SKjvbBG%1bl!4OLWo9sZ@)#KPDkFP<;Q)**k-(wswY}gIIGZV#Rlmhu-4ib z##i8Z4_&B-dpW6TZ37ugLpVgo#ww<@#vQvSTKlmdBdp$Ria{V49tA@BLAY#T)Q9{5 z`zT(K(0U?$P$pPn$vh&RITjDF-6~Kraexg)?OD7N)~4%mU_fSAI4K}60(f@Dx`T;B*794+BJ7(Fj1v_Ek;rN0wy!VBC zTTP^~5B6fMvj5YVRozkfA|gKWd?vB_?ZIl#aj+ zVTOqEDHx9_!40{{kbrrOqlw&xxXUmyT{M+_qhm8H6!_OjSzpCV?DR~{!iOufDvksz z4FXDeriYX8G1MiL~ix62oPu_=|95cfDH#J!FQai6|k z-vD(}zrGQw$W4yNZ>?#<6X>XFcR5*|TBx@+F)ghee;2UuRZqup;;Wv}pTruMo>!FR z5t$v9wzr{^fCfFqjV@+0bhwyBXj1525bTIdRYpBn*JkA9yDl2Pfl8$(z8l-7sLgQ_ zR>4UF0m~;*(#{yQg+_I%COy^egZB_Wtm0rqRu?%B6xSKo$?qvVSkCi>PWZ`1zSGA) zQEwL&pHp+j=SYsC%Y@K&A39>|e)6-45E#{D+z}_e&Pas