psutil
/
setup.py
569 строк · 17.7 Кб
1#!/usr/bin/env python3
2
3# Copyright (c) 2009 Giampaolo Rodola'. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7"""Cross-platform lib for process and system monitoring in Python."""
8
9from __future__ import print_function10
11import ast12import contextlib13import glob14import io15import os16import platform17import re18import shutil19import struct20import subprocess21import sys22import sysconfig23import tempfile24import warnings25
26
27with warnings.catch_warnings():28warnings.simplefilter("ignore")29try:30import setuptools31from setuptools import Extension32from setuptools import setup33except ImportError:34setuptools = None35from distutils.core import Extension36from distutils.core import setup37try:38from wheel.bdist_wheel import bdist_wheel39except ImportError:40if "CIBUILDWHEEL" in os.environ:41raise42bdist_wheel = None43
44HERE = os.path.abspath(os.path.dirname(__file__))45
46# ...so we can import _common.py and _compat.py
47sys.path.insert(0, os.path.join(HERE, "psutil"))48
49from _common import AIX # NOQA50from _common import BSD # NOQA51from _common import FREEBSD # NOQA52from _common import LINUX # NOQA53from _common import MACOS # NOQA54from _common import NETBSD # NOQA55from _common import OPENBSD # NOQA56from _common import POSIX # NOQA57from _common import SUNOS # NOQA58from _common import WINDOWS # NOQA59from _common import hilite # NOQA60from _compat import PY3 # NOQA61from _compat import which # NOQA62
63
64PYPY = '__pypy__' in sys.builtin_module_names65PY36_PLUS = sys.version_info[:2] >= (3, 6)66PY37_PLUS = sys.version_info[:2] >= (3, 7)67CP36_PLUS = PY36_PLUS and sys.implementation.name == "cpython"68CP37_PLUS = PY37_PLUS and sys.implementation.name == "cpython"69Py_GIL_DISABLED = sysconfig.get_config_var("Py_GIL_DISABLED")70
71macros = []72if POSIX:73macros.append(("PSUTIL_POSIX", 1))74if BSD:75macros.append(("PSUTIL_BSD", 1))76
77# Needed to determine _Py_PARSE_PID in case it's missing (Python 2, PyPy).
78# Taken from Lib/test/test_fcntl.py.
79# XXX: not bullet proof as the (long long) case is missing.
80if struct.calcsize('l') <= 8:81macros.append(('PSUTIL_SIZEOF_PID_T', '4')) # int82else:83macros.append(('PSUTIL_SIZEOF_PID_T', '8')) # long84
85
86sources = ['psutil/_psutil_common.c']87if POSIX:88sources.append('psutil/_psutil_posix.c')89
90
91extras_require = {92"test": [93"enum34; python_version <= '3.4'",94"ipaddress; python_version < '3.0'",95"mock; python_version < '3.0'",96]97}
98if not PYPY:99extras_require['test'].extend(100["pywin32; sys.platform == 'win32'", "wmi; sys.platform == 'win32'"]101)102
103
104def get_version():105INIT = os.path.join(HERE, 'psutil/__init__.py')106with open(INIT) as f:107for line in f:108if line.startswith('__version__'):109ret = ast.literal_eval(line.strip().split(' = ')[1])110assert ret.count('.') == 2, ret111for num in ret.split('.'):112assert num.isdigit(), ret113return ret114msg = "couldn't find version string"115raise ValueError(msg)116
117
118VERSION = get_version()119macros.append(('PSUTIL_VERSION', int(VERSION.replace('.', ''))))120
121# Py_LIMITED_API lets us create a single wheel which works with multiple
122# python versions, including unreleased ones.
123if bdist_wheel and CP36_PLUS and (MACOS or LINUX) and not Py_GIL_DISABLED:124py_limited_api = {"py_limited_api": True}125macros.append(('Py_LIMITED_API', '0x03060000'))126elif bdist_wheel and CP37_PLUS and WINDOWS and not Py_GIL_DISABLED:127# PyErr_SetFromWindowsErr / PyErr_SetFromWindowsErrWithFilename are128# part of the stable API/ABI starting with CPython 3.7129py_limited_api = {"py_limited_api": True}130macros.append(('Py_LIMITED_API', '0x03070000'))131else:132py_limited_api = {}133
134
135def get_long_description():136script = os.path.join(HERE, "scripts", "internal", "convert_readme.py")137readme = os.path.join(HERE, 'README.rst')138p = subprocess.Popen(139[sys.executable, script, readme],140stdout=subprocess.PIPE,141stderr=subprocess.PIPE,142universal_newlines=True,143)144stdout, stderr = p.communicate()145if p.returncode != 0:146raise RuntimeError(stderr)147return stdout148
149
150@contextlib.contextmanager151def silenced_output(stream_name):152class DummyFile(io.BytesIO):153# see: https://github.com/giampaolo/psutil/issues/678154errors = "ignore"155
156def write(self, s):157pass158
159orig = getattr(sys, stream_name)160try:161setattr(sys, stream_name, DummyFile())162yield163finally:164setattr(sys, stream_name, orig)165
166
167def missdeps(cmdline):168s = "psutil could not be installed from sources"169if not SUNOS and not which("gcc"):170s += " because gcc is not installed. "171else:172s += ". Perhaps Python header files are not installed. "173s += "Try running:\n"174s += " %s" % cmdline175print(hilite(s, color="red", bold=True), file=sys.stderr)176
177
178def unix_can_compile(c_code):179from distutils.errors import CompileError180from distutils.unixccompiler import UnixCCompiler181
182with tempfile.NamedTemporaryFile(183suffix='.c', delete=False, mode="wt"184) as f:185f.write(c_code)186
187tempdir = tempfile.mkdtemp()188try:189compiler = UnixCCompiler()190# https://github.com/giampaolo/psutil/pull/1568191if os.getenv('CC'):192compiler.set_executable('compiler_so', os.getenv('CC'))193with silenced_output('stderr'):194with silenced_output('stdout'):195compiler.compile([f.name], output_dir=tempdir)196except CompileError:197return False198else:199return True200finally:201os.remove(f.name)202shutil.rmtree(tempdir)203
204
205if WINDOWS:206
207def get_winver():208maj, min = sys.getwindowsversion()[0:2]209return '0x0%s' % ((maj * 100) + min)210
211if sys.getwindowsversion()[0] < 6:212msg = "this Windows version is too old (< Windows Vista); "213msg += "psutil 3.4.2 is the latest version which supports Windows "214msg += "2000, XP and 2003 server"215raise RuntimeError(msg)216
217macros.append(("PSUTIL_WINDOWS", 1))218macros.extend([219# be nice to mingw, see:220# http://www.mingw.org/wiki/Use_more_recent_defined_functions221('_WIN32_WINNT', get_winver()),222('_AVAIL_WINVER_', get_winver()),223('_CRT_SECURE_NO_WARNINGS', None),224# see: https://github.com/giampaolo/psutil/issues/348225('PSAPI_VERSION', 1),226])227
228ext = Extension(229'psutil._psutil_windows',230sources=(231sources
232+ ["psutil/_psutil_windows.c"]233+ glob.glob("psutil/arch/windows/*.c")234),235define_macros=macros,236libraries=[237"psapi",238"kernel32",239"advapi32",240"shell32",241"netapi32",242"ws2_32",243"PowrProf",244"pdh",245],246# extra_compile_args=["/W 4"],247# extra_link_args=["/DEBUG"],248# fmt: off249# python 2.7 compatibility requires no comma250**py_limited_api251# fmt: on252)253
254elif MACOS:255macros.append(("PSUTIL_OSX", 1))256ext = Extension(257'psutil._psutil_osx',258sources=(259sources
260+ ["psutil/_psutil_osx.c"]261+ glob.glob("psutil/arch/osx/*.c")262),263define_macros=macros,264extra_link_args=[265'-framework',266'CoreFoundation',267'-framework',268'IOKit',269],270# fmt: off271# python 2.7 compatibility requires no comma272**py_limited_api273# fmt: on274)275
276elif FREEBSD:277macros.append(("PSUTIL_FREEBSD", 1))278ext = Extension(279'psutil._psutil_bsd',280sources=(281sources
282+ ["psutil/_psutil_bsd.c"]283+ glob.glob("psutil/arch/bsd/*.c")284+ glob.glob("psutil/arch/freebsd/*.c")285),286define_macros=macros,287libraries=["devstat"],288# fmt: off289# python 2.7 compatibility requires no comma290**py_limited_api291# fmt: on292)293
294elif OPENBSD:295macros.append(("PSUTIL_OPENBSD", 1))296ext = Extension(297'psutil._psutil_bsd',298sources=(299sources
300+ ["psutil/_psutil_bsd.c"]301+ glob.glob("psutil/arch/bsd/*.c")302+ glob.glob("psutil/arch/openbsd/*.c")303),304define_macros=macros,305libraries=["kvm"],306# fmt: off307# python 2.7 compatibility requires no comma308**py_limited_api309# fmt: on310)311
312elif NETBSD:313macros.append(("PSUTIL_NETBSD", 1))314ext = Extension(315'psutil._psutil_bsd',316sources=(317sources
318+ ["psutil/_psutil_bsd.c"]319+ glob.glob("psutil/arch/bsd/*.c")320+ glob.glob("psutil/arch/netbsd/*.c")321),322define_macros=macros,323libraries=["kvm"],324# fmt: off325# python 2.7 compatibility requires no comma326**py_limited_api327# fmt: on328)329
330elif LINUX:331# see: https://github.com/giampaolo/psutil/issues/659332if not unix_can_compile("#include <linux/ethtool.h>"):333macros.append(("PSUTIL_ETHTOOL_MISSING_TYPES", 1))334
335macros.append(("PSUTIL_LINUX", 1))336ext = Extension(337'psutil._psutil_linux',338sources=(339sources
340+ ["psutil/_psutil_linux.c"]341+ glob.glob("psutil/arch/linux/*.c")342),343define_macros=macros,344# fmt: off345# python 2.7 compatibility requires no comma346**py_limited_api347# fmt: on348)349
350elif SUNOS:351macros.append(("PSUTIL_SUNOS", 1))352ext = Extension(353'psutil._psutil_sunos',354sources=sources355+ [356'psutil/_psutil_sunos.c',357'psutil/arch/solaris/v10/ifaddrs.c',358'psutil/arch/solaris/environ.c',359],360define_macros=macros,361libraries=['kstat', 'nsl', 'socket'],362# fmt: off363# python 2.7 compatibility requires no comma364**py_limited_api365# fmt: on366)367
368elif AIX:369macros.append(("PSUTIL_AIX", 1))370ext = Extension(371'psutil._psutil_aix',372sources=sources373+ [374'psutil/_psutil_aix.c',375'psutil/arch/aix/net_connections.c',376'psutil/arch/aix/common.c',377'psutil/arch/aix/ifaddrs.c',378],379libraries=['perfstat'],380define_macros=macros,381# fmt: off382# python 2.7 compatibility requires no comma383**py_limited_api384# fmt: on385)386
387else:388sys.exit('platform %s is not supported' % sys.platform)389
390
391if POSIX:392posix_extension = Extension(393'psutil._psutil_posix',394define_macros=macros,395sources=sources,396# fmt: off397# python 2.7 compatibility requires no comma398**py_limited_api399# fmt: on400)401if SUNOS:402
403def get_sunos_update():404# See https://serverfault.com/q/524883405# for an explanation of Solaris /etc/release406with open('/etc/release') as f:407update = re.search(r'(?<=s10s_u)[0-9]{1,2}', f.readline())408return int(update.group(0)) if update else 0409
410posix_extension.libraries.append('socket')411if platform.release() == '5.10':412# Detect Solaris 5.10, update >= 4, see:413# https://github.com/giampaolo/psutil/pull/1638414if get_sunos_update() >= 4:415# MIB compliance starts with SunOS 5.10 Update 4:416posix_extension.define_macros.append(('NEW_MIB_COMPLIANT', 1))417posix_extension.sources.append('psutil/arch/solaris/v10/ifaddrs.c')418posix_extension.define_macros.append(('PSUTIL_SUNOS10', 1))419else:420# Other releases are by default considered to be new mib compliant.421posix_extension.define_macros.append(('NEW_MIB_COMPLIANT', 1))422elif AIX:423posix_extension.sources.append('psutil/arch/aix/ifaddrs.c')424
425extensions = [ext, posix_extension]426else:427extensions = [ext]428
429cmdclass = {}430if py_limited_api:431
432class bdist_wheel_abi3(bdist_wheel):433def get_tag(self):434python, _abi, plat = bdist_wheel.get_tag(self)435return python, "abi3", plat436
437cmdclass["bdist_wheel"] = bdist_wheel_abi3438
439
440def main():441kwargs = dict(442name='psutil',443version=VERSION,444cmdclass=cmdclass,445description=__doc__.replace('\n', ' ').strip() if __doc__ else '',446long_description=get_long_description(),447long_description_content_type='text/x-rst',448# fmt: off449keywords=[450'ps', 'top', 'kill', 'free', 'lsof', 'netstat', 'nice', 'tty',451'ionice', 'uptime', 'taskmgr', 'process', 'df', 'iotop', 'iostat',452'ifconfig', 'taskset', 'who', 'pidof', 'pmap', 'smem', 'pstree',453'monitoring', 'ulimit', 'prlimit', 'smem', 'performance',454'metrics', 'agent', 'observability',455],456# fmt: on457author='Giampaolo Rodola',458author_email='g.rodola@gmail.com',459url='https://github.com/giampaolo/psutil',460platforms='Platform Independent',461license='BSD-3-Clause',462packages=['psutil', 'psutil.tests'],463ext_modules=extensions,464classifiers=[465'Development Status :: 5 - Production/Stable',466'Environment :: Console',467'Environment :: Win32 (MS Windows)',468'Intended Audience :: Developers',469'Intended Audience :: Information Technology',470'Intended Audience :: System Administrators',471'License :: OSI Approved :: BSD License',472'Operating System :: MacOS :: MacOS X',473'Operating System :: Microsoft :: Windows :: Windows 10',474'Operating System :: Microsoft :: Windows :: Windows 7',475'Operating System :: Microsoft :: Windows :: Windows 8',476'Operating System :: Microsoft :: Windows :: Windows 8.1',477'Operating System :: Microsoft :: Windows :: Windows Server 2003',478'Operating System :: Microsoft :: Windows :: Windows Server 2008',479'Operating System :: Microsoft :: Windows :: Windows Vista',480'Operating System :: Microsoft',481'Operating System :: OS Independent',482'Operating System :: POSIX :: AIX',483'Operating System :: POSIX :: BSD :: FreeBSD',484'Operating System :: POSIX :: BSD :: NetBSD',485'Operating System :: POSIX :: BSD :: OpenBSD',486'Operating System :: POSIX :: BSD',487'Operating System :: POSIX :: Linux',488'Operating System :: POSIX :: SunOS/Solaris',489'Operating System :: POSIX',490'Programming Language :: C',491'Programming Language :: Python :: 2',492'Programming Language :: Python :: 2.7',493'Programming Language :: Python :: 3',494'Programming Language :: Python :: Implementation :: CPython',495'Programming Language :: Python :: Implementation :: PyPy',496'Programming Language :: Python',497'Topic :: Software Development :: Libraries :: Python Modules',498'Topic :: Software Development :: Libraries',499'Topic :: System :: Benchmark',500'Topic :: System :: Hardware :: Hardware Drivers',501'Topic :: System :: Hardware',502'Topic :: System :: Monitoring',503'Topic :: System :: Networking :: Monitoring :: Hardware Watchdog',504'Topic :: System :: Networking :: Monitoring',505'Topic :: System :: Networking',506'Topic :: System :: Operating System',507'Topic :: System :: Systems Administration',508'Topic :: Utilities',509],510)511if setuptools is not None:512kwargs.update(513python_requires=(514">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"515),516extras_require=extras_require,517zip_safe=False,518)519success = False520try:521setup(**kwargs)522success = True523finally:524cmd = sys.argv[1] if len(sys.argv) >= 2 else ''525if (526not success527and POSIX528and cmd.startswith(529("build", "install", "sdist", "bdist", "develop")530)531):532py3 = "3" if PY3 else ""533if LINUX:534pyimpl = "pypy" if PYPY else "python"535if which('dpkg'):536missdeps(537"sudo apt-get install gcc %s%s-dev" % (pyimpl, py3)538)539elif which('rpm'):540missdeps("sudo yum install gcc %s%s-devel" % (pyimpl, py3))541elif which('apk'):542missdeps(543"sudo apk add gcc %s%s-dev musl-dev linux-headers"544% (pyimpl, py3)545)546elif MACOS:547msg = (548"XCode (https://developer.apple.com/xcode/)"549" is not installed"550)551print(hilite(msg, color="red"), file=sys.stderr)552elif FREEBSD:553if which('pkg'):554missdeps("pkg install gcc python%s" % py3)555elif which('mport'): # MidnightBSD556missdeps("mport install gcc python%s" % py3)557elif OPENBSD:558missdeps("pkg_add -v gcc python%s" % py3)559elif NETBSD:560missdeps("pkgin install gcc python%s" % py3)561elif SUNOS:562missdeps(563"sudo ln -s /usr/bin/gcc /usr/local/bin/cc && "564"pkg install gcc"565)566
567
568if __name__ == '__main__':569main()570