+License-Expression: Apache-2.0
+Requires-Python: >=3.8
+Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
+Project-URL: Documentation, https://huggingface.co/docs/hub/xet/index
+Project-URL: Homepage, https://github.com/huggingface/xet-core
+Project-URL: Issues, https://github.com/huggingface/xet-core/issues
+Project-URL: Repository, https://github.com/huggingface/xet-core.git
+
+
+
+
+
+
+
+
+
+
🤗 hf-xet - xet client tech, used in huggingface_hub
+
+
+## Welcome
+
+`hf-xet` enables `huggingface_hub` to utilize xet storage for uploading and downloading to HF Hub. Xet storage provides chunk-based deduplication, efficient storage/retrieval with local disk caching, and backwards compatibility with Git LFS. This library is not meant to be used directly, and is instead intended to be used from [huggingface_hub](https://pypi.org/project/huggingface-hub).
+
+## Key features
+
+♻ **chunk-based deduplication implementation**: avoid transferring and storing chunks that are shared across binary files (models, datasets, etc).
+
+🤗 **Python bindings**: bindings for [huggingface_hub](https://github.com/huggingface/huggingface_hub/) package.
+
+↔ **network communications**: concurrent communication to HF Hub Xet backend services (CAS).
+
+🔖 **local disk caching**: chunk-based cache that sits alongside the existing [huggingface_hub disk cache](https://huggingface.co/docs/huggingface_hub/guides/manage-cache).
+
+## Installation
+
+Install the `hf_xet` package with [pip](https://pypi.org/project/hf-xet/):
+
+```bash
+pip install hf_xet
+```
+
+## Quick Start
+
+`hf_xet` is not intended to be run independently as it is expected to be used from `huggingface_hub`, so to get started with `huggingface_hub` check out the documentation [here]("https://hf.co/docs/huggingface_hub").
+
+## Contributions (feature requests, bugs, etc.) are encouraged & appreciated 💙💚💛💜🧡❤️
+
+Please join us in making hf-xet better. We value everyone's contributions. Code is not the only way to help. Answering questions, helping each other, improving documentation, filing issues all help immensely. If you are interested in contributing (please do!), check out the [contribution guide](https://github.com/huggingface/xet-core/blob/main/CONTRIBUTING.md) for this repository.
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/hf_xet-1.3.2.dist-info/RECORD b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/hf_xet-1.3.2.dist-info/RECORD
new file mode 100644
index 0000000000000000000000000000000000000000..3943f0b7838d0a67f488c360d8eaa244896318bb
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/hf_xet-1.3.2.dist-info/RECORD
@@ -0,0 +1,9 @@
+hf_xet-1.3.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+hf_xet-1.3.2.dist-info/METADATA,sha256=VdBkvkyMsWS6C51XipEai-iZGPIt9ydUqE6iReFQdVI,4882
+hf_xet-1.3.2.dist-info/RECORD,,
+hf_xet-1.3.2.dist-info/WHEEL,sha256=ycZRBBQNh-_vBSCR_X0ck7NlL8NDEI7G-tWH-Cjb8uw,143
+hf_xet-1.3.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
+hf_xet-1.3.2.dist-info/sboms/hf_xet.cyclonedx.json,sha256=Z8lgnfjLuQ1OS7SIhJmZNn9qdETBotCqRMS1kgQOnxE,394826
+hf_xet/__init__.py,sha256=E8UDdyQ8glZ_nve9hHEf22bPang8-RKx4VuApXYeQUo,107
+hf_xet/__pycache__/__init__.cpython-312.pyc,,
+hf_xet/hf_xet.abi3.so,sha256=35NZSsDbLEwZbmB-1aRzdjHhZD_MwMLDqP-tmCeN2gE,10594520
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/hf_xet-1.3.2.dist-info/WHEEL b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/hf_xet-1.3.2.dist-info/WHEEL
new file mode 100644
index 0000000000000000000000000000000000000000..e3c7eedd8e94fbe7277127c82058423fa8d80b38
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/hf_xet-1.3.2.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: maturin (1.12.4)
+Root-Is-Purelib: false
+Tag: cp37-abi3-manylinux_2_17_x86_64
+Tag: cp37-abi3-manylinux2014_x86_64
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/INSTALLER b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/INSTALLER
new file mode 100644
index 0000000000000000000000000000000000000000..a1b589e38a32041e49332e5e81c2d363dc418d68
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/LICENSE.md b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/LICENSE.md
new file mode 100644
index 0000000000000000000000000000000000000000..19b6b45242c16a1025465309eec2ca5009319de3
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/LICENSE.md
@@ -0,0 +1,31 @@
+BSD 3-Clause License
+
+Copyright (c) 2013-2024, Kim Davies and contributors.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. 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.
+
+3. Neither the name of the copyright holder 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
+HOLDER 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/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/METADATA b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/METADATA
new file mode 100644
index 0000000000000000000000000000000000000000..c42623e9423c23b555d9d352bc5dab518ede02c2
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/METADATA
@@ -0,0 +1,250 @@
+Metadata-Version: 2.1
+Name: idna
+Version: 3.10
+Summary: Internationalized Domain Names in Applications (IDNA)
+Author-email: Kim Davies
+Requires-Python: >=3.6
+Description-Content-Type: text/x-rst
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: System Administrators
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
+Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Internet :: Name Service (DNS)
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Utilities
+Requires-Dist: ruff >= 0.6.2 ; extra == "all"
+Requires-Dist: mypy >= 1.11.2 ; extra == "all"
+Requires-Dist: pytest >= 8.3.2 ; extra == "all"
+Requires-Dist: flake8 >= 7.1.1 ; extra == "all"
+Project-URL: Changelog, https://github.com/kjd/idna/blob/master/HISTORY.rst
+Project-URL: Issue tracker, https://github.com/kjd/idna/issues
+Project-URL: Source, https://github.com/kjd/idna
+Provides-Extra: all
+
+Internationalized Domain Names in Applications (IDNA)
+=====================================================
+
+Support for the Internationalized Domain Names in
+Applications (IDNA) protocol as specified in `RFC 5891
+`_. This is the latest version of
+the protocol and is sometimes referred to as “IDNA 2008”.
+
+This library also provides support for Unicode Technical
+Standard 46, `Unicode IDNA Compatibility Processing
+`_.
+
+This acts as a suitable replacement for the “encodings.idna”
+module that comes with the Python standard library, but which
+only supports the older superseded IDNA specification (`RFC 3490
+`_).
+
+Basic functions are simply executed:
+
+.. code-block:: pycon
+
+ >>> import idna
+ >>> idna.encode('ドメイン.テスト')
+ b'xn--eckwd4c7c.xn--zckzah'
+ >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah'))
+ ドメイン.テスト
+
+
+Installation
+------------
+
+This package is available for installation from PyPI:
+
+.. code-block:: bash
+
+ $ python3 -m pip install idna
+
+
+Usage
+-----
+
+For typical usage, the ``encode`` and ``decode`` functions will take a
+domain name argument and perform a conversion to A-labels or U-labels
+respectively.
+
+.. code-block:: pycon
+
+ >>> import idna
+ >>> idna.encode('ドメイン.テスト')
+ b'xn--eckwd4c7c.xn--zckzah'
+ >>> print(idna.decode('xn--eckwd4c7c.xn--zckzah'))
+ ドメイン.テスト
+
+You may use the codec encoding and decoding methods using the
+``idna.codec`` module:
+
+.. code-block:: pycon
+
+ >>> import idna.codec
+ >>> print('домен.испытание'.encode('idna2008'))
+ b'xn--d1acufc.xn--80akhbyknj4f'
+ >>> print(b'xn--d1acufc.xn--80akhbyknj4f'.decode('idna2008'))
+ домен.испытание
+
+Conversions can be applied at a per-label basis using the ``ulabel`` or
+``alabel`` functions if necessary:
+
+.. code-block:: pycon
+
+ >>> idna.alabel('测试')
+ b'xn--0zwm56d'
+
+Compatibility Mapping (UTS #46)
++++++++++++++++++++++++++++++++
+
+As described in `RFC 5895 `_, the
+IDNA specification does not normalize input from different potential
+ways a user may input a domain name. This functionality, known as
+a “mapping”, is considered by the specification to be a local
+user-interface issue distinct from IDNA conversion functionality.
+
+This library provides one such mapping that was developed by the
+Unicode Consortium. Known as `Unicode IDNA Compatibility Processing
+`_, it provides for both a regular
+mapping for typical applications, as well as a transitional mapping to
+help migrate from older IDNA 2003 applications. Strings are
+preprocessed according to Section 4.4 “Preprocessing for IDNA2008”
+prior to the IDNA operations.
+
+For example, “Königsgäßchen” is not a permissible label as *LATIN
+CAPITAL LETTER K* is not allowed (nor are capital letters in general).
+UTS 46 will convert this into lower case prior to applying the IDNA
+conversion.
+
+.. code-block:: pycon
+
+ >>> import idna
+ >>> idna.encode('Königsgäßchen')
+ ...
+ idna.core.InvalidCodepoint: Codepoint U+004B at position 1 of 'Königsgäßchen' not allowed
+ >>> idna.encode('Königsgäßchen', uts46=True)
+ b'xn--knigsgchen-b4a3dun'
+ >>> print(idna.decode('xn--knigsgchen-b4a3dun'))
+ königsgäßchen
+
+Transitional processing provides conversions to help transition from
+the older 2003 standard to the current standard. For example, in the
+original IDNA specification, the *LATIN SMALL LETTER SHARP S* (ß) was
+converted into two *LATIN SMALL LETTER S* (ss), whereas in the current
+IDNA specification this conversion is not performed.
+
+.. code-block:: pycon
+
+ >>> idna.encode('Königsgäßchen', uts46=True, transitional=True)
+ 'xn--knigsgsschen-lcb0w'
+
+Implementers should use transitional processing with caution, only in
+rare cases where conversion from legacy labels to current labels must be
+performed (i.e. IDNA implementations that pre-date 2008). For typical
+applications that just need to convert labels, transitional processing
+is unlikely to be beneficial and could produce unexpected incompatible
+results.
+
+``encodings.idna`` Compatibility
+++++++++++++++++++++++++++++++++
+
+Function calls from the Python built-in ``encodings.idna`` module are
+mapped to their IDNA 2008 equivalents using the ``idna.compat`` module.
+Simply substitute the ``import`` clause in your code to refer to the new
+module name.
+
+Exceptions
+----------
+
+All errors raised during the conversion following the specification
+should raise an exception derived from the ``idna.IDNAError`` base
+class.
+
+More specific exceptions that may be generated as ``idna.IDNABidiError``
+when the error reflects an illegal combination of left-to-right and
+right-to-left characters in a label; ``idna.InvalidCodepoint`` when
+a specific codepoint is an illegal character in an IDN label (i.e.
+INVALID); and ``idna.InvalidCodepointContext`` when the codepoint is
+illegal based on its positional context (i.e. it is CONTEXTO or CONTEXTJ
+but the contextual requirements are not satisfied.)
+
+Building and Diagnostics
+------------------------
+
+The IDNA and UTS 46 functionality relies upon pre-calculated lookup
+tables for performance. These tables are derived from computing against
+eligibility criteria in the respective standards. These tables are
+computed using the command-line script ``tools/idna-data``.
+
+This tool will fetch relevant codepoint data from the Unicode repository
+and perform the required calculations to identify eligibility. There are
+three main modes:
+
+* ``idna-data make-libdata``. Generates ``idnadata.py`` and
+ ``uts46data.py``, the pre-calculated lookup tables used for IDNA and
+ UTS 46 conversions. Implementers who wish to track this library against
+ a different Unicode version may use this tool to manually generate a
+ different version of the ``idnadata.py`` and ``uts46data.py`` files.
+
+* ``idna-data make-table``. Generate a table of the IDNA disposition
+ (e.g. PVALID, CONTEXTJ, CONTEXTO) in the format found in Appendix
+ B.1 of RFC 5892 and the pre-computed tables published by `IANA
+ `_.
+
+* ``idna-data U+0061``. Prints debugging output on the various
+ properties associated with an individual Unicode codepoint (in this
+ case, U+0061), that are used to assess the IDNA and UTS 46 status of a
+ codepoint. This is helpful in debugging or analysis.
+
+The tool accepts a number of arguments, described using ``idna-data
+-h``. Most notably, the ``--version`` argument allows the specification
+of the version of Unicode to be used in computing the table data. For
+example, ``idna-data --version 9.0.0 make-libdata`` will generate
+library data against Unicode 9.0.0.
+
+
+Additional Notes
+----------------
+
+* **Packages**. The latest tagged release version is published in the
+ `Python Package Index `_.
+
+* **Version support**. This library supports Python 3.6 and higher.
+ As this library serves as a low-level toolkit for a variety of
+ applications, many of which strive for broad compatibility with older
+ Python versions, there is no rush to remove older interpreter support.
+ Removing support for older versions should be well justified in that the
+ maintenance burden has become too high.
+
+* **Python 2**. Python 2 is supported by version 2.x of this library.
+ Use "idna<3" in your requirements file if you need this library for
+ a Python 2 application. Be advised that these versions are no longer
+ actively developed.
+
+* **Testing**. The library has a test suite based on each rule of the
+ IDNA specification, as well as tests that are provided as part of the
+ Unicode Technical Standard 46, `Unicode IDNA Compatibility Processing
+ `_.
+
+* **Emoji**. It is an occasional request to support emoji domains in
+ this library. Encoding of symbols like emoji is expressly prohibited by
+ the technical standard IDNA 2008 and emoji domains are broadly phased
+ out across the domain industry due to associated security risks. For
+ now, applications that need to support these non-compliant labels
+ may wish to consider trying the encode/decode operation in this library
+ first, and then falling back to using `encodings.idna`. See `the Github
+ project `_ for more discussion.
+
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/RECORD b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/RECORD
new file mode 100644
index 0000000000000000000000000000000000000000..9cfce7f9f4c1a64d85642f865f9d0a3d138a82c6
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/RECORD
@@ -0,0 +1,22 @@
+idna-3.10.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+idna-3.10.dist-info/LICENSE.md,sha256=pZ8LDvNjWHQQmkRhykT_enDVBpboFHZ7-vch1Mmw2w8,1541
+idna-3.10.dist-info/METADATA,sha256=URR5ZyDfQ1PCEGhkYoojqfi2Ra0tau2--lhwG4XSfjI,10158
+idna-3.10.dist-info/RECORD,,
+idna-3.10.dist-info/WHEEL,sha256=EZbGkh7Ie4PoZfRQ8I0ZuP9VklN_TvcZ6DSE5Uar4z4,81
+idna/__init__.py,sha256=MPqNDLZbXqGaNdXxAFhiqFPKEQXju2jNQhCey6-5eJM,868
+idna/__pycache__/__init__.cpython-312.pyc,,
+idna/__pycache__/codec.cpython-312.pyc,,
+idna/__pycache__/compat.cpython-312.pyc,,
+idna/__pycache__/core.cpython-312.pyc,,
+idna/__pycache__/idnadata.cpython-312.pyc,,
+idna/__pycache__/intranges.cpython-312.pyc,,
+idna/__pycache__/package_data.cpython-312.pyc,,
+idna/__pycache__/uts46data.cpython-312.pyc,,
+idna/codec.py,sha256=PEew3ItwzjW4hymbasnty2N2OXvNcgHB-JjrBuxHPYY,3422
+idna/compat.py,sha256=RzLy6QQCdl9784aFhb2EX9EKGCJjg0P3PilGdeXXcx8,316
+idna/core.py,sha256=YJYyAMnwiQEPjVC4-Fqu_p4CJ6yKKuDGmppBNQNQpFs,13239
+idna/idnadata.py,sha256=W30GcIGvtOWYwAjZj4ZjuouUutC6ffgNuyjJy7fZ-lo,78306
+idna/intranges.py,sha256=amUtkdhYcQG8Zr-CoMM_kVRacxkivC1WgxN1b63KKdU,1898
+idna/package_data.py,sha256=q59S3OXsc5VI8j6vSD0sGBMyk6zZ4vWFREE88yCJYKs,21
+idna/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+idna/uts46data.py,sha256=rt90K9J40gUSwppDPCrhjgi5AA6pWM65dEGRSf6rIhM,239289
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/WHEEL b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/WHEEL
new file mode 100644
index 0000000000000000000000000000000000000000..3b5e64b5e6c4a210201d1676a891fd57b15cda99
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/idna-3.10.dist-info/WHEEL
@@ -0,0 +1,4 @@
+Wheel-Version: 1.0
+Generator: flit 3.9.0
+Root-Is-Purelib: true
+Tag: py3-none-any
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/INSTALLER b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/INSTALLER
new file mode 100644
index 0000000000000000000000000000000000000000..a1b589e38a32041e49332e5e81c2d363dc418d68
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/METADATA b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/METADATA
new file mode 100644
index 0000000000000000000000000000000000000000..267439298875d4fb658a6913dc51b48c9026e3ea
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/METADATA
@@ -0,0 +1,45 @@
+Metadata-Version: 2.4
+Name: nvidia-nccl-cu12
+Version: 2.27.5
+Summary: NVIDIA Collective Communication Library (NCCL) Runtime
+Home-page: https://developer.nvidia.com/cuda-zone
+Author: Nvidia CUDA Installer Team
+Author-email: compute_installer@nvidia.com
+License: BSD-3-Clause
+Keywords: cuda,nvidia,runtime,machine learning,deep learning
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Education
+Classifier: Intended Audience :: Science/Research
+Classifier: License :: Other/Proprietary License
+Classifier: Natural Language :: English
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Topic :: Scientific/Engineering
+Classifier: Topic :: Scientific/Engineering :: Mathematics
+Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
+Classifier: Topic :: Software Development
+Classifier: Topic :: Software Development :: Libraries
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: POSIX :: Linux
+Requires-Python: >=3
+License-File: License.txt
+Dynamic: author
+Dynamic: author-email
+Dynamic: classifier
+Dynamic: description
+Dynamic: home-page
+Dynamic: keywords
+Dynamic: license
+Dynamic: license-file
+Dynamic: requires-python
+Dynamic: summary
+
+NCCL (pronounced "Nickel") is a stand-alone library of standard collective communication routines for GPUs, implementing all-reduce, all-gather, reduce, broadcast, and reduce-scatter. It has been optimized to achieve high bandwidth on any platform using PCIe, NVLink, NVswitch, as well as networking using InfiniBand Verbs or TCP/IP sockets.
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/RECORD b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/RECORD
new file mode 100644
index 0000000000000000000000000000000000000000..d5cd7999f23e3c076bf3e6003af961d30e12e933
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/RECORD
@@ -0,0 +1,8 @@
+nvidia/nccl/include/nccl.h,sha256=SyQKH6eYWMqM3_z1wvxArqyos-rsYXKCE3FfCQKro6g,22566
+nvidia/nccl/lib/libnccl.so.2,sha256=HZwQMi76zeaVz2QNsfKfwVhskp8Qh_DhIC0tXnD7cWg,429628328
+nvidia_nccl_cu12-2.27.5.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+nvidia_nccl_cu12-2.27.5.dist-info/METADATA,sha256=8QYX3uAOzTd6A-kQPrzyDDMwXQ30cZGlQEmKtF-Kxn0,2019
+nvidia_nccl_cu12-2.27.5.dist-info/RECORD,,
+nvidia_nccl_cu12-2.27.5.dist-info/WHEEL,sha256=gy6FWQgpujK_dnYc155G2NL32NQjpi5ebTEXjh8SGZQ,144
+nvidia_nccl_cu12-2.27.5.dist-info/licenses/License.txt,sha256=DwF0prTgszrCY3W_cpUzB1sy9MUaW2gCo9dC19zcmnY,1895
+nvidia_nccl_cu12-2.27.5.dist-info/top_level.txt,sha256=fTkAtiFuL16nUrB9ytDDtpytz2t0B4NvYTnRzwAhO14,7
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/WHEEL b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/WHEEL
new file mode 100644
index 0000000000000000000000000000000000000000..29738220b339f398b2cbbc9ac8ccb38a39bdd7b2
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/WHEEL
@@ -0,0 +1,6 @@
+Wheel-Version: 1.0
+Generator: setuptools (80.9.0)
+Root-Is-Purelib: true
+Tag: py3-none-manylinux2014_x86_64
+Tag: py3-none-manylinux_2_17_x86_64
+
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/top_level.txt b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/top_level.txt
new file mode 100644
index 0000000000000000000000000000000000000000..862f7abf232cdfbb928609856247292e81c9decb
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/nvidia_nccl_cu12-2.27.5.dist-info/top_level.txt
@@ -0,0 +1 @@
+nvidia
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..880e1a9ddfc1a95b9388ee4d6c1b06c9d53dd6f1
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/__init__.py
@@ -0,0 +1,2485 @@
+# 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
+
+Supported Python versions are cPython 3.6+ and PyPy.
+"""
+
+import collections
+import contextlib
+import datetime
+import functools
+import os
+import signal
+import socket
+import subprocess
+import sys
+import threading
+import time
+
+try:
+ import pwd
+except ImportError:
+ pwd = None
+
+from . import _common
+from . import _ntuples as _ntp
+from ._common import AIX
+from ._common import BSD
+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 FREEBSD
+from ._common import LINUX
+from ._common import MACOS
+from ._common import NETBSD
+from ._common import NIC_DUPLEX_FULL
+from ._common import NIC_DUPLEX_HALF
+from ._common import NIC_DUPLEX_UNKNOWN
+from ._common import OPENBSD
+from ._common import OSX # deprecated alias
+from ._common import POSIX
+from ._common import POWER_TIME_UNKNOWN
+from ._common import POWER_TIME_UNLIMITED
+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 SUNOS
+from ._common import WINDOWS
+from ._common import AccessDenied
+from ._common import Error
+from ._common import NoSuchProcess
+from ._common import TimeoutExpired
+from ._common import ZombieProcess
+from ._common import debug
+from ._common import memoize_when_activated
+from ._common import wrap_numbers as _wrap_numbers
+
+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: F401
+ from ._pslinux import IOPRIO_CLASS_IDLE # noqa: F401
+ from ._pslinux import IOPRIO_CLASS_NONE # noqa: F401
+ from ._pslinux import IOPRIO_CLASS_RT # noqa: F401
+
+elif WINDOWS:
+ from . import _pswindows as _psplatform
+ from ._psutil_windows import ABOVE_NORMAL_PRIORITY_CLASS # noqa: F401
+ from ._psutil_windows import BELOW_NORMAL_PRIORITY_CLASS # noqa: F401
+ from ._psutil_windows import HIGH_PRIORITY_CLASS # noqa: F401
+ from ._psutil_windows import IDLE_PRIORITY_CLASS # noqa: F401
+ from ._psutil_windows import NORMAL_PRIORITY_CLASS # noqa: F401
+ from ._psutil_windows import REALTIME_PRIORITY_CLASS # noqa: F401
+ from ._pswindows import CONN_DELETE_TCB # noqa: F401
+ from ._pswindows import IOPRIO_HIGH # noqa: F401
+ from ._pswindows import IOPRIO_LOW # noqa: F401
+ from ._pswindows import IOPRIO_NORMAL # noqa: F401
+ from ._pswindows import IOPRIO_VERYLOW # noqa: F401
+
+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: F401
+ from ._pssunos import CONN_IDLE # noqa: F401
+
+ # 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
+ msg = f"platform {sys.platform} is not supported"
+ raise NotImplementedError(msg)
+
+
+# fmt: off
+__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",
+ # "CONN_IDLE", "CONN_BOUND",
+
+ "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",
+
+ # "RLIM_INFINITY", "RLIMIT_AS", "RLIMIT_CORE", "RLIMIT_CPU", "RLIMIT_DATA",
+ # "RLIMIT_FSIZE", "RLIMIT_LOCKS", "RLIMIT_MEMLOCK", "RLIMIT_NOFILE",
+ # "RLIMIT_NPROC", "RLIMIT_RSS", "RLIMIT_STACK", "RLIMIT_MSGQUEUE",
+ # "RLIMIT_NICE", "RLIMIT_RTPRIO", "RLIMIT_RTTIME", "RLIMIT_SIGPENDING",
+
+ # 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", "getloadavg"
+ "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
+]
+# fmt: on
+
+
+__all__.extend(_psplatform.__extra__all__)
+
+# Linux, FreeBSD
+if hasattr(_psplatform.Process, "rlimit"):
+ # Populate global namespace with RLIM* constants.
+ _globals = globals()
+ _name = None
+ for _name in dir(_psplatform.cext):
+ if _name.startswith('RLIM') and _name.isupper():
+ _globals[_name] = getattr(_psplatform.cext, _name)
+ __all__.append(_name)
+ del _globals, _name
+
+AF_LINK = _psplatform.AF_LINK
+
+__author__ = "Giampaolo Rodola'"
+__version__ = "7.2.2"
+version_info = tuple(int(num) for num in __version__.split('.'))
+
+_timer = getattr(time, 'monotonic', time.time)
+_TOTAL_PHYMEM = None
+_LOWEST_PID = None
+_SENTINEL = object()
+
+# 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 = f"version conflict: {_psplatform.cext.__file__!r} C extension "
+ msg += "module was built for another version of psutil"
+ if hasattr(_psplatform.cext, 'version'):
+ v = ".".join(list(str(_psplatform.cext.version)))
+ msg += f" ({v} instead of {__version__})"
+ else:
+ msg += f" (different than {__version__})"
+ what = getattr(
+ _psplatform.cext,
+ "__file__",
+ "the existing psutil install directory",
+ )
+ msg += f"; you may try to 'pip uninstall psutil', manually remove {what}"
+ msg += " or clean the virtual env somehow, then reinstall"
+ raise ImportError(msg)
+
+
+# =====================================================================
+# --- Utils
+# =====================================================================
+
+
+if hasattr(_psplatform, 'ppid_map'):
+ # Faster version (Windows and Linux).
+ _ppid_map = _psplatform.ppid_map
+else: # pragma: no cover
+
+ 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 _pprint_secs(secs):
+ """Format seconds in a human readable form."""
+ now = time.time()
+ secs_ago = int(now - secs)
+ fmt = "%H:%M:%S" if secs_ago < 60 * 60 * 24 else "%Y-%m-%d %H:%M:%S"
+ return datetime.datetime.fromtimestamp(secs).strftime(fmt)
+
+
+def _check_conn_kind(kind):
+ """Check net_connections()'s `kind` parameter."""
+ kinds = tuple(_common.conn_tmap)
+ if kind not in kinds:
+ msg = f"invalid kind argument {kind!r}; valid ones are: {kinds}"
+ raise ValueError(msg)
+
+
+# =====================================================================
+# --- Process class
+# =====================================================================
+
+
+class Process:
+ """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 that
+ the PID of the process being queried has been reused. That means
+ that you may end up retrieving information for another process.
+
+ 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.
+ """
+
+ def __init__(self, pid=None):
+ self._init(pid)
+
+ def _init(self, pid, _ignore_nsp=False):
+ if pid is None:
+ pid = os.getpid()
+ else:
+ if pid < 0:
+ msg = f"pid must be a positive integer (got {pid})"
+ raise ValueError(msg)
+ try:
+ _psplatform.cext.check_pid_range(pid)
+ except OverflowError as err:
+ msg = "process PID out of range"
+ raise NoSuchProcess(pid, msg=msg) from err
+
+ self._pid = pid
+ self._name = None
+ self._exe = None
+ self._create_time = None
+ self._gone = False
+ self._pid_reused = 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
+ self._exitcode = _SENTINEL
+ self._ident = (self.pid, None)
+ try:
+ self._ident = self._get_ident()
+ except AccessDenied:
+ # This should happen on Windows only, since we use the fast
+ # create time method. AFAIK, on all other platforms we are
+ # able to get create time for all PIDs.
+ 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 = "process PID not found"
+ raise NoSuchProcess(pid, msg=msg) from None
+ self._gone = True
+
+ def _get_ident(self):
+ """Return a (pid, uid) tuple which is supposed to identify a
+ Process instance univocally over time. The PID alone is not
+ enough, as it can be assigned to a new process after this one
+ terminates, so we add process creation time to the mix. We need
+ this in order to prevent killing the wrong process later on.
+ This is also known as PID reuse or PID recycling problem.
+
+ The reliability of this strategy mostly depends on
+ create_time() precision, which is 0.01 secs on Linux. The
+ assumption is that, after a process terminates, the kernel
+ won't reuse the same PID after such a short period of time
+ (0.01 secs). Technically this is inherently racy, but
+ practically it should be good enough.
+
+ NOTE: unreliable on FreeBSD and OpenBSD as ctime is subject to
+ system clock updates.
+ """
+
+ if WINDOWS:
+ # Use create_time() fast method in order to speedup
+ # `process_iter()`. This means we'll get AccessDenied for
+ # most ADMIN processes, but that's fine since it means
+ # we'll also get AccessDenied on kill().
+ # https://github.com/giampaolo/psutil/issues/2366#issuecomment-2381646555
+ self._create_time = self._proc.create_time(fast_only=True)
+ return (self.pid, self._create_time)
+ elif LINUX or NETBSD or OSX:
+ # Use 'monotonic' process starttime since boot to form unique
+ # process identity, since it is stable over changes to system
+ # time.
+ return (self.pid, self._proc.create_time(monotonic=True))
+ else:
+ return (self.pid, self.create_time())
+
+ def __str__(self):
+ info = collections.OrderedDict()
+ info["pid"] = self.pid
+ if self._name:
+ info['name'] = self._name
+ with self.oneshot():
+ if self._pid_reused:
+ info["status"] = "terminated + PID reused"
+ else:
+ try:
+ info["name"] = self.name()
+ info["status"] = self.status()
+ except ZombieProcess:
+ info["status"] = "zombie"
+ except NoSuchProcess:
+ info["status"] = "terminated"
+ except AccessDenied:
+ pass
+
+ if self._exitcode not in {_SENTINEL, None}:
+ info["exitcode"] = self._exitcode
+ if self._create_time is not None:
+ info['started'] = _pprint_secs(self._create_time)
+
+ return "{}.{}({})".format(
+ self.__class__.__module__,
+ self.__class__.__name__,
+ ", ".join([f"{k}={v!r}" 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
+ if OPENBSD or NETBSD or SUNOS: # pragma: no cover
+ # Zombie processes on Open/NetBSD/illumos/Solaris have a
+ # creation time of 0.0. This covers the case when a process
+ # started normally (so it has a ctime), then it turned into a
+ # zombie. It's important to do this because is_running()
+ # depends on __eq__.
+ pid1, ident1 = self._ident
+ pid2, ident2 = other._ident
+ if pid1 == pid2:
+ if ident1 and not ident2:
+ try:
+ return self.status() == STATUS_ZOMBIE
+ except Error:
+ pass
+ 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
+
+ def _raise_if_pid_reused(self):
+ """Raises NoSuchProcess in case process PID has been reused."""
+ if self._pid_reused or (not self.is_running() and self._pid_reused):
+ # We may directly raise NSP in here already if PID is just
+ # not running, but I prefer NSP to be raised naturally by
+ # the actual Process API call. This way unit tests will tell
+ # us if the API is broken (aka don't raise NSP when it
+ # should). We also remain consistent with all other "get"
+ # APIs which don't use _raise_if_pid_reused().
+ msg = "process no longer exists and its PID has been reused"
+ raise NoSuchProcess(self.pid, self._name, msg=msg)
+
+ @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)):
+ msg = f"invalid attrs type {type(attrs)}"
+ raise TypeError(msg)
+ attrs = set(attrs)
+ invalid_names = attrs - valid_names
+ if invalid_names:
+ msg = "invalid attr name{} {}".format(
+ "s" if len(invalid_names) > 1 else "",
+ ", ".join(map(repr, invalid_names)),
+ )
+ raise ValueError(msg)
+
+ retdict = {}
+ 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:
+ # Get a fresh (non-cached) ctime in case the system clock
+ # was updated. TODO: use a monotonic ctime on platforms
+ # where it's supported.
+ proc_ctime = Process(self.pid).create_time()
+ try:
+ parent = Process(ppid)
+ if parent.create_time() <= proc_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 it will remove the process from `process_iter()`
+ internal cache and return False.
+ """
+ if self._gone or self._pid_reused:
+ return False
+ try:
+ # Checking if PID is alive is not enough as the PID might
+ # have been reused by another process. Process identity /
+ # uniqueness over time is guaranteed by (PID + creation
+ # time) and that is verified in __eq__.
+ self._pid_reused = self != Process(self.pid)
+ if self._pid_reused:
+ _pids_reused.add(self.pid)
+ raise NoSuchProcess(self.pid)
+ return True
+ 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()?
+ self._raise_if_pid_reused()
+ 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, ZombieProcess):
+ # Just pass and return the truncated name: it's better
+ # than nothing. Note: there are actual cases where a
+ # zombie process can return a name() but not a
+ # cmdline(), see:
+ # https://github.com/giampaolo/psutil/issues/2239
+ 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
+ msg = "requires pwd module shipped with standard python"
+ raise ImportError(msg)
+ 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 (seconds since January 1,
+ 1970, at midnight UTC). The return value, which is cached after
+ first call, is based on the system clock, which means it may be
+ affected by changes such as manual adjustments or time
+ synchronization (e.g. NTP).
+ """
+ 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:
+ self._raise_if_pid_reused()
+ 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
+ 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:
+ msg = "'ioclass' argument must be specified"
+ raise ValueError(msg)
+ return self._proc.ionice_get()
+ else:
+ self._raise_if_pid_reused()
+ return self._proc.ionice_set(ioclass, value)
+
+ # Linux / FreeBSD 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 and FreeBSD only.
+ """
+ if limits is not None:
+ self._raise_if_pid_reused()
+ 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 sorted(set(self._proc.cpu_affinity_get()))
+ else:
+ self._raise_if_pid_reused()
+ 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()
+
+ # All platforms has it, but maybe not in the future.
+ 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()
+
+ 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.
+ """
+ self._raise_if_pid_reused()
+ ppid_map = _ppid_map()
+ # Get a fresh (non-cached) ctime in case the system clock was
+ # updated. TODO: use a monotonic ctime on platforms where it's
+ # supported.
+ proc_ctime = Process(self.pid).create_time()
+ 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 proc_ctime <= 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 = proc_ctime <= 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:
+ msg = f"interval is not positive (got {interval!r})"
+ raise ValueError(msg)
+ 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 platforms are `rss` and `vms`.
+
+ All numbers are expressed in bytes.
+ """
+ return self._proc.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(_ntp.pfullmem._fields)
+ if memtype not in valid_types:
+ msg = (
+ f"invalid memtype {memtype!r}; valid types are"
+ f" {tuple(valid_types)!r}"
+ )
+ raise ValueError(msg)
+ fun = (
+ self.memory_info
+ if memtype in _ntp.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
+ msg = (
+ "can't calculate process memory percent because total physical"
+ f" system memory is not positive ({total_phymem!r})"
+ )
+ raise ValueError(msg)
+ 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] = list(map(lambda x, y: x + y, d[path], nums))
+ except KeyError:
+ d[path] = nums
+ return [_ntp.pmmap_grouped(path, *d[path]) for path in d]
+ else:
+ return [_ntp.pmmap_ext(*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 net_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 |
+ +------------+----------------------------------------------------+
+ """
+ _check_conn_kind(kind)
+ return self._proc.net_connections(kind)
+
+ @_common.deprecated_method(replacement="net_connections")
+ def connections(self, kind="inet"):
+ return self.net_connections(kind=kind)
+
+ # --- signals
+
+ if POSIX:
+
+ def _send_signal(self, sig):
+ assert not self.pid < 0, self.pid
+ self._raise_if_pid_reused()
+
+ pid, ppid, name = self.pid, self._ppid, self._name
+ if pid == 0:
+ # see "man 2 kill"
+ msg = (
+ "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"
+ )
+ raise ValueError(msg)
+ try:
+ os.kill(pid, sig)
+ except ProcessLookupError as err:
+ if OPENBSD and pid_exists(pid):
+ # We do this because os.kill() lies in case of
+ # zombie processes.
+ raise ZombieProcess(pid, name, ppid) from err
+ self._gone = True
+ raise NoSuchProcess(pid, name) from err
+ except PermissionError as err:
+ raise AccessDenied(pid, name) from err
+
+ 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
+ self._raise_if_pid_reused()
+ if sig != signal.SIGTERM and not self.is_running():
+ msg = "process no longer exists"
+ raise NoSuchProcess(self.pid, self._name, msg=msg)
+ self._proc.send_signal(sig)
+
+ def suspend(self):
+ """Suspend process execution with SIGSTOP pre-emptively checking
+ whether PID has been reused.
+ On Windows this has the effect of suspending all process threads.
+ """
+ if POSIX:
+ self._send_signal(signal.SIGSTOP)
+ else: # pragma: no cover
+ self._raise_if_pid_reused()
+ self._proc.suspend()
+
+ 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._raise_if_pid_reused()
+ self._proc.resume()
+
+ 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._raise_if_pid_reused()
+ self._proc.kill()
+
+ 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._raise_if_pid_reused()
+ 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.
+ On Windows there's no such limitation (exit code is always
+ returned).
+
+ 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.
+
+ If *timeout=0* either return immediately or raise
+ TimeoutExpired (non-blocking).
+
+ To wait for multiple Process objects use psutil.wait_procs().
+ """
+ if self.pid == 0:
+ msg = "can't wait for PID 0"
+ raise ValueError(msg)
+ if timeout is not None:
+ if not isinstance(timeout, (int, float)):
+ msg = f"timeout must be an int or float (got {type(timeout)})"
+ raise TypeError(msg)
+ if timeout < 0:
+ msg = f"timeout must be positive or zero (got {timeout})"
+ raise ValueError(msg)
+
+ if self._exitcode is not _SENTINEL:
+ return self._exitcode
+
+ try:
+ self._exitcode = self._proc.wait(timeout)
+ except TimeoutExpired as err:
+ exc = TimeoutExpired(timeout, pid=self.pid, name=self._name)
+ raise exc from err
+
+ return self._exitcode
+
+
+# The valid attr names which can be processed by Process.as_dict().
+# fmt: off
+_as_dict_attrnames = {
+ 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',
+ 'connections', 'oneshot'}
+}
+# fmt: on
+
+
+# =====================================================================
+# --- Popen class
+# =====================================================================
+
+
+class Popen(Process):
+ """Same as subprocess.Popen, but in addition it provides all
+ psutil.Process methods in a single class.
+ For the following methods which are common to both classes, psutil
+ implementation takes precedence:
+
+ * send_signal()
+ * terminate()
+ * kill()
+
+ This is done in order to avoid killing another process in case its
+ PID has been reused, fixing BPO-6973.
+
+ >>> 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', None)
+ >>> p.terminate()
+ >>> p.wait(timeout=2)
+ 0
+ >>>
+ """
+
+ 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:
+ msg = f"{self.__class__!r} has no attribute {name!r}"
+ raise AttributeError(msg) from None
+
+ def wait(self, timeout=None):
+ if self.__subproc.returncode is not None:
+ return self.__subproc.returncode
+ ret = super().wait(timeout)
+ self.__subproc.returncode = ret
+ return ret
+
+
+# =====================================================================
+# --- 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 = {}
+_pids_reused = set()
+
+
+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.
+ Cache can optionally be cleared via `process_iter.cache_clear()`.
+
+ 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).
+ """
+ global _pmap
+
+ def add(pid):
+ proc = Process(pid)
+ pmap[proc.pid] = proc
+ return proc
+
+ def remove(pid):
+ pmap.pop(pid, None)
+
+ pmap = _pmap.copy()
+ a = set(pids())
+ b = set(pmap.keys())
+ new_pids = a - b
+ gone_pids = b - a
+ for pid in gone_pids:
+ remove(pid)
+ while _pids_reused:
+ pid = _pids_reused.pop()
+ debug(f"refreshing Process instance for reused PID {pid}")
+ remove(pid)
+ try:
+ ls = sorted(list(pmap.items()) + list(dict.fromkeys(new_pids).items()))
+ for pid, proc in ls:
+ try:
+ if proc is None: # new process
+ proc = add(pid)
+ if attrs is not None:
+ proc.info = proc.as_dict(attrs=attrs, ad_value=ad_value)
+ yield proc
+ except NoSuchProcess:
+ remove(pid)
+ finally:
+ _pmap = pmap
+
+
+process_iter.cache_clear = lambda: _pmap.clear() # noqa: PLW0108
+process_iter.cache_clear.__doc__ = "Clear process_iter() internal cache."
+
+
+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, subprocess.TimeoutExpired):
+ pass
+ else:
+ if returncode is not None or not proc.is_running():
+ # Set new Process instance attribute.
+ proc.returncode = returncode
+ gone.add(proc)
+ if callback is not None:
+ callback(proc)
+
+ if timeout is not None and not timeout >= 0:
+ msg = f"timeout must be a positive integer, got {timeout}"
+ raise ValueError(msg)
+ if callback is not None and not callable(callback):
+ msg = f"callback {callback!r} is not a callable"
+ raise TypeError(msg)
+
+ gone = set()
+ alive = set(procs)
+ 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 # noqa: PLR6104
+
+ 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 # noqa: PLR6104
+
+ 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()).
+
+ 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_cores()
+ 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 = {threading.current_thread().ident: cpu_times()}
+except Exception: # noqa: BLE001
+ # Don't want to crash at import time.
+ _last_cpu_times = {}
+
+try:
+ _last_per_cpu_times = {
+ threading.current_thread().ident: cpu_times(percpu=True)
+ }
+except Exception: # noqa: BLE001
+ # Don't want to crash at import time.
+ _last_per_cpu_times = {}
+
+
+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 _ntp.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 _ntp.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
+ >>>
+ """
+ tid = threading.current_thread().ident
+ blocking = interval is not None and interval > 0.0
+ if interval is not None and interval < 0:
+ msg = f"interval is not positive (got {interval})"
+ raise ValueError(msg)
+
+ 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.get(tid) or cpu_times()
+ _last_cpu_times[tid] = cpu_times()
+ return calculate(t1, _last_cpu_times[tid])
+ # per-cpu usage
+ else:
+ ret = []
+ if blocking:
+ tot1 = cpu_times(percpu=True)
+ time.sleep(interval)
+ else:
+ tot1 = _last_per_cpu_times.get(tid) or cpu_times(percpu=True)
+ _last_per_cpu_times[tid] = cpu_times(percpu=True)
+ for t1, t2 in zip(tot1, _last_per_cpu_times[tid]):
+ ret.append(calculate(t1, t2))
+ return ret
+
+
+# Use a separate dict for cpu_times_percent(), so it's independent from
+# cpu_percent() and they can both be used within the same program.
+_last_cpu_times_2 = _last_cpu_times.copy()
+_last_per_cpu_times_2 = _last_per_cpu_times.copy()
+
+
+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().
+ """
+ tid = threading.current_thread().ident
+ blocking = interval is not None and interval > 0.0
+ if interval is not None and interval < 0:
+ msg = f"interval is not positive (got {interval!r})"
+ raise ValueError(msg)
+
+ 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 _ntp.scputimes(*nums)
+
+ # system-wide usage
+ if not percpu:
+ if blocking:
+ t1 = cpu_times()
+ time.sleep(interval)
+ else:
+ t1 = _last_cpu_times_2.get(tid) or cpu_times()
+ _last_cpu_times_2[tid] = cpu_times()
+ return calculate(t1, _last_cpu_times_2[tid])
+ # per-cpu usage
+ else:
+ ret = []
+ if blocking:
+ tot1 = cpu_times(percpu=True)
+ time.sleep(interval)
+ else:
+ tot1 = _last_per_cpu_times_2.get(tid) or cpu_times(percpu=True)
+ _last_per_cpu_times_2[tid] = cpu_times(percpu=True)
+ for t1, t2 in zip(tot1, _last_per_cpu_times_2[tid]):
+ 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 namedtuple 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 _ntp.scpufreq(current, min_, max_)
+
+ __all__.append("cpu_freq")
+
+
+if hasattr(os, "getloadavg") or hasattr(_psplatform, "getloadavg"):
+ # Perform this hasattr check once on import time to either use the
+ # platform based code or proxy straight from the os module.
+ if hasattr(os, "getloadavg"):
+ getloadavg = os.getloadavg
+ else:
+ getloadavg = _psplatform.getloadavg
+
+ __all__.append("getloadavg")
+
+
+# =====================================================================
+# --- 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 + 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/partitions 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')
+ if perdisk:
+ for disk, fields in rawdict.items():
+ rawdict[disk] = _ntp.sdiskio(*fields)
+ return rawdict
+ else:
+ return _ntp.sdiskio(*(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.
+ "net_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] = _ntp.snetio(*fields)
+ return rawdict
+ else:
+ return _ntp.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.
+ """
+ _check_conn_kind(kind)
+ 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.
+ """
+ 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:
+ try:
+ fam = socket.AddressFamily(fam)
+ except ValueError:
+ if WINDOWS and fam == -1:
+ fam = _psplatform.AF_LINK
+ elif (
+ hasattr(_psplatform, "AF_LINK") and fam == _psplatform.AF_LINK
+ ):
+ # 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 += f"{separator}00"
+
+ nt = _ntp.snicaddr(fam, addr, mask, broadcast, ptp)
+
+ # On Windows broadcast is None, so we determine it via
+ # ipaddress module.
+ if WINDOWS and fam in {socket.AF_INET, socket.AF_INET6}:
+ try:
+ broadcast = _common.broadcast_addr(nt)
+ except Exception as err: # noqa: BLE001
+ debug(err)
+ else:
+ if broadcast is not None:
+ nt._replace(broadcast=broadcast)
+
+ ret[name].append(nt)
+
+ 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(_ntp.shwtemp(label, current, high, critical))
+
+ return dict(ret)
+
+ __all__.append("sensors_temperatures")
+
+
+# Linux
+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
+ (seconds since January 1, 1970, at midnight UTC). The returned
+ value is based on the system clock, which means it may be affected
+ by changes such as manual adjustments or time synchronization (e.g.
+ NTP).
+ """
+ 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)
+
+
+# =====================================================================
+# --- malloc / heap
+# =====================================================================
+
+
+# Linux + glibc, Windows, macOS, FreeBSD, NetBSD
+if hasattr(_psplatform, "heap_info"):
+
+ def heap_info():
+ """Return low-level heap statistics from the C heap allocator
+ (glibc).
+
+ - `heap_used`: the total number of bytes allocated via
+ malloc/free. These are typically allocations smaller than
+ MMAP_THRESHOLD.
+
+ - `mmap_used`: the total number of bytes allocated via `mmap()`
+ or via large ``malloc()`` allocations.
+
+ - `heap_count` (Windows only): number of private heaps created
+ via `HeapCreate()`.
+ """
+ return _ntp.pheap(*_psplatform.heap_info())
+
+ def heap_trim():
+ """Request that the underlying allocator free any unused memory
+ it's holding in the heap (typically small `malloc()`
+ allocations).
+
+ In practice, modern allocators rarely comply, so this is not a
+ general-purpose memory-reduction tool and won't meaningfully
+ shrink RSS in real programs. Its primary value is in **leak
+ detection tools**.
+
+ Calling `heap_trim()` before taking measurements helps reduce
+ allocator noise, giving you a cleaner baseline so that changes
+ in `heap_used` come from the code you're testing, not from
+ internal allocator caching or fragmentation. Its effectiveness
+ depends on allocator behavior and fragmentation patterns.
+ """
+ _psplatform.heap_trim()
+
+ __all__.append("heap_info")
+ __all__.append("heap_trim")
+
+
+# =====================================================================
+
+
+def _set_debug(value):
+ """Enable or disable PSUTIL_DEBUG option, which prints debugging
+ messages to stderr.
+ """
+ import psutil._common
+
+ psutil._common.PSUTIL_DEBUG = bool(value)
+ _psplatform.cext.set_debug(bool(value))
+
+
+del memoize_when_activated
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_common.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_common.py
new file mode 100644
index 0000000000000000000000000000000000000000..33b6282253ac3321193fdd882aaf38185dee9d49
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_common.py
@@ -0,0 +1,861 @@
+# 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.
+"""
+
+import collections
+import enum
+import functools
+import os
+import socket
+import stat
+import sys
+import threading
+import warnings
+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
+
+
+PSUTIL_DEBUG = bool(os.getenv('PSUTIL_DEBUG'))
+_DEFAULT = object()
+
+# fmt: off
+__all__ = [
+ # OS constants
+ 'FREEBSD', 'BSD', 'LINUX', 'NETBSD', 'OPENBSD', 'MACOS', 'OSX', 'POSIX',
+ 'SUNOS', 'WINDOWS',
+ # 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', # noqa: F822
+ # 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',
+ # other constants
+ 'ENCODING', 'ENCODING_ERRS', 'AF_INET6',
+ # 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",
+ 'open_text', 'open_binary', 'cat', 'bcat',
+ 'bytes2human', 'conn_to_ntuple', 'debug',
+ # shell utils
+ 'hilite', 'term_supports_colors', 'print_color',
+]
+# fmt: on
+
+
+# ===================================================================
+# --- 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", "midnightbsd"))
+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.net_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()
+class NicDuplex(enum.IntEnum):
+ NIC_DUPLEX_FULL = 2
+ NIC_DUPLEX_HALF = 1
+ NIC_DUPLEX_UNKNOWN = 0
+
+
+globals().update(NicDuplex.__members__)
+
+
+# sensors_battery()
+class BatteryTime(enum.IntEnum):
+ POWER_TIME_UNKNOWN = -1
+ POWER_TIME_UNLIMITED = -2
+
+
+globals().update(BatteryTime.__members__)
+
+# --- others
+
+ENCODING = sys.getfilesystemencoding()
+ENCODING_ERRS = sys.getfilesystemencodeerrors()
+
+
+# ===================================================================
+# --- Process.net_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 and not SUNOS:
+ conn_tmap.update({"unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM])})
+
+
+# =====================================================================
+# --- Exceptions
+# =====================================================================
+
+
+class Error(Exception):
+ """Base exception class. All other psutil exceptions inherit
+ from this one.
+ """
+
+ __module__ = 'psutil'
+
+ def _infodict(self, attrs):
+ info = collections.OrderedDict()
+ for name in attrs:
+ value = getattr(self, name, None)
+ if value or (name == "pid" and value == 0):
+ info[name] = value
+ return info
+
+ def __str__(self):
+ # invoked on `raise Error`
+ info = self._infodict(("pid", "ppid", "name"))
+ if info:
+ details = "({})".format(
+ ", ".join([f"{k}={v!r}" for k, v in info.items()])
+ )
+ else:
+ details = None
+ return " ".join([x for x in (getattr(self, "msg", ""), details) if x])
+
+ def __repr__(self):
+ # invoked on `repr(Error)`
+ info = self._infodict(("pid", "ppid", "name", "seconds", "msg"))
+ details = ", ".join([f"{k}={v!r}" for k, v in info.items()])
+ return f"psutil.{self.__class__.__name__}({details})"
+
+
+class NoSuchProcess(Error):
+ """Exception raised when a process with a certain PID doesn't
+ or no longer exists.
+ """
+
+ __module__ = 'psutil'
+
+ def __init__(self, pid, name=None, msg=None):
+ Error.__init__(self)
+ self.pid = pid
+ self.name = name
+ self.msg = msg or "process no longer exists"
+
+ def __reduce__(self):
+ return (self.__class__, (self.pid, self.name, self.msg))
+
+
+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.
+ """
+
+ __module__ = 'psutil'
+
+ def __init__(self, pid, name=None, ppid=None, msg=None):
+ NoSuchProcess.__init__(self, pid, name, msg)
+ self.ppid = ppid
+ self.msg = msg or "PID still exists but it's a zombie"
+
+ def __reduce__(self):
+ return (self.__class__, (self.pid, self.name, self.ppid, self.msg))
+
+
+class AccessDenied(Error):
+ """Exception raised when permission to perform an action is denied."""
+
+ __module__ = 'psutil'
+
+ def __init__(self, pid=None, name=None, msg=None):
+ Error.__init__(self)
+ self.pid = pid
+ self.name = name
+ self.msg = msg or ""
+
+ def __reduce__(self):
+ return (self.__class__, (self.pid, self.name, self.msg))
+
+
+class TimeoutExpired(Error):
+ """Raised on Process.wait(timeout) if timeout expires and process
+ is still alive.
+ """
+
+ __module__ = 'psutil'
+
+ def __init__(self, seconds, pid=None, name=None):
+ Error.__init__(self)
+ self.seconds = seconds
+ self.pid = pid
+ self.name = name
+ self.msg = f"timeout after {seconds} seconds"
+
+ def __reduce__(self):
+ return (self.__class__, (self.seconds, self.pid, self.name))
+
+
+# ===================================================================
+# --- utils
+# ===================================================================
+
+
+def usage_percent(used, total, round_=None):
+ """Calculate percentage usage of 'used' against 'total'."""
+ try:
+ ret = (float(used) / total) * 100
+ except ZeroDivisionError:
+ return 0.0
+ else:
+ if round_ is not None:
+ ret = round(ret, round_)
+ 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()
+ >>>
+
+ It supports:
+ - functions
+ - classes (acts as a @singleton)
+ - staticmethods
+ - classmethods
+
+ It does NOT support:
+ - methods
+ """
+
+ @functools.wraps(fun)
+ def wrapper(*args, **kwargs):
+ key = (args, frozenset(sorted(kwargs.items())))
+ try:
+ return cache[key]
+ except KeyError:
+ try:
+ ret = cache[key] = fun(*args, **kwargs)
+ except Exception as err:
+ raise err from None
+ 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
+ try:
+ return fun(self)
+ except Exception as err:
+ raise err from None
+ except KeyError:
+ # case 3: we entered oneshot() ctx but there's no cache
+ # for this entry yet
+ try:
+ ret = fun(self)
+ except Exception as err:
+ raise err from None
+ try:
+ self._cache[fun] = ret
+ except AttributeError:
+ # multi-threading race condition, see:
+ # https://github.com/giampaolo/psutil/issues/1948
+ pass
+ 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 PermissionError:
+ raise
+ except OSError:
+ 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 PermissionError:
+ raise
+ except OSError:
+ return False
+ else:
+ return True
+
+
+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:
+ with socket.socket(AF_INET6, socket.SOCK_STREAM) as sock:
+ sock.bind(("::1", 0))
+ return True
+ except OSError:
+ 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.
+ """
+ try:
+ return socket.AddressFamily(num)
+ except ValueError:
+ 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.
+ """
+ try:
+ return socket.SocketKind(num)
+ except ValueError:
+ return num
+
+
+def conn_to_ntuple(fd, fam, type_, laddr, raddr, status, status_map, pid=None):
+ """Convert a raw connection tuple to a proper ntuple."""
+ from . import _ntuples as ntp
+
+ if fam in {socket.AF_INET, AF_INET6}:
+ if laddr:
+ laddr = ntp.addr(*laddr)
+ if raddr:
+ raddr = ntp.addr(*raddr)
+ if type_ == socket.SOCK_STREAM and fam in {AF_INET, AF_INET6}:
+ status = status_map.get(status, CONN_NONE)
+ else:
+ status = CONN_NONE # ignore whatever C returned to us
+ fam = sockfam_to_enum(fam)
+ type_ = socktype_to_enum(type_)
+ if pid is None:
+ return ntp.pconn(fd, fam, type_, laddr, raddr, status)
+ else:
+ return ntp.sconn(fd, fam, type_, laddr, raddr, status, pid)
+
+
+def broadcast_addr(addr):
+ """Given the address ntuple returned by ``net_if_addrs()``
+ calculates the broadcast address.
+ """
+ import ipaddress
+
+ if not addr.address or not addr.netmask:
+ return None
+ if addr.family == socket.AF_INET:
+ return str(
+ ipaddress.IPv4Network(
+ f"{addr.address}/{addr.netmask}", strict=False
+ ).broadcast_address
+ )
+ if addr.family == socket.AF_INET6:
+ return str(
+ ipaddress.IPv6Network(
+ f"{addr.address}/{addr.netmask}", strict=False
+ ).broadcast_address
+ )
+
+
+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 = (
+ f"{fun.__name__}() is deprecated and will be removed; use"
+ f" {replacement}() instead"
+ )
+ 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] = collections.defaultdict(int)
+ self.reminder_keys[name] = collections.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:
+ 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
+
+
+# The read buffer size for open() builtin. This (also) dictates how
+# much data we read(2) when iterating over file lines as in:
+# >>> with open(file) as f:
+# ... for line in f:
+# ... ...
+# Default per-line buffer size for binary files is 1K. For text files
+# is 8K. We use a bigger buffer (32K) in order to have more consistent
+# results when reading /proc pseudo files on Linux, see:
+# https://github.com/giampaolo/psutil/issues/2050
+# https://github.com/giampaolo/psutil/issues/708
+FILE_READ_BUFFER_SIZE = 32 * 1024
+
+
+def open_binary(fname):
+ return open(fname, "rb", buffering=FILE_READ_BUFFER_SIZE)
+
+
+def open_text(fname):
+ """Open a file in text mode by using the proper FS encoding and
+ en/decoding error handlers.
+ """
+ # See:
+ # https://github.com/giampaolo/psutil/issues/675
+ # https://github.com/giampaolo/psutil/pull/733
+ fobj = open( # noqa: SIM115
+ fname,
+ buffering=FILE_READ_BUFFER_SIZE,
+ encoding=ENCODING,
+ errors=ENCODING_ERRS,
+ )
+ try:
+ # Dictates per-line read(2) buffer size. Defaults is 8k. See:
+ # https://github.com/giampaolo/psutil/issues/2050#issuecomment-1013387546
+ fobj._CHUNK_SIZE = FILE_READ_BUFFER_SIZE
+ except AttributeError:
+ pass
+ except Exception:
+ fobj.close()
+ raise
+
+ return fobj
+
+
+def cat(fname, fallback=_DEFAULT, _open=open_text):
+ """Read entire file content and return it as a string. File is
+ opened in text mode. If specified, `fallback` is the value
+ returned in case of error, either if the file does not exist or
+ it can't be read().
+ """
+ if fallback is _DEFAULT:
+ with _open(fname) as f:
+ return f.read()
+ else:
+ try:
+ with _open(fname) as f:
+ return f.read()
+ except OSError:
+ return fallback
+
+
+def bcat(fname, fallback=_DEFAULT):
+ """Same as above but opens file in binary mode."""
+ return cat(fname, fallback=fallback, _open=open_binary)
+
+
+def bytes2human(n, format="%(value).1f%(symbol)s"):
+ """Used by various scripts. See: https://code.activestate.com/recipes/578019-bytes-to-human-human-to-bytes-converter/?in=user-4178764.
+
+ >>> bytes2human(10000)
+ '9.8K'
+ >>> bytes2human(100001221)
+ '95.4M'
+ """
+ symbols = ('B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y')
+ prefix = {}
+ for i, s in enumerate(symbols[1:]):
+ prefix[s] = 1 << (i + 1) * 10
+ for symbol in reversed(symbols[1:]):
+ if abs(n) >= prefix[symbol]:
+ value = float(n) / prefix[symbol]
+ return format % locals()
+ return format % dict(symbol=symbols[0], value=n)
+
+
+def get_procfs_path():
+ """Return updated psutil.PROCFS_PATH constant."""
+ return sys.modules['psutil'].PROCFS_PATH
+
+
+def decode(s):
+ return s.decode(encoding=ENCODING, errors=ENCODING_ERRS)
+
+
+# =====================================================================
+# --- shell utils
+# =====================================================================
+
+
+@memoize
+def term_supports_colors(file=sys.stdout): # pragma: no cover
+ if not hasattr(file, "isatty") or not file.isatty():
+ return False
+ try:
+ file.fileno()
+ except Exception: # noqa: BLE001
+ return False
+ return True
+
+
+def hilite(s, color=None, bold=False): # pragma: no cover
+ """Return an highlighted version of 'string'."""
+ if not term_supports_colors():
+ return s
+ attr = []
+ colors = dict(
+ blue='34',
+ brown='33',
+ darkgrey='30',
+ green='32',
+ grey='37',
+ lightblue='36',
+ red='91',
+ violet='35',
+ yellow='93',
+ )
+ colors[None] = '29'
+ try:
+ color = colors[color]
+ except KeyError:
+ msg = f"invalid color {color!r}; choose amongst {list(colors.keys())}"
+ raise ValueError(msg) from None
+ attr.append(color)
+ if bold:
+ attr.append('1')
+ return f"\x1b[{';'.join(attr)}m{s}\x1b[0m"
+
+
+def print_color(
+ s, color=None, bold=False, file=sys.stdout
+): # pragma: no cover
+ """Print a colorized version of string."""
+ if not term_supports_colors():
+ print(s, file=file)
+ elif POSIX:
+ print(hilite(s, color, bold), file=file)
+ else:
+ import ctypes
+
+ DEFAULT_COLOR = 7
+ GetStdHandle = ctypes.windll.Kernel32.GetStdHandle
+ SetConsoleTextAttribute = (
+ ctypes.windll.Kernel32.SetConsoleTextAttribute
+ )
+
+ colors = dict(green=2, red=4, brown=6, yellow=6)
+ colors[None] = DEFAULT_COLOR
+ try:
+ color = colors[color]
+ except KeyError:
+ msg = (
+ f"invalid color {color!r}; choose between"
+ f" {list(colors.keys())!r}"
+ )
+ raise ValueError(msg) from None
+ if bold and color <= 7:
+ color += 8
+
+ handle_id = -12 if file is sys.stderr else -11
+ GetStdHandle.restype = ctypes.c_ulong
+ handle = GetStdHandle(handle_id)
+ SetConsoleTextAttribute(handle, color)
+ try:
+ print(s, file=file)
+ finally:
+ SetConsoleTextAttribute(handle, DEFAULT_COLOR)
+
+
+def debug(msg):
+ """If PSUTIL_DEBUG env var is set, print a debug message to stderr."""
+ if PSUTIL_DEBUG:
+ import inspect
+
+ fname, lineno, _, _lines, _index = inspect.getframeinfo(
+ inspect.currentframe().f_back
+ )
+ if isinstance(msg, Exception):
+ if isinstance(msg, OSError):
+ # ...because str(exc) may contain info about the file name
+ msg = f"ignoring {msg}"
+ else:
+ msg = f"ignoring {msg!r}"
+ print( # noqa: T201
+ f"psutil-debug [{fname}:{lineno}]> {msg}", file=sys.stderr
+ )
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_ntuples.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_ntuples.py
new file mode 100644
index 0000000000000000000000000000000000000000..f0ab0393763f0969d2f4b4302fa638771c6c0bdb
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_ntuples.py
@@ -0,0 +1,429 @@
+# 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.
+
+from collections import namedtuple as nt
+
+from ._common import AIX
+from ._common import BSD
+from ._common import FREEBSD
+from ._common import LINUX
+from ._common import MACOS
+from ._common import SUNOS
+from ._common import WINDOWS
+
+# ===================================================================
+# --- system functions
+# ===================================================================
+
+# psutil.swap_memory()
+sswap = nt("sswap", ("total", "used", "free", "percent", "sin", "sout"))
+
+# psutil.disk_usage()
+sdiskusage = nt("sdiskusage", ("total", "used", "free", "percent"))
+
+# psutil.disk_io_counters()
+sdiskio = nt(
+ "sdiskio",
+ (
+ "read_count",
+ "write_count",
+ "read_bytes",
+ "write_bytes",
+ "read_time",
+ "write_time",
+ ),
+)
+
+# psutil.disk_partitions()
+sdiskpart = nt("sdiskpart", ("device", "mountpoint", "fstype", "opts"))
+
+# psutil.net_io_counters()
+snetio = nt(
+ "snetio",
+ (
+ "bytes_sent",
+ "bytes_recv",
+ "packets_sent",
+ "packets_recv",
+ "errin",
+ "errout",
+ "dropin",
+ "dropout",
+ ),
+)
+
+# psutil.users()
+suser = nt("suser", ("name", "terminal", "host", "started", "pid"))
+
+# psutil.net_connections()
+sconn = nt(
+ "sconn", ("fd", "family", "type", "laddr", "raddr", "status", "pid")
+)
+
+# psutil.net_if_addrs()
+snicaddr = nt("snicaddr", ("family", "address", "netmask", "broadcast", "ptp"))
+
+# psutil.net_if_stats()
+snicstats = nt("snicstats", ("isup", "duplex", "speed", "mtu", "flags"))
+
+# psutil.cpu_stats()
+scpustats = nt(
+ "scpustats", ("ctx_switches", "interrupts", "soft_interrupts", "syscalls")
+)
+
+# psutil.cpu_freq()
+scpufreq = nt("scpufreq", ("current", "min", "max"))
+
+# psutil.sensors_temperatures()
+shwtemp = nt("shwtemp", ("label", "current", "high", "critical"))
+
+# psutil.sensors_battery()
+sbattery = nt("sbattery", ("percent", "secsleft", "power_plugged"))
+
+# psutil.sensors_fans()
+sfan = nt("sfan", ("label", "current"))
+
+# psutil.heap_info() (mallinfo2 Linux struct)
+if LINUX or WINDOWS or MACOS or BSD:
+ pheap = nt(
+ "pheap",
+ [
+ "heap_used", # uordblks, memory allocated via malloc()
+ "mmap_used", # hblkhd, memory allocated via mmap() (large blocks)
+ ],
+ )
+ if WINDOWS:
+ pheap = nt("pheap", pheap._fields + ("heap_count",))
+
+# ===================================================================
+# --- Process class
+# ===================================================================
+
+# psutil.Process.cpu_times()
+pcputimes = nt(
+ "pcputimes", ("user", "system", "children_user", "children_system")
+)
+
+# psutil.Process.open_files()
+popenfile = nt("popenfile", ("path", "fd"))
+
+# psutil.Process.threads()
+pthread = nt("pthread", ("id", "user_time", "system_time"))
+
+# psutil.Process.uids()
+puids = nt("puids", ("real", "effective", "saved"))
+
+# psutil.Process.gids()
+pgids = nt("pgids", ("real", "effective", "saved"))
+
+# psutil.Process.io_counters()
+pio = nt("pio", ("read_count", "write_count", "read_bytes", "write_bytes"))
+
+# psutil.Process.ionice()
+pionice = nt("pionice", ("ioclass", "value"))
+
+# psutil.Process.ctx_switches()
+pctxsw = nt("pctxsw", ("voluntary", "involuntary"))
+
+# psutil.Process.net_connections()
+pconn = nt("pconn", ("fd", "family", "type", "laddr", "raddr", "status"))
+
+# psutil.net_connections() and psutil.Process.net_connections()
+addr = nt("addr", ("ip", "port"))
+
+# ===================================================================
+# --- Linux
+# ===================================================================
+
+if LINUX:
+
+ # This gets set from _pslinux.py
+ scputimes = None
+
+ # psutil.virtual_memory()
+ svmem = nt(
+ "svmem",
+ (
+ "total",
+ "available",
+ "percent",
+ "used",
+ "free",
+ "active",
+ "inactive",
+ "buffers",
+ "cached",
+ "shared",
+ "slab",
+ ),
+ )
+
+ # psutil.disk_io_counters()
+ sdiskio = nt(
+ "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 = nt("popenfile", ("path", "fd", "position", "mode", "flags"))
+
+ # psutil.Process().memory_info()
+ pmem = nt("pmem", ("rss", "vms", "shared", "text", "lib", "data", "dirty"))
+
+ # psutil.Process().memory_full_info()
+ pfullmem = nt("pfullmem", pmem._fields + ("uss", "pss", "swap"))
+
+ # psutil.Process().memory_maps(grouped=True)
+ pmmap_grouped = nt(
+ "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 = nt(
+ "pmmap_ext", "addr perms " + " ".join(pmmap_grouped._fields)
+ )
+
+ # psutil.Process.io_counters()
+ pio = nt(
+ "pio",
+ (
+ "read_count",
+ "write_count",
+ "read_bytes",
+ "write_bytes",
+ "read_chars",
+ "write_chars",
+ ),
+ )
+
+ # psutil.Process.cpu_times()
+ pcputimes = nt(
+ "pcputimes",
+ ("user", "system", "children_user", "children_system", "iowait"),
+ )
+
+# ===================================================================
+# --- Windows
+# ===================================================================
+
+elif WINDOWS:
+
+ # psutil.cpu_times()
+ scputimes = nt("scputimes", ("user", "system", "idle", "interrupt", "dpc"))
+
+ # psutil.virtual_memory()
+ svmem = nt("svmem", ("total", "available", "percent", "used", "free"))
+
+ # psutil.Process.memory_info()
+ pmem = nt(
+ "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 = nt("pfullmem", pmem._fields + ("uss",))
+
+ # psutil.Process.memory_maps(grouped=True)
+ pmmap_grouped = nt("pmmap_grouped", ("path", "rss"))
+
+ # psutil.Process.memory_maps(grouped=False)
+ pmmap_ext = nt(
+ "pmmap_ext", "addr perms " + " ".join(pmmap_grouped._fields)
+ )
+
+ # psutil.Process.io_counters()
+ pio = nt(
+ "pio",
+ (
+ "read_count",
+ "write_count",
+ "read_bytes",
+ "write_bytes",
+ "other_count",
+ "other_bytes",
+ ),
+ )
+
+# ===================================================================
+# --- macOS
+# ===================================================================
+
+elif MACOS:
+
+ # psutil.cpu_times()
+ scputimes = nt("scputimes", ("user", "nice", "system", "idle"))
+
+ # psutil.virtual_memory()
+ svmem = nt(
+ "svmem",
+ (
+ "total",
+ "available",
+ "percent",
+ "used",
+ "free",
+ "active",
+ "inactive",
+ "wired",
+ ),
+ )
+
+ # psutil.Process.memory_info()
+ pmem = nt("pmem", ("rss", "vms", "pfaults", "pageins"))
+
+ # psutil.Process.memory_full_info()
+ pfullmem = nt("pfullmem", pmem._fields + ("uss",))
+
+# ===================================================================
+# --- BSD
+# ===================================================================
+
+elif BSD:
+
+ # psutil.virtual_memory()
+ svmem = nt(
+ "svmem",
+ (
+ "total",
+ "available",
+ "percent",
+ "used",
+ "free",
+ "active",
+ "inactive",
+ "buffers",
+ "cached",
+ "shared",
+ "wired",
+ ),
+ )
+
+ # psutil.cpu_times()
+ scputimes = nt("scputimes", ("user", "nice", "system", "idle", "irq"))
+
+ # psutil.Process.memory_info()
+ pmem = nt("pmem", ("rss", "vms", "text", "data", "stack"))
+
+ # psutil.Process.memory_full_info()
+ pfullmem = pmem
+
+ # psutil.Process.cpu_times()
+ pcputimes = nt(
+ "pcputimes", ("user", "system", "children_user", "children_system")
+ )
+
+ # psutil.Process.memory_maps(grouped=True)
+ pmmap_grouped = nt(
+ "pmmap_grouped", "path rss, private, ref_count, shadow_count"
+ )
+
+ # psutil.Process.memory_maps(grouped=False)
+ pmmap_ext = nt(
+ "pmmap_ext", "addr, perms path rss, private, ref_count, shadow_count"
+ )
+
+ # psutil.disk_io_counters()
+ if FREEBSD:
+ sdiskio = nt(
+ "sdiskio",
+ (
+ "read_count",
+ "write_count",
+ "read_bytes",
+ "write_bytes",
+ "read_time",
+ "write_time",
+ "busy_time",
+ ),
+ )
+ else:
+ sdiskio = nt(
+ "sdiskio",
+ ("read_count", "write_count", "read_bytes", "write_bytes"),
+ )
+
+# ===================================================================
+# --- SunOS
+# ===================================================================
+
+elif SUNOS:
+
+ # psutil.cpu_times()
+ scputimes = nt("scputimes", ("user", "system", "idle", "iowait"))
+
+ # psutil.cpu_times(percpu=True)
+ pcputimes = nt(
+ "pcputimes", ("user", "system", "children_user", "children_system")
+ )
+
+ # psutil.virtual_memory()
+ svmem = nt("svmem", ("total", "available", "percent", "used", "free"))
+
+ # psutil.Process.memory_info()
+ pmem = nt("pmem", ("rss", "vms"))
+
+ # psutil.Process.memory_full_info()
+ pfullmem = pmem
+
+ # psutil.Process.memory_maps(grouped=True)
+ pmmap_grouped = nt("pmmap_grouped", ("path", "rss", "anonymous", "locked"))
+
+ # psutil.Process.memory_maps(grouped=False)
+ pmmap_ext = nt(
+ "pmmap_ext", "addr perms " + " ".join(pmmap_grouped._fields)
+ )
+
+# ===================================================================
+# --- AIX
+# ===================================================================
+
+elif AIX:
+
+ # psutil.Process.memory_info()
+ pmem = nt("pmem", ("rss", "vms"))
+
+ # psutil.Process.memory_full_info()
+ pfullmem = pmem
+
+ # psutil.Process.cpu_times()
+ scputimes = nt("scputimes", ("user", "system", "idle", "iowait"))
+
+ # psutil.virtual_memory()
+ svmem = nt("svmem", ("total", "available", "percent", "used", "free"))
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_psaix.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_psaix.py
new file mode 100644
index 0000000000000000000000000000000000000000..1f628ad93c1b1464b16d63daee79fe161204730e
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_psaix.py
@@ -0,0 +1,546 @@
+# 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 functools
+import glob
+import os
+import re
+import subprocess
+import sys
+
+from . import _common
+from . import _ntuples as ntp
+from . import _psposix
+from . import _psutil_aix as cext
+from ._common import NIC_DUPLEX_FULL
+from ._common import NIC_DUPLEX_HALF
+from ._common import NIC_DUPLEX_UNKNOWN
+from ._common import AccessDenied
+from ._common import NoSuchProcess
+from ._common import ZombieProcess
+from ._common import conn_to_ntuple
+from ._common import get_procfs_path
+from ._common import memoize_when_activated
+from ._common import usage_percent
+
+__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 = cext.getpagesize()
+AF_LINK = cext.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,
+)
+
+
+# =====================================================================
+# --- memory
+# =====================================================================
+
+
+def virtual_memory():
+ total, avail, free, _pinned, inuse = cext.virtual_mem()
+ percent = usage_percent((total - avail), total, round_=1)
+ return ntp.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 ntp.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 ntp.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 [ntp.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_cores():
+ cmd = ["lsdev", "-Cc", "processor"]
+ p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ stdout, stderr = p.communicate()
+ stdout, stderr = (x.decode(sys.stdout.encoding) for x in (stdout, stderr))
+ if p.returncode != 0:
+ msg = f"{cmd!r} command error\n{stderr}"
+ raise RuntimeError(msg)
+ 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 ntp.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 = ntp.sdiskpart(device, mountpoint, fstype, opts)
+ retlist.append(ntuple)
+ return retlist
+
+
+# =====================================================================
+# --- network
+# =====================================================================
+
+
+net_if_addrs = cext.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).
+ """
+ families, types = _common.conn_tmap[kind]
+ rawlist = cext.net_connections(_pid)
+ ret = []
+ for item in rawlist:
+ fd, fam, type_, laddr, raddr, status, pid = item
+ if fam not in families:
+ continue
+ if type_ not in types:
+ continue
+ nt = conn_to_ntuple(
+ fd,
+ fam,
+ type_,
+ laddr,
+ raddr,
+ status,
+ TCP_STATUSES,
+ pid=pid if _pid == -1 else None,
+ )
+ ret.append(nt)
+ return ret
+
+
+def net_if_stats():
+ """Get NIC stats (isup, duplex, speed, mtu)."""
+ duplex_map = {"Full": NIC_DUPLEX_FULL, "Half": NIC_DUPLEX_HALF}
+ names = {x[0] for x in net_if_addrs()}
+ ret = {}
+ for name in names:
+ mtu = cext.net_if_mtu(name)
+ flags = cext.net_if_flags(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()
+ 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)
+
+ output_flags = ','.join(flags)
+ isup = 'running' in flags
+ duplex = duplex_map.get(duplex, NIC_DUPLEX_UNKNOWN)
+ ret[name] = ntp.snicstats(isup, duplex, speed, mtu, output_flags)
+ 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 = ntp.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.
+ """
+
+ @functools.wraps(fun)
+ def wrapper(self, *args, **kwargs):
+ pid, ppid, name = self.pid, self._ppid, self._name
+ try:
+ return fun(self, *args, **kwargs)
+ except (FileNotFoundError, ProcessLookupError) 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 not pid_exists(pid):
+ raise NoSuchProcess(pid, name) from err
+ raise ZombieProcess(pid, name, ppid) from err
+ except PermissionError as err:
+ raise AccessDenied(pid, name) from err
+
+ return wrapper
+
+
+class Process:
+ """Wrapper class around underlying C implementation."""
+
+ __slots__ = ["_cache", "_name", "_ppid", "_procfs_path", "pid"]
+
+ 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_basic_info.cache_activate(self)
+ self._proc_cred.cache_activate(self)
+
+ def oneshot_exit(self):
+ self._proc_basic_info.cache_deactivate(self)
+ self._proc_cred.cache_deactivate(self)
+
+ @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: max 16 characters
+ return cext.proc_name(self.pid, self._procfs_path).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
+ cmdline = self.cmdline()
+ if not cmdline:
+ return ''
+ exe = 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 cext.proc_args(self.pid)
+
+ @wrap_exceptions
+ def environ(self):
+ return cext.proc_environ(self.pid)
+
+ @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 = ntp.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(f"{self._procfs_path}/{self.pid}")
+ return retlist
+
+ @wrap_exceptions
+ def net_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(f"{self._procfs_path}/{self.pid}")
+ return ret
+
+ @wrap_exceptions
+ def nice_get(self):
+ return cext.proc_priority_get(self.pid)
+
+ @wrap_exceptions
+ def nice_set(self, value):
+ return cext.proc_priority_set(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 ntp.puids(real, effective, saved)
+
+ @wrap_exceptions
+ def gids(self):
+ _, _, _, real, effective, saved = self._proc_cred()
+ return ntp.puids(real, effective, saved)
+
+ @wrap_exceptions
+ def cpu_times(self):
+ t = cext.proc_cpu_times(self.pid, self._procfs_path)
+ return ntp.pcputimes(*t)
+
+ @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(f"{procfs_path}/{self.pid}/cwd")
+ return result.rstrip('/')
+ except FileNotFoundError:
+ os.stat(f"{procfs_path}/{self.pid}") # raise NSP or AD
+ return ""
+
+ @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 ntp.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()
+ 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.*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(ntp.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(f"{self._procfs_path}/{self.pid}/fd"))
+
+ @wrap_exceptions
+ def num_ctx_switches(self):
+ return ntp.pctxsw(*cext.proc_num_ctx_switches(self.pid))
+
+ @wrap_exceptions
+ def wait(self, timeout=None):
+ return _psposix.wait_pid(self.pid, timeout)
+
+ if HAS_PROC_IO_COUNTERS:
+
+ @wrap_exceptions
+ def io_counters(self):
+ try:
+ rc, wc, rb, wb = cext.proc_io_counters(self.pid)
+ except OSError as err:
+ # if process is terminated, proc_io_counters returns OSError
+ # instead of NSP
+ if not pid_exists(self.pid):
+ raise NoSuchProcess(self.pid, self._name) from err
+ raise
+ return ntp.pio(rc, wc, rb, wb)
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_psbsd.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_psbsd.py
new file mode 100644
index 0000000000000000000000000000000000000000..a75cd1af131973c0f78caa65a22c0a7e91645959
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_psbsd.py
@@ -0,0 +1,904 @@
+# 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
+from collections import defaultdict
+from collections import namedtuple
+from xml.etree import ElementTree # noqa: ICN001
+
+from . import _common
+from . import _ntuples as ntp
+from . import _psposix
+from . import _psutil_bsd as cext
+from ._common import FREEBSD
+from ._common import NETBSD
+from ._common import OPENBSD
+from ._common import AccessDenied
+from ._common import NoSuchProcess
+from ._common import ZombieProcess
+from ._common import conn_tmap
+from ._common import conn_to_ntuple
+from ._common import debug
+from ._common import memoize
+from ._common import memoize_when_activated
+from ._common import usage_percent
+
+__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:
+ 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.SSLEEP: _common.STATUS_SLEEPING,
+ cext.SSTOP: _common.STATUS_STOPPED,
+ cext.SZOMB: _common.STATUS_ZOMBIE,
+ cext.SRUN: _common.STATUS_WAKING,
+ cext.SONPROC: _common.STATUS_RUNNING,
+ }
+
+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,
+}
+
+PAGESIZE = cext.getpagesize()
+AF_LINK = cext.AF_LINK
+
+HAS_PROC_NUM_THREADS = hasattr(cext, "proc_num_threads")
+
+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,
+)
+
+
+# =====================================================================
+# --- memory
+# =====================================================================
+
+
+def virtual_memory():
+ mem = cext.virtual_mem()
+ if NETBSD:
+ total, free, active, inactive, wired, cached = mem
+ # 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
+ # Before avail was calculated as (inactive + cached + free),
+ # same as zabbix, but it turned out it could exceed total (see
+ # #2233), so zabbix seems to be wrong. Htop calculates it
+ # differently, and the used value seem more realistic, so let's
+ # match htop.
+ # https://github.com/htop-dev/htop/blob/e7f447b/netbsd/NetBSDProcessList.c#L162
+ # https://github.com/zabbix/zabbix/blob/af5e0f8/src/libs/zbxsysinfo/netbsd/memory.c#L135
+ used = active + wired
+ avail = total - used
+ else:
+ total, free, active, inactive, wired, cached, buffers, shared = mem
+ # matches freebsd-memory CLI:
+ # * https://people.freebsd.org/~rse/dist/freebsd-memory
+ # * https://www.cyberciti.biz/files/scripts/freebsd-memory.pl.txt
+ # matches zabbix:
+ # * https://github.com/zabbix/zabbix/blob/af5e0f8/src/libs/zbxsysinfo/freebsd/memory.c#L143
+ avail = inactive + cached + free
+ used = active + wired + cached
+
+ percent = usage_percent((total - avail), total, round_=1)
+ return ntp.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 ntp.sswap(total, used, free, percent, sin, sout)
+
+
+# malloc / heap functions (FreeBSD / NetBSD)
+if hasattr(cext, "heap_info"):
+ heap_info = cext.heap_info
+ heap_trim = cext.heap_trim
+
+
+# =====================================================================
+# --- CPU
+# =====================================================================
+
+
+def cpu_times():
+ """Return system per-CPU times as a namedtuple."""
+ user, nice, system, idle, irq = cext.cpu_times()
+ return ntp.scputimes(user, nice, system, idle, irq)
+
+
+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 = ntp.scputimes(user, nice, system, idle, irq)
+ ret.append(item)
+ return ret
+
+
+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_cores():
+ # OpenBSD and NetBSD do not implement this.
+ return 1 if cpu_count_logical() == 1 else None
+
+else:
+
+ def cpu_count_cores():
+ """Return the number of CPU cores 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_topology()
+ 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 = ElementTree.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 == 1 it's obvious we' have only 1 core.
+ 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 ntp.scpustats(ctxsw, intrs, soft_intrs, syscalls)
+
+
+if FREEBSD:
+
+ 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_freq(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(ntp.scpufreq(current, min_freq, max_freq))
+ return ret
+
+elif OPENBSD:
+
+ def cpu_freq():
+ curr = float(cext.cpu_freq())
+ return [ntp.scpufreq(curr, 0.0, 0.0)]
+
+
+# =====================================================================
+# --- 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 = ntp.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.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.net_if_mtu(name)
+ flags = cext.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:
+ if hasattr(_common, 'NicDuplex'):
+ duplex = _common.NicDuplex(duplex)
+ output_flags = ','.join(flags)
+ isup = 'running' in flags
+ ret[name] = ntp.snicstats(isup, duplex, speed, mtu, output_flags)
+ return ret
+
+
+def net_connections(kind):
+ """System-wide network connections."""
+ families, types = conn_tmap[kind]
+ ret = set()
+ if OPENBSD:
+ rawlist = cext.net_connections(-1, families, types)
+ elif NETBSD:
+ rawlist = cext.net_connections(-1, kind)
+ else: # FreeBSD
+ rawlist = cext.net_connections(families, types)
+
+ for item in rawlist:
+ fd, fam, type, laddr, raddr, status, pid = item
+ nt = conn_to_ntuple(
+ fd, fam, type, laddr, raddr, status, TCP_STATUSES, 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 ntp.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 = f"Core {cpu}"
+ ret["coretemp"].append(ntp.shwtemp(name, current, high, high))
+ except NotImplementedError:
+ pass
+
+ return ret
+
+
+# =====================================================================
+# --- other system functions
+# =====================================================================
+
+
+def boot_time():
+ """The system boot time expressed in seconds since the epoch."""
+ return cext.boot_time()
+
+
+if NETBSD:
+
+ try:
+ INIT_BOOT_TIME = boot_time()
+ except Exception as err: # noqa: BLE001
+ # Don't want to crash at import time.
+ debug(f"ignoring exception on import: {err!r}")
+ INIT_BOOT_TIME = 0
+
+ def adjust_proc_create_time(ctime):
+ """Account for system clock updates."""
+ if INIT_BOOT_TIME == 0:
+ return ctime
+
+ diff = INIT_BOOT_TIME - boot_time()
+ if diff == 0 or abs(diff) < 1:
+ return ctime
+
+ debug("system clock was updated; adjusting process create_time()")
+ if diff < 0:
+ return ctime - diff
+ return ctime + diff
+
+
+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
+ nt = ntp.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 NETBSD:
+
+ def pid_exists(pid):
+ 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
+
+elif OPENBSD:
+
+ def pid_exists(pid):
+ exists = _psposix.pid_exists(pid)
+ if not exists:
+ return False
+ else:
+ # OpenBSD seems to be the only BSD platform where
+ # _psposix.pid_exists() returns True for thread IDs (tids),
+ # so we can't use it.
+ return pid in pids()
+
+else: # FreeBSD
+ 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):
+ pid, ppid, name = self.pid, self._ppid, self._name
+ try:
+ return fun(self, *args, **kwargs)
+ except ProcessLookupError as err:
+ if cext.proc_is_zombie(pid):
+ raise ZombieProcess(pid, name, ppid) from err
+ raise NoSuchProcess(pid, name) from err
+ except PermissionError as err:
+ raise AccessDenied(pid, name) from err
+ except cext.ZombieProcessError as err:
+ raise ZombieProcess(pid, name, ppid) from err
+ except OSError as err:
+ if pid == 0 and 0 in pids():
+ raise AccessDenied(pid, name) from err
+ raise err from None
+
+ return wrapper
+
+
+@contextlib.contextmanager
+def wrap_exceptions_procfs(inst):
+ """Same as above, for routines relying on reading /proc fs."""
+ pid, name, ppid = inst.pid, inst._name, inst._ppid
+ try:
+ yield
+ except (ProcessLookupError, FileNotFoundError) 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 cext.proc_is_zombie(inst.pid):
+ raise ZombieProcess(pid, name, ppid) from err
+ else:
+ raise NoSuchProcess(pid, name) from err
+ except PermissionError as err:
+ raise AccessDenied(pid, name) from err
+
+
+class Process:
+ """Wrapper class around underlying C implementation."""
+
+ __slots__ = ["_cache", "_name", "_ppid", "pid"]
+
+ 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:
+ if self.pid == 0:
+ return '' # else NSP
+ 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(f"/proc/{self.pid}/exe")
+ 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).
+ import shutil
+
+ cmdline = self.cmdline()
+ if cmdline:
+ return shutil.which(cmdline[0]) or ""
+ 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
+ # NetBSD and OpenBSD 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:
+ pid, name, ppid = self.pid, self._name, self._ppid
+ if cext.proc_is_zombie(self.pid):
+ raise ZombieProcess(pid, name, ppid) from err
+ if not pid_exists(self.pid):
+ raise NoSuchProcess(pid, name, ppid) from err
+ # XXX: this happens with unicode tests. It means the C
+ # routine is unable to decode invalid unicode chars.
+ debug(f"ignoring {err!r} and returning an empty list")
+ return []
+ else:
+ raise
+ else:
+ return cext.proc_cmdline(self.pid)
+
+ @wrap_exceptions
+ def environ(self):
+ return cext.proc_environ(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 ntp.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 ntp.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 ntp.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 ntp.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, monotonic=False):
+ ctime = self.oneshot()[kinfo_proc_map['create_time']]
+ if NETBSD and not monotonic:
+ # NetBSD: ctime subject to system clock updates.
+ ctime = adjust_proc_create_time(ctime)
+ return ctime
+
+ @wrap_exceptions
+ def num_threads(self):
+ if HAS_PROC_NUM_THREADS:
+ # FreeBSD / NetBSD
+ return cext.proc_num_threads(self.pid)
+ else:
+ return len(self.threads())
+
+ @wrap_exceptions
+ def num_ctx_switches(self):
+ rawtuple = self.oneshot()
+ return ntp.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 = ntp.pthread(thread_id, utime, stime)
+ retlist.append(ntuple)
+ if OPENBSD:
+ self._assert_alive()
+ return retlist
+
+ @wrap_exceptions
+ def net_connections(self, kind='inet'):
+ families, types = conn_tmap[kind]
+ ret = []
+
+ if NETBSD:
+ rawlist = cext.net_connections(self.pid, kind)
+ elif OPENBSD:
+ rawlist = cext.net_connections(self.pid, families, types)
+ else:
+ rawlist = cext.proc_net_connections(self.pid, families, types)
+
+ for item in rawlist:
+ fd, fam, type, laddr, raddr, status = item[:6]
+ if FREEBSD:
+ if (fam not in families) or (type not in types):
+ continue
+ nt = conn_to_ntuple(
+ fd, fam, type, laddr, raddr, status, TCP_STATUSES
+ )
+ ret.append(nt)
+
+ self._assert_alive()
+ return ret
+
+ @wrap_exceptions
+ def wait(self, timeout=None):
+ return _psposix.wait_pid(self.pid, timeout)
+
+ @wrap_exceptions
+ def nice_get(self):
+ return cext.proc_priority_get(self.pid)
+
+ @wrap_exceptions
+ def nice_set(self, value):
+ return cext.proc_priority_set(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 ntp.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 "" # ...else it would raise EINVAL
+ return cext.proc_cwd(self.pid)
+
+ 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'
+ )
+
+ @wrap_exceptions
+ def open_files(self):
+ """Return files opened by process as a list of namedtuples."""
+ rawlist = cext.proc_open_files(self.pid)
+ return [ntp.popenfile(path, fd) for path, fd in rawlist]
+
+ @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
+
+ # --- 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 = set(range(len(per_cpu_times())))
+ for cpu in cpus:
+ if cpu not in allcpus:
+ msg = f"invalid CPU {cpu!r} (choose between {allcpus})"
+ raise ValueError(msg)
+ 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:
+ msg = (
+ f"invalid CPU {cpu!r} (choose between"
+ f" {allcpus})"
+ )
+ raise ValueError(msg) from err
+ raise
+
+ @wrap_exceptions
+ def memory_maps(self):
+ return cext.proc_memory_maps(self.pid)
+
+ @wrap_exceptions
+ def rlimit(self, resource, limits=None):
+ if limits is None:
+ return cext.proc_getrlimit(self.pid, resource)
+ else:
+ if len(limits) != 2:
+ msg = (
+ "second argument must be a (soft, hard) tuple, got"
+ f" {limits!r}"
+ )
+ raise ValueError(msg)
+ soft, hard = limits
+ return cext.proc_setrlimit(self.pid, resource, soft, hard)
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_pslinux.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_pslinux.py
new file mode 100644
index 0000000000000000000000000000000000000000..dc305b59559e9b97f96eacf2a2002d2b02e3fe41
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_pslinux.py
@@ -0,0 +1,2269 @@
+# 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."""
+
+import base64
+import collections
+import enum
+import errno
+import functools
+import glob
+import os
+import re
+import resource
+import socket
+import struct
+import sys
+import warnings
+from collections import defaultdict
+from collections import namedtuple
+
+from . import _common
+from . import _ntuples as ntp
+from . import _psposix
+from . import _psutil_linux as cext
+from ._common import ENCODING
+from ._common import NIC_DUPLEX_FULL
+from ._common import NIC_DUPLEX_HALF
+from ._common import NIC_DUPLEX_UNKNOWN
+from ._common import AccessDenied
+from ._common import NoSuchProcess
+from ._common import ZombieProcess
+from ._common import bcat
+from ._common import cat
+from ._common import debug
+from ._common import decode
+from ._common import get_procfs_path
+from ._common import isfile_strict
+from ._common import memoize
+from ._common import memoize_when_activated
+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
+
+# fmt: off
+__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",
+]
+# fmt: on
+
+
+# =====================================================================
+# --- globals
+# =====================================================================
+
+
+POWER_SUPPLY_PATH = "/sys/class/power_supply"
+HAS_PROC_SMAPS = os.path.exists(f"/proc/{os.getpid()}/smaps")
+HAS_PROC_SMAPS_ROLLUP = os.path.exists(f"/proc/{os.getpid()}/smaps_rollup")
+HAS_PROC_IO_PRIORITY = hasattr(cext, "proc_ioprio_get")
+HAS_CPU_AFFINITY = hasattr(cext, "proc_cpu_affinity_get")
+
+# Number of clock ticks per second
+CLOCK_TICKS = os.sysconf("SC_CLK_TCK")
+PAGESIZE = cext.getpagesize()
+LITTLE_ENDIAN = sys.byteorder == 'little'
+UNSET = object()
+
+# "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
+
+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
+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,
+}
+
+
+# =====================================================================
+# --- utils
+# =====================================================================
+
+
+def readlink(path):
+ """Wrapper around os.readlink()."""
+ assert isinstance(path, str), 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.
+ """
+ # Re-adapted 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 = f"/sys/block/{name}"
+ else:
+ path = f"/sys/block/{name}/device"
+ return os.access(path, os.F_OK)
+
+
+@memoize
+def _scputimes_ntuple(procfs_path):
+ """Return 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.
+ """
+ with open_binary(f"{procfs_path}/stat") 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')
+ return namedtuple('scputimes', fields)
+
+
+# Set it into _ntuples.py namespace.
+try:
+ ntp.scputimes = _scputimes_ntuple("/proc")
+except Exception as err: # noqa: BLE001
+ # Don't want to crash at import time.
+ debug(f"ignoring exception on import: {err!r}")
+ ntp.scputimes = namedtuple('scputimes', 'user system idle')(0.0, 0.0, 0.0)
+
+# XXX: must be available also at this module level in order to be
+# serialized (tests/test_misc.py::TestMisc::test_serialization).
+scputimes = ntp.scputimes
+
+
+# =====================================================================
+# --- system memory
+# =====================================================================
+
+
+def calculate_avail_vmem(mems):
+ """Fallback for kernels < 3.14 where /proc/meminfo does not provide
+ "MemAvailable", 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
+
+ We use this function also when "MemAvailable" returns 0 (possibly a
+ kernel bug, see: https://github.com/giampaolo/psutil/issues/1915).
+ In that case this routine matches "free" CLI tool result ("available"
+ column).
+
+ XXX: on recent kernels this calculation may differ by ~1.5% compared
+ to "MemAvailable:", as it's calculated slightly differently.
+ It is still way more realistic than doing (free + cached) though.
+ See:
+ * https://gitlab.com/procps-ng/procps/issues/42
+ * https://github.com/famzah/linux-memavailable-procfs/issues/2
+ """
+ # Note about "fallback" value. According to:
+ # https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/
+ # commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
+ # ...long ago "available" memory was calculated as (free + cached),
+ # We use fallback when one of these is missing from /proc/meminfo:
+ # "Active(file)": introduced in 2.6.28 / Dec 2008
+ # "Inactive(file)": introduced in 2.6.28 / Dec 2008
+ # "SReclaimable": introduced in 2.6.19 / Nov 2006
+ # /proc/zoneinfo: introduced in 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 as err:
+ debug(
+ f"{err.args[0]} is missing from /proc/meminfo; using an"
+ " approximation for calculating available memory"
+ )
+ return fallback
+ try:
+ f = open_binary(f"{get_procfs_path()}/zoneinfo")
+ except OSError:
+ 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
+
+ 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 mimics procps-ng-3.3.12, aka "free" CLI tool:
+ https://gitlab.com/procps-ng/procps/blob/
+ 24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c#L778-791
+ The returned values are supposed to match both "free" and "vmstat -s"
+ CLI tools.
+ """
+ missing_fields = []
+ mems = {}
+ with open_binary(f"{get_procfs_path()}/meminfo") 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
+
+ # - 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)
+ else:
+ if avail == 0:
+ # Yes, it can happen (probably a kernel bug):
+ # https://github.com/giampaolo/psutil/issues/1915
+ # In this case "free" CLI tool makes an estimate. We do the same,
+ # and it matches "free" CLI tool.
+ avail = calculate_avail_vmem(mems)
+
+ if avail < 0:
+ avail = 0
+ missing_fields.append('available')
+ elif avail > total:
+ # 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
+ avail = free
+
+ used = total - avail
+
+ percent = usage_percent((total - avail), total, round_=1)
+
+ # Warn about missing metrics which are set to 0.
+ if missing_fields:
+ msg = "{} memory stats couldn't be determined and {} set to 0".format(
+ ", ".join(missing_fields),
+ "was" if len(missing_fields) == 1 else "were",
+ )
+ warnings.warn(msg, RuntimeWarning, stacklevel=2)
+
+ return ntp.svmem(
+ total,
+ avail,
+ percent,
+ used,
+ free,
+ active,
+ inactive,
+ buffers,
+ cached,
+ shared,
+ slab,
+ )
+
+
+def swap_memory():
+ """Return swap memory metrics."""
+ mems = {}
+ with open_binary(f"{get_procfs_path()}/meminfo") 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(f"{get_procfs_path()}/vmstat")
+ except OSError as err:
+ # see https://github.com/giampaolo/psutil/issues/722
+ msg = (
+ "'sin' and 'sout' swap memory stats couldn't "
+ f"be determined and were set to 0 ({err})"
+ )
+ warnings.warn(msg, RuntimeWarning, stacklevel=2)
+ 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 "
+ msg += "be determined and were set to 0"
+ warnings.warn(msg, RuntimeWarning, stacklevel=2)
+ sin = sout = 0
+ return ntp.sswap(total, used, free, percent, sin, sout)
+
+
+# malloc / heap functions; require glibc
+if hasattr(cext, "heap_info"):
+ heap_info = cext.heap_info
+ heap_trim = cext.heap_trim
+
+
+# =====================================================================
+# --- 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()
+ with open_binary(f"{procfs_path}/stat") as f:
+ values = f.readline().split()
+ fields = values[1 : len(ntp.scputimes._fields) + 1]
+ fields = [float(x) / CLOCK_TICKS for x in fields]
+ return ntp.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()
+ cpus = []
+ with open_binary(f"{procfs_path}/stat") 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(ntp.scputimes._fields) + 1]
+ fields = [float(x) / CLOCK_TICKS for x in fields]
+ entry = ntp.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(f"{get_procfs_path()}/cpuinfo") 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(f"{get_procfs_path()}/stat") 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_cores():
+ """Return the number of CPU cores in the system."""
+ # Method #1
+ ls = set()
+ # These 2 files are the same but */core_cpus_list is newer while
+ # */thread_siblings_list is deprecated and may disappear in the future.
+ # https://www.kernel.org/doc/Documentation/admin-guide/cputopology.rst
+ # https://github.com/giampaolo/psutil/pull/1727#issuecomment-707624964
+ # https://lkml.org/lkml/2019/2/26/41
+ p1 = "/sys/devices/system/cpu/cpu[0-9]*/topology/core_cpus_list"
+ p2 = "/sys/devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list"
+ for path in glob.glob(p1) or glob.glob(p2):
+ with open_binary(path) as f:
+ ls.add(f.read().strip())
+ result = len(ls)
+ if result != 0:
+ return result
+
+ # Method #2
+ mapping = {}
+ current_info = {}
+ with open_binary(f"{get_procfs_path()}/cpuinfo") as f:
+ for line in f:
+ line = line.strip().lower()
+ if not line:
+ # new section
+ try:
+ mapping[current_info[b'physical id']] = current_info[
+ b'cpu cores'
+ ]
+ except KeyError:
+ pass
+ current_info = {}
+ elif line.startswith((b'physical id', b'cpu cores')):
+ # ongoing section
+ key, value = line.split(b'\t:', 1)
+ current_info[key] = int(value)
+
+ result = sum(mapping.values())
+ return result or None # mimic os.cpu_count()
+
+
+def cpu_stats():
+ """Return various CPU stats as a named tuple."""
+ with open_binary(f"{get_procfs_path()}/stat") 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 ntp.scpustats(ctx_switches, interrupts, soft_interrupts, syscalls)
+
+
+def _cpu_get_cpuinfo_freq():
+ """Return current CPU frequency from cpuinfo if available."""
+ with open_binary(f"{get_procfs_path()}/cpuinfo") as f:
+ return [
+ float(line.split(b':', 1)[1])
+ for line in f
+ if line.lower().startswith(b'cpu mhz')
+ ]
+
+
+if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") 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.
+ """
+ cpuinfo_freqs = _cpu_get_cpuinfo_freq()
+ paths = glob.glob(
+ "/sys/devices/system/cpu/cpufreq/policy[0-9]*"
+ ) or glob.glob("/sys/devices/system/cpu/cpu[0-9]*/cpufreq")
+ paths.sort(key=lambda x: int(re.search(r"[0-9]+", x).group()))
+ ret = []
+ pjoin = os.path.join
+ for i, path in enumerate(paths):
+ if len(paths) == len(cpuinfo_freqs):
+ # take cached value from cpuinfo if available, see:
+ # https://github.com/giampaolo/psutil/issues/1851
+ curr = cpuinfo_freqs[i] * 1000
+ else:
+ curr = bcat(pjoin(path, "scaling_cur_freq"), fallback=None)
+ if curr is None:
+ # Likely an old RedHat, see:
+ # https://github.com/giampaolo/psutil/issues/1071
+ curr = bcat(pjoin(path, "cpuinfo_cur_freq"), fallback=None)
+ if curr is None:
+ online_path = f"/sys/devices/system/cpu/cpu{i}/online"
+ # if cpu core is offline, set to all zeroes
+ if cat(online_path, fallback=None) == "0\n":
+ ret.append(ntp.scpufreq(0.0, 0.0, 0.0))
+ continue
+ msg = "can't find current frequency file"
+ raise NotImplementedError(msg)
+ curr = int(curr) / 1000
+ max_ = int(bcat(pjoin(path, "scaling_max_freq"))) / 1000
+ min_ = int(bcat(pjoin(path, "scaling_min_freq"))) / 1000
+ ret.append(ntp.scpufreq(curr, min_, max_))
+ return ret
+
+else:
+
+ def cpu_freq():
+ """Alternate implementation using /proc/cpuinfo.
+ min and max frequencies are not available and are set to None.
+ """
+ return [ntp.scpufreq(x, 0.0, 0.0) for x in _cpu_get_cpuinfo_freq()]
+
+
+# =====================================================================
+# --- network
+# =====================================================================
+
+
+net_if_addrs = cext.net_if_addrs
+
+
+class _Ipv6UnsupportedError(Exception):
+ pass
+
+
+class NetConnections:
+ """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):
+ # The string represents the basename of the corresponding
+ # /proc/net/{proto_name} file.
+ 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(f"{self._procfs_path}/{pid}/fd"):
+ try:
+ inode = readlink(f"{self._procfs_path}/{pid}/fd/{fd}")
+ except (FileNotFoundError, ProcessLookupError):
+ # ENOENT == file which is gone in the meantime;
+ # os.stat(f"/proc/{self.pid}") will be done later
+ # to force NSP (if it's the case)
+ continue
+ except OSError as err:
+ if err.errno == errno.EINVAL:
+ # not a link
+ continue
+ if err.errno == errno.ENAMETOOLONG:
+ # file name too long
+ debug(err)
+ continue
+ 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 (FileNotFoundError, ProcessLookupError, PermissionError):
+ # 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.
+ continue
+ 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 ()
+ 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
+ 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 from None
+ raise
+ return ntp.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) 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:
+ msg = (
+ f"error while parsing {file}; malformed line"
+ f" {lineno} {line!r}"
+ )
+ raise RuntimeError(msg) from None
+ 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("ambiguous 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 = NetConnections.decode_address(laddr, family)
+ raddr = NetConnections.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) 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
+ msg = (
+ f"error while parsing {file}; malformed line {line!r}"
+ )
+ raise RuntimeError(msg) # noqa: B904
+ if inode in inodes: # noqa: SIM108
+ # 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:
+ path = tokens[-1] if len(tokens) == 8 else ''
+ type_ = _common.socktype_to_enum(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):
+ 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 proto_name, family, type_ in self.tmap[kind]:
+ path = f"{self._procfs_path}/net/{proto_name}"
+ if family in {socket.AF_INET, socket.AF_INET6}:
+ ls = self.process_inet(
+ path, family, type_, inodes, filter_pid=pid
+ )
+ else:
+ ls = self.process_unix(path, family, inodes, filter_pid=pid)
+ for fd, family, type_, laddr, raddr, status, bound_pid in ls:
+ if pid:
+ conn = ntp.pconn(fd, family, type_, laddr, raddr, status)
+ else:
+ conn = ntp.sconn(
+ fd, family, type_, laddr, raddr, status, bound_pid
+ )
+ ret.add(conn)
+ return list(ret)
+
+
+_net_connections = NetConnections()
+
+
+def net_connections(kind='inet'):
+ """Return system-wide open connections."""
+ return _net_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(f"{get_procfs_path()}/net/dev") 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, # unused
+ ) = 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.net_if_mtu(name)
+ flags = cext.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
+ debug(err)
+ else:
+ output_flags = ','.join(flags)
+ isup = 'running' in flags
+ ret[name] = ntp.snicstats(
+ isup, duplex_map[duplex], speed, mtu, output_flags
+ )
+ 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"
+ # 5.5 has 2 more fields.
+ # See:
+ # https://www.kernel.org/doc/Documentation/iostats.txt
+ # https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats
+ with open_text(f"{get_procfs_path()}/diskstats") as f:
+ lines = f.readlines()
+ for line in lines:
+ fields = line.split()
+ flen = len(fields)
+ # fmt: off
+ 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:
+ msg = f"not sure how to interpret line {line!r}"
+ raise ValueError(msg)
+ yield (name, reads, writes, rbytes, wbytes, rtime, wtime,
+ reads_merged, writes_merged, busy_time)
+ # fmt: on
+
+ 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)
+ # fmt: off
+ (reads, reads_merged, rbytes, rtime, writes, writes_merged,
+ wbytes, wtime, _, busy_time) = map(int, fields[:10])
+ yield (name, reads, writes, rbytes, wbytes, rtime,
+ wtime, reads_merged, writes_merged, busy_time)
+ # fmt: on
+
+ if os.path.exists(f"{get_procfs_path()}/diskstats"):
+ gen = read_procfs()
+ elif os.path.exists('/sys/block'):
+ gen = read_sysfs()
+ else:
+ msg = (
+ f"{get_procfs_path()}/diskstats nor /sys/block are available on"
+ " this system"
+ )
+ raise NotImplementedError(msg)
+
+ retdict = {}
+ for entry in gen:
+ # fmt: off
+ (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)
+ # fmt: on
+
+ return retdict
+
+
+class RootFsDeviceFinder:
+ """disk_partitions() may return partitions with device == "/dev/root"
+ or "rootfs". This container class uses different strategies to try to
+ obtain the real device path. Resources:
+ https://bootlin.com/blog/find-root-device/
+ https://www.systutorials.com/how-to-find-the-disk-where-root-is-on-in-bash-on-linux/.
+ """
+
+ __slots__ = ['major', 'minor']
+
+ def __init__(self):
+ dev = os.stat("/").st_dev
+ self.major = os.major(dev)
+ self.minor = os.minor(dev)
+
+ def ask_proc_partitions(self):
+ with open_text(f"{get_procfs_path()}/partitions") as f:
+ for line in f.readlines()[2:]:
+ fields = line.split()
+ if len(fields) < 4: # just for extra safety
+ continue
+ major = int(fields[0]) if fields[0].isdigit() else None
+ minor = int(fields[1]) if fields[1].isdigit() else None
+ name = fields[3]
+ if major == self.major and minor == self.minor:
+ if name: # just for extra safety
+ return f"/dev/{name}"
+
+ def ask_sys_dev_block(self):
+ path = f"/sys/dev/block/{self.major}:{self.minor}/uevent"
+ with open_text(path) as f:
+ for line in f:
+ if line.startswith("DEVNAME="):
+ name = line.strip().rpartition("DEVNAME=")[2]
+ if name: # just for extra safety
+ return f"/dev/{name}"
+
+ def ask_sys_class_block(self):
+ needle = f"{self.major}:{self.minor}"
+ files = glob.iglob("/sys/class/block/*/dev")
+ for file in files:
+ try:
+ f = open_text(file)
+ except FileNotFoundError: # race condition
+ continue
+ else:
+ with f:
+ data = f.read().strip()
+ if data == needle:
+ name = os.path.basename(os.path.dirname(file))
+ return f"/dev/{name}"
+
+ def find(self):
+ path = None
+ if path is None:
+ try:
+ path = self.ask_proc_partitions()
+ except OSError as err:
+ debug(err)
+ if path is None:
+ try:
+ path = self.ask_sys_dev_block()
+ except OSError as err:
+ debug(err)
+ if path is None:
+ try:
+ path = self.ask_sys_class_block()
+ except OSError as err:
+ debug(err)
+ # We use exists() because the "/dev/*" part of the path is hard
+ # coded, so we want to be sure.
+ if path is not None and os.path.exists(path):
+ return path
+
+
+def disk_partitions(all=False):
+ """Return mounted disk partitions as a list of namedtuples."""
+ fstypes = set()
+ procfs_path = get_procfs_path()
+ if not all:
+ with open_text(f"{procfs_path}/filesystems") 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" and os.path.isfile('/etc/mtab'):
+ mounts_path = os.path.realpath("/etc/mtab")
+ else:
+ mounts_path = os.path.realpath(f"{procfs_path}/self/mounts")
+
+ retlist = []
+ partitions = cext.disk_partitions(mounts_path)
+ for partition in partitions:
+ device, mountpoint, fstype, opts = partition
+ if device == 'none':
+ device = ''
+ if device in {"/dev/root", "rootfs"}:
+ device = RootFsDeviceFinder().find() or device
+ if not all:
+ if not device or fstype not in fstypes:
+ continue
+ ntuple = ntp.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({x.split('_')[0] for x in basenames})
+
+ # Only add the coretemp hwmon entries if they're not already in
+ # /sys/class/hwmon/
+ # https://github.com/giampaolo/psutil/issues/1708
+ # https://github.com/giampaolo/psutil/pull/1648
+ basenames2 = glob.glob(
+ '/sys/devices/platform/coretemp.*/hwmon/hwmon*/temp*_*'
+ )
+ repl = re.compile(r"/sys/devices/platform/coretemp.*/hwmon/")
+ for name in basenames2:
+ altname = repl.sub('/sys/class/hwmon/', name)
+ if altname not in basenames:
+ basenames.append(name)
+
+ for base in basenames:
+ try:
+ path = base + '_input'
+ current = float(bcat(path)) / 1000.0
+ path = os.path.join(os.path.dirname(base), 'name')
+ unit_name = cat(path).strip()
+ except (OSError, ValueError):
+ # 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
+ continue
+
+ high = bcat(base + '_max', fallback=None)
+ critical = bcat(base + '_crit', fallback=None)
+ label = cat(base + '_label', fallback='').strip()
+
+ 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(bcat(path)) / 1000.0
+ path = os.path.join(base, 'type')
+ unit_name = cat(path).strip()
+ except (OSError, ValueError) as err:
+ debug(err)
+ continue
+
+ trip_paths = glob.glob(base + '/trip_point*')
+ trip_points = {
+ '_'.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='').strip()
+ if trip_type == 'critical':
+ critical = bcat(
+ os.path.join(base, trip_point + "_temp"), fallback=None
+ )
+ elif trip_type == 'high':
+ high = bcat(
+ 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({x.split("_")[0] for x in basenames})
+ for base in basenames:
+ try:
+ current = int(bcat(base + '_input'))
+ except OSError as err:
+ debug(err)
+ continue
+ unit_name = cat(os.path.join(os.path.dirname(base), 'name')).strip()
+ label = cat(base + '_label', fallback='').strip()
+ ret[unit_name].append(ntp.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_bcat(*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 = bcat(path, fallback=null)
+ if ret != null:
+ try:
+ return int(ret)
+ except ValueError:
+ return ret.strip()
+ return None
+
+ bats = [
+ x
+ for x in os.listdir(POWER_SUPPLY_PATH)
+ if x.startswith('BAT') or 'battery' in x.lower()
+ ]
+ 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, min(bats))
+
+ # Base metrics.
+ energy_now = multi_bcat(root + "/energy_now", root + "/charge_now")
+ power_now = multi_bcat(root + "/power_now", root + "/current_now")
+ energy_full = multi_bcat(root + "/energy_full", root + "/charge_full")
+ time_to_empty = multi_bcat(root + "/time_to_empty_now")
+
+ # 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 and energy_now 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_bcat(
+ 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="").strip().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
+ elif energy_now is not None and power_now is not None:
+ try:
+ secsleft = int(energy_now / abs(power_now) * 3600)
+ except ZeroDivisionError:
+ secsleft = _common.POWER_TIME_UNKNOWN
+ elif time_to_empty is not None:
+ secsleft = int(time_to_empty * 60)
+ if secsleft < 0:
+ secsleft = _common.POWER_TIME_UNKNOWN
+ else:
+ secsleft = _common.POWER_TIME_UNKNOWN
+
+ return ntp.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, pid = item
+ nt = ntp.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."""
+ path = f"{get_procfs_path()}/stat"
+ with open_binary(path) as f:
+ for line in f:
+ if line.startswith(b'btime'):
+ return float(line.strip().split()[1])
+ msg = f"line 'btime' not found in {path}"
+ raise RuntimeError(msg)
+
+
+# =====================================================================
+# --- processes
+# =====================================================================
+
+
+def pids():
+ """Returns a list of PIDs currently running on the system."""
+ path = get_procfs_path().encode(ENCODING)
+ return [int(x) for x in os.listdir(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 = f"{get_procfs_path()}/{pid}/status"
+ 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
+ msg = f"'Tgid' line not found in {path}"
+ raise ValueError(msg)
+ except (OSError, 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(f"{procfs_path}/{pid}/stat") as f:
+ data = f.read()
+ except (FileNotFoundError, ProcessLookupError):
+ pass
+ except PermissionError as err:
+ raise AccessDenied(pid) from err
+ 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 exceptions into
+ NoSuchProcess and AccessDenied.
+ """
+
+ @functools.wraps(fun)
+ def wrapper(self, *args, **kwargs):
+ pid, name = self.pid, self._name
+ try:
+ return fun(self, *args, **kwargs)
+ except PermissionError as err:
+ raise AccessDenied(pid, name) from err
+ except ProcessLookupError as err:
+ self._raise_if_zombie()
+ raise NoSuchProcess(pid, name) from err
+ except FileNotFoundError as err:
+ self._raise_if_zombie()
+ # /proc/PID directory may still exist, but the files within
+ # it may not, indicating the process is gone, see:
+ # https://github.com/giampaolo/psutil/issues/2418
+ if not os.path.exists(f"{self._procfs_path}/{pid}/stat"):
+ raise NoSuchProcess(pid, name) from err
+ raise
+
+ return wrapper
+
+
+class Process:
+ """Linux process implementation."""
+
+ __slots__ = [
+ "_cache",
+ "_ctime",
+ "_name",
+ "_ppid",
+ "_procfs_path",
+ "pid",
+ ]
+
+ def __init__(self, pid):
+ self.pid = pid
+ self._name = None
+ self._ppid = None
+ self._ctime = None
+ self._procfs_path = get_procfs_path()
+
+ def _is_zombie(self):
+ # Note: most of the times Linux is able to return info about the
+ # process even if it's a zombie, and /proc/{pid} will exist.
+ # There are some exceptions though, like exe(), cmdline() and
+ # memory_maps(). In these cases /proc/{pid}/{file} exists but
+ # it's empty. Instead of returning a "null" value we'll raise an
+ # exception.
+ try:
+ data = bcat(f"{self._procfs_path}/{self.pid}/stat")
+ except OSError:
+ return False
+ else:
+ rpar = data.rfind(b')')
+ status = data[rpar + 2 : rpar + 3]
+ return status == b"Z"
+
+ def _raise_if_zombie(self):
+ if self._is_zombie():
+ raise ZombieProcess(self.pid, self._name, self._ppid)
+
+ def _raise_if_not_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(f"{self._procfs_path}/{self.pid}")
+
+ def _readlink(self, path, fallback=UNSET):
+ # * https://github.com/giampaolo/psutil/issues/503
+ # os.readlink('/proc/pid/exe') may raise ESRCH (ProcessLookupError)
+ # instead of ENOENT (FileNotFoundError) when it races.
+ # * ENOENT may occur also if the path actually exists if PID is
+ # a low PID (~0-20 range).
+ # * https://github.com/giampaolo/psutil/issues/2514
+ try:
+ return readlink(path)
+ except (FileNotFoundError, ProcessLookupError):
+ if os.path.lexists(f"{self._procfs_path}/{self.pid}"):
+ self._raise_if_zombie()
+ if fallback is not UNSET:
+ return fallback
+ raise
+
+ @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 subtract 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.
+ """
+ data = bcat(f"{self._procfs_path}/{self.pid}/stat")
+ # 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 occurrence 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]
+ try:
+ ret['blkio_ticks'] = fields[39] # aka 'delayacct_blkio_ticks'
+ except IndexError:
+ # https://github.com/giampaolo/psutil/issues/2455
+ debug("can't get blkio_ticks, set iowait to 0")
+ ret['blkio_ticks'] = 0
+
+ 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(f"{self._procfs_path}/{self.pid}/status") as f:
+ return f.read()
+
+ @wrap_exceptions
+ @memoize_when_activated
+ def _read_smaps_file(self):
+ with open_binary(f"{self._procfs_path}/{self.pid}/smaps") 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):
+ # XXX - gets changed later and probably needs refactoring
+ return decode(self._parse_stat_file()['name'])
+
+ @wrap_exceptions
+ def exe(self):
+ return self._readlink(
+ f"{self._procfs_path}/{self.pid}/exe", fallback=""
+ )
+
+ @wrap_exceptions
+ def cmdline(self):
+ with open_text(f"{self._procfs_path}/{self.pid}/cmdline") as f:
+ data = f.read()
+ if not data:
+ # may happen in case of zombie process
+ self._raise_if_zombie()
+ 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]
+ cmdline = data.split(sep)
+ # Sometimes last char is a null byte '\0' but the args are
+ # separated by spaces, see: https://github.com/giampaolo/psutil/
+ # issues/1179#issuecomment-552984549
+ if sep == '\x00' and len(cmdline) == 1 and ' ' in data:
+ cmdline = data.split(' ')
+ return cmdline
+
+ @wrap_exceptions
+ def environ(self):
+ with open_text(f"{self._procfs_path}/{self.pid}/environ") 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(f"/proc/{os.getpid()}/io"):
+
+ @wrap_exceptions
+ def io_counters(self):
+ fname = f"{self._procfs_path}/{self.pid}/io"
+ 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:
+ msg = f"{fname} file was empty"
+ raise RuntimeError(msg)
+ try:
+ return ntp.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:
+ msg = (
+ f"{err.args[0]!r} field was not found in {fname}; found"
+ f" fields are {fields!r}"
+ )
+ raise ValueError(msg) from None
+
+ @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
+ iowait = float(values['blkio_ticks']) / CLOCK_TICKS
+ return ntp.pcputimes(
+ utime, stime, children_utime, children_stime, iowait
+ )
+
+ @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)
+
+ @wrap_exceptions
+ def create_time(self, monotonic=False):
+ # The 'starttime' field in /proc/[pid]/stat is expressed in
+ # jiffies (clock ticks per second), a relative value which
+ # represents the number of clock ticks that have passed since
+ # the system booted until the process was created. It never
+ # changes and is unaffected by system clock updates.
+ if self._ctime is None:
+ self._ctime = (
+ float(self._parse_stat_file()['create_time']) / CLOCK_TICKS
+ )
+ if monotonic:
+ return self._ctime
+ # Add the boot time, returning time expressed in seconds since
+ # the epoch. This is subject to system clock updates.
+ return self._ctime + boot_time()
+
+ @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(f"{self._procfs_path}/{self.pid}/statm") as f:
+ vms, rss, shared, text, lib, data, dirty = (
+ int(x) * PAGESIZE for x in f.readline().split()[:7]
+ )
+ return ntp.pmem(rss, vms, shared, text, lib, data, dirty)
+
+ if HAS_PROC_SMAPS_ROLLUP or HAS_PROC_SMAPS:
+
+ def _parse_smaps_rollup(self):
+ # /proc/pid/smaps_rollup was added to Linux in 2017. Faster
+ # than /proc/pid/smaps. It reports higher PSS than */smaps
+ # (from 1k up to 200k higher; tested against all processes).
+ # IMPORTANT: /proc/pid/smaps_rollup is weird, because it
+ # raises ESRCH / ENOENT for many PIDs, even if they're alive
+ # (also as root). In that case we'll use /proc/pid/smaps as
+ # fallback, which is slower but has a +50% success rate
+ # compared to /proc/pid/smaps_rollup.
+ uss = pss = swap = 0
+ with open_binary(
+ f"{self._procfs_path}/{self.pid}/smaps_rollup"
+ ) as f:
+ for line in f:
+ if line.startswith(b"Private_"):
+ # Private_Clean, Private_Dirty, Private_Hugetlb
+ uss += int(line.split()[1]) * 1024
+ elif line.startswith(b"Pss:"):
+ pss = int(line.split()[1]) * 1024
+ elif line.startswith(b"Swap:"):
+ swap = int(line.split()[1]) * 1024
+ return (uss, pss, swap)
+
+ @wrap_exceptions
+ def _parse_smaps(
+ 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+)"),
+ ):
+ # /proc/pid/smaps does not exist on kernels < 2.6.14 or if
+ # CONFIG_MMU kernel configuration option is not enabled.
+
+ # Note: using 3 regexes is faster than reading the file
+ # line by line.
+ #
+ # 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 (uss, pss, swap)
+
+ @wrap_exceptions
+ def memory_full_info(self):
+ if HAS_PROC_SMAPS_ROLLUP: # faster
+ try:
+ uss, pss, swap = self._parse_smaps_rollup()
+ except (ProcessLookupError, FileNotFoundError):
+ uss, pss, swap = self._parse_smaps()
+ else:
+ uss, pss, swap = self._parse_smaps()
+ basic_mem = self.memory_info()
+ return ntp.pfullmem(*basic_mem + (uss, pss, swap))
+
+ else:
+ memory_full_info = memory_info
+
+ if HAS_PROC_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: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/proc.txt?id=b76437579d1344b612cf1851ae610c636cec7db0.
+
+ /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, IndexError):
+ if fields[0].startswith(b'VmFlags:'):
+ # see issue #369
+ continue
+ msg = f"don't know how to interpret line {line!r}"
+ raise ValueError(msg) from None
+ yield (current_block.pop(), data)
+
+ data = self._read_smaps_file()
+ # Note: smaps file can be empty for certain processes or for
+ # zombies.
+ if not data:
+ self._raise_if_zombie()
+ 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:
+ path = decode(path)
+ path = path.strip()
+ if path.endswith(' (deleted)') and not path_exists_strict(
+ path
+ ):
+ path = path[:-10]
+ item = (
+ decode(addr),
+ decode(perms),
+ path,
+ data.get(b'Rss:', 0),
+ 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),
+ )
+ ls.append(item)
+ return ls
+
+ @wrap_exceptions
+ def cwd(self):
+ return self._readlink(
+ f"{self._procfs_path}/{self.pid}/cwd", fallback=""
+ )
+
+ @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:
+ msg = (
+ "'voluntary_ctxt_switches' and"
+ " 'nonvoluntary_ctxt_switches'lines were not found in"
+ f" {self._procfs_path}/{self.pid}/status; the kernel is"
+ " probably older than 2.6.23"
+ )
+ raise NotImplementedError(msg)
+ return ntp.pctxsw(int(ctxsw[0]), int(ctxsw[1]))
+
+ @wrap_exceptions
+ def num_threads(self, _num_threads_re=re.compile(br'Threads:\t(\d+)')):
+ # Using a re is faster than iterating over file line by line.
+ data = self._read_status_file()
+ return int(_num_threads_re.findall(data)[0])
+
+ @wrap_exceptions
+ def threads(self):
+ thread_ids = os.listdir(f"{self._procfs_path}/{self.pid}/task")
+ thread_ids.sort()
+ retlist = []
+ hit_enoent = False
+ for thread_id in thread_ids:
+ fname = f"{self._procfs_path}/{self.pid}/task/{thread_id}/stat"
+ try:
+ with open_binary(fname) as f:
+ st = f.read().strip()
+ except (FileNotFoundError, ProcessLookupError):
+ # no such file or directory or no such process;
+ # it means thread disappeared on us
+ hit_enoent = True
+ continue
+ # 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 = ntp.pthread(int(thread_id), utime, stime)
+ retlist.append(ntuple)
+ if hit_enoent:
+ self._raise_if_not_alive()
+ return retlist
+
+ @wrap_exceptions
+ def nice_get(self):
+ # with open_text(f"{self._procfs_path}/{self.pid}/stat") as f:
+ # data = f.read()
+ # return int(data.split()[18])
+
+ # Use C implementation
+ return cext.proc_priority_get(self.pid)
+
+ @wrap_exceptions
+ def nice_set(self, value):
+ return cext.proc_priority_set(self.pid, value)
+
+ # starting from CentOS 6.
+ if HAS_CPU_AFFINITY:
+
+ @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:
+ msg = (
+ f"invalid CPU {cpu!r}; choose between"
+ f" {eligible_cpus!r}"
+ )
+ raise ValueError(msg) from None
+ if cpu not in eligible_cpus:
+ msg = (
+ f"CPU number {cpu} is not eligible; choose"
+ f" between {eligible_cpus}"
+ )
+ raise ValueError(msg) from err
+ 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)
+ ioclass = IOPriority(ioclass)
+ return ntp.pionice(ioclass, value)
+
+ @wrap_exceptions
+ def ionice_set(self, ioclass, value):
+ if value is None:
+ value = 0
+ if value and ioclass in {
+ IOPriority.IOPRIO_CLASS_IDLE,
+ IOPriority.IOPRIO_CLASS_NONE,
+ }:
+ msg = f"{ioclass!r} ioclass accepts no value"
+ raise ValueError(msg)
+ if value < 0 or value > 7:
+ msg = "value not in 0-7 range"
+ raise ValueError(msg)
+ return cext.proc_ioprio_set(self.pid, ioclass, value)
+
+ if hasattr(resource, "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:
+ msg = "can't use prlimit() against PID 0 process"
+ raise ValueError(msg)
+ try:
+ if limits is None:
+ # get
+ return resource.prlimit(self.pid, resource_)
+ else:
+ # set
+ if len(limits) != 2:
+ msg = (
+ "second argument must be a (soft, hard) "
+ f"tuple, got {limits!r}"
+ )
+ raise ValueError(msg)
+ resource.prlimit(self.pid, resource_, limits)
+ except OSError as err:
+ if err.errno == errno.ENOSYS:
+ # I saw this happening on Travis:
+ # https://travis-ci.org/giampaolo/psutil/jobs/51368273
+ self._raise_if_zombie()
+ raise
+
+ @wrap_exceptions
+ def status(self):
+ letter = self._parse_stat_file()['status']
+ 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(f"{self._procfs_path}/{self.pid}/fd")
+ hit_enoent = False
+ for fd in files:
+ file = f"{self._procfs_path}/{self.pid}/fd/{fd}"
+ try:
+ path = readlink(file)
+ except (FileNotFoundError, ProcessLookupError):
+ # ENOENT == file which is gone in the meantime
+ hit_enoent = True
+ continue
+ except OSError as err:
+ if err.errno == errno.EINVAL:
+ # not a link
+ continue
+ if err.errno == errno.ENAMETOOLONG:
+ # file name too long
+ debug(err)
+ continue
+ 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 = f"{self._procfs_path}/{self.pid}/fdinfo/{fd}"
+ try:
+ with open_binary(file) as f:
+ pos = int(f.readline().split()[1])
+ flags = int(f.readline().split()[1], 8)
+ except (FileNotFoundError, ProcessLookupError):
+ # fd gone in the meantime; process may
+ # still be alive
+ hit_enoent = True
+ else:
+ mode = file_flags_to_mode(flags)
+ ntuple = ntp.popenfile(
+ path, int(fd), int(pos), mode, flags
+ )
+ retlist.append(ntuple)
+ if hit_enoent:
+ self._raise_if_not_alive()
+ return retlist
+
+ @wrap_exceptions
+ def net_connections(self, kind='inet'):
+ ret = _net_connections.retrieve(kind, self.pid)
+ self._raise_if_not_alive()
+ return ret
+
+ @wrap_exceptions
+ def num_fds(self):
+ return len(os.listdir(f"{self._procfs_path}/{self.pid}/fd"))
+
+ @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 ntp.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 ntp.pgids(int(real), int(effective), int(saved))
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_psosx.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_psosx.py
new file mode 100644
index 0000000000000000000000000000000000000000..b14d5e023bec1f9cb5cb06b4caf7170489f3d4c7
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_psosx.py
@@ -0,0 +1,549 @@
+# 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 errno
+import functools
+import os
+
+from . import _common
+from . import _ntuples as ntp
+from . import _psposix
+from . import _psutil_osx as cext
+from ._common import AccessDenied
+from ._common import NoSuchProcess
+from ._common import ZombieProcess
+from ._common import conn_tmap
+from ._common import conn_to_ntuple
+from ._common import debug
+from ._common import isfile_strict
+from ._common import memoize_when_activated
+from ._common import parse_environ_block
+from ._common import usage_percent
+
+__extra__all__ = []
+
+
+# =====================================================================
+# --- globals
+# =====================================================================
+
+
+PAGESIZE = cext.getpagesize()
+AF_LINK = cext.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,
+)
+
+
+# =====================================================================
+# --- 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/master/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 ntp.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 ntp.sswap(total, used, free, percent, sin, sout)
+
+
+# malloc / heap functions
+heap_info = cext.heap_info
+heap_trim = cext.heap_trim
+
+
+# =====================================================================
+# --- CPU
+# =====================================================================
+
+
+def cpu_times():
+ """Return system CPU times as a namedtuple."""
+ user, nice, system, idle = cext.cpu_times()
+ return ntp.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 = ntp.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_cores():
+ """Return the number of CPU cores in the system."""
+ return cext.cpu_count_cores()
+
+
+def cpu_stats():
+ ctx_switches, interrupts, soft_interrupts, syscalls, _traps = (
+ cext.cpu_stats()
+ )
+ return ntp.scpustats(ctx_switches, interrupts, soft_interrupts, syscalls)
+
+
+if cext.has_cpu_freq(): # not always available on ARM64
+
+ 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 [ntp.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 = ntp.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 ntp.sbattery(percent, secsleft, power_plugged)
+
+
+# =====================================================================
+# --- network
+# =====================================================================
+
+
+net_io_counters = cext.net_io_counters
+net_if_addrs = cext.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).net_connections(kind)
+ except NoSuchProcess:
+ continue
+ else:
+ if cons:
+ for c in cons:
+ c = list(c) + [pid]
+ ret.append(ntp.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.net_if_mtu(name)
+ flags = cext.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:
+ if hasattr(_common, 'NicDuplex'):
+ duplex = _common.NicDuplex(duplex)
+ output_flags = ','.join(flags)
+ isup = 'running' in flags
+ ret[name] = ntp.snicstats(isup, duplex, speed, mtu, output_flags)
+ return ret
+
+
+# =====================================================================
+# --- other system functions
+# =====================================================================
+
+
+def boot_time():
+ """The system boot time expressed in seconds since the epoch."""
+ return cext.boot_time()
+
+
+try:
+ INIT_BOOT_TIME = boot_time()
+except Exception as err: # noqa: BLE001
+ # Don't want to crash at import time.
+ debug(f"ignoring exception on import: {err!r}")
+ INIT_BOOT_TIME = 0
+
+
+def adjust_proc_create_time(ctime):
+ """Account for system clock updates."""
+ if INIT_BOOT_TIME == 0:
+ return ctime
+
+ diff = INIT_BOOT_TIME - boot_time()
+ if diff == 0 or abs(diff) < 1:
+ return ctime
+
+ debug("system clock was updated; adjusting process create_time()")
+ if diff < 0:
+ return ctime - diff
+ return ctime + diff
+
+
+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 = ntp.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):
+ pid, ppid, name = self.pid, self._ppid, self._name
+ try:
+ return fun(self, *args, **kwargs)
+ except ProcessLookupError as err:
+ if cext.proc_is_zombie(pid):
+ raise ZombieProcess(pid, name, ppid) from err
+ raise NoSuchProcess(pid, name) from err
+ except PermissionError as err:
+ raise AccessDenied(pid, name) from err
+ except cext.ZombieProcessError as err:
+ raise ZombieProcess(pid, name, ppid) from err
+
+ return wrapper
+
+
+class Process:
+ """Wrapper class around underlying C implementation."""
+
+ __slots__ = ["_cache", "_name", "_ppid", "pid"]
+
+ 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.
+ 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):
+ return cext.proc_exe(self.pid)
+
+ @wrap_exceptions
+ def cmdline(self):
+ return cext.proc_cmdline(self.pid)
+
+ @wrap_exceptions
+ def environ(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):
+ return cext.proc_cwd(self.pid)
+
+ @wrap_exceptions
+ def uids(self):
+ rawtuple = self._get_kinfo_proc()
+ return ntp.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 ntp.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 ntp.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 ntp.pfullmem(*basic_mem + (uss,))
+
+ @wrap_exceptions
+ def cpu_times(self):
+ rawtuple = self._get_pidtaskinfo()
+ return ntp.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, monotonic=False):
+ ctime = self._get_kinfo_proc()[kinfo_proc_map['ctime']]
+ if not monotonic:
+ ctime = adjust_proc_create_time(ctime)
+ return 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 ntp.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 = []
+ rawlist = cext.proc_open_files(self.pid)
+ for path, fd in rawlist:
+ if isfile_strict(path):
+ ntuple = ntp.popenfile(path, fd)
+ files.append(ntuple)
+ return files
+
+ @wrap_exceptions
+ def net_connections(self, kind='inet'):
+ families, types = conn_tmap[kind]
+ rawlist = cext.proc_net_connections(self.pid, families, types)
+ ret = []
+ for item in rawlist:
+ fd, fam, type, laddr, raddr, status = item
+ nt = conn_to_ntuple(
+ fd, fam, type, laddr, raddr, status, TCP_STATUSES
+ )
+ ret.append(nt)
+ return ret
+
+ @wrap_exceptions
+ def num_fds(self):
+ if self.pid == 0:
+ return 0
+ return cext.proc_num_fds(self.pid)
+
+ @wrap_exceptions
+ def wait(self, timeout=None):
+ return _psposix.wait_pid(self.pid, timeout)
+
+ @wrap_exceptions
+ def nice_get(self):
+ return cext.proc_priority_get(self.pid)
+
+ @wrap_exceptions
+ def nice_set(self, value):
+ return cext.proc_priority_set(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 = ntp.pthread(thread_id, utime, stime)
+ retlist.append(ntuple)
+ return retlist
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_psposix.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_psposix.py
new file mode 100644
index 0000000000000000000000000000000000000000..c7ad2fdabd30ee585642b49e38db9afc489b6ede
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_psposix.py
@@ -0,0 +1,363 @@
+# 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 enum
+import errno
+import glob
+import os
+import select
+import signal
+import time
+
+from . import _ntuples as ntp
+from ._common import MACOS
+from ._common import TimeoutExpired
+from ._common import debug
+from ._common import memoize
+from ._common import usage_percent
+
+if MACOS:
+ from . import _psutil_osx
+
+
+__all__ = ['pid_exists', 'wait_pid', 'disk_usage', 'get_terminal_map']
+
+
+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 ProcessLookupError:
+ return False
+ except PermissionError:
+ # EPERM clearly means there's a process to deny access to
+ return True
+ # According to "man 2 kill" possible error values are
+ # (EINVAL, EPERM, ESRCH)
+ else:
+ return True
+
+
+Negsignal = enum.IntEnum(
+ 'Negsignal', {x.name: -x.value for x in signal.Signals}
+)
+
+
+def negsig_to_enum(num):
+ """Convert a negative signal value to an enum."""
+ try:
+ return Negsignal(num)
+ except ValueError:
+ return num
+
+
+def convert_exit_code(status):
+ """Convert a os.waitpid() status to an exit code."""
+ if os.WIFEXITED(status):
+ # Process terminated normally by calling exit(3) or _exit(2),
+ # or by returning from main(). The return value is the
+ # positive integer passed to *exit().
+ return os.WEXITSTATUS(status)
+ if os.WIFSIGNALED(status):
+ # Process exited due to a signal. Return the negative value
+ # of that signal.
+ return negsig_to_enum(-os.WTERMSIG(status))
+ # if os.WIFSTOPPED(status):
+ # # Process was stopped via SIGSTOP or is being traced, and
+ # # waitpid() was called with WUNTRACED flag. PID is still
+ # # alive. From now on waitpid() will keep returning (0, 0)
+ # # until the process state doesn't change.
+ # # It may make sense to catch/enable this since stopped PIDs
+ # # ignore SIGTERM.
+ # interval = sleep(interval)
+ # continue
+ # if os.WIFCONTINUED(status):
+ # # Process was resumed via SIGCONT and waitpid() was called
+ # # with WCONTINUED flag.
+ # interval = sleep(interval)
+ # continue
+
+ # Should never happen.
+ msg = f"unknown process exit status {status!r}"
+ raise ValueError(msg)
+
+
+def wait_pid_posix(
+ pid,
+ timeout=None,
+ _waitpid=os.waitpid,
+ _timer=getattr(time, 'monotonic', time.time), # noqa: B008
+ _min=min,
+ _sleep=time.sleep,
+ _pid_exists=pid_exists,
+):
+ """Wait for a process PID to terminate.
+
+ If the process terminated normally by calling exit(3) or _exit(2),
+ or by returning from main(), the return value is the positive integer
+ passed to *exit().
+
+ If it was terminated by a signal it returns the negated value of the
+ signal which caused the termination (e.g. -SIGTERM).
+
+ If PID is not a children of os.getpid() (current process) just
+ wait until the process disappears and return None.
+
+ If PID does not exist at all return None immediately.
+
+ If timeout is specified and process is still alive raise
+ TimeoutExpired.
+
+ If timeout=0 either return immediately or raise TimeoutExpired
+ (non-blocking).
+ """
+ interval = 0.0001
+ max_interval = 0.04
+ flags = 0
+ stop_at = None
+
+ if timeout is not None:
+ flags |= os.WNOHANG
+ if timeout != 0:
+ stop_at = _timer() + timeout
+
+ def sleep_or_timeout(interval):
+ # Sleep for some time and return a new increased interval.
+ if timeout == 0 or (stop_at is not None and _timer() >= stop_at):
+ raise TimeoutExpired(timeout)
+ _sleep(interval)
+ return _min(interval * 2, max_interval)
+
+ # See: https://linux.die.net/man/2/waitpid
+ while True:
+ try:
+ retpid, status = os.waitpid(pid, flags)
+ except ChildProcessError:
+ # 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 _pid_exists(pid):
+ interval = sleep_or_timeout(interval)
+ return None
+ else:
+ if retpid == 0:
+ # WNOHANG flag was used and PID is still running.
+ interval = sleep_or_timeout(interval)
+ else:
+ return convert_exit_code(status)
+
+
+def _waitpid(pid, timeout):
+ """Wrapper around os.waitpid(). PID is supposed to be gone already,
+ it just returns the exit code.
+ """
+ try:
+ retpid, status = os.waitpid(pid, 0)
+ except ChildProcessError:
+ # PID is not a child of os.getpid().
+ return wait_pid_posix(pid, timeout)
+ else:
+ assert retpid != 0
+ return convert_exit_code(status)
+
+
+def wait_pid_pidfd_open(pid, timeout=None):
+ """Wait for PID to terminate using pidfd_open() + poll(). Linux >=
+ 5.3 + Python >= 3.9 only.
+ """
+ try:
+ pidfd = os.pidfd_open(pid, 0)
+ except OSError as err:
+ if err.errno == errno.ESRCH:
+ # No such process. os.waitpid() may still be able to return
+ # the status code.
+ return wait_pid_posix(pid, timeout)
+ if err.errno in {errno.EMFILE, errno.ENFILE, errno.ENODEV}:
+ # EMFILE, ENFILE: too many open files
+ # ENODEV: anonymous inode filesystem not supported
+ debug(f"pidfd_open() failed ({err!r}); use fallback")
+ return wait_pid_posix(pid, timeout)
+ raise
+
+ try:
+ # poll() / select() have the advantage of not requiring any
+ # extra file descriptor, contrary to epoll() / kqueue().
+ # select() crashes if process opens > 1024 FDs, so we use
+ # poll().
+ poller = select.poll()
+ poller.register(pidfd, select.POLLIN)
+ timeout_ms = None if timeout is None else int(timeout * 1000)
+ events = poller.poll(timeout_ms) # wait
+
+ if not events:
+ raise TimeoutExpired(timeout)
+ return _waitpid(pid, timeout)
+ finally:
+ os.close(pidfd)
+
+
+def wait_pid_kqueue(pid, timeout=None):
+ """Wait for PID to terminate using kqueue(). macOS and BSD only."""
+ try:
+ kq = select.kqueue()
+ except OSError as err:
+ if err.errno in {errno.EMFILE, errno.ENFILE}: # too many open files
+ debug(f"kqueue() failed ({err!r}); use fallback")
+ return wait_pid_posix(pid, timeout)
+ raise
+
+ try:
+ kev = select.kevent(
+ pid,
+ filter=select.KQ_FILTER_PROC,
+ flags=select.KQ_EV_ADD | select.KQ_EV_ONESHOT,
+ fflags=select.KQ_NOTE_EXIT,
+ )
+ try:
+ events = kq.control([kev], 1, timeout) # wait
+ except OSError as err:
+ if err.errno in {errno.EACCES, errno.EPERM, errno.ESRCH}:
+ debug(f"kqueue.control() failed ({err!r}); use fallback")
+ return wait_pid_posix(pid, timeout)
+ raise
+ else:
+ if not events:
+ raise TimeoutExpired(timeout)
+ return _waitpid(pid, timeout)
+ finally:
+ kq.close()
+
+
+@memoize
+def can_use_pidfd_open():
+ # Availability: Linux >= 5.3, Python >= 3.9
+ if not hasattr(os, "pidfd_open"):
+ return False
+ try:
+ pidfd = os.pidfd_open(os.getpid(), 0)
+ except OSError as err:
+ if err.errno in {errno.EMFILE, errno.ENFILE}: # noqa: SIM103
+ # transitory 'too many open files'
+ return True
+ # likely blocked by security policy like SECCOMP (EPERM,
+ # EACCES, ENOSYS)
+ return False
+ else:
+ os.close(pidfd)
+ return True
+
+
+@memoize
+def can_use_kqueue():
+ # Availability: macOS, BSD
+ names = (
+ "kqueue",
+ "KQ_EV_ADD",
+ "KQ_EV_ONESHOT",
+ "KQ_FILTER_PROC",
+ "KQ_NOTE_EXIT",
+ )
+ if not all(hasattr(select, x) for x in names):
+ return False
+ kq = None
+ try:
+ kq = select.kqueue()
+ kev = select.kevent(
+ os.getpid(),
+ filter=select.KQ_FILTER_PROC,
+ flags=select.KQ_EV_ADD | select.KQ_EV_ONESHOT,
+ fflags=select.KQ_NOTE_EXIT,
+ )
+ kq.control([kev], 1, 0)
+ return True
+ except OSError as err:
+ if err.errno in {errno.EMFILE, errno.ENFILE}: # noqa: SIM103
+ # transitory 'too many open files'
+ return True
+ return False
+ finally:
+ if kq is not None:
+ kq.close()
+
+
+def wait_pid(pid, timeout=None):
+ # PID 0 passed to waitpid() waits for any child of the current
+ # process to change state.
+ assert pid > 0
+ if timeout is not None:
+ assert timeout >= 0
+
+ if can_use_pidfd_open():
+ return wait_pid_pidfd_open(pid, timeout)
+ elif can_use_kqueue():
+ return wait_pid_kqueue(pid, timeout)
+ else:
+ return wait_pid_posix(pid, timeout)
+
+
+wait_pid.__doc__ = wait_pid_posix.__doc__
+
+
+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.
+ """
+ st = os.statvfs(path)
+ # 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
+ if MACOS:
+ # see: https://github.com/giampaolo/psutil/pull/2152
+ used = _psutil_osx.disk_usage_used(path, used)
+ # 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 ntp.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 FileNotFoundError:
+ pass
+ return ret
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_pssunos.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_pssunos.py
new file mode 100644
index 0000000000000000000000000000000000000000..a0e70581f5a02dfbc8e61a9d26e105ee6160a8aa
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_pssunos.py
@@ -0,0 +1,704 @@
+# 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 functools
+import os
+import socket
+import subprocess
+import sys
+from collections import namedtuple
+from socket import AF_INET
+
+from . import _common
+from . import _ntuples as ntp
+from . import _psposix
+from . import _psutil_sunos as cext
+from ._common import AF_INET6
+from ._common import ENCODING
+from ._common import AccessDenied
+from ._common import NoSuchProcess
+from ._common import ZombieProcess
+from ._common import debug
+from ._common import get_procfs_path
+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
+
+__extra__all__ = ["CONN_IDLE", "CONN_BOUND", "PROCFS_PATH"]
+
+
+# =====================================================================
+# --- globals
+# =====================================================================
+
+
+PAGE_SIZE = cext.getpagesize()
+AF_LINK = cext.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,
+)
+
+
+# =====================================================================
+# --- 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 ntp.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',
+ f"PATH=/usr/sbin:/sbin:{os.environ['PATH']}",
+ 'swap',
+ '-l',
+ ],
+ stdout=subprocess.PIPE,
+ )
+ stdout, _ = p.communicate()
+ stdout = stdout.decode(sys.stdout.encoding)
+ if p.returncode != 0:
+ msg = f"'swap -l' failed (retcode={p.returncode})"
+ raise RuntimeError(msg)
+
+ lines = stdout.strip().split('\n')[1:]
+ if not lines:
+ msg = 'no swap device(s) configured'
+ raise RuntimeError(msg)
+ total = free = 0
+ for line in lines:
+ line = line.split()
+ t, f = line[3:5]
+ total += int(int(t) * 512)
+ free += int(int(f) * 512)
+ used = total - free
+ percent = usage_percent(used, total, round_=1)
+ return ntp.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 ntp.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 [ntp.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_cores():
+ """Return the number of CPU cores in the system."""
+ return cext.cpu_count_cores()
+
+
+def cpu_stats():
+ """Return various CPU stats as a named tuple."""
+ ctx_switches, interrupts, syscalls, _traps = cext.cpu_stats()
+ soft_interrupts = 0
+ return ntp.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.
+ try:
+ if not disk_usage(mountpoint).total:
+ continue
+ except OSError as err:
+ # https://github.com/giampaolo/psutil/issues/1674
+ debug(f"skipping {mountpoint!r}: {err}")
+ continue
+ ntuple = ntp.sdiskpart(device, mountpoint, fstype, opts)
+ retlist.append(ntuple)
+ return retlist
+
+
+# =====================================================================
+# --- network
+# =====================================================================
+
+
+net_io_counters = cext.net_io_counters
+net_if_addrs = cext.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).
+ """
+ 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
+ # TODO: refactor and use _common.conn_to_ntuple.
+ if fam in {AF_INET, AF_INET6}:
+ if laddr:
+ laddr = ntp.addr(*laddr)
+ if raddr:
+ raddr = ntp.addr(*raddr)
+ status = TCP_STATUSES[status]
+ fam = sockfam_to_enum(fam)
+ type_ = socktype_to_enum(type_)
+ if _pid == -1:
+ nt = ntp.sconn(fd, fam, type_, laddr, raddr, status, pid)
+ else:
+ nt = ntp.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] = ntp.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 = ntp.suser(user, tty, hostname, tstamp, pid)
+ retlist.append(nt)
+ return retlist
+
+
+# =====================================================================
+# --- processes
+# =====================================================================
+
+
+def pids():
+ """Returns a list of PIDs currently running on the system."""
+ path = get_procfs_path().encode(ENCODING)
+ return [int(x) for x in os.listdir(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.
+ """
+
+ @functools.wraps(fun)
+ def wrapper(self, *args, **kwargs):
+ pid, ppid, name = self.pid, self._ppid, self._name
+ try:
+ return fun(self, *args, **kwargs)
+ except (FileNotFoundError, ProcessLookupError) 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 not pid_exists(pid):
+ raise NoSuchProcess(pid, name) from err
+ raise ZombieProcess(pid, name, ppid) from err
+ except PermissionError as err:
+ raise AccessDenied(pid, name) from err
+ except OSError as err:
+ if pid == 0:
+ if 0 in pids():
+ raise AccessDenied(pid, name) from err
+ raise
+ raise
+
+ return wrapper
+
+
+class Process:
+ """Wrapper class around underlying C implementation."""
+
+ __slots__ = ["_cache", "_name", "_ppid", "_procfs_path", "pid"]
+
+ 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(f"{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):
+ if self.pid == 0 and not os.path.exists(
+ f"{self._procfs_path}/{self.pid}/psinfo"
+ ):
+ raise AccessDenied(self.pid)
+ 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(f"{self._procfs_path}/{self.pid}/path/a.out")
+ 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]
+
+ @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.proc_priority_set(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 ntp.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 ntp.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 ntp.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(f"{procfs_path}/{self.pid}/path/{x}")
+ except FileNotFoundError:
+ hit_enoent = True
+ continue
+ 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: https://groups.google.com/g/comp.unix.solaris/c/tcqvhTNFCAs
+ procfs_path = self._procfs_path
+ try:
+ return os.readlink(f"{procfs_path}/{self.pid}/path/cwd")
+ except FileNotFoundError:
+ os.stat(f"{procfs_path}/{self.pid}") # raise NSP or AD
+ return ""
+
+ @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 ntp.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(f"{procfs_path}/{self.pid}/lwp")
+ hit_enoent = False
+ for tid in tids:
+ tid = int(tid)
+ try:
+ utime, stime = cext.query_process_thread(
+ self.pid, tid, 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
+ continue
+ # ENOENT == thread gone in meantime
+ if err.errno == errno.ENOENT:
+ hit_enoent = True
+ continue
+ raise
+ else:
+ nt = ntp.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 = f"{procfs_path}/{self.pid}/path"
+ for fd in os.listdir(f"{procfs_path}/{self.pid}/fd"):
+ path = os.path.join(pathdir, fd)
+ if os.path.islink(path):
+ try:
+ file = os.readlink(path)
+ except FileNotFoundError:
+ hit_enoent = True
+ continue
+ else:
+ if isfile_strict(file):
+ retlist.append(ntp.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", str(pid)]
+ p = subprocess.Popen(
+ cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE
+ )
+ stdout, stderr = p.communicate()
+ 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)
+ msg = f"{cmd!r} command error\n{stderr}"
+ raise RuntimeError(msg)
+
+ 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 net_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(f"{self._procfs_path}/{self.pid}")
+
+ # UNIX sockets
+ if kind in {'all', 'unix'}:
+ ret.extend(
+ [ntp.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 "{}-{}".format(
+ 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(f"{procfs_path}/{self.pid}/path/{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 inconsistency with /proc similar
+ # to: http://goo.gl/55XgO
+ name = f"{procfs_path}/{self.pid}/path/{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(f"{self._procfs_path}/{self.pid}/fd"))
+
+ @wrap_exceptions
+ def num_ctx_switches(self):
+ return ntp.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)
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_pswindows.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_pswindows.py
new file mode 100644
index 0000000000000000000000000000000000000000..3ee1eafce0bb08f86df6d08d30a66bb2058c6f7c
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/psutil/_pswindows.py
@@ -0,0 +1,1096 @@
+# 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 enum
+import functools
+import os
+import signal
+import sys
+import threading
+import time
+
+from . import _common
+from . import _ntuples as ntp
+from ._common import ENCODING
+from ._common import AccessDenied
+from ._common import NoSuchProcess
+from ._common import TimeoutExpired
+from ._common import conn_tmap
+from ._common import conn_to_ntuple
+from ._common import debug
+from ._common import isfile_strict
+from ._common import memoize
+from ._common import memoize_when_activated
+from ._common import parse_environ_block
+from ._common import usage_percent
+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
+
+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
+ 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) from err
+ else:
+ raise
+
+
+# process priority constants, import from __init__.py:
+# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx
+# fmt: off
+__extra__all__ = [
+ "win_service_iter", "win_service_get",
+ # Process priority
+ "ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS",
+ "HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS", "NORMAL_PRIORITY_CLASS",
+ "REALTIME_PRIORITY_CLASS",
+ # IO priority
+ "IOPRIO_VERYLOW", "IOPRIO_LOW", "IOPRIO_NORMAL", "IOPRIO_HIGH",
+ # others
+ "CONN_DELETE_TCB", "AF_LINK",
+]
+# fmt: on
+
+
+# =====================================================================
+# --- globals
+# =====================================================================
+
+CONN_DELETE_TCB = "DELETE_TCB"
+ERROR_PARTIAL_COPY = 299
+PYPY = '__pypy__' in sys.builtin_module_names
+
+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,
+}
+
+
+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__)
+
+
+class IOPriority(enum.IntEnum):
+ IOPRIO_VERYLOW = 0
+ IOPRIO_LOW = 1
+ IOPRIO_NORMAL = 2
+ IOPRIO_HIGH = 3
+
+
+globals().update(IOPriority.__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,
+)
+
+
+# =====================================================================
+# --- utils
+# =====================================================================
+
+
+@functools.lru_cache(maxsize=512)
+def convert_dos_path(s):
+ r"""Convert paths using native DOS format like:
+ "\Device\HarddiskVolume1\Windows\systemew\file.txt" or
+ "\??\C:\Windows\systemew\file.txt"
+ into:
+ "C:\Windows\systemew\file.txt".
+ """
+ if s.startswith('\\\\'):
+ return s
+ rawdrive = '\\'.join(s.split('\\')[:3])
+ if rawdrive in {"\\??\\UNC", "\\Device\\Mup"}:
+ rawdrive = '\\'.join(s.split('\\')[:5])
+ driveletter = '\\\\' + '\\'.join(s.split('\\')[3:5])
+ elif rawdrive.startswith('\\??\\'):
+ driveletter = s.split('\\')[2]
+ else:
+ driveletter = cext.QueryDosDevice(rawdrive)
+ remainder = s[len(rawdrive) :]
+ return os.path.join(driveletter, remainder)
+
+
+@memoize
+def getpagesize():
+ return cext.getpagesize()
+
+
+# =====================================================================
+# --- memory
+# =====================================================================
+
+
+def virtual_memory():
+ """System virtual memory as a namedtuple."""
+ mem = cext.virtual_mem()
+ totphys, availphys, _totsys, _availsys = mem
+ total = totphys
+ avail = availphys
+ free = availphys
+ used = total - avail
+ percent = usage_percent((total - avail), total, round_=1)
+ return ntp.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_phys = mem[0]
+ total_system = mem[2]
+
+ # system memory (commit total/limit) is the sum of physical and swap
+ # thus physical memory values need to be subtracted to get swap values
+ total = total_system - total_phys
+ # commit total is incremented immediately (decrementing free_system)
+ # while the corresponding free physical value is not decremented until
+ # pages are accessed, so we can't use free system memory for swap.
+ # instead, we calculate page file usage based on performance counter
+ if total > 0:
+ percentswap = cext.swap_percent()
+ used = int(0.01 * percentswap * total)
+ else:
+ percentswap = 0.0
+ used = 0
+
+ free = total - used
+ percent = round(percentswap, 1)
+ return ntp.sswap(total, used, free, percent, 0, 0)
+
+
+# malloc / heap functions
+heap_info = cext.heap_info
+heap_trim = cext.heap_trim
+
+
+# =====================================================================
+# --- disk
+# =====================================================================
+
+
+disk_io_counters = cext.disk_io_counters
+
+
+def disk_usage(path):
+ """Return disk usage associated with path."""
+ if 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, used, free = cext.disk_usage(path)
+ percent = usage_percent(used, total, round_=1)
+ return ntp.sdiskusage(total, used, free, percent)
+
+
+def disk_partitions(all):
+ """Return disk partitions."""
+ rawlist = cext.disk_partitions(all)
+ return [ntp.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 = ntp.scputimes(
+ *[sum(n) for n in zip(*cext.per_cpu_times())]
+ )
+ return ntp.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 = ntp.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_cores():
+ """Return the number of CPU cores in the system."""
+ return cext.cpu_count_cores()
+
+
+def cpu_stats():
+ """Return CPU statistics."""
+ ctx_switches, interrupts, _dpcs, syscalls = cext.cpu_stats()
+ soft_interrupts = 0
+ return ntp.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 [ntp.scpufreq(float(curr), min_, float(max_))]
+
+
+_loadavg_initialized = False
+_lock = threading.Lock()
+
+
+def _getloadavg_impl():
+ # Drop to 2 decimal points which is what Linux does
+ raw_loads = cext.getloadavg()
+ return tuple(round(load, 2) for load in raw_loads)
+
+
+def getloadavg():
+ """Return the number of processes in the system run queue averaged
+ over the last 1, 5, and 15 minutes respectively as a tuple.
+ """
+ global _loadavg_initialized
+
+ if _loadavg_initialized:
+ return _getloadavg_impl()
+
+ with _lock:
+ if not _loadavg_initialized:
+ cext.init_loadavg_counter()
+ _loadavg_initialized = True
+
+ return _getloadavg_impl()
+
+
+# =====================================================================
+# --- 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).
+ """
+ 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
+ nt = conn_to_ntuple(
+ fd,
+ fam,
+ type,
+ laddr,
+ raddr,
+ status,
+ TCP_STATUSES,
+ pid=pid if _pid == -1 else None,
+ )
+ 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():
+ isup, duplex, speed, mtu = items
+ if hasattr(_common, 'NicDuplex'):
+ duplex = _common.NicDuplex(duplex)
+ ret[name] = ntp.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.
+ """
+ return cext.net_io_counters()
+
+
+def net_if_addrs():
+ """Return the addresses associated to each NIC."""
+ return cext.net_if_addrs()
+
+
+# =====================================================================
+# --- 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 ntp.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
+ also includes the time spent during hybernate / suspend.
+ """
+ # 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 = time.time() - cext.uptime()
+ 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
+ nt = ntp.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(name, 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: # noqa: PLW1641
+ """Represents an installed Windows service."""
+
+ def __init__(self, name, display_name):
+ self._name = name
+ self._display_name = display_name
+
+ def __str__(self):
+ details = f"(name={self._name!r}, display_name={self._display_name!r})"
+ return f"{self.__class__.__name__}{details}"
+
+ def __repr__(self):
+ return f"<{self.__str__()} at {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=display_name,
+ binpath=binpath,
+ username=username,
+ start_type=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 OSError as err:
+ name = self._name
+ if is_permission_err(err):
+ msg = (
+ f"service {name!r} is not querable (not enough privileges)"
+ )
+ raise AccessDenied(pid=None, name=name, msg=msg) from err
+ elif err.winerror in {
+ cext.ERROR_INVALID_NAME,
+ cext.ERROR_SERVICE_DOES_NOT_EXIST,
+ }:
+ msg = f"service {name!r} does not exist"
+ raise NoSuchProcess(pid=None, name=name, msg=msg) from err
+ 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 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 is_permission_err(exc):
+ """Return True if this is a permission error."""
+ assert isinstance(exc, OSError), exc
+ return isinstance(exc, PermissionError) or exc.winerror in {
+ cext.ERROR_ACCESS_DENIED,
+ cext.ERROR_PRIVILEGE_NOT_HELD,
+ }
+
+
+def convert_oserror(exc, pid=None, name=None):
+ """Convert OSError into NoSuchProcess or AccessDenied."""
+ assert isinstance(exc, OSError), exc
+ if is_permission_err(exc):
+ return AccessDenied(pid=pid, name=name)
+ if isinstance(exc, ProcessLookupError):
+ return NoSuchProcess(pid=pid, name=name)
+ raise exc
+
+
+def wrap_exceptions(fun):
+ """Decorator which converts OSError into NoSuchProcess or AccessDenied."""
+
+ @functools.wraps(fun)
+ def wrapper(self, *args, **kwargs):
+ try:
+ return fun(self, *args, **kwargs)
+ except OSError as err:
+ raise convert_oserror(err, pid=self.pid, name=self._name) from err
+
+ return wrapper
+
+
+def retry_error_partial_copy(fun):
+ """Workaround for https://github.com/giampaolo/psutil/issues/875.
+ See: https://stackoverflow.com/questions/4457745#4457745.
+ """
+
+ @functools.wraps(fun)
+ def wrapper(self, *args, **kwargs):
+ delay = 0.0001
+ times = 33
+ for _ in range(times): # retries for roughly 1 second
+ try:
+ return fun(self, *args, **kwargs)
+ except OSError as _:
+ err = _
+ if err.winerror == ERROR_PARTIAL_COPY:
+ time.sleep(delay)
+ delay = min(delay * 2, 0.04)
+ continue
+ raise
+ msg = (
+ f"{fun} retried {times} times, converted to AccessDenied as it's "
+ f"still returning {err}"
+ )
+ raise AccessDenied(pid=self.pid, name=self._name, msg=msg)
+
+ return wrapper
+
+
+class Process:
+ """Wrapper class around underlying C implementation."""
+
+ __slots__ = ["_cache", "_name", "_ppid", "pid"]
+
+ def __init__(self, pid):
+ self.pid = pid
+ self._name = None
+ self._ppid = None
+
+ # --- oneshot() stuff
+
+ def oneshot_enter(self):
+ self._proc_info.cache_activate(self)
+ self.exe.cache_activate(self)
+
+ def oneshot_exit(self):
+ self._proc_info.cache_deactivate(self)
+ self.exe.cache_deactivate(self)
+
+ @memoize_when_activated
+ def _proc_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
+
+ 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"
+ if self.pid == 4:
+ return "System"
+ return os.path.basename(self.exe())
+
+ @wrap_exceptions
+ @memoize_when_activated
+ def exe(self):
+ if PYPY:
+ try:
+ exe = cext.proc_exe(self.pid)
+ except OSError as err:
+ # 24 = ERROR_TOO_MANY_OPEN_FILES. Not sure why this happens
+ # (perhaps PyPy's JIT delaying garbage collection of files?).
+ if err.errno == 24:
+ debug(f"{err!r} translated into AccessDenied")
+ raise AccessDenied(self.pid, self._name) from err
+ raise
+ else:
+ exe = cext.proc_exe(self.pid)
+ if exe.startswith('\\'):
+ return convert_dos_path(exe)
+ return exe # May be "Registry", "MemCompression", ...
+
+ @wrap_exceptions
+ @retry_error_partial_copy
+ 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:
+ return cext.proc_cmdline(self.pid, use_peb=True)
+ except OSError as err:
+ if is_permission_err(err):
+ return cext.proc_cmdline(self.pid, use_peb=False)
+ else:
+ raise
+ else:
+ return cext.proc_cmdline(self.pid, use_peb=True)
+
+ @wrap_exceptions
+ @retry_error_partial_copy
+ def environ(self):
+ s = cext.proc_environ(self.pid)
+ return parse_environ_block(s)
+
+ def ppid(self):
+ try:
+ return ppid_map()[self.pid]
+ except KeyError:
+ raise NoSuchProcess(self.pid, self._name) from None
+
+ def _get_raw_meminfo(self):
+ try:
+ return cext.proc_memory_info(self.pid)
+ except OSError as err:
+ if is_permission_err(err):
+ # TODO: the C ext can probably be refactored in order
+ # to get this from cext.proc_info()
+ debug("attempting memory_info() fallback (slower)")
+ info = self._proc_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 ntp.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 ntp.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.
+ raise convert_oserror(err, self.pid, self._name) from err
+ else:
+ for addr, perm, path, rss in raw:
+ path = convert_dos_path(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):
+ if sig == signal.SIGTERM:
+ cext.proc_kill(self.pid)
+ elif sig in {signal.CTRL_C_EVENT, signal.CTRL_BREAK_EVENT}:
+ os.kill(self.pid, sig)
+ else:
+ msg = (
+ "only SIGTERM, CTRL_C_EVENT and CTRL_BREAK_EVENT signals "
+ "are supported on Windows"
+ )
+ raise ValueError(msg)
+
+ @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 as err:
+ # WaitForSingleObject() returned WAIT_TIMEOUT. Just raise.
+ raise TimeoutExpired(timeout, self.pid, self._name) from err
+ 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 f"{domain}\\{user}"
+
+ @wrap_exceptions
+ def create_time(self, fast_only=False):
+ # Note: proc_times() not put under oneshot() 'cause create_time()
+ # is already cached by the main Process class.
+ try:
+ _user, _system, created = cext.proc_times(self.pid)
+ return created
+ except OSError as err:
+ if is_permission_err(err):
+ if fast_only:
+ raise
+ debug("attempting create_time() fallback (slower)")
+ return self._proc_info()[pinfo_map['create_time']]
+ raise
+
+ @wrap_exceptions
+ def num_threads(self):
+ return self._proc_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 = ntp.pthread(thread_id, utime, stime)
+ retlist.append(ntuple)
+ return retlist
+
+ @wrap_exceptions
+ def cpu_times(self):
+ try:
+ user, system, _created = cext.proc_times(self.pid)
+ except OSError as err:
+ if not is_permission_err(err):
+ raise
+ debug("attempting cpu_times() fallback (slower)")
+ info = self._proc_info()
+ user = info[pinfo_map['user_time']]
+ system = info[pinfo_map['kernel_time']]
+ # Children user/system times are not retrievable (set to 0).
+ return ntp.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
+ @retry_error_partial_copy
+ 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 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):
+ ntuple = ntp.popenfile(file, -1)
+ ret.add(ntuple)
+ return list(ret)
+
+ @wrap_exceptions
+ def net_connections(self, kind='inet'):
+ return net_connections(kind, _pid=self.pid)
+
+ @wrap_exceptions
+ def nice_get(self):
+ value = cext.proc_priority_get(self.pid)
+ value = Priority(value)
+ return value
+
+ @wrap_exceptions
+ def nice_set(self, value):
+ return cext.proc_priority_set(self.pid, value)
+
+ @wrap_exceptions
+ def ionice_get(self):
+ ret = cext.proc_io_priority_get(self.pid)
+ ret = IOPriority(ret)
+ return ret
+
+ @wrap_exceptions
+ def ionice_set(self, ioclass, value):
+ if value:
+ msg = "value argument not accepted on Windows"
+ raise TypeError(msg)
+ if ioclass not in {
+ IOPriority.IOPRIO_VERYLOW,
+ IOPriority.IOPRIO_LOW,
+ IOPriority.IOPRIO_NORMAL,
+ IOPriority.IOPRIO_HIGH,
+ }:
+ msg = f"{ioclass} is not a valid priority"
+ raise ValueError(msg)
+ cext.proc_io_priority_set(self.pid, ioclass)
+
+ @wrap_exceptions
+ def io_counters(self):
+ try:
+ ret = cext.proc_io_counters(self.pid)
+ except OSError as err:
+ if not is_permission_err(err):
+ raise
+ debug("attempting io_counters() fallback (slower)")
+ info = self._proc_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']],
+ )
+ return ntp.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 range(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(ls):
+ if not ls:
+ msg = f"invalid argument {ls!r}"
+ raise ValueError(msg)
+ out = 0
+ for b in ls:
+ 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):
+ msg = f"invalid CPU {cpu!r}; an integer is required"
+ raise TypeError(msg)
+ msg = f"invalid CPU {cpu!r}"
+ raise ValueError(msg)
+
+ 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 is_permission_err(err):
+ debug("attempting num_handles() fallback (slower)")
+ return self._proc_info()[pinfo_map['num_handles']]
+ raise
+
+ @wrap_exceptions
+ def num_ctx_switches(self):
+ ctx_switches = self._proc_info()[pinfo_map['ctx_switches']]
+ # only voluntary ctx switches are supported
+ return ntp.pctxsw(ctx_switches, 0)
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/INSTALLER b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/INSTALLER
new file mode 100644
index 0000000000000000000000000000000000000000..a1b589e38a32041e49332e5e81c2d363dc418d68
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/INSTALLER
@@ -0,0 +1 @@
+pip
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/LICENSE b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..3e3c2f9d5e2bc9c160cda612c58f5fb61df672d0
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016-2025 Tsuyoshi Hombashi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/METADATA b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/METADATA
new file mode 100644
index 0000000000000000000000000000000000000000..013bef3e8bd46cf7b5c6c3b40ec30a4553b338ce
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/METADATA
@@ -0,0 +1,932 @@
+Metadata-Version: 2.1
+Name: pytablewriter
+Version: 1.2.1
+Summary: pytablewriter is a Python library to write a table in various formats: AsciiDoc / CSV / Elasticsearch / HTML / JavaScript / JSON / LaTeX / LDJSON / LTSV / Markdown / MediaWiki / NumPy / Excel / Pandas / Python / reStructuredText / SQLite / TOML / TSV / YAML.
+Home-page: https://github.com/thombashi/pytablewriter
+Author: Tsuyoshi Hombashi
+Author-email: tsuyoshi.hombashi@gmail.com
+License: MIT License
+Project-URL: Changelog, https://github.com/thombashi/pytablewriter/blob/master/CHANGELOG.md
+Project-URL: Documentation, https://pytablewriter.rtfd.io/
+Project-URL: Funding, https://github.com/sponsors/thombashi
+Project-URL: Source, https://github.com/thombashi/pytablewriter
+Project-URL: Tracker, https://github.com/thombashi/pytablewriter/issues
+Keywords: AsciiDoc,table,CSV,Excel,JavaScript,JSON,LaTeX,LTSV,Markdown,MediaWiki,HTML,pandas,reStructuredText,SQLite,TSV,TOML
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: Information Technology
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: 3.11
+Classifier: Programming Language :: Python :: 3.12
+Classifier: Programming Language :: Python :: 3.13
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Software Development :: Code Generators
+Classifier: Topic :: Software Development :: Libraries
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Text Processing
+Classifier: Topic :: Text Processing :: Markup :: HTML
+Classifier: Topic :: Text Processing :: Markup :: LaTeX
+Classifier: Topic :: Text Processing :: Markup :: Markdown
+Classifier: Topic :: Text Processing :: Markup :: reStructuredText
+Classifier: Typing :: Typed
+Requires-Python: >=3.9
+Description-Content-Type: text/x-rst
+License-File: LICENSE
+Requires-Dist: setuptools>=38.3.0
+Requires-Dist: DataProperty<2,>=1.1.0
+Requires-Dist: mbstrdecoder<2,>=1.0.0
+Requires-Dist: pathvalidate<4,>=2.3.0
+Requires-Dist: tabledata<2,>=1.3.1
+Requires-Dist: tcolorpy<1,>=0.0.5
+Requires-Dist: typepy[datetime]<2,>=1.3.2
+Provides-Extra: all
+Requires-Dist: xlwt; extra == "all"
+Requires-Dist: XlsxWriter<4,>=0.9.6; extra == "all"
+Requires-Dist: elasticsearch<9,>=8.0.1; extra == "all"
+Requires-Dist: pytablereader<2,>=0.31.3; extra == "all"
+Requires-Dist: dominate<3,>=2.1.5; extra == "all"
+Requires-Dist: loguru<1,>=0.4.1; extra == "all"
+Requires-Dist: SimpleSQLite<2,>=1.3.2; extra == "all"
+Requires-Dist: pytablewriter-altrow-theme<1,>=0.2.0; extra == "all"
+Requires-Dist: pytablewriter-altcol-theme<1,>=0.1.0; extra == "all"
+Requires-Dist: toml<1,>=0.9.3; extra == "all"
+Requires-Dist: PyYAML<7,>=3.11; extra == "all"
+Requires-Dist: simplejson<4,>=3.8.1; extra == "all"
+Requires-Dist: pandas<3,>=0.25.3; extra == "all"
+Provides-Extra: docs
+Requires-Dist: sphinx_rtd_theme>=1.2.2; extra == "docs"
+Requires-Dist: Sphinx>=2.4; extra == "docs"
+Requires-Dist: xlwt; extra == "docs"
+Requires-Dist: XlsxWriter<4,>=0.9.6; extra == "docs"
+Requires-Dist: elasticsearch<9,>=8.0.1; extra == "docs"
+Requires-Dist: pytablereader<2,>=0.31.3; extra == "docs"
+Requires-Dist: dominate<3,>=2.1.5; extra == "docs"
+Requires-Dist: loguru<1,>=0.4.1; extra == "docs"
+Requires-Dist: SimpleSQLite<2,>=1.3.2; extra == "docs"
+Requires-Dist: pytablewriter-altrow-theme<1,>=0.2.0; extra == "docs"
+Requires-Dist: pytablewriter-altcol-theme<1,>=0.1.0; extra == "docs"
+Requires-Dist: toml<1,>=0.9.3; extra == "docs"
+Requires-Dist: PyYAML<7,>=3.11; extra == "docs"
+Requires-Dist: simplejson<4,>=3.8.1; extra == "docs"
+Requires-Dist: pandas<3,>=0.25.3; extra == "docs"
+Provides-Extra: es
+Requires-Dist: elasticsearch<9,>=8.0.1; extra == "es"
+Provides-Extra: es8
+Requires-Dist: elasticsearch<9,>=8.0.1; extra == "es8"
+Provides-Extra: excel
+Requires-Dist: xlwt; extra == "excel"
+Requires-Dist: XlsxWriter<4,>=0.9.6; extra == "excel"
+Provides-Extra: from
+Requires-Dist: pytablereader<2,>=0.31.3; extra == "from"
+Provides-Extra: html
+Requires-Dist: dominate<3,>=2.1.5; extra == "html"
+Provides-Extra: logging
+Requires-Dist: loguru<1,>=0.4.1; extra == "logging"
+Provides-Extra: pandas
+Requires-Dist: pandas<3,>=0.25.3; extra == "pandas"
+Provides-Extra: sqlite
+Requires-Dist: SimpleSQLite<2,>=1.3.2; extra == "sqlite"
+Provides-Extra: test
+Requires-Dist: pytest-md-report>=0.6.2; extra == "test"
+Requires-Dist: pytablewriter-altcol-theme<1,>=0.1.0; extra == "test"
+Requires-Dist: PyYAML<7,>=3.11; extra == "test"
+Requires-Dist: pytablereader[excel,sqlite]>=0.31.3; extra == "test"
+Requires-Dist: dominate<3,>=2.1.5; extra == "test"
+Requires-Dist: pytablewriter-altrow-theme<1,>=0.2.0; extra == "test"
+Requires-Dist: toml<1,>=0.9.3; extra == "test"
+Requires-Dist: simplejson<4,>=3.8.1; extra == "test"
+Requires-Dist: pytest>=6.0.1; extra == "test"
+Requires-Dist: beautifulsoup4>=4.10; extra == "test"
+Requires-Dist: SimpleSQLite<2,>=1.3.2; extra == "test"
+Requires-Dist: pytablereader<2,>=0.31.3; extra == "test"
+Requires-Dist: elasticsearch<9,>=8.0.1; extra == "test"
+Requires-Dist: xlwt; extra == "test"
+Requires-Dist: tablib>=3.2.0; extra == "test"
+Requires-Dist: sqliteschema>=2; extra == "test"
+Requires-Dist: loguru<1,>=0.4.1; extra == "test"
+Requires-Dist: XlsxWriter<4,>=0.9.6; extra == "test"
+Requires-Dist: pandas<3,>=0.25.3; extra == "test"
+Provides-Extra: theme
+Requires-Dist: pytablewriter-altrow-theme<1,>=0.2.0; extra == "theme"
+Requires-Dist: pytablewriter-altcol-theme<1,>=0.1.0; extra == "theme"
+Provides-Extra: toml
+Requires-Dist: toml<1,>=0.9.3; extra == "toml"
+Provides-Extra: yaml
+Requires-Dist: PyYAML<7,>=3.11; extra == "yaml"
+
+.. contents:: **pytablewriter**
+ :backlinks: top
+ :depth: 2
+
+Summary
+=========
+`pytablewriter `__ is a Python library to write a table in various formats: AsciiDoc / CSV / Elasticsearch / HTML / JavaScript / JSON / LaTeX / LDJSON / LTSV / Markdown / MediaWiki / NumPy / Excel / Pandas / Python / reStructuredText / SQLite / TOML / TSV / YAML.
+
+.. image:: https://badge.fury.io/py/pytablewriter.svg
+ :target: https://badge.fury.io/py/pytablewriter
+ :alt: PyPI package version
+
+.. image:: https://anaconda.org/conda-forge/pytablewriter/badges/version.svg
+ :target: https://anaconda.org/conda-forge/pytablewriter
+ :alt: conda-forge package version
+
+.. image:: https://img.shields.io/pypi/pyversions/pytablewriter.svg
+ :target: https://pypi.org/project/pytablewriter/
+ :alt: Supported Python versions
+
+.. image:: https://img.shields.io/pypi/implementation/pytablewriter.svg
+ :target: https://pypi.org/project/pytablewriter
+ :alt: Supported Python implementations
+
+.. image:: https://github.com/thombashi/pytablewriter/actions/workflows/ci.yml/badge.svg
+ :target: https://github.com/thombashi/pytablewriter/actions/workflows/ci.yml
+ :alt: CI status of Linux/macOS/Windows
+
+.. image:: https://coveralls.io/repos/github/thombashi/pytablewriter/badge.svg?branch=master
+ :target: https://coveralls.io/github/thombashi/pytablewriter?branch=master
+ :alt: Test coverage
+
+.. image:: https://github.com/thombashi/pytablewriter/actions/workflows/github-code-scanning/codeql/badge.svg
+ :target: https://github.com/thombashi/pytablewriter/actions/workflows/github-code-scanning/codeql
+ :alt: CodeQL
+
+Features
+--------
+- Write a table in various formats:
+ - Text formats:
+ - `AsciiDoc `__
+ - CSV / Tab-separated values (TSV) / Space-separated values (SSV)
+ - HTML / CSS
+ - JSON / `Line-delimited JSON(LDJSON) `__
+ - `Labeled Tab-separated Values (LTSV) `__
+ - LaTeX: ``tabular``/``array`` environment
+ - Markdown: CommonMark / `GitHub Flavored Markdown (GFM) `__ / `kramdown `__
+ - `MediaWiki `__
+ - reStructuredText: `Grid Tables `__/`Simple Tables `__/`CSV Table `__
+ - Source code (definition of a variable that represents tabular data)
+ - JavaScript / `NumPy `__ (`numpy.array `__) / `Pandas `__ (`pandas.DataFrame `__) / Python
+ - `TOML `__
+ - `YAML `__
+ - Unicode
+ - Binary file formats:
+ - Microsoft Excel :superscript:`TM` (``.xlsx``/``.xls`` file format)
+ - `pandas.DataFrame `__ pickle file
+ - `SQLite `__ database
+ - Application-specific formats:
+ - `Elasticsearch `__
+- Automatic table cell formatting:
+ - Alignment
+ - Padding
+ - Decimal places of numbers
+- Customize table cell styles:
+ - Text/Background color
+ - Text alignment
+ - Font size/weight
+ - Thousand separator for numbers: e.g. ``1,000``/``1 000``
+- Configure output:
+ - Write a table to a stream such as a file/standard-output/string-buffer/Jupyter-Notebook
+ - Get rendered tabular text
+- Data sources:
+ - nested list
+ - CSV
+ - `pandas.DataFrame `__ / `pandas.Series `__
+ - etc.
+- Multibyte character support
+- ANSI color support
+
+Installation
+============
+
+Installation: pip
+------------------------------
+::
+
+ pip install pytablewriter
+
+Some of the formats require additional dependency packages, you can install these packages as follows:
+
+.. csv-table:: Installation of optional dependencies
+ :header: Installation example, Remark
+
+ ``pip install pytablewriter[es]``, Elasticsearch
+ ``pip install pytablewriter[excel]``, Excel
+ ``pip install pytablewriter[html]``, HTML
+ ``pip install pytablewriter[sqlite]``, SQLite database
+ ``pip install pytablewriter[toml]``, TOML
+ ``pip install pytablewriter[theme]``, pytablewriter theme plugins
+ ``pip install pytablewriter[all]``, Install all of the optional dependencies
+
+Installation: conda
+------------------------------
+::
+
+ conda install -c conda-forge pytablewriter
+
+Installation: apt
+------------------------------
+::
+
+ sudo add-apt-repository ppa:thombashi/ppa
+ sudo apt update
+ sudo apt install python3-pytablewriter
+
+Examples
+==========
+Write tables
+--------------
+Write a Markdown table
+~~~~~~~~~~~~~~~~~~~~~~~~
+:Sample Code:
+ .. code-block:: python
+
+ from pytablewriter import MarkdownTableWriter
+
+ def main():
+ writer = MarkdownTableWriter(
+ table_name="example_table",
+ headers=["int", "float", "str", "bool", "mix", "time"],
+ value_matrix=[
+ [0, 0.1, "hoge", True, 0, "2017-01-01 03:04:05+0900"],
+ [2, "-2.23", "foo", False, None, "2017-12-23 45:01:23+0900"],
+ [3, 0, "bar", "true", "inf", "2017-03-03 33:44:55+0900"],
+ [-10, -9.9, "", "FALSE", "nan", "2017-01-01 00:00:00+0900"],
+ ],
+ )
+ writer.write_table()
+
+ if __name__ == "__main__":
+ main()
+
+:Output:
+ .. code-block::
+
+ # example_table
+ |int|float|str |bool | mix | time |
+ |--:|----:|----|-----|-------:|------------------------|
+ | 0| 0.10|hoge|True | 0|2017-01-01 03:04:05+0900|
+ | 2|-2.23|foo |False| |2017-12-23 12:34:51+0900|
+ | 3| 0.00|bar |True |Infinity|2017-03-03 22:44:55+0900|
+ |-10|-9.90| |False| NaN|2017-01-01 00:00:00+0900|
+
+:Rendering Result:
+ .. figure:: https://cdn.jsdelivr.net/gh/thombashi/pytablewriter@master/docs/pages/examples/table_format/text/ss/markdown.png
+ :alt: https://github.com/thombashi/pytablewriter/blob/master/docs/pages/examples/table_format/text/ss/markdown.png
+
+ Rendered markdown at GitHub
+
+Write a Markdown table with margins
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+:Sample Code:
+ .. code-block:: python
+
+ from pytablewriter import MarkdownTableWriter
+
+ def main():
+ writer = MarkdownTableWriter(
+ table_name="write a table with margins",
+ headers=["int", "float", "str", "bool", "mix", "time"],
+ value_matrix=[
+ [0, 0.1, "hoge", True, 0, "2017-01-01 03:04:05+0900"],
+ [2, "-2.23", "foo", False, None, "2017-12-23 45:01:23+0900"],
+ [3, 0, "bar", "true", "inf", "2017-03-03 33:44:55+0900"],
+ [-10, -9.9, "", "FALSE", "nan", "2017-01-01 00:00:00+0900"],
+ ],
+ margin=1 # add a whitespace for both sides of each cell
+ )
+ writer.write_table()
+
+ if __name__ == "__main__":
+ main()
+
+:Output:
+ .. code-block::
+
+ # write a table with margins
+ | int | float | str | bool | mix | time |
+ | --: | ----: | ---- | ----- | -------: | ------------------------ |
+ | 0 | 0.10 | hoge | True | 0 | 2017-01-01 03:04:05+0900 |
+ | 2 | -2.23 | foo | False | | 2017-12-23 12:34:51+0900 |
+ | 3 | 0.00 | bar | True | Infinity | 2017-03-03 22:44:55+0900 |
+ | -10 | -9.90 | | False | NaN | 2017-01-01 00:00:00+0900 |
+
+``margin`` attribute can be available for all of the text format writer classes.
+
+Write a GitHub Flavored Markdown (GFM) table
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+If you set ``flavor`` keyword argument of ``MarkdownTableWriter`` class to ``"github"`` or ``"gfm"``, the writer will output markdown tables with GitHub flavor.
+GFM can apply some additional styles to tables such as ``fg_color`` (text color).
+
+:Sample Code:
+ .. code-block:: python
+
+ from pytablewriter import MarkdownTableWriter
+ from pytablewriter.style import Style
+
+ writer = MarkdownTableWriter(
+ column_styles=[
+ Style(fg_color="red"),
+ Style(fg_color="green", decoration_line="underline"),
+ ],
+ headers=["A", "B"],
+ value_matrix=[
+ ["abc", 1],
+ ["efg", 2],
+ ],
+ margin=1,
+ flavor="github",
+ enable_ansi_escape=False,
+ )
+ writer.write_table()
+
+Rendered results can be found at `here `__
+
+Apply styles to GFM table with programmatically
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Applying style filters to GFM allows for more flexible style settings for cells.
+See also the `example <#style-filter>`_
+
+Write a Markdown table to a stream or a file
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+`Refer an example `__
+
+Write a table to an Excel sheet
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+:Sample Code:
+ .. code-block:: python
+
+ from pytablewriter import ExcelXlsxTableWriter
+
+ def main():
+ writer = ExcelXlsxTableWriter()
+ writer.table_name = "example"
+ writer.headers = ["int", "float", "str", "bool", "mix", "time"]
+ writer.value_matrix = [
+ [0, 0.1, "hoge", True, 0, "2017-01-01 03:04:05+0900"],
+ [2, "-2.23", "foo", False, None, "2017-12-23 12:34:51+0900"],
+ [3, 0, "bar", "true", "inf", "2017-03-03 22:44:55+0900"],
+ [-10, -9.9, "", "FALSE", "nan", "2017-01-01 00:00:00+0900"],
+ ]
+ writer.dump("sample.xlsx")
+
+ if __name__ == "__main__":
+ main()
+
+:Output:
+ .. figure:: https://cdn.jsdelivr.net/gh/thombashi/pytablewriter@master/docs/pages/examples/table_format/binary/spreadsheet/ss/excel_single.png
+ :alt: https://github.com/thombashi/pytablewriter/blob/master/docs/pages/examples/table_format/binary/spreadsheet/ss/excel_single.png
+
+ Output excel file (``sample_single.xlsx``)
+
+Write a Unicode table
+~~~~~~~~~~~~~~~~~~~~~~~
+:Sample Code:
+ .. code-block:: python
+
+ from pytablewriter import UnicodeTableWriter
+
+ def main():
+ writer = UnicodeTableWriter(
+ table_name="example_table",
+ headers=["int", "float", "str", "bool", "mix", "time"],
+ value_matrix=[
+ [0, 0.1, "hoge", True, 0, "2017-01-01 03:04:05+0900"],
+ [2, "-2.23", "foo", False, None, "2017-12-23 45:01:23+0900"],
+ [3, 0, "bar", "true", "inf", "2017-03-03 33:44:55+0900"],
+ [-10, -9.9, "", "FALSE", "nan", "2017-01-01 00:00:00+0900"],
+ ]
+ )
+ writer.write_table()
+
+ if __name__ == "__main__":
+ main()
+
+:Output:
+ .. code-block::
+
+ ┌───┬─────┬────┬─────┬────────┬────────────────────────┐
+ │int│float│str │bool │ mix │ time │
+ ├───┼─────┼────┼─────┼────────┼────────────────────────┤
+ │ 0│ 0.10│hoge│True │ 0│2017-01-01 03:04:05+0900│
+ ├───┼─────┼────┼─────┼────────┼────────────────────────┤
+ │ 2│-2.23│foo │False│ │2017-12-23 12:34:51+0900│
+ ├───┼─────┼────┼─────┼────────┼────────────────────────┤
+ │ 3│ 0.00│bar │True │Infinity│2017-03-03 22:44:55+0900│
+ ├───┼─────┼────┼─────┼────────┼────────────────────────┤
+ │-10│-9.90│ │False│ NaN│2017-01-01 00:00:00+0900│
+ └───┴─────┴────┴─────┴────────┴────────────────────────┘
+
+Write a table with JavaScript format (as a nested list variable definition)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+:Sample Code:
+ .. code-block:: python
+
+ import pytablewriter as ptw
+
+
+ def main():
+ writer = ptw.JavaScriptTableWriter(
+ table_name="js_variable",
+ headers=["int", "float", "str", "bool", "mix", "time"],
+ value_matrix=[
+ [0, 0.1, "hoge", True, 0, "2017-01-01 03:04:05+0900"],
+ [2, "-2.23", "foo", False, None, "2017-12-23 45:01:23+0900"],
+ [3, 0, "bar", "true", "inf", "2017-03-03 33:44:55+0900"],
+ [-10, -9.9, "", "FALSE", "nan", "2017-01-01 00:00:00+0900"],
+ ],
+ )
+
+ writer.write_table()
+
+
+ if __name__ == "__main__":
+ main()
+
+:Output:
+ .. code-block:: js
+
+ const js_variable = [
+ ["int", "float", "str", "bool", "mix", "time"],
+ [0, 0.1, "hoge", true, 0, "2017-01-01 03:04:05+0900"],
+ [2, -2.23, "foo", false, null, "2017-12-23 45:01:23+0900"],
+ [3, 0, "bar", true, Infinity, "2017-03-03 33:44:55+0900"],
+ [-10, -9.9, "", "FALSE", NaN, "2017-01-01 00:00:00+0900"]
+ ];
+
+Write a Markdown table from ``pandas.DataFrame`` instance
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+``from_dataframe`` method of writer classes will set up tabular data from ``pandas.DataFrame``:
+
+:Sample Code:
+ .. code-block:: python
+
+ from textwrap import dedent
+ import pandas as pd
+ import io
+ from pytablewriter import MarkdownTableWriter
+
+ def main():
+ csv_data = io.StringIO(dedent("""\
+ "i","f","c","if","ifc","bool","inf","nan","mix_num","time"
+ 1,1.10,"aa",1.0,"1",True,Infinity,NaN,1,"2017-01-01 00:00:00+09:00"
+ 2,2.20,"bbb",2.2,"2.2",False,Infinity,NaN,Infinity,"2017-01-02 03:04:05+09:00"
+ 3,3.33,"cccc",-3.0,"ccc",True,Infinity,NaN,NaN,"2017-01-01 00:00:00+09:00"
+ """))
+ df = pd.read_csv(csv_data, sep=',')
+
+ writer = MarkdownTableWriter(dataframe=df)
+ writer.write_table()
+
+ if __name__ == "__main__":
+ main()
+
+:Output:
+ .. code-block::
+
+ | i | f | c | if |ifc|bool | inf |nan|mix_num | time |
+ |--:|---:|----|---:|---|-----|--------|---|-------:|-------------------------|
+ | 1|1.10|aa | 1.0| 1|True |Infinity|NaN| 1|2017-01-01 00:00:00+09:00|
+ | 2|2.20|bbb | 2.2|2.2|False|Infinity|NaN|Infinity|2017-01-02 03:04:05+09:00|
+ | 3|3.33|cccc|-3.0|ccc|True |Infinity|NaN| NaN|2017-01-01 00:00:00+09:00|
+
+
+Adding a column of the DataFrame index if you specify ``add_index_column=True``:
+
+:Sample Code:
+ .. code-block:: python
+
+ import pandas as pd
+ import pytablewriter as ptw
+
+ def main():
+ writer = ptw.MarkdownTableWriter(table_name="add_index_column")
+ writer.from_dataframe(
+ pd.DataFrame({"A": [1, 2], "B": [10, 11]}, index=["a", "b"]),
+ add_index_column=True,
+ )
+ writer.write_table()
+
+ if __name__ == "__main__":
+ main()
+
+:Output:
+ .. code-block::
+
+ # add_index_column
+ | | A | B |
+ |---|--:|--:|
+ |a | 1| 10|
+ |b | 2| 11|
+
+Write a Markdown table from space-separated values
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+:Sample Code:
+ .. code-block:: python
+
+ import pytablewriter as ptw
+
+
+ def main():
+ writer = ptw.MarkdownTableWriter(table_name="ps")
+ writer.from_csv(
+ """
+ USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
+ root 1 0.0 0.4 77664 8784 ? Ss May11 0:02 /sbin/init
+ root 2 0.0 0.0 0 0 ? S May11 0:00 [kthreadd]
+ root 4 0.0 0.0 0 0 ? I< May11 0:00 [kworker/0:0H]
+ root 6 0.0 0.0 0 0 ? I< May11 0:00 [mm_percpu_wq]
+ root 7 0.0 0.0 0 0 ? S May11 0:01 [ksoftirqd/0]
+ """,
+ delimiter=" ",
+ )
+ writer.write_table()
+
+
+ if __name__ == "__main__":
+ main()
+
+:Output:
+ .. code-block::
+
+ # ps
+ |USER|PID|%CPU|%MEM| VSZ |RSS |TTY|STAT|START|TIME| COMMAND |
+ |----|--:|---:|---:|----:|---:|---|----|-----|----|--------------|
+ |root| 1| 0| 0.4|77664|8784|? |Ss |May11|0:02|/sbin/init |
+ |root| 2| 0| 0.0| 0| 0|? |S |May11|0:00|[kthreadd] |
+ |root| 4| 0| 0.0| 0| 0|? |I< |May11|0:00|[kworker/0:0H]|
+ |root| 6| 0| 0.0| 0| 0|? |I< |May11|0:00|[mm_percpu_wq]|
+ |root| 7| 0| 0.0| 0| 0|? |S |May11|0:01|[ksoftirqd/0] |
+
+Get rendered tabular text as str
+----------------------------------
+``dumps`` method returns rendered tabular text.
+``dumps`` only available for text format writers.
+
+:Sample Code:
+ .. code-block:: python
+
+ import pytablewriter as ptw
+
+
+ def main():
+ writer = ptw.MarkdownTableWriter(
+ headers=["int", "float", "str", "bool", "mix", "time"],
+ value_matrix=[
+ [0, 0.1, "hoge", True, 0, "2017-01-01 03:04:05+0900"],
+ [2, "-2.23", "foo", False, None, "2017-12-23 45:01:23+0900"],
+ [3, 0, "bar", "true", "inf", "2017-03-03 33:44:55+0900"],
+ [-10, -9.9, "", "FALSE", "nan", "2017-01-01 00:00:00+0900"],
+ ],
+ )
+
+ print(writer.dumps())
+
+
+ if __name__ == "__main__":
+ main()
+
+:Output:
+ .. code-block::
+
+ |int|float|str |bool | mix | time |
+ |--:|----:|----|-----|-------:|------------------------|
+ | 0| 0.10|hoge|True | 0|2017-01-01 03:04:05+0900|
+ | 2|-2.23|foo |False| |2017-12-23 45:01:23+0900|
+ | 3| 0.00|bar |True |Infinity|2017-03-03 33:44:55+0900|
+ |-10|-9.90| |False| NaN|2017-01-01 00:00:00+0900|
+
+Configure table styles
+------------------------
+Column styles
+~~~~~~~~~~~~~~~
+Writers can specify
+`Style `__
+for each column by ``column_styles`` attribute of writer classes.
+
+:Sample Code:
+ .. code-block:: python
+
+ import pytablewriter as ptw
+ from pytablewriter.style import Style
+
+
+ def main():
+ writer = ptw.MarkdownTableWriter(
+ table_name="set style by column_styles",
+ headers=[
+ "auto align",
+ "left align",
+ "center align",
+ "bold",
+ "italic",
+ "bold italic ts",
+ ],
+ value_matrix=[
+ [11, 11, 11, 11, 11, 11],
+ [1234, 1234, 1234, 1234, 1234, 1234],
+ ],
+ column_styles=[
+ Style(),
+ Style(align="left"),
+ Style(align="center"),
+ Style(font_weight="bold"),
+ Style(font_style="italic"),
+ Style(font_weight="bold", font_style="italic", thousand_separator=","),
+ ], # specify styles for each column
+ )
+ writer.write_table()
+
+
+ if __name__ == "__main__":
+ main()
+
+:Output:
+ .. code-block::
+
+ # set style by styles
+ |auto align|left align|center align| bold |italic|bold italic ts|
+ |---------:|----------|:----------:|-------:|-----:|-------------:|
+ | 11|11 | 11 | **11**| _11_| _**11**_|
+ | 1234|1234 | 1234 |**1234**|_1234_| _**1,234**_|
+
+ `Rendering result `__
+
+
+You can also set ``Style`` to a specific column with an index or header by using ``set_style`` method:
+
+:Sample Code:
+ .. code-block:: python
+
+ from pytablewriter import MarkdownTableWriter
+ from pytablewriter.style import Style
+
+ def main():
+ writer = MarkdownTableWriter()
+ writer.headers = ["A", "B", "C",]
+ writer.value_matrix = [[11, 11, 11], [1234, 1234, 1234]]
+
+ writer.table_name = "set style by column index"
+ writer.set_style(1, Style(align="center", font_weight="bold"))
+ writer.set_style(2, Style(thousand_separator=" "))
+ writer.write_table()
+ writer.write_null_line()
+
+ writer.table_name = "set style by header"
+ writer.set_style("B", Style(font_style="italic"))
+ writer.write_table()
+
+ if __name__ == "__main__":
+ main()
+
+:Output:
+ .. code-block::
+
+ # set style by column index
+ | A | B | C |
+ |---:|:------:|----:|
+ | 11| **11** | 11|
+ |1234|**1234**|1 234|
+
+ # set style by header
+ | A | B | C |
+ |---:|-----:|----:|
+ | 11| _11_| 11|
+ |1234|_1234_|1 234|
+
+Style filter
+~~~~~~~~~~~~~~
+You can apply styles to specific cells by using style filters.
+Style filters will be written as Python functions.
+Examples of a style filter function and how you apply it are as follows:
+
+:Sample Code:
+ .. code-block:: python
+
+ from typing import Any, Optional
+
+ from pytablewriter import MarkdownTableWriter
+ from pytablewriter.style import Cell, Style
+
+
+ def style_filter(cell: Cell, **kwargs: Any) -> Optional[Style]:
+ if cell.is_header_row():
+ return None
+
+ if cell.col == 0:
+ return Style(font_weight="bold")
+
+ value = int(cell.value)
+
+ if value > 80:
+ return Style(fg_color="red", font_weight="bold", decoration_line="underline")
+ elif value > 50:
+ return Style(fg_color="yellow", font_weight="bold")
+ elif value > 20:
+ return Style(fg_color="green")
+
+ return Style(fg_color="lightblue")
+
+
+ writer = MarkdownTableWriter(
+ table_name="style filter example",
+ headers=["Key", "Value 1", "Value 2"],
+ value_matrix=[
+ ["A", 95, 40],
+ ["B", 55, 5],
+ ["C", 30, 85],
+ ["D", 0, 69],
+ ],
+ flavor="github",
+ enable_ansi_escape=False,
+ )
+ writer.add_style_filter(style_filter)
+ writer.write_table()
+
+Rendered results can be found at `here `__
+
+Theme
+~~~~~~~
+`Theme `
+consists of a set of style filters.
+The following command will install external predefined themes:
+
+::
+
+ pip install pytablewriter[theme]
+
+Themes can be set via the constructor of the writer classes or the ``set_theme`` method.
+The following is an example of setting the ``altrow`` theme via the constructor.
+``altrow`` theme will be colored rows alternatively:
+
+:Sample Code:
+ .. code-block:: python
+
+ import pytablewriter as ptw
+
+ writer = ptw.TableWriterFactory.create_from_format_name(
+ "markdown",
+ headers=["INT", "STR"],
+ value_matrix=[[1, "hoge"], [2, "foo"], [3, "bar"]],
+ margin=1,
+ theme="altrow",
+ )
+ writer.write_table()
+
+:Output:
+ .. figure:: https://cdn.jsdelivr.net/gh/thombashi/pytablewriter-altrow-theme@master/ss/ptw-altrow-theme_example_default.png
+ :alt: https://github.com/thombashi/pytablewriter-altrow-theme/blob/master/ss/ptw-altrow-theme_example_default.png
+
+`[theme]` extras includes the following themes:
+
+- `pytablewriter-altrow-theme `__
+ - `Generated HTML table example `__
+- `pytablewriter-altcol-theme `__
+ - `Generated HTML table example `__
+
+Make tables for specific applications
+---------------------------------------
+Render a table on Jupyter Notebook
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+All table writer class instances in ``pytablewriter`` can render in Jupyter Notebook.
+To render writers at notebook cells, you will require the dependency packages to be installed either by:
+
+- ``pip install pytablewriter[html]`` or
+- ``pip install pytablewriter[all]``
+
+Jupyter Notebook code examples can be found `here `__:
+
+.. figure:: https://cdn.jsdelivr.net/gh/thombashi/pytablewriter@master/ss/jupyter_notebook.png
+ :alt: https://github.com/thombashi/pytablewriter/blob/master/ss/jupyter_notebook.png
+
+ Table rendering results of Jupyter Notebook
+
+Multibyte character support
+-----------------------------
+Write a table using multibyte character
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+You can use multibyte characters as table data.
+Multibyte characters are also properly padded and aligned.
+
+:Sample Code:
+ .. code-block:: python
+
+ import pytablewriter as ptw
+
+
+ def main():
+ writer = ptw.RstSimpleTableWriter(
+ table_name="生成に関するパターン",
+ headers=["パターン名", "概要", "GoF", "Code Complete[1]"],
+ value_matrix=[
+ ["Abstract Factory", "関連する一連のインスタンスを状況に応じて、適切に生成する方法を提供する。", "Yes", "Yes"],
+ ["Builder", "複合化されたインスタンスの生成過程を隠蔽する。", "Yes", "No"],
+ ["Factory Method", "実際に生成されるインスタンスに依存しない、インスタンスの生成方法を提供する。", "Yes", "Yes"],
+ ["Prototype", "同様のインスタンスを生成するために、原型のインスタンスを複製する。", "Yes", "No"],
+ ["Singleton", "あるクラスについて、インスタンスが単一であることを保証する。", "Yes", "Yes"],
+ ],
+ )
+ writer.write_table()
+
+
+ if __name__ == "__main__":
+ main()
+
+:Output:
+ .. figure:: https://cdn.jsdelivr.net/gh/thombashi/pytablewriter@master/docs/pages/examples/multibyte/ss/multi_byte_char.png
+ :alt: https://github.com/thombashi/pytablewriter/blob/master/docs/pages/examples/multibyte/ss/multi_byte_char.png
+
+ Output of multi-byte character table
+
+Multiprocessing
+-----------------
+You can increase the number of workers to process table data via ``max_workers`` attribute of a writer.
+The more ``max_workers`` the less processing time when tabular data is large and the execution environment has available cores.
+
+If you increase ``max_workers`` larger than one, recommend using main guarded as follows to avoid problems caused by multi-processing:
+
+.. code-block:: python
+
+ from multiprocessing import cpu_count
+ import pytablewriter as ptw
+
+ def main():
+ writer = ptw.MarkdownTableWriter()
+ writer.max_workers = cpu_count()
+ ...
+
+ if __name__ == "__main__":
+ main()
+
+For more information
+----------------------
+More examples are available at
+https://pytablewriter.rtfd.io/en/latest/pages/examples/index.html
+
+Dependencies
+============
+- Python 3.9+
+- `Python package dependencies (automatically installed) `__
+
+
+Optional dependencies
+---------------------
+- ``logging`` extras
+ - `loguru `__: Used for logging if the package installed
+- ``from`` extras
+ - `pytablereader `__
+- ``es`` extra
+ - `elasticsearch `__
+- ``excel`` extras
+ - `xlwt `__
+ - `XlsxWriter `__
+- ``html`` extras
+ - `dominate `__
+- ``sqlite`` extras
+ - `SimpleSQLite `__
+- ``theme`` extras
+ - `pytablewriter-altrow-theme `__
+ - `pytablewriter-altcol-theme `__
+- ``toml`` extras
+ - `toml `__
+
+Documentation
+===============
+https://pytablewriter.rtfd.io/
+
+Projects using pytablewriter
+==================================
+- `pytest-md-report `__
+
+
+Related Projects
+==================================
+- `pytablereader `__
+ - Tabular data loaded by ``pytablereader`` can be written another tabular data format with ``pytablewriter``.
+
+Sponsors
+====================================
+|chasbecker| |shiguredo| |b4tman| |Arturi0| |github|
+
+.. |chasbecker| image:: https://avatars.githubusercontent.com/u/44389260?s=48&u=6da7176e51ae2654bcfd22564772ef8a3bb22318&v=4
+ :target: https://github.com/chasbecker
+ :alt: ex-sponsor: Charles Becker (chasbecker)
+.. |shiguredo| image:: https://avatars.githubusercontent.com/u/2549434?s=48&v=4
+ :target: https://github.com/shiguredo
+ :alt: ex-sponsor: 時雨堂 (shiguredo)
+.. |b4tman| image:: https://avatars.githubusercontent.com/u/3658062?s=48&v=4
+ :target: https://github.com/b4tman
+ :alt: onetime: Dmitry Belyaev (b4tman)
+.. |Arturi0| image:: https://avatars.githubusercontent.com/u/46711571?s=48&u=57687c0e02d5d6e8eeaf9177f7b7af4c9f275eb5&v=4
+ :target: https://github.com/Arturi0
+ :alt: onetime: Arturi0
+.. |github| image:: https://avatars.githubusercontent.com/u/9919?s=48&v=4
+ :target: https://github.com/github
+ :alt: onetime: GitHub (github)
+
+`Become a sponsor `__
+
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/RECORD b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/RECORD
new file mode 100644
index 0000000000000000000000000000000000000000..5c67b3693aa9a1d2fa7daebedddbff3a6490c552
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/RECORD
@@ -0,0 +1,138 @@
+pytablewriter-1.2.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+pytablewriter-1.2.1.dist-info/LICENSE,sha256=Ewo1uRffGVGu-_NmEgSR1RJARah97RI_IN7SFSH046I,1089
+pytablewriter-1.2.1.dist-info/METADATA,sha256=Egd2rPMhFcp60Ff2zC2VEmUjSIV6V6Vnn7mTDeb8PR4,38178
+pytablewriter-1.2.1.dist-info/RECORD,,
+pytablewriter-1.2.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+pytablewriter-1.2.1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
+pytablewriter-1.2.1.dist-info/top_level.txt,sha256=4qovxzrpT62Feu8LLdPGtIqYBswTr4QcU4mRmpM61-k,14
+pytablewriter/__init__.py,sha256=E2Y4TxopUWgqMateYeM22S6pGZct8qa_S78a1J_x9ao,2942
+pytablewriter/__pycache__/__init__.cpython-312.pyc,,
+pytablewriter/__pycache__/__version__.cpython-312.pyc,,
+pytablewriter/__pycache__/_converter.cpython-312.pyc,,
+pytablewriter/__pycache__/_factory.cpython-312.pyc,,
+pytablewriter/__pycache__/_function.cpython-312.pyc,,
+pytablewriter/__pycache__/_table_format.cpython-312.pyc,,
+pytablewriter/__pycache__/error.cpython-312.pyc,,
+pytablewriter/__version__.py,sha256=Yl4cZCSg_uar8nSXzhiZUTsEIwUveZ9Wn1et0RO9RL8,268
+pytablewriter/_converter.py,sha256=iPlzCNzbGPJ4eSfgMz7DwD7GjaV0n1zxBm_iIzbvG7E,238
+pytablewriter/_factory.py,sha256=JEzLpd5ri6DqGynTvMQ7DVhK36aoKKe-IedMxXjyVds,10847
+pytablewriter/_function.py,sha256=HkZK5rZRRzzOG0qCtLfoLQE8s6ruifdMvQYXePOUgrw,2396
+pytablewriter/_logger/__init__.py,sha256=DzORajZGSzcVR5wMlNgQ2b54Pr1CBgaN3OycGTp9s7g,107
+pytablewriter/_logger/__pycache__/__init__.cpython-312.pyc,,
+pytablewriter/_logger/__pycache__/_logger.cpython-312.pyc,,
+pytablewriter/_logger/__pycache__/_null_logger.cpython-312.pyc,,
+pytablewriter/_logger/_logger.py,sha256=OFQ-ZwE7Ly_HCW2fATCowChDvkFF2G_CjFwu6A2f5v8,3311
+pytablewriter/_logger/_null_logger.py,sha256=QJuaErUIV_x6NjQ9qNX9eNSi_GB_9CrO7lKeXYZnuaw,1088
+pytablewriter/_table_format.py,sha256=0OMnMrF0H9Wms7FKQM-JaMGob2qjgaIKWb3shQqXeuM,9479
+pytablewriter/error.py,sha256=MwPbc4EtUklc7X3eVWADVCA6rrzelfsBcH16E0pJQeE,787
+pytablewriter/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+pytablewriter/sanitizer/__init__.py,sha256=Ob9cbVV0DBI6W6fupmMIHEgoSCdaGeyxo_VhfvNizEM,703
+pytablewriter/sanitizer/__pycache__/__init__.cpython-312.pyc,,
+pytablewriter/sanitizer/__pycache__/_base.cpython-312.pyc,,
+pytablewriter/sanitizer/__pycache__/_elasticsearch.cpython-312.pyc,,
+pytablewriter/sanitizer/__pycache__/_excel.cpython-312.pyc,,
+pytablewriter/sanitizer/__pycache__/_interface.cpython-312.pyc,,
+pytablewriter/sanitizer/__pycache__/_javascript.cpython-312.pyc,,
+pytablewriter/sanitizer/__pycache__/_python.cpython-312.pyc,,
+pytablewriter/sanitizer/_base.py,sha256=jSpUcAA532hUAB9FFmYmh4Syp2hDlWsb_MnTIoCe6oc,2957
+pytablewriter/sanitizer/_elasticsearch.py,sha256=SB8GCeR_yl509Lz2uyblGnpYI56P4DSFaC3byB0BdQI,732
+pytablewriter/sanitizer/_excel.py,sha256=G5hot3llV_qMyziwOJwjZhSR1rTwqNdjRDEO3-29BnE,2510
+pytablewriter/sanitizer/_interface.py,sha256=YRioPeXRAPnDBgZ7G30CnpjivNwfbaxBemjWYi7P6e8,901
+pytablewriter/sanitizer/_javascript.py,sha256=WpX6Pq9JvcxTxK9nlb3IXl-YglE_YHcfp_PDk5jFMRY,3620
+pytablewriter/sanitizer/_python.py,sha256=GLF9rDttSEklwpnMRzAI6VLQVqext6O9_QGWEcgHqDM,3115
+pytablewriter/style/__init__.py,sha256=OmdQIAKEu8o5E9Xu9fN_kQ1SAtCZZPebFEY8QQjGFpQ,1107
+pytablewriter/style/__pycache__/__init__.cpython-312.pyc,,
+pytablewriter/style/__pycache__/_cell.cpython-312.pyc,,
+pytablewriter/style/__pycache__/_font.cpython-312.pyc,,
+pytablewriter/style/__pycache__/_style.cpython-312.pyc,,
+pytablewriter/style/__pycache__/_styler.cpython-312.pyc,,
+pytablewriter/style/__pycache__/_styler_interface.cpython-312.pyc,,
+pytablewriter/style/__pycache__/_theme.cpython-312.pyc,,
+pytablewriter/style/_cell.py,sha256=Ggaq9xm2r_oXUv_W2eV1YLZeI-U0AVsTpAJBfj1Dozw,549
+pytablewriter/style/_font.py,sha256=f3e9bKB83JYu7Yow7EYA_6XCJvqyCSMvjrIXC-Uelfc,341
+pytablewriter/style/_style.py,sha256=QJImo6VRWMSZT64yEqpeOyaVuYYbuOCVrlvrvmGvQ0E,12448
+pytablewriter/style/_styler.py,sha256=ceB6An1OIg-cx6lwPvSwRxUriF0EEUwHpmTOrucil9Y,9963
+pytablewriter/style/_styler_interface.py,sha256=rM1OX8rYIQsk9vtPmbrrcTlf4e0_So2XrHT3L4z1bF8,828
+pytablewriter/style/_theme.py,sha256=CpYbRacbIFWoMLxfG4qp2otbtLXLmQIDWyyp2VSSNcc,2836
+pytablewriter/typehint/__init__.py,sha256=FDTB4uiJDm2b0A6IsYtTVO2Z994tb5o3kcXbwkDDKYQ,545
+pytablewriter/typehint/__pycache__/__init__.cpython-312.pyc,,
+pytablewriter/writer/__init__.py,sha256=r0ZSklAeSM84jA4xzvTFaXHVe0Il0GjAQ8vk2_mtplQ,1766
+pytablewriter/writer/__pycache__/__init__.cpython-312.pyc,,
+pytablewriter/writer/__pycache__/_common.cpython-312.pyc,,
+pytablewriter/writer/__pycache__/_elasticsearch.cpython-312.pyc,,
+pytablewriter/writer/__pycache__/_interface.cpython-312.pyc,,
+pytablewriter/writer/__pycache__/_msgfy.cpython-312.pyc,,
+pytablewriter/writer/__pycache__/_null.cpython-312.pyc,,
+pytablewriter/writer/__pycache__/_table_writer.cpython-312.pyc,,
+pytablewriter/writer/_common.py,sha256=BjKw-NvsyNQw9D8Zrpg8RyjLjgQjc0QiLbp1bQoGROE,221
+pytablewriter/writer/_elasticsearch.py,sha256=OSfj__QgUmz5TKOdlL9iCZ7256iwLEi6ca8t7q0HrFc,6308
+pytablewriter/writer/_interface.py,sha256=SBLhByN6K5EUi3B8hyWZKMIg14P_lLGHA_WjV-sM2jA,2671
+pytablewriter/writer/_msgfy.py,sha256=Qf3VIhuCfstgGOEaYQswrW9R1lgYFknjw33YZJGNyFo,1777
+pytablewriter/writer/_null.py,sha256=YPBm1lc23wCQbVHuYKPPOTtdlZKfZOBIEWpkuBKQEw4,1590
+pytablewriter/writer/_table_writer.py,sha256=86W952psHB-jIzLN9uhCFjsLVKgugn8w-q56bfBAJiA,42116
+pytablewriter/writer/binary/__init__.py,sha256=akvPmDxtQjvKEac2yx9c-96CURTFx0809iPPskpa25c,281
+pytablewriter/writer/binary/__pycache__/__init__.cpython-312.pyc,,
+pytablewriter/writer/binary/__pycache__/_excel.cpython-312.pyc,,
+pytablewriter/writer/binary/__pycache__/_excel_workbook.cpython-312.pyc,,
+pytablewriter/writer/binary/__pycache__/_interface.cpython-312.pyc,,
+pytablewriter/writer/binary/__pycache__/_pandas.cpython-312.pyc,,
+pytablewriter/writer/binary/__pycache__/_sqlite.cpython-312.pyc,,
+pytablewriter/writer/binary/_excel.py,sha256=BzH-PEkUd90F-e5WvFNTmGiUXo5Om35ntw_Js5sM-3E,15543
+pytablewriter/writer/binary/_excel_workbook.py,sha256=ZQyXi3FOms6z5GhcGq6-18sY9Y3GM2GqRmLfQEyKij0,3954
+pytablewriter/writer/binary/_interface.py,sha256=U48pCiVMUgeYSKCINncSN5Sy9OnYQ90LMhC7Ls1C8O0,1487
+pytablewriter/writer/binary/_pandas.py,sha256=7UVtUNYGIIywe7GyOT8uDYLtYezoK9FZzk_NhwHNYQo,2660
+pytablewriter/writer/binary/_sqlite.py,sha256=ZnXqvidGUri1SM-Cxls1NwgVg9riDaPkFnr9iQjGchQ,2982
+pytablewriter/writer/text/__init__.py,sha256=_rk5sczp6H9sag4PXgKIbxSTrgW8HktmlJqN0cXR01M,1384
+pytablewriter/writer/text/__pycache__/__init__.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_asciidoc.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_borderless.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_common.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_css.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_csv.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_html.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_interface.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_json.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_jsonlines.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_latex.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_ltsv.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_markdown.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_mediawiki.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_rst.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_spacealigned.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_text_writer.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_toml.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_tsv.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_unicode.cpython-312.pyc,,
+pytablewriter/writer/text/__pycache__/_yaml.cpython-312.pyc,,
+pytablewriter/writer/text/_asciidoc.py,sha256=E2MO-Z3yVuF3eviwMqNvgkk5_-1R_u-I31bvH85xVHI,4410
+pytablewriter/writer/text/_borderless.py,sha256=4RhWiSppkS2bRIl8osmqkSst-hwDzaAT-GaSyHyHft4,1010
+pytablewriter/writer/text/_common.py,sha256=1YRanAyjyEgo9muaUM3n9pPieKsX0d5Y-_ktI92B_tA,554
+pytablewriter/writer/text/_css.py,sha256=kXaOogifXdFcDgV83D3zd2k1MlfDotv2gTEjgYaJ6cI,5496
+pytablewriter/writer/text/_csv.py,sha256=MBkHpdC7u9L8p9FNws-IpTECzn2-LpbsT9lg1sKEJzg,1484
+pytablewriter/writer/text/_html.py,sha256=lgCJYXuCtWJ9maF4HooylRaYtwYPPrUpHYHAb_VWEAU,6328
+pytablewriter/writer/text/_interface.py,sha256=Qcwjq6w_dz5Lk7Txr42ESnomW0316-LqPBo1HmcRP7I,642
+pytablewriter/writer/text/_json.py,sha256=kAGiwnbFWyLoqbNZL6at4u_DcS1JrUzJV5wOYQZk_J0,5081
+pytablewriter/writer/text/_jsonlines.py,sha256=si6GB85HhqIaTjBYNjg8xD4HhqvYlCHnOTOSl7xY0G4,1296
+pytablewriter/writer/text/_latex.py,sha256=_w_2c2fimZk2TL402lInpWzb3FtQpH6r6KdWbQaGet4,6336
+pytablewriter/writer/text/_ltsv.py,sha256=xsMAMMU2F5UdznagXnQJbz62-nstSiSbjm7vgHlLm_s,1517
+pytablewriter/writer/text/_markdown.py,sha256=ZfBhMN1CgLt5a-2ZxV4QHpiIs3pY-Sh8Fla3w1BXvkA,6201
+pytablewriter/writer/text/_mediawiki.py,sha256=lNGMwtLClFIMYWQeNTZ52wk8SHiT7FO93C580vPqMqU,3312
+pytablewriter/writer/text/_rst.py,sha256=aiE7zHflwU6RnOGQAowbhTF6onBjmPhx6QvQyaDco4Y,6906
+pytablewriter/writer/text/_spacealigned.py,sha256=osMTS0cvNl8qWthlUkB6noAaKGlBUL02MW-YEvMXEgA,897
+pytablewriter/writer/text/_text_writer.py,sha256=u21ijkBHg3KAtOT58yz5gQWeNTy82hAYxSQiO2RxFNE,20556
+pytablewriter/writer/text/_toml.py,sha256=oUQRIiNIXQ47ccGasVohbDGBksMMxDETv0mnbCngVC8,2265
+pytablewriter/writer/text/_tsv.py,sha256=xLXiOznMZ8W8fKa-xfZCNlTl2Q4_HWFTUQlR4__DjuU,467
+pytablewriter/writer/text/_unicode.py,sha256=-2W2O-FaBkPDAJuwBKLEutGS09y7DcasK4Q83K0GXiE,3532
+pytablewriter/writer/text/_yaml.py,sha256=ERDWX60MWjPRHf0Gs3q-m38n49NGf460YRR0ru_RF0s,1968
+pytablewriter/writer/text/sourcecode/__init__.py,sha256=25ju5UpRUV7DBNsusSj4YLzOLY5akmmEW7gKegSVtu4,297
+pytablewriter/writer/text/sourcecode/__pycache__/__init__.cpython-312.pyc,,
+pytablewriter/writer/text/sourcecode/__pycache__/_javascript.cpython-312.pyc,,
+pytablewriter/writer/text/sourcecode/__pycache__/_numpy.cpython-312.pyc,,
+pytablewriter/writer/text/sourcecode/__pycache__/_pandas.cpython-312.pyc,,
+pytablewriter/writer/text/sourcecode/__pycache__/_python.cpython-312.pyc,,
+pytablewriter/writer/text/sourcecode/__pycache__/_sourcecode.cpython-312.pyc,,
+pytablewriter/writer/text/sourcecode/_javascript.py,sha256=MHxFDde91ekZ8J0SfblFa7yO8vE8zKsKRJVY6hEsPok,4725
+pytablewriter/writer/text/sourcecode/_numpy.py,sha256=XGIHnGIpu7r5RPBhaadPXuPSSOWLAd2rss8OiI2huNM,1902
+pytablewriter/writer/text/sourcecode/_pandas.py,sha256=3wgXSSpD7UVNp9vmhmNb-lgZrdpZ66Ol8KEFeXLMl1k,2550
+pytablewriter/writer/text/sourcecode/_python.py,sha256=IQwuSTULsksIqp0tH6lpHGkuOQfC4IxxGrlmG-CGrbI,2535
+pytablewriter/writer/text/sourcecode/_sourcecode.py,sha256=BDr9hGrzmukvZzO48jsEInmeOSigJSBblhtgO5OEC7Y,2239
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/REQUESTED b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/REQUESTED
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/WHEEL b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/WHEEL
new file mode 100644
index 0000000000000000000000000000000000000000..ae527e7d64811439e61b93aa375defb30e06edfe
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/WHEEL
@@ -0,0 +1,5 @@
+Wheel-Version: 1.0
+Generator: setuptools (75.6.0)
+Root-Is-Purelib: true
+Tag: py3-none-any
+
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/top_level.txt b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/top_level.txt
new file mode 100644
index 0000000000000000000000000000000000000000..ee171b9ce88fa902be1b06281de4ce7ade6e10f9
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/pytablewriter-1.2.1.dist-info/top_level.txt
@@ -0,0 +1 @@
+pytablewriter
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..3d637cf0b25c543046eb6a62ee6d5f11f1f2c1d4
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/__init__.py
@@ -0,0 +1,82 @@
+"""isort:skip_file"""
+__version__ = '3.6.0'
+
+# ---------------------------------------
+# Note: import order is significant here.
+
+# submodules
+from .runtime import (
+ autotune,
+ Config,
+ heuristics,
+ JITFunction,
+ KernelInterface,
+ reinterpret,
+ TensorWrapper,
+ OutOfResources,
+ InterpreterError,
+ MockTensor,
+)
+from .runtime.jit import constexpr_function, jit
+from .runtime._async_compile import AsyncCompileMode, FutureKernel
+from .compiler import compile, CompilationError
+from .errors import TritonError
+from .runtime._allocation import set_allocator
+
+from . import language
+from . import testing
+from . import tools
+
+must_use_result = language.core.must_use_result
+
+__all__ = [
+ "AsyncCompileMode",
+ "autotune",
+ "cdiv",
+ "CompilationError",
+ "compile",
+ "Config",
+ "constexpr_function",
+ "FutureKernel",
+ "heuristics",
+ "InterpreterError",
+ "jit",
+ "JITFunction",
+ "KernelInterface",
+ "language",
+ "MockTensor",
+ "must_use_result",
+ "next_power_of_2",
+ "OutOfResources",
+ "reinterpret",
+ "runtime",
+ "set_allocator",
+ "TensorWrapper",
+ "TritonError",
+ "testing",
+ "tools",
+]
+
+# -------------------------------------
+# misc. utilities that don't fit well
+# into any specific module
+# -------------------------------------
+
+
+@constexpr_function
+def cdiv(x: int, y: int):
+ return (x + y - 1) // y
+
+
+@constexpr_function
+def next_power_of_2(n: int):
+ """Return the smallest power of 2 greater than or equal to n"""
+ n -= 1
+ n |= n >> 1
+ n |= n >> 2
+ n |= n >> 4
+ n |= n >> 8
+ n |= n >> 16
+ n |= n >> 32
+ n += 1
+ return n
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/_filecheck.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/_filecheck.py
new file mode 100644
index 0000000000000000000000000000000000000000..d96eb3cca718dd10eb097314aae3209aed100139
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/_filecheck.py
@@ -0,0 +1,96 @@
+import functools
+import os
+import inspect
+import subprocess
+import tempfile
+
+import triton
+from triton.compiler import ASTSource, make_backend
+from triton.backends.compiler import GPUTarget
+from triton.experimental.gluon._runtime import GluonASTSource
+from triton.runtime.jit import create_function_from_signature
+from triton._C.libtriton import ir
+
+# ===-----------------------------------------------------------------------===#
+# filecheck_test
+# ===-----------------------------------------------------------------------===#
+
+# Stub target for testing the frontend.
+stub_target = GPUTarget("cuda", 100, 32)
+
+triton_dir = os.path.dirname(__file__)
+filecheck_path = os.path.join(triton_dir, "FileCheck")
+
+
+class MatchError(ValueError):
+
+ def __init__(self, message, module_str):
+ super().__init__(message)
+ self.module_str = module_str
+
+ def __str__(self):
+ return f"{super().__str__()}\n{self.module_str}"
+
+
+def run_filecheck(name, module_str, check_template):
+ with tempfile.TemporaryDirectory() as tempdir:
+ temp_module = os.path.join(tempdir, "module")
+ with open(temp_module, "w") as temp:
+ temp.write(module_str)
+
+ temp_expected = os.path.join(tempdir, "expected")
+ with open(temp_expected, "w") as temp:
+ temp.write(check_template)
+
+ try:
+ subprocess.check_output(
+ [filecheck_path, temp_expected, "--input-file", temp_module, "--dump-input-context=50"],
+ stderr=subprocess.STDOUT)
+ except subprocess.CalledProcessError as error:
+ decoded = error.output.decode('unicode_escape')
+ raise ValueError(decoded)
+
+
+def run_parser(kernel_fn, args=(), kwargs={}, target=stub_target):
+ if "sanitize_overflow" not in kwargs:
+ kwargs = dict(kwargs)
+ kwargs["sanitize_overflow"] = False
+ backend = make_backend(target)
+ binder = create_function_from_signature(
+ kernel_fn.signature,
+ kernel_fn.params,
+ backend,
+ )
+
+ bound_args, specialization, options = binder(*args, **kwargs)
+ options, signature, constexprs, attrs = kernel_fn._pack_args(backend, kwargs, bound_args, specialization, options)
+ source_cls = GluonASTSource if kernel_fn.is_gluon() else ASTSource
+ src = source_cls(kernel_fn, signature, constexprs, attrs)
+
+ context = ir.context()
+ ir.load_dialects(context)
+ backend.load_dialects(context)
+
+ codegen_fns = backend.get_codegen_implementation(options)
+ module_map = backend.get_module_map()
+ module = src.make_ir(target, options, codegen_fns, module_map, context)
+ return module
+
+
+def run_filecheck_test(kernel_fn):
+ assert isinstance(kernel_fn, triton.runtime.JITFunction)
+ check_template = inspect.getsource(kernel_fn.fn)
+ if check_template is None:
+ raise ValueError("kernel function must have a docstring with FileCheck template")
+ mlir_module = run_parser(kernel_fn)
+
+ run_filecheck("placeholder", mlir_module.str_nodebug(), check_template)
+
+
+def filecheck_test(fn):
+
+ @functools.wraps(fn)
+ def test_fn():
+ run_filecheck_test(fn)
+
+ return test_fn
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/_internal_testing.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/_internal_testing.py
new file mode 100644
index 0000000000000000000000000000000000000000..562e8df721ea7e025101429fb5ca25c9702ebf92
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/_internal_testing.py
@@ -0,0 +1,272 @@
+import os
+import re
+import numpy as np
+import torch
+import triton
+import triton.language as tl
+from triton import knobs
+from typing import Optional, Set, Union
+import pytest
+
+from numpy.random import RandomState
+from triton.runtime.jit import TensorWrapper, reinterpret, type_canonicalisation_dict
+
+int_dtypes = ['int8', 'int16', 'int32', 'int64']
+uint_dtypes = ['uint8', 'uint16', 'uint32', 'uint64']
+integral_dtypes = int_dtypes + uint_dtypes
+float_dtypes = ['float16', 'float32', 'float64']
+float_dtypes_with_bfloat16 = float_dtypes + ['bfloat16']
+dtypes = integral_dtypes + float_dtypes
+dtypes_with_bfloat16 = dtypes + ['bfloat16']
+torch_float8_dtypes = ['float8_e4m3fn', 'float8_e5m2']
+torch_dtypes = ['bool'] + int_dtypes + ['uint8'] + float_dtypes + ['bfloat16']
+tma_dtypes = sorted(set(dtypes_with_bfloat16) - {"int64", "uint64", "float64"})
+
+
+def is_interpreter():
+ return os.environ.get('TRITON_INTERPRET', '0') == '1'
+
+
+def get_current_target():
+ if is_interpreter():
+ return None
+ return triton.runtime.driver.active.get_current_target()
+
+
+def is_cuda():
+ target = get_current_target()
+ return False if target is None else target.backend == "cuda"
+
+
+def is_ampere_or_newer():
+ return is_cuda() and torch.cuda.get_device_capability()[0] >= 8
+
+
+def is_blackwell():
+ return is_cuda() and torch.cuda.get_device_capability()[0] == 10
+
+
+def is_hopper_or_newer():
+ return is_cuda() and torch.cuda.get_device_capability()[0] >= 9
+
+
+def is_hopper():
+ return is_cuda() and torch.cuda.get_device_capability()[0] == 9
+
+
+def is_sm12x():
+ return is_cuda() and torch.cuda.get_device_capability()[0] == 12
+
+
+def is_hip():
+ target = get_current_target()
+ return False if target is None else target.backend == "hip"
+
+
+def is_hip_cdna2():
+ target = get_current_target()
+ return target is not None and target.backend == 'hip' and target.arch == 'gfx90a'
+
+
+def is_hip_cdna3():
+ target = get_current_target()
+ return target is not None and target.backend == 'hip' and target.arch == 'gfx942'
+
+
+def is_hip_cdna4():
+ target = get_current_target()
+ return target is not None and target.backend == 'hip' and target.arch == 'gfx950'
+
+
+def is_hip_gfx11():
+ target = get_current_target()
+ return target is not None and target.backend == 'hip' and 'gfx11' in target.arch
+
+
+def is_hip_gfx12():
+ target = get_current_target()
+ return target is not None and target.backend == 'hip' and 'gfx12' in target.arch
+
+
+def is_hip_gfx1250():
+ target = get_current_target()
+ return target is not None and target.backend == 'hip' and 'gfx1250' in target.arch
+
+
+def is_hip_cdna():
+ return is_hip_cdna2() or is_hip_cdna3() or is_hip_cdna4()
+
+
+def get_hip_lds_size():
+ return 163840 if is_hip_cdna4() else 65536
+
+
+def is_xpu():
+ target = get_current_target()
+ return False if target is None else target.backend == "xpu"
+
+
+def get_arch():
+ target = get_current_target()
+ return "" if target is None else str(target.arch)
+
+
+def numpy_random(shape, dtype_str, rs: Optional[RandomState] = None, low=None, high=None):
+ """
+ Override `rs` if you're calling this function twice and don't want the same
+ result for both calls.
+ """
+ if isinstance(shape, int):
+ shape = (shape, )
+ if rs is None:
+ rs = RandomState(seed=17)
+ if dtype_str in int_dtypes + uint_dtypes:
+ iinfo = np.iinfo(getattr(np, dtype_str))
+ low = iinfo.min if low is None else max(low, iinfo.min)
+ high = iinfo.max if high is None else min(high, iinfo.max)
+ dtype = getattr(np, dtype_str)
+ x = rs.randint(low, high, shape, dtype=dtype)
+ x[x == 0] = 1 # Workaround. Never return zero so tests of division don't error out.
+ return x
+ elif dtype_str and 'float8' in dtype_str:
+ x = rs.randint(20, 40, shape, dtype=np.int8)
+ return x
+ elif dtype_str in float_dtypes:
+ return rs.normal(0, 1, shape).astype(dtype_str)
+ elif dtype_str == 'bfloat16':
+ return (rs.normal(0, 1, shape).astype('float32').view('uint32') & np.uint32(0xffff0000)).view('float32')
+ elif dtype_str in ['bool', 'int1', 'bool_']:
+ return rs.normal(0, 1, shape) > 0.0
+ else:
+ raise RuntimeError(f'Unknown dtype {dtype_str}')
+
+
+def to_triton(x: np.ndarray, device, dst_type=None) -> Union[TensorWrapper, torch.Tensor]:
+ '''
+ Note: We need dst_type because the type of x can be different from dst_type.
+ For example: x is of type `float32`, dst_type is `bfloat16`.
+ If dst_type is None, we infer dst_type from x.
+ '''
+ t = x.dtype.name
+ if t in uint_dtypes:
+ signed_type_name = t.lstrip('u') # e.g. "uint16" -> "int16"
+ x_signed = x.astype(getattr(np, signed_type_name))
+ return reinterpret(torch.tensor(x_signed, device=device), getattr(tl, t))
+ else:
+ if dst_type and 'float8' in dst_type:
+ return reinterpret(torch.tensor(x, device=device), getattr(tl, dst_type))
+ if t == 'float32' and dst_type == 'bfloat16':
+ return torch.tensor(x, device=device).bfloat16()
+ return torch.tensor(x, device=device)
+
+
+def str_to_triton_dtype(x: str) -> tl.dtype:
+ return tl.str_to_ty(type_canonicalisation_dict[x], None)
+
+
+def torch_dtype_name(dtype) -> str:
+ if isinstance(dtype, triton.language.dtype):
+ return dtype.name
+ elif isinstance(dtype, torch.dtype):
+ # 'torch.int64' -> 'int64'
+ m = re.match(r'^torch\.(\w+)$', str(dtype))
+ return m.group(1)
+ else:
+ raise TypeError(f'not a triton or torch dtype: {type(dtype)}')
+
+
+def to_numpy(x):
+ if isinstance(x, TensorWrapper):
+ return x.base.cpu().numpy().astype(getattr(np, torch_dtype_name(x.dtype)))
+ elif isinstance(x, torch.Tensor):
+ if x.dtype is torch.bfloat16:
+ return x.cpu().float().numpy()
+ return x.cpu().numpy()
+ else:
+ raise ValueError(f"Not a triton-compatible tensor: {x}")
+
+
+def supports_tma(byval_only=False):
+ if is_interpreter():
+ return True
+ if not is_cuda():
+ return False
+ cuda_version = knobs.nvidia.ptxas.version
+ min_cuda_version = (12, 0) if byval_only else (12, 3)
+ cuda_version_tuple = tuple(map(int, cuda_version.split(".")))
+ assert len(cuda_version_tuple) == 2, cuda_version_tuple
+ return torch.cuda.get_device_capability()[0] >= 9 and cuda_version_tuple >= min_cuda_version
+
+
+def supports_ws():
+ if is_interpreter():
+ return True
+ if not is_cuda():
+ return False
+ return torch.cuda.get_device_capability()[0] >= 9
+
+
+def tma_skip_msg(byval_only=False):
+ if byval_only:
+ return "Requires __grid_constant__ TMA support (NVIDIA Hopper or higher, CUDA 12.0 or higher)"
+ else:
+ return "Requires advanced TMA support (NVIDIA Hopper or higher, CUDA 12.3 or higher)"
+
+
+requires_tma = pytest.mark.skipif(not supports_tma(), reason=tma_skip_msg())
+
+
+def default_alloc_fn(size: int, align: int, _):
+ return torch.empty(size, dtype=torch.int8, device="cuda")
+
+
+def unwrap_tensor(t: Union[torch.Tensor, triton.runtime.jit.TensorWrapper]) -> torch.Tensor:
+ if isinstance(t, triton.runtime.jit.TensorWrapper):
+ return t.base
+ return t
+
+
+def _fresh_knobs_impl(skipped_attr: Optional[Set[str]] = None):
+ from triton import knobs
+
+ if skipped_attr is None:
+ skipped_attr = set()
+
+ monkeypatch = pytest.MonkeyPatch()
+
+ knobs_map = {
+ name: knobset
+ for name, knobset in knobs.__dict__.items()
+ if isinstance(knobset, knobs.base_knobs) and knobset != knobs.base_knobs and name not in skipped_attr
+ }
+
+ # We store which variables we need to unset below in finally because
+ # monkeypatch doesn't appear to reset variables that were never set
+ # before the monkeypatch.delenv call below.
+ env_to_unset = []
+ prev_propagate_env = knobs.propagate_env
+
+ def fresh_function():
+ nonlocal env_to_unset
+ for name, knobset in knobs_map.items():
+ setattr(knobs, name, knobset.copy().reset())
+ for knob in knobset.knob_descriptors.values():
+ if knob.key in os.environ:
+ monkeypatch.delenv(knob.key, raising=False)
+ else:
+ env_to_unset.append(knob.key)
+ knobs.propagate_env = True
+ return knobs
+
+ def reset_function():
+ for name, knobset in knobs_map.items():
+ setattr(knobs, name, knobset)
+ # `undo` should be placed before `del os.environ`
+ # Otherwise, it may restore environment variables that monkeypatch deleted
+ monkeypatch.undo()
+ for k in env_to_unset:
+ if k in os.environ:
+ del os.environ[k]
+ knobs.propagate_env = prev_propagate_env
+
+ return fresh_function, reset_function
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/_utils.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/_utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..a3cf0ff0cbdb6047e9379cbc38cc44e5c2b52a62
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/_utils.py
@@ -0,0 +1,134 @@
+from __future__ import annotations
+
+from functools import reduce
+from typing import Any, Callable, TYPE_CHECKING, Union, List, Dict
+
+if TYPE_CHECKING:
+ from .language import core
+ IterableType = Union[list[Any], tuple[Any, ...], core.tuple, core.tuple_type]
+ ObjPath = tuple[int, ...]
+
+TRITON_MAX_TENSOR_NUMEL = 1048576
+
+
+def get_iterable_path(iterable: IterableType, path: ObjPath) -> Any:
+ return reduce(lambda a, idx: a[idx], path, iterable) # type: ignore[index]
+
+
+def set_iterable_path(iterable: IterableType, path: tuple[int, ...], val: Any):
+ from .language import core
+ assert len(path) != 0
+ prev = iterable if len(path) == 1 else get_iterable_path(iterable, path[:-1])
+ assert isinstance(prev, core.tuple)
+ prev._setitem(path[-1], val)
+
+
+def find_paths_if(iterable: Union[IterableType, Any], pred: Callable[[ObjPath, Any], bool]) -> list[ObjPath]:
+ from .language import core
+ is_iterable: Callable[[Any], bool] = lambda x: isinstance(x, (list, tuple, core.tuple, core.tuple_type))
+ # We need to use dict so that ordering is maintained, while set doesn't guarantee order
+ ret: dict[ObjPath, None] = {}
+
+ def _impl(path: tuple[int, ...], current: Any):
+ if is_iterable(current):
+ for idx, item in enumerate(current):
+ _impl((*path, idx), item)
+ elif pred(path, current):
+ ret[path] = None
+
+ _impl((), iterable)
+
+ return list(ret.keys())
+
+
+def is_power_of_two(x):
+ return (x & (x - 1)) == 0
+
+
+def validate_block_shape(shape: List[int]):
+ numel = 1
+ for i, d in enumerate(shape):
+ if not isinstance(d, int):
+ raise TypeError(f"Shape element {i} must have type `constexpr[int]`, got `constexpr[{type(d)}]")
+ if not is_power_of_two(d):
+ raise ValueError(f"Shape element {i} must be a power of 2")
+ numel *= d
+
+ if numel > TRITON_MAX_TENSOR_NUMEL:
+ raise ValueError(f"numel ({numel}) exceeds triton maximum tensor numel ({TRITON_MAX_TENSOR_NUMEL})")
+ return numel
+
+
+type_canonicalisation_dict = {
+ # we canonicalise all bools to be unsigned:
+ "bool": "u1",
+ "int1": "u1",
+ "uint1": "u1",
+ "i1": "u1",
+ # floating-point dtypes:
+ "float8e4nv": "fp8e4nv",
+ "float8e5": "fp8e5",
+ "float8e4b15": "fp8e4b15",
+ "float8_e4m3fn": "fp8e4nv",
+ "float8e4b8": "fp8e4b8",
+ "float8_e4m3fnuz": "fp8e4b8",
+ "float8_e5m2": "fp8e5",
+ "float8e5b16": "fp8e5b16",
+ "float8_e5m2fnuz": "fp8e5b16",
+ "half": "fp16",
+ "float16": "fp16",
+ "bfloat16": "bf16",
+ "float": "fp32",
+ "float32": "fp32",
+ "double": "fp64",
+ "float64": "fp64",
+ # signed integers:
+ "int8": "i8",
+ "int16": "i16",
+ "int": "i32",
+ "int32": "i32",
+ "int64": "i64",
+ # unsigned integers:
+ "uint8": "u8",
+ "uint16": "u16",
+ "uint32": "u32",
+ "uint64": "u64",
+ "void": "void",
+}
+
+for v in list(type_canonicalisation_dict.values()):
+ type_canonicalisation_dict[v] = v
+
+
+def canonicalize_dtype(dtype):
+ dtype_str = str(dtype).split(".")[-1]
+ return type_canonicalisation_dict[dtype_str]
+
+
+def canonicalize_ptr_dtype(dtype, is_const):
+ return f"{'*k' if is_const else '*'}{canonicalize_dtype(dtype)}"
+
+
+BITWIDTH_DICT: Dict[str, int] = {
+ **{f"u{n}": n
+ for n in (1, 8, 16, 32, 64)},
+ **{f"i{n}": n
+ for n in (1, 8, 16, 32, 64)},
+ **{f"fp{n}": n
+ for n in (16, 32, 64)},
+ **{f"fp8{suffix}": 8
+ for suffix in ("e4nv", "e4b15", "e4b8", "e5", "e5b16")},
+ "bf16": 16,
+ "void": 0,
+}
+
+for k, v in type_canonicalisation_dict.items():
+ BITWIDTH_DICT[k] = BITWIDTH_DICT[v]
+
+
+def get_primitive_bitwidth(dtype: str) -> int:
+ return BITWIDTH_DICT[dtype]
+
+
+def is_namedtuple(val):
+ return isinstance(val, type) and issubclass(val, tuple) and hasattr(val, "_fields")
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/errors.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/errors.py
new file mode 100644
index 0000000000000000000000000000000000000000..3a0a863553b9d62ccb60d0090ee6d66f8b9e3b79
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/errors.py
@@ -0,0 +1,5 @@
+"""Base class for all errors raised by Triton"""
+
+
+class TritonError(Exception):
+ ...
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/knobs.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/knobs.py
new file mode 100644
index 0000000000000000000000000000000000000000..b55bd3de3218a55c4682d60ad95a851db1d3eea2
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/knobs.py
@@ -0,0 +1,543 @@
+from __future__ import annotations
+
+import functools
+import importlib
+import os
+import re
+import subprocess
+import sysconfig
+import pathlib
+
+from dataclasses import dataclass
+from contextlib import contextmanager
+from typing import cast, Any, Callable, Generator, Generic, Optional, Protocol, Type, TypeVar, TypedDict, TYPE_CHECKING, Union
+
+from triton._C.libtriton import getenv, getenv_bool # type: ignore
+
+if TYPE_CHECKING:
+ from .runtime.cache import CacheManager, RemoteCacheBackend
+ from .runtime.jit import JitFunctionInfo, KernelParam
+ from .compiler.compiler import ASTSource, LazyDict, IRSource
+
+
+class Env:
+ pass
+
+
+env = Env()
+
+propagate_env: bool = True
+
+
+def setenv(key: str, value: Optional[str]) -> None:
+ if not propagate_env:
+ return
+
+ if value is not None:
+ os.environ[key] = value
+ elif key in os.environ:
+ del os.environ[key]
+
+
+def toenv(val: Any) -> Union[None, tuple[Optional[str]]]:
+ if val is None:
+ return (None, )
+
+ t = type(val)
+ if t is bool:
+ return ("1" if val else "0", )
+
+ if t is str:
+ return (val, )
+
+ if t is int:
+ return (str(val), )
+
+ return None
+
+
+# There's an asymmetry here so that e.g. env_nvidia_tool can be specified with a
+# a string but return an NvidiaTool.
+SetType = TypeVar("SetType")
+GetType = TypeVar("GetType")
+
+_NOTHING = object()
+
+
+class env_base(Generic[SetType, GetType]):
+
+ def __init__(self, key: str) -> None:
+ self.key = key
+
+ def __set_name__(self, objclass: Type[object], name: str) -> None:
+ self.name = name
+
+ def __get__(self, obj: Optional[object], objclass: Optional[Type[object]]) -> GetType:
+ py_val = obj.__dict__.get(self.name, _NOTHING)
+ if py_val is _NOTHING:
+ return self.get()
+ return self.transform(py_val)
+
+ def get(self) -> GetType:
+ raise NotImplementedError()
+
+ def __set__(self, obj: object, value: Union[SetType, Env]) -> None:
+ if isinstance(value, Env):
+ obj.__dict__.pop(self.name, None)
+ else:
+ obj.__dict__[self.name] = value
+ if env_val := toenv(value):
+ setenv(self.key, env_val[0])
+
+ def __delete__(self, obj: object) -> None:
+ obj.__dict__.pop(self.name, None)
+
+ def transform(self, val: SetType) -> GetType:
+ # See comment about GetType/SetType in their definition above. Only needed
+ # if GetType != SetType.
+ return cast(GetType, val)
+
+
+class env_str(env_base[str, str]):
+
+ def __init__(self, key: str, default: str):
+ super().__init__(key)
+ self.default = default
+
+ def get(self) -> str:
+ return getenv(self.key, self.default)
+
+
+class env_str_callable_default(env_base[str, str]):
+
+ def __init__(self, key: str, default_factory: Callable[[], str]):
+ super().__init__(key)
+ self.default_factory = default_factory
+
+ def get(self) -> str:
+ env_val = getenv(self.key)
+ if env_val is None:
+ return self.default_factory()
+ return env_val
+
+
+class env_bool(env_base[bool, bool]):
+
+ def __init__(self, key: str, default: bool = False) -> None:
+ super().__init__(key)
+ self.default = default
+
+ def get(self) -> bool:
+ return getenv_bool(self.key, self.default)
+
+
+class env_int(env_base[int, int]):
+
+ def __init__(self, key: str, default: int = 0) -> None:
+ super().__init__(key)
+ self.default = default
+
+ def get(self) -> int:
+ val = getenv(self.key)
+ if val is None:
+ return self.default
+ try:
+ return int(val)
+ except ValueError as exc:
+ raise RuntimeError(f"Unable to use {self.key}={val}: expected int") from exc
+
+
+ClassType = TypeVar("ClassType")
+
+
+class env_class(Generic[ClassType], env_base[Optional[Type[ClassType]], Optional[Type[ClassType]]]):
+
+ def __init__(self, key: str, type: str) -> None:
+ super().__init__(key)
+ # We can't pass the type directly to avoid import cycles
+ self.type = type
+
+ def get(self) -> Optional[Type[ClassType]]:
+ val = getenv(self.key)
+ if val is None:
+ return None
+ comps = val.split(":", 1)
+ if len(comps) != 2:
+ raise RuntimeError(f"Unable to read {self.key}: '{val}' isn't of the form MODULE:CLASS")
+ cls = getattr(importlib.import_module(comps[0]), comps[1])
+
+ if not any((c.__name__ == self.type for c in cls.mro())):
+ raise RuntimeError(f"Unable to use '{val}' from {self.key}: not of type '{self.type}'")
+
+ return cast(Type[ClassType], cls)
+
+
+@dataclass
+class NvidiaTool:
+ path: str
+ version: str
+
+ @staticmethod
+ @functools.lru_cache
+ def from_path(path: str) -> Optional[NvidiaTool]:
+ try:
+ result = subprocess.check_output([path, "--version"], stderr=subprocess.STDOUT)
+ version = re.search(r".*release (\d+\.\d+).*", result.decode("utf-8"), flags=re.MULTILINE)
+ if version is None:
+ return None
+ return NvidiaTool(path, version.group(1))
+ except (subprocess.CalledProcessError, FileNotFoundError):
+ return None
+
+
+class env_nvidia_tool(env_base[str, NvidiaTool]):
+
+ def __init__(self, binary: str) -> None:
+ binary += sysconfig.get_config_var("EXE")
+ self.binary = binary
+ self.default_path = os.path.join(os.path.dirname(__file__), "backends", "nvidia", "bin", binary)
+ # Convert ptxas-blackwell to PTXAS_BLACKWELL, not PTXAS-BLACKWELL
+ super().__init__(f"TRITON_{binary.upper().replace('-', '_')}_PATH")
+
+ def get(self) -> NvidiaTool:
+ return self.transform(getenv(self.key))
+
+ def transform(self, path: str) -> NvidiaTool:
+ # We still add default as fallback in case the pointed binary isn't
+ # accessible.
+ if path is not None:
+ paths = [path, self.default_path]
+ else:
+ paths = [self.default_path]
+
+ for path in paths:
+ if tool := NvidiaTool.from_path(path):
+ return tool
+
+ raise RuntimeError(f"Cannot find {self.binary}")
+
+
+# Separate classes so that types are correct
+class env_opt_str(env_base[Optional[str], Optional[str]]):
+
+ def get(self) -> Optional[str]:
+ return getenv(self.key)
+
+
+class env_opt_bool(env_base):
+
+ def get(self) -> Optional[str]:
+ return getenv_bool(self.key, None)
+
+
+@dataclass(frozen=True)
+class CompileTimes:
+ """
+ Model holding timing information for an invocation of the compiler.
+
+ All times in microseconds.
+ """
+
+ # Duration of make_ir
+ ir_initialization: int
+
+ # Ordered mapping from lowering stage to duration spent in that stage.
+ # Keyed by stage extension, e.g. ttir, ttgir
+ lowering_stages: list[tuple[str, int]]
+
+ # Duration of saving artifacts/metadata to cache
+ store_results: int
+
+ @property
+ def total_lowering(self) -> int:
+ return sum((stage[1] for stage in self.lowering_stages))
+
+ @property
+ def total(self) -> int:
+ return self.ir_initialization + self.total_lowering + self.store_results
+
+
+class CompilationListener(Protocol):
+
+ def __call__(self, *, src: Union[ASTSource, IRSource], metadata: dict[str, Any], metadata_group: dict[str, str],
+ times: CompileTimes, cache_hit: bool) -> None:
+ ...
+
+
+knobs_type = TypeVar("knobs_type", bound='base_knobs')
+
+
+class base_knobs:
+
+ @property
+ def knob_descriptors(self) -> dict[str, env_base]:
+ return {
+ k: v
+ # data descriptors live on the class object
+ for k, v in type(self).__dict__.items()
+ if isinstance(v, env_base)
+ }
+
+ @property
+ def knobs(self) -> dict[str, Any]:
+ return {k: getattr(self, k) for k in self.knob_descriptors.keys()}
+
+ def copy(self: knobs_type) -> knobs_type:
+ res = type(self)()
+ res.__dict__.update(self.__dict__)
+ return res
+
+ def reset(self: knobs_type) -> knobs_type:
+ for knob in self.knob_descriptors.keys():
+ delattr(self, knob)
+ return self
+
+ @contextmanager
+ def scope(self) -> Generator[None, None, None]:
+ try:
+ initial_env = {knob.key: getenv(knob.key) for knob in self.knob_descriptors.values()}
+ orig = dict(self.__dict__)
+ yield
+ finally:
+ self.__dict__.clear()
+ self.__dict__.update(orig)
+
+ for k, v in initial_env.items():
+ if v is not None:
+ os.environ[k] = v
+ elif k in os.environ:
+ del os.environ[k]
+
+
+class BuildImpl(Protocol):
+
+ def __call__(self, name: str, src: str, srcdir: str, library_dirs: list[str], include_dirs: list[str],
+ libraries: list[str], /) -> str:
+ ...
+
+
+class build_knobs(base_knobs):
+ """Configuration controlling how the native compiler is invoked"""
+ cc: env_opt_str = env_opt_str("CC")
+
+ cudacrt_path: env_opt_str = env_opt_str("TRITON_CUDACRT_PATH")
+ cudart_path: env_opt_str = env_opt_str("TRITON_CUDART_PATH")
+
+ impl: Optional[BuildImpl] = None
+
+ @property
+ def backend_dirs(self) -> set[str]:
+ return {path for path in (self.cudacrt_path, self.cudart_path) if path is not None}
+
+
+class redis_knobs(base_knobs):
+ key_format: env_str = env_str("TRITON_REDIS_KEY_FORMAT", "triton:{key}:{filename}")
+ host: env_str = env_str("TRITON_REDIS_HOST", "localhost")
+ port: env_int = env_int("TRITON_REDIS_PORT", 6379)
+
+
+cache: cache_knobs
+
+
+class cache_knobs(base_knobs):
+ home_dir: env_str = env_str("TRITON_HOME", os.path.expanduser("~/"))
+
+ dump_dir = env_str_callable_default("TRITON_DUMP_DIR", lambda: cache.get_triton_dir("dump"))
+ override_dir = env_str_callable_default("TRITON_OVERRIDE_DIR", lambda: cache.get_triton_dir("override"))
+ dir = env_str_callable_default("TRITON_CACHE_DIR", lambda: cache.get_triton_dir("cache"))
+
+ manager_class: env_class[CacheManager] = env_class("TRITON_CACHE_MANAGER", "CacheManager")
+ remote_manager_class: env_class[RemoteCacheBackend] = env_class("TRITON_REMOTE_CACHE_BACKEND", "RemoteCacheBackend")
+
+ def get_triton_dir(self, dirname: str) -> str:
+ return os.path.join(self.home_dir, ".triton", dirname)
+
+
+class compilation_knobs(base_knobs):
+ override: env_bool = env_bool("TRITON_KERNEL_OVERRIDE")
+ dump_ir: env_bool = env_bool("TRITON_KERNEL_DUMP")
+ dump_ir_extract_di_local_variables: env_bool = env_bool("LLVM_EXTRACT_DI_LOCAL_VARIABLES")
+ store_binary_only: env_bool = env_bool("TRITON_STORE_BINARY_ONLY")
+ always_compile: env_bool = env_bool("TRITON_ALWAYS_COMPILE")
+ # TODO: Use enum to constrain / 'typecheck' the values
+ use_ir_loc: env_opt_str = env_opt_str("USE_IR_LOC")
+ enable_asan: env_bool = env_bool("TRITON_ENABLE_ASAN")
+ disable_line_info: env_bool = env_bool("TRITON_DISABLE_LINE_INFO")
+ front_end_debugging: env_bool = env_bool("TRITON_FRONT_END_DEBUGGING")
+ allow_non_constexpr_globals: env_bool = env_bool("TRITON_ALLOW_NON_CONSTEXPR_GLOBALS")
+ # Instrumentation mode is checked on every run, which is expensive.
+ # We cache the value here to avoid the expensive check on every run.
+ instrumentation_mode: str = env_str("TRITON_INSTRUMENTATION_MODE", "").get()
+ listener: Union[CompilationListener, None] = None
+
+
+class autotuning_knobs(base_knobs):
+ cache: env_bool = env_bool("TRITON_CACHE_AUTOTUNING")
+ print: env_bool = env_bool("TRITON_PRINT_AUTOTUNING")
+
+
+class LaunchHook(Protocol):
+ """Hook invoked before and after kernel launching
+ """
+
+ def __call__(self, metadata: LazyDict) -> None:
+ ...
+
+
+class InitHandleHook(Protocol):
+ """Hook invoked around kernel binary/module loading.
+ module/function can be None for the *start* hook (before loading).
+ """
+
+ def __call__(
+ self,
+ module: Optional[object],
+ function: Optional[Callable],
+ name: str,
+ metadata_group: dict[str, str],
+ hash: str,
+ ) -> None:
+ ...
+
+
+F = TypeVar("F", bound=Callable)
+
+
+class HookChain(Generic[F]):
+ """A chain of hooks of the same type F to be called in order.
+ """
+
+ def __init__(self, reversed: bool = False):
+ self.calls: list[F] = []
+ self.reversed = reversed
+
+ def add(self, func: F) -> None:
+ if func not in self.calls:
+ self.calls.append(func)
+
+ def remove(self, func: F) -> None:
+ if func in self.calls:
+ self.calls.remove(func)
+
+ def __call__(self, *args, **kwargs):
+ for call in self.calls if not self.reversed else reversed(self.calls):
+ call(*args, **kwargs)
+
+
+# This is of the form [attr_name, attr_val]
+# TODO: Use tuple instead of list for better typing.
+KernelAttr = list[Union[str, int]]
+
+
+class JITHookCompileInfo(TypedDict):
+ key: str
+ signature: dict[KernelParam, str]
+ device: int
+ constants: None
+ num_warps: int
+ num_ctas: int
+ num_stages: int
+ enable_fp_fusion: bool
+ launch_cooperative_grid: bool
+ extern_libs: tuple[tuple[str, str], ...]
+ configs: list[dict[tuple[int, ...], list[KernelAttr]]]
+ specialization_data: str
+ is_warmup: bool
+
+
+class JITHook(Protocol):
+
+ def __call__(self, *, key: str, repr: str, fn: JitFunctionInfo, compile: JITHookCompileInfo, is_manual_warmup: bool,
+ already_compiled: bool) -> Optional[bool]:
+ ...
+
+
+class PipelineStagesHook(Protocol):
+
+ def __call__(self, stages, options, language, capability):
+ ...
+
+
+class runtime_knobs(base_knobs):
+ interpret: env_bool = env_bool("TRITON_INTERPRET")
+ # debug is on critical path for kernel launches
+ # avoid repeated reads from env-var by calling get directly
+ debug: bool = env_bool("TRITON_DEBUG").get()
+ override_arch: env_opt_str = env_opt_str("TRITON_OVERRIDE_ARCH")
+
+ launch_enter_hook: HookChain[LaunchHook] = HookChain()
+ launch_exit_hook: HookChain[LaunchHook] = HookChain(reversed=True)
+ kernel_load_start_hook: HookChain[InitHandleHook] = HookChain()
+ kernel_load_end_hook: HookChain[InitHandleHook] = HookChain(reversed=True)
+
+ # Hook for inspecting compiled functions and modules
+ jit_cache_hook: Optional[JITHook] = None
+ # Hook to signal that a kernel is done compiling and inspect compiled function.
+ # jit_cache_hook will always be called before compilation and jit_post_compile_hook after.
+ jit_post_compile_hook: Optional[JITHook] = None
+
+ # Hook for inspecting compiler pipeline stages
+ add_stages_inspection_hook: Optional[PipelineStagesHook] = None
+
+
+class language_knobs(base_knobs):
+ fp32_default: env_opt_str = env_opt_str("TRITON_F32_DEFAULT")
+ default_fp_fusion: env_bool = env_bool("TRITON_DEFAULT_FP_FUSION", True)
+
+
+class nvidia_knobs(base_knobs):
+ cuobjdump: env_nvidia_tool = env_nvidia_tool("cuobjdump")
+ nvdisasm: env_nvidia_tool = env_nvidia_tool("nvdisasm")
+ ptxas: env_nvidia_tool = env_nvidia_tool("ptxas")
+ ptxas_blackwell: env_nvidia_tool = env_nvidia_tool("ptxas-blackwell")
+
+ dump_nvptx: env_bool = env_bool("NVPTX_ENABLE_DUMP")
+ disable_ptxas_opt: env_bool = env_bool("DISABLE_PTXAS_OPT")
+ ptxas_options: env_opt_str = env_opt_str("PTXAS_OPTIONS")
+ mock_ptx_version: env_opt_str = env_opt_str("TRITON_MOCK_PTX_VERSION")
+ dump_ptxas_log: env_bool = env_bool("TRITON_DUMP_PTXAS_LOG")
+
+ libdevice_path: env_opt_str = env_opt_str("TRITON_LIBDEVICE_PATH")
+ libcuda_path: env_opt_str = env_opt_str("TRITON_LIBCUDA_PATH")
+
+
+class amd_knobs(base_knobs):
+ use_buffer_ops: env_bool = env_bool("AMDGCN_USE_BUFFER_OPS", True)
+ # Note: This requires use_buffer_ops be true to have any effect
+ use_buffer_atomics: env_bool = env_bool("AMDGCN_USE_BUFFER_ATOMICS", True)
+ # Note: This requires use_buffer_ops be true to have any effect
+ buffer_ops_analyze_small_tensor_range: env_bool = env_bool("AMDGCN_ANALYZE_SMALL_TENSOR_RANGE", False)
+ dump_amdgcn: env_bool = env_bool("AMDGCN_ENABLE_DUMP")
+ libhip_path: env_opt_str = env_opt_str("TRITON_LIBHIP_PATH")
+
+ # We use strs so that we can have a default value based on other runtime info
+ use_block_pingpong: env_opt_bool = env_opt_bool("TRITON_HIP_USE_BLOCK_PINGPONG")
+ use_in_thread_transpose: env_opt_bool = env_opt_bool("TRITON_HIP_USE_IN_THREAD_TRANSPOSE")
+
+ use_async_copy: env_bool = env_bool("TRITON_HIP_USE_ASYNC_COPY")
+ scalarize_packed_fops: env_bool = env_bool("AMDGCN_SCALARIZE_PACKED_FOPS")
+
+
+class proton_knobs(base_knobs):
+ disable: env_bool = env_bool("TRITON_PROTON_DISABLE", False)
+ cupti_lib_dir: env_str = env_str(
+ "TRITON_CUPTI_LIB_PATH",
+ str(pathlib.Path(__file__).parent.absolute() / "backends" / "nvidia" / "lib" / "cupti"))
+ enable_nvtx: env_bool = env_bool("TRITON_ENABLE_NVTX", True)
+
+
+build = build_knobs()
+redis = redis_knobs()
+cache = cache_knobs()
+compilation = compilation_knobs()
+autotuning = autotuning_knobs()
+runtime = runtime_knobs()
+language = language_knobs()
+nvidia = nvidia_knobs()
+amd = amd_knobs()
+proton = proton_knobs()
+
+
+def refresh_knobs():
+ runtime.debug = env_bool("TRITON_DEBUG").get()
+ compilation.instrumentation_mode = env_str("TRITON_INSTRUMENTATION_MODE", "").get()
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/testing.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/testing.py
new file mode 100644
index 0000000000000000000000000000000000000000..8cfc40a97182239f1b56b850109acaaa61c0e15d
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/triton/testing.py
@@ -0,0 +1,542 @@
+import functools
+import math
+import os
+import statistics
+import subprocess
+import sys
+from contextlib import contextmanager
+from typing import Any, Dict, List
+from . import language as tl
+from . import runtime
+
+
+def nvsmi(attrs):
+ attrs = ','.join(attrs)
+ cmd = ['nvidia-smi', '-i', '0', '--query-gpu=' + attrs, '--format=csv,noheader,nounits']
+ out = subprocess.check_output(cmd)
+ ret = out.decode(sys.stdout.encoding).split(',')
+ ret = [int(x) for x in ret]
+ return ret
+
+
+# pure Python implementation of np.quantile/torch.quantile
+# to avoid unnecessary runtime dependency on numpy/torch
+
+
+def _quantile(a, q):
+ n = len(a)
+ a = sorted(a)
+
+ def get_quantile(q):
+ if not (0 <= q <= 1):
+ raise ValueError("Quantiles must be in the range [0, 1]")
+ point = q * (n - 1)
+ lower = math.floor(point)
+ upper = math.ceil(point)
+ t = point - lower
+ return (1 - t) * a[lower] + t * a[upper]
+
+ return [get_quantile(q) for q in q]
+
+
+def _summarize_statistics(times, quantiles, return_mode):
+ if quantiles is not None:
+ ret = _quantile(times, quantiles)
+ if len(ret) == 1:
+ ret = ret[0]
+ return ret
+ if return_mode == "all":
+ return times
+ elif return_mode == "min":
+ return min(times)
+ elif return_mode == "max":
+ return max(times)
+ elif return_mode == "mean":
+ return statistics.mean(times)
+ elif return_mode == "median":
+ return statistics.median(times)
+
+
+def do_bench_cudagraph(fn, rep=20, grad_to_none=None, quantiles=None, return_mode="mean"):
+ """
+ Benchmark the runtime of the provided function.
+
+ :param fn: Function to benchmark
+ :type fn: Callable
+ :param rep: Repetition time (in ms)
+ :type rep: int
+ :param grad_to_none: Reset the gradient of the provided tensor to None
+ :type grad_to_none: torch.tensor, optional
+ :param return_mode: The statistical measure to return. Options are "min", "max", "mean", "median", or "all". Default is "mean".
+ :type return_mode: str
+ """
+ import torch
+ assert return_mode in ["min", "max", "mean", "median", "all"]
+
+ with torch.cuda.stream(torch.cuda.Stream()):
+ # warmup
+ fn()
+ if grad_to_none is not None:
+ for x in grad_to_none:
+ x.detach_()
+ x.requires_grad_(True)
+ x.grad = None
+ # step 1 - we estimate the amount of time the kernel call takes
+ # NOTE: this estimate isn't super accurate because the GPU isn't warmed up at this point
+ # but it is probably good enough
+ # NOTE: we don't use a graph to estimate the runtime because creating a graph is expensive,
+ # ~300ms on A100, so we default to the same method used in `do_bench` (minus the L2
+ # cache flush).
+ start_event = torch.cuda.Event(enable_timing=True)
+ end_event = torch.cuda.Event(enable_timing=True)
+ start_event.record()
+ for _ in range(5):
+ fn()
+ end_event.record()
+ torch.cuda.synchronize()
+ estimate_ms = start_event.elapsed_time(end_event) / 5
+ # Rewrite to avoid possible division by 0 issues with fast benchmarks
+ if estimate_ms == 0:
+ n_repeat = 1000
+ else:
+ n_repeat = max(1, int(rep / estimate_ms))
+ # step 2 - construct a cuda graph with `n_repeat` unrolled function calls to minimize
+ # host overhead
+ g = torch.cuda.CUDAGraph()
+ with torch.cuda.graph(g):
+ for _ in range(n_repeat):
+ if grad_to_none is not None:
+ for x in grad_to_none:
+ x.grad = None
+ fn()
+ torch.cuda.synchronize()
+ # measure time and return
+ ret = []
+ n_retries = 10
+ for _ in range(n_retries):
+ start_event = torch.cuda.Event(enable_timing=True)
+ end_event = torch.cuda.Event(enable_timing=True)
+ start_event.record()
+ g.replay()
+ end_event.record()
+ torch.cuda.synchronize()
+ ret += [start_event.elapsed_time(end_event) / n_repeat]
+ return _summarize_statistics(ret, quantiles, return_mode)
+
+
+def do_bench(fn, warmup=25, rep=100, grad_to_none=None, quantiles=None, return_mode="mean"):
+ """
+ Benchmark the runtime of the provided function. By default, return the median runtime of :code:`fn` along with
+ the 20-th and 80-th performance percentile.
+
+ :param fn: Function to benchmark
+ :type fn: Callable
+ :param warmup: Warmup time (in ms)
+ :type warmup: int
+ :param rep: Repetition time (in ms)
+ :type rep: int
+ :param grad_to_none: Reset the gradient of the provided tensor to None
+ :type grad_to_none: torch.tensor, optional
+ :param quantiles: Performance percentile to return in addition to the median.
+ :type quantiles: list[float], optional
+ :param return_mode: The statistical measure to return. Options are "min", "max", "mean", "median", or "all". Default is "mean".
+ :type return_mode: str
+ """
+ assert return_mode in ["min", "max", "mean", "median", "all"]
+
+ di = runtime.driver.active.get_device_interface()
+
+ fn()
+ di.synchronize()
+
+ cache = runtime.driver.active.get_empty_cache_for_benchmark()
+
+ # Estimate the runtime of the function
+ start_event = di.Event(enable_timing=True)
+ end_event = di.Event(enable_timing=True)
+ start_event.record()
+ for _ in range(5):
+ runtime.driver.active.clear_cache(cache)
+ fn()
+ end_event.record()
+ di.synchronize()
+ estimate_ms = start_event.elapsed_time(end_event) / 5
+
+ # compute number of warmup and repeat
+ n_warmup = max(1, int(warmup / estimate_ms))
+ n_repeat = max(1, int(rep / estimate_ms))
+ start_event = [di.Event(enable_timing=True) for i in range(n_repeat)]
+ end_event = [di.Event(enable_timing=True) for i in range(n_repeat)]
+ # Warm-up
+ for _ in range(n_warmup):
+ fn()
+ # Benchmark
+ for i in range(n_repeat):
+ # we don't want `fn` to accumulate gradient values
+ # if it contains a backward pass. So we clear the
+ # provided gradients
+ if grad_to_none is not None:
+ for x in grad_to_none:
+ x.grad = None
+ # we clear the L2 cache before each run
+ runtime.driver.active.clear_cache(cache)
+ # record time of `fn`
+ start_event[i].record()
+ fn()
+ end_event[i].record()
+ # Record clocks
+ di.synchronize()
+ times = [s.elapsed_time(e) for s, e in zip(start_event, end_event)]
+ return _summarize_statistics(times, quantiles, return_mode)
+
+
+def assert_close(x, y, atol=None, rtol=None, err_msg=''):
+ """
+ Asserts that two inputs are close within a certain tolerance.
+
+ :param x: The first input.
+ :type x: scala, list, numpy.ndarray, or torch.Tensor
+ :param y: The second input.
+ :type y: scala, list, numpy.ndarray, or torch.Tensor
+ :param atol: The absolute tolerance. Default value is 1e-2.
+ :type atol: float, optional
+ :param rtol: The relative tolerance. Default value is 0.
+ :type rtol: float, optional
+ :param err_msg: The error message to use if the assertion fails.
+ :type err_msg: str
+ """
+ import numpy as np
+ import torch
+
+ # canonicalize arguments to be tensors
+ if not isinstance(x, torch.Tensor):
+ x = torch.tensor(x)
+ if not isinstance(y, torch.Tensor):
+ y = torch.tensor(y)
+ # absolute tolerance
+ if atol is None:
+ atol = 1e-2
+ atol = atol(x.dtype) if callable(atol) else atol
+ # relative tolerance hook
+ if rtol is None:
+ rtol = 0.
+ rtol = rtol(x.dtype) if callable(rtol) else rtol
+ # we use numpy instead of pytorch
+ # as it seems more memory efficient
+ # pytorch tends to oom on large tensors
+ if isinstance(x, torch.Tensor):
+ if x.dtype == torch.bfloat16:
+ x = x.float()
+ x = x.cpu().detach().numpy()
+ if isinstance(y, torch.Tensor):
+ if y.dtype == torch.bfloat16:
+ y = y.float()
+ y = y.cpu().detach().numpy()
+ # we handle size==1 case separately as we can
+ # provide better error message there
+ if x.size > 1 or y.size > 1:
+ np.testing.assert_allclose(x, y, atol=atol, rtol=rtol, equal_nan=True)
+ return
+ if not np.allclose(x, y, atol=atol, rtol=rtol):
+ raise AssertionError(f'{err_msg} {x} is not close to {y} (atol={atol}, rtol={rtol})')
+
+
+class Benchmark:
+ """
+ This class is used by the :code:`perf_report` function to generate line plots with a concise API.
+ """
+
+ def __init__(
+ self,
+ x_names: List[str],
+ x_vals: List[Any],
+ line_arg: str,
+ line_vals: List[Any],
+ line_names: List[str],
+ plot_name: str,
+ args: Dict[str, Any],
+ xlabel: str = '',
+ ylabel: str = '',
+ x_log: bool = False,
+ y_log: bool = False,
+ styles=None,
+ ):
+ """
+ Constructor.
+ x_vals can be a list of scalars or a list of tuples/lists. If x_vals is a list
+ of scalars and there are multiple x_names, all arguments will have the same value.
+ If x_vals is a list of tuples/lists, each element should have the same length as
+ x_names.
+
+ :param x_names: Name of the arguments that should appear on the x axis of the plot.
+ :type x_names: List[str]
+ :param x_vals: List of values to use for the arguments in :code:`x_names`.
+ :type x_vals: List[Any]
+ :param line_arg: Argument name for which different values correspond to different lines in the plot.
+ :type line_arg: str
+ :param line_vals: List of values to use for the arguments in :code:`line_arg`.
+ :type line_vals: List[Any]
+ :param line_names: Label names for the different lines.
+ :type line_names: List[str]
+ :param plot_name: Name of the plot.
+ :type plot_name: str
+ :param args: Dictionary of keyword arguments to remain fixed throughout the benchmark.
+ :type args: Dict[str, Any]
+ :param xlabel: Label for the x axis of the plot.
+ :type xlabel: str, optional
+ :param ylabel: Label for the y axis of the plot.
+ :type ylabel: str, optional
+ :param x_log: Whether the x axis should be log scale.
+ :type x_log: bool, optional
+ :param y_log: Whether the y axis should be log scale.
+ :type y_log: bool, optional
+ :param styles: A list of tuples, where each tuple contains two elements: a color and a linestyle.
+ :type styles: list[tuple[str, str]]
+ """
+ self.x_names = x_names
+ self.x_vals = x_vals
+ self.x_log = x_log
+ self.line_arg = line_arg
+ self.line_vals = line_vals
+ self.line_names = line_names
+ self.y_log = y_log
+ self.styles = styles
+ # plot info
+ self.xlabel = xlabel
+ self.ylabel = ylabel
+ self.plot_name = plot_name
+ self.args = args
+
+
+class Mark:
+
+ def __init__(self, fn, benchmarks):
+ self.fn = fn
+ self.benchmarks = benchmarks
+
+ def _run(self, bench: Benchmark, save_path: str, show_plots: bool, print_data: bool, diff_col=False,
+ save_precision=6, **kwrags):
+ import os
+
+ import matplotlib.pyplot as plt
+ import pandas as pd
+ y_mean_labels = [f'{x} ({bench.ylabel})' for x in bench.line_names]
+ y_min_labels = [f'{x}-min ({bench.ylabel})' for x in bench.line_names]
+ y_max_labels = [f'{x}-max ({bench.ylabel})' for x in bench.line_names]
+ x_names = list(bench.x_names)
+ df = pd.DataFrame(columns=x_names + y_mean_labels + y_min_labels + y_max_labels)
+ for x in bench.x_vals:
+ # x can be a single value or a sequence of values.
+ if not isinstance(x, (list, tuple)):
+ x = [x for _ in x_names]
+
+ if len(x) != len(x_names):
+ raise ValueError(f"Expected {len(x_names)} values, got {x}")
+ x_args = dict(zip(x_names, x))
+
+ row_mean, row_min, row_max = [], [], []
+ for y in bench.line_vals:
+ ret = self.fn(**x_args, **{bench.line_arg: y}, **bench.args, **kwrags)
+ try:
+ y_mean, y_min, y_max = ret
+ except TypeError:
+ y_mean, y_min, y_max = ret, None, None
+ row_mean += [y_mean]
+ row_min += [y_min]
+ row_max += [y_max]
+ df.loc[len(df)] = list(x) + row_mean + row_min + row_max
+
+ if bench.plot_name:
+ plt.figure()
+ ax = plt.subplot()
+ # Plot first x value on x axis if there are multiple.
+ first_x = x_names[0]
+ for i, (mean_label, min_label, max_label) in enumerate(zip(y_mean_labels, y_min_labels, y_max_labels)):
+ y_min, y_max = df[min_label], df[max_label]
+ col = bench.styles[i][0] if bench.styles else None
+ sty = bench.styles[i][1] if bench.styles else None
+ ax.plot(df[first_x], df[mean_label], label=mean_label, color=col, ls=sty)
+ if not y_min.isnull().all() and not y_max.isnull().all():
+ y_min = y_min.astype(float)
+ y_max = y_max.astype(float)
+ ax.fill_between(df[first_x], y_min, y_max, alpha=0.15, color=col)
+ ax.legend()
+ ax.set_xlabel(bench.xlabel or first_x)
+ ax.set_ylabel(bench.ylabel)
+ # ax.set_title(bench.plot_name)
+ ax.set_xscale("log" if bench.x_log else "linear")
+ ax.set_yscale("log" if bench.y_log else "linear")
+ if show_plots:
+ plt.show()
+ if save_path:
+ plt.savefig(os.path.join(save_path, f"{bench.plot_name}.png"))
+ df = df[x_names + y_mean_labels]
+ if diff_col and df.shape[1] == 2:
+ col0, col1 = df.columns.tolist()
+ df['Diff'] = df[col1] - df[col0]
+
+ if print_data:
+ print(bench.plot_name + ':')
+ print(df.to_string())
+ if save_path:
+ df.to_csv(os.path.join(save_path, f"{bench.plot_name}.csv"), float_format=f"%.{save_precision}f",
+ index=False)
+ return df
+
+ def run(self, show_plots=False, print_data=False, save_path='', return_df=False, **kwargs):
+ has_single_bench = isinstance(self.benchmarks, Benchmark)
+ benchmarks = [self.benchmarks] if has_single_bench else self.benchmarks
+ result_dfs = []
+ try:
+ for bench in benchmarks:
+ result_dfs.append(self._run(bench, save_path, show_plots, print_data, **kwargs))
+ finally:
+ if save_path:
+ # Create directory if it doesn't exist
+ os.makedirs(save_path, exist_ok=True)
+ with open(os.path.join(save_path, "results.html"), "w") as html:
+ html.write("\n")
+ for bench in benchmarks[:len(result_dfs)]:
+ html.write(f"\n")
+ html.write("\n")
+ if return_df:
+ if has_single_bench:
+ return result_dfs[0]
+ else:
+ return result_dfs
+ return None
+
+
+def perf_report(benchmarks):
+ """
+ Mark a function for benchmarking. The benchmark can then be executed by using the :code:`.run` method on the return value.
+
+ :param benchmarks: Benchmarking configurations.
+ :type benchmarks: List of :class:`Benchmark`
+ """
+ wrapper = lambda fn: Mark(fn, benchmarks)
+ return wrapper
+
+
+def get_dram_gbps(device=None):
+ ''' return DRAM bandwidth in GB/s '''
+
+ from .runtime import driver
+ if device is None:
+ device = driver.active.get_device_interface().current_device()
+ mem_clock_khz = driver.active.utils.get_device_properties(device)["mem_clock_rate"] # in kHz
+ bus_width = driver.active.utils.get_device_properties(device)["mem_bus_width"]
+ bw_gbps = mem_clock_khz * bus_width * 2 / 1e6 / 8 # In GB/s
+ return bw_gbps
+
+
+def get_max_tensorcore_tflops(dtype, clock_rate, device=None):
+ import torch
+
+ from .runtime import driver
+ if not device:
+ device = torch.cuda.current_device()
+
+ num_subcores = driver.active.utils.get_device_properties(device)["multiprocessor_count"] * 4
+ capability = torch.cuda.get_device_capability(device)
+ if capability[0] < 8:
+ assert dtype == torch.float16
+ ops_per_sub_core = 256 # 2 4x4x4 Tensor Cores
+ else:
+ if dtype in [torch.float32, torch.int32]:
+ ops_per_sub_core = 256
+ elif dtype in [torch.float16, torch.bfloat16, torch.int16]:
+ ops_per_sub_core = 512
+ elif dtype in [torch.int8, tl.float8e4nv, tl.float8e4b15, tl.float8e5]:
+ ops_per_sub_core = 1024
+ else:
+ raise RuntimeError("dtype not supported")
+ tflops = num_subcores * clock_rate * ops_per_sub_core * 1e-9
+ return tflops
+
+
+# create decorator that wraps test function into
+# a cuda-memcheck system call
+
+
+def cuda_memcheck(**target_kwargs):
+
+ def decorator(test_fn):
+
+ @functools.wraps(test_fn)
+ def wrapper(*args, **kwargs):
+ import psutil
+ ppid_name = psutil.Process(os.getppid()).name()
+ run_cuda_memcheck = target_kwargs.items() <= kwargs.items()
+ if run_cuda_memcheck and ppid_name != "cuda-memcheck":
+ path = os.path.realpath(test_fn.__globals__["__file__"])
+ # get path of current file
+ env = {"PATH": os.environ["PATH"], "PYTORCH_NO_CUDA_MEMORY_CACHING": "1"}
+ assert 'request' in kwargs, "memcheck'ed test must have a (possibly unused) `request` fixture"
+ test_id = kwargs['request'].node.callspec.id
+ cmd = f"{path}::{test_fn.__name__}[{test_id}]"
+ out = subprocess.run(["cuda-memcheck", "pytest", "-vs", cmd], capture_output=True, env=env)
+ assert out.returncode == 0, "cuda-memcheck returned an error: bounds checking failed"
+ assert "ERROR SUMMARY: 0 errors" in str(out.stdout)
+ else:
+ test_fn(*args, **kwargs)
+
+ return wrapper
+
+ return decorator
+
+
+@contextmanager
+def set_gpu_clock(ref_sm_clock=1350, ref_mem_clock=1215):
+ try:
+ subprocess.check_output(["nvidia-smi", "-i", "0", "-pm", "1"])
+ subprocess.check_output([
+ "nvidia-smi",
+ "-i",
+ "0",
+ f"--lock-gpu-clocks={ref_sm_clock},{ref_sm_clock}",
+ ])
+ subprocess.check_output([
+ "nvidia-smi",
+ "-i",
+ "0",
+ f"--lock-memory-clocks={ref_mem_clock},{ref_mem_clock}",
+ ])
+ cur_sm_clock = nvsmi(["clocks.current.sm"])[0]
+ cur_mem_clock = nvsmi(["clocks.current.memory"])[0]
+ assert abs(cur_sm_clock - ref_sm_clock) < 10, f"GPU SMs must run at {ref_sm_clock} MHz"
+ assert abs(cur_mem_clock - ref_mem_clock) < 10, f"GPU SMs must run at {ref_mem_clock} MHz"
+ tflops = 1e-6 * 2 * 108 * 4 * 256 * ref_sm_clock
+ gbps = 640 * 2 * ref_mem_clock * 1e-3
+ yield tflops, gbps
+ finally:
+ subprocess.check_output(["nvidia-smi", "-i", "0", "-pm", "0"])
+ subprocess.check_output(["nvidia-smi", "-i", "0", "-rgc"])
+ subprocess.check_output(["nvidia-smi", "-i", "0", "-rmc"])
+
+
+def get_max_simd_tflops(dtype, clock_rate, device=None):
+ import torch
+
+ from .runtime import driver
+ if not device:
+ device = torch.cuda.current_device()
+
+ num_subcores = driver.active.utils.get_device_properties(device)["multiprocessor_count"] * 4
+ capability = torch.cuda.get_device_capability()
+ if capability[0] < 8:
+ if dtype == torch.float32:
+ ops_per_sub_core = 32 # 2*16
+ elif dtype == torch.float16:
+ ops_per_sub_core = 64
+ else:
+ raise RuntimeError("dtype not supported")
+ else:
+ if dtype == torch.float32:
+ ops_per_sub_core = 32
+ elif dtype in [torch.float16, torch.bfloat16]:
+ ops_per_sub_core = 64
+ else:
+ raise RuntimeError("dtype not supported")
+ tflops = num_subcores * clock_rate * ops_per_sub_core * 1e-9
+ return tflops
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/__init__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..3ab8f72d8b2e31b1cb8456ee1c4b8e62d4aba252
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/__init__.py
@@ -0,0 +1,3 @@
+from __future__ import annotations
+
+__version__ = "0.45.1"
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/__main__.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/__main__.py
new file mode 100644
index 0000000000000000000000000000000000000000..0be74537494dc2cf18c2e3b318ffd22b886aef6b
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/__main__.py
@@ -0,0 +1,23 @@
+"""
+Wheel command line tool (enable python -m wheel syntax)
+"""
+
+from __future__ import annotations
+
+import sys
+
+
+def main(): # needed for console script
+ if __package__ == "":
+ # To be able to run 'python wheel-0.9.whl/wheel':
+ import os.path
+
+ path = os.path.dirname(os.path.dirname(__file__))
+ sys.path[0:0] = [path]
+ import wheel.cli
+
+ sys.exit(wheel.cli.main())
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/_bdist_wheel.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/_bdist_wheel.py
new file mode 100644
index 0000000000000000000000000000000000000000..88973ebfb88f9521e5f0613b5cedf1204d10a8f1
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/_bdist_wheel.py
@@ -0,0 +1,613 @@
+"""
+Create a wheel (.whl) distribution.
+
+A wheel is a built archive format.
+"""
+
+from __future__ import annotations
+
+import os
+import re
+import shutil
+import stat
+import struct
+import sys
+import sysconfig
+import warnings
+from email.generator import BytesGenerator, Generator
+from email.policy import EmailPolicy
+from glob import iglob
+from shutil import rmtree
+from typing import TYPE_CHECKING, Callable, Iterable, Literal, Sequence, cast
+from zipfile import ZIP_DEFLATED, ZIP_STORED
+
+import setuptools
+from setuptools import Command
+
+from . import __version__ as wheel_version
+from .metadata import pkginfo_to_metadata
+from .util import log
+from .vendored.packaging import tags
+from .vendored.packaging import version as _packaging_version
+from .wheelfile import WheelFile
+
+if TYPE_CHECKING:
+ import types
+
+# ensure Python logging is configured
+try:
+ __import__("setuptools.logging")
+except ImportError:
+ # setuptools < ??
+ from . import _setuptools_logging
+
+ _setuptools_logging.configure()
+
+
+def safe_name(name: str) -> str:
+ """Convert an arbitrary string to a standard distribution name
+ Any runs of non-alphanumeric/. characters are replaced with a single '-'.
+ """
+ return re.sub("[^A-Za-z0-9.]+", "-", name)
+
+
+def safe_version(version: str) -> str:
+ """
+ Convert an arbitrary string to a standard version string
+ """
+ try:
+ # normalize the version
+ return str(_packaging_version.Version(version))
+ except _packaging_version.InvalidVersion:
+ version = version.replace(" ", ".")
+ return re.sub("[^A-Za-z0-9.]+", "-", version)
+
+
+setuptools_major_version = int(setuptools.__version__.split(".")[0])
+
+PY_LIMITED_API_PATTERN = r"cp3\d"
+
+
+def _is_32bit_interpreter() -> bool:
+ return struct.calcsize("P") == 4
+
+
+def python_tag() -> str:
+ return f"py{sys.version_info[0]}"
+
+
+def get_platform(archive_root: str | None) -> str:
+ """Return our platform name 'win32', 'linux_x86_64'"""
+ result = sysconfig.get_platform()
+ if result.startswith("macosx") and archive_root is not None:
+ from .macosx_libfile import calculate_macosx_platform_tag
+
+ result = calculate_macosx_platform_tag(archive_root, result)
+ elif _is_32bit_interpreter():
+ if result == "linux-x86_64":
+ # pip pull request #3497
+ result = "linux-i686"
+ elif result == "linux-aarch64":
+ # packaging pull request #234
+ # TODO armv8l, packaging pull request #690 => this did not land
+ # in pip/packaging yet
+ result = "linux-armv7l"
+
+ return result.replace("-", "_")
+
+
+def get_flag(
+ var: str, fallback: bool, expected: bool = True, warn: bool = True
+) -> bool:
+ """Use a fallback value for determining SOABI flags if the needed config
+ var is unset or unavailable."""
+ val = sysconfig.get_config_var(var)
+ if val is None:
+ if warn:
+ warnings.warn(
+ f"Config variable '{var}' is unset, Python ABI tag may be incorrect",
+ RuntimeWarning,
+ stacklevel=2,
+ )
+ return fallback
+ return val == expected
+
+
+def get_abi_tag() -> str | None:
+ """Return the ABI tag based on SOABI (if available) or emulate SOABI (PyPy2)."""
+ soabi: str = sysconfig.get_config_var("SOABI")
+ impl = tags.interpreter_name()
+ if not soabi and impl in ("cp", "pp") and hasattr(sys, "maxunicode"):
+ d = ""
+ m = ""
+ u = ""
+ if get_flag("Py_DEBUG", hasattr(sys, "gettotalrefcount"), warn=(impl == "cp")):
+ d = "d"
+
+ if get_flag(
+ "WITH_PYMALLOC",
+ impl == "cp",
+ warn=(impl == "cp" and sys.version_info < (3, 8)),
+ ) and sys.version_info < (3, 8):
+ m = "m"
+
+ abi = f"{impl}{tags.interpreter_version()}{d}{m}{u}"
+ elif soabi and impl == "cp" and soabi.startswith("cpython"):
+ # non-Windows
+ abi = "cp" + soabi.split("-")[1]
+ elif soabi and impl == "cp" and soabi.startswith("cp"):
+ # Windows
+ abi = soabi.split("-")[0]
+ elif soabi and impl == "pp":
+ # we want something like pypy36-pp73
+ abi = "-".join(soabi.split("-")[:2])
+ abi = abi.replace(".", "_").replace("-", "_")
+ elif soabi and impl == "graalpy":
+ abi = "-".join(soabi.split("-")[:3])
+ abi = abi.replace(".", "_").replace("-", "_")
+ elif soabi:
+ abi = soabi.replace(".", "_").replace("-", "_")
+ else:
+ abi = None
+
+ return abi
+
+
+def safer_name(name: str) -> str:
+ return safe_name(name).replace("-", "_")
+
+
+def safer_version(version: str) -> str:
+ return safe_version(version).replace("-", "_")
+
+
+def remove_readonly(
+ func: Callable[..., object],
+ path: str,
+ excinfo: tuple[type[Exception], Exception, types.TracebackType],
+) -> None:
+ remove_readonly_exc(func, path, excinfo[1])
+
+
+def remove_readonly_exc(func: Callable[..., object], path: str, exc: Exception) -> None:
+ os.chmod(path, stat.S_IWRITE)
+ func(path)
+
+
+class bdist_wheel(Command):
+ description = "create a wheel distribution"
+
+ supported_compressions = {
+ "stored": ZIP_STORED,
+ "deflated": ZIP_DEFLATED,
+ }
+
+ user_options = [
+ ("bdist-dir=", "b", "temporary directory for creating the distribution"),
+ (
+ "plat-name=",
+ "p",
+ "platform name to embed in generated filenames "
+ f"(default: {get_platform(None)})",
+ ),
+ (
+ "keep-temp",
+ "k",
+ "keep the pseudo-installation tree around after "
+ "creating the distribution archive",
+ ),
+ ("dist-dir=", "d", "directory to put final built distributions in"),
+ ("skip-build", None, "skip rebuilding everything (for testing/debugging)"),
+ (
+ "relative",
+ None,
+ "build the archive using relative paths (default: false)",
+ ),
+ (
+ "owner=",
+ "u",
+ "Owner name used when creating a tar file [default: current user]",
+ ),
+ (
+ "group=",
+ "g",
+ "Group name used when creating a tar file [default: current group]",
+ ),
+ ("universal", None, "make a universal wheel (default: false)"),
+ (
+ "compression=",
+ None,
+ "zipfile compression (one of: {}) (default: 'deflated')".format(
+ ", ".join(supported_compressions)
+ ),
+ ),
+ (
+ "python-tag=",
+ None,
+ f"Python implementation compatibility tag (default: '{python_tag()}')",
+ ),
+ (
+ "build-number=",
+ None,
+ "Build number for this particular version. "
+ "As specified in PEP-0427, this must start with a digit. "
+ "[default: None]",
+ ),
+ (
+ "py-limited-api=",
+ None,
+ "Python tag (cp32|cp33|cpNN) for abi3 wheel tag (default: false)",
+ ),
+ ]
+
+ boolean_options = ["keep-temp", "skip-build", "relative", "universal"]
+
+ def initialize_options(self):
+ self.bdist_dir: str = None
+ self.data_dir = None
+ self.plat_name: str | None = None
+ self.plat_tag = None
+ self.format = "zip"
+ self.keep_temp = False
+ self.dist_dir: str | None = None
+ self.egginfo_dir = None
+ self.root_is_pure: bool | None = None
+ self.skip_build = None
+ self.relative = False
+ self.owner = None
+ self.group = None
+ self.universal: bool = False
+ self.compression: str | int = "deflated"
+ self.python_tag: str = python_tag()
+ self.build_number: str | None = None
+ self.py_limited_api: str | Literal[False] = False
+ self.plat_name_supplied = False
+
+ def finalize_options(self):
+ if self.bdist_dir is None:
+ bdist_base = self.get_finalized_command("bdist").bdist_base
+ self.bdist_dir = os.path.join(bdist_base, "wheel")
+
+ egg_info = self.distribution.get_command_obj("egg_info")
+ egg_info.ensure_finalized() # needed for correct `wheel_dist_name`
+
+ self.data_dir = self.wheel_dist_name + ".data"
+ self.plat_name_supplied = self.plat_name is not None
+
+ try:
+ self.compression = self.supported_compressions[self.compression]
+ except KeyError:
+ raise ValueError(f"Unsupported compression: {self.compression}") from None
+
+ need_options = ("dist_dir", "plat_name", "skip_build")
+
+ self.set_undefined_options("bdist", *zip(need_options, need_options))
+
+ self.root_is_pure = not (
+ self.distribution.has_ext_modules() or self.distribution.has_c_libraries()
+ )
+
+ if self.py_limited_api and not re.match(
+ PY_LIMITED_API_PATTERN, self.py_limited_api
+ ):
+ raise ValueError(f"py-limited-api must match '{PY_LIMITED_API_PATTERN}'")
+
+ # Support legacy [wheel] section for setting universal
+ wheel = self.distribution.get_option_dict("wheel")
+ if "universal" in wheel:
+ # please don't define this in your global configs
+ log.warning(
+ "The [wheel] section is deprecated. Use [bdist_wheel] instead.",
+ )
+ val = wheel["universal"][1].strip()
+ if val.lower() in ("1", "true", "yes"):
+ self.universal = True
+
+ if self.build_number is not None and not self.build_number[:1].isdigit():
+ raise ValueError("Build tag (build-number) must start with a digit.")
+
+ @property
+ def wheel_dist_name(self):
+ """Return distribution full name with - replaced with _"""
+ components = (
+ safer_name(self.distribution.get_name()),
+ safer_version(self.distribution.get_version()),
+ )
+ if self.build_number:
+ components += (self.build_number,)
+ return "-".join(components)
+
+ def get_tag(self) -> tuple[str, str, str]:
+ # bdist sets self.plat_name if unset, we should only use it for purepy
+ # wheels if the user supplied it.
+ if self.plat_name_supplied:
+ plat_name = cast(str, self.plat_name)
+ elif self.root_is_pure:
+ plat_name = "any"
+ else:
+ # macosx contains system version in platform name so need special handle
+ if self.plat_name and not self.plat_name.startswith("macosx"):
+ plat_name = self.plat_name
+ else:
+ # on macosx always limit the platform name to comply with any
+ # c-extension modules in bdist_dir, since the user can specify
+ # a higher MACOSX_DEPLOYMENT_TARGET via tools like CMake
+
+ # on other platforms, and on macosx if there are no c-extension
+ # modules, use the default platform name.
+ plat_name = get_platform(self.bdist_dir)
+
+ if _is_32bit_interpreter():
+ if plat_name in ("linux-x86_64", "linux_x86_64"):
+ plat_name = "linux_i686"
+ if plat_name in ("linux-aarch64", "linux_aarch64"):
+ # TODO armv8l, packaging pull request #690 => this did not land
+ # in pip/packaging yet
+ plat_name = "linux_armv7l"
+
+ plat_name = (
+ plat_name.lower().replace("-", "_").replace(".", "_").replace(" ", "_")
+ )
+
+ if self.root_is_pure:
+ if self.universal:
+ impl = "py2.py3"
+ else:
+ impl = self.python_tag
+ tag = (impl, "none", plat_name)
+ else:
+ impl_name = tags.interpreter_name()
+ impl_ver = tags.interpreter_version()
+ impl = impl_name + impl_ver
+ # We don't work on CPython 3.1, 3.0.
+ if self.py_limited_api and (impl_name + impl_ver).startswith("cp3"):
+ impl = self.py_limited_api
+ abi_tag = "abi3"
+ else:
+ abi_tag = str(get_abi_tag()).lower()
+ tag = (impl, abi_tag, plat_name)
+ # issue gh-374: allow overriding plat_name
+ supported_tags = [
+ (t.interpreter, t.abi, plat_name) for t in tags.sys_tags()
+ ]
+ assert (
+ tag in supported_tags
+ ), f"would build wheel with unsupported tag {tag}"
+ return tag
+
+ def run(self):
+ build_scripts = self.reinitialize_command("build_scripts")
+ build_scripts.executable = "python"
+ build_scripts.force = True
+
+ build_ext = self.reinitialize_command("build_ext")
+ build_ext.inplace = False
+
+ if not self.skip_build:
+ self.run_command("build")
+
+ install = self.reinitialize_command("install", reinit_subcommands=True)
+ install.root = self.bdist_dir
+ install.compile = False
+ install.skip_build = self.skip_build
+ install.warn_dir = False
+
+ # A wheel without setuptools scripts is more cross-platform.
+ # Use the (undocumented) `no_ep` option to setuptools'
+ # install_scripts command to avoid creating entry point scripts.
+ install_scripts = self.reinitialize_command("install_scripts")
+ install_scripts.no_ep = True
+
+ # Use a custom scheme for the archive, because we have to decide
+ # at installation time which scheme to use.
+ for key in ("headers", "scripts", "data", "purelib", "platlib"):
+ setattr(install, "install_" + key, os.path.join(self.data_dir, key))
+
+ basedir_observed = ""
+
+ if os.name == "nt":
+ # win32 barfs if any of these are ''; could be '.'?
+ # (distutils.command.install:change_roots bug)
+ basedir_observed = os.path.normpath(os.path.join(self.data_dir, ".."))
+ self.install_libbase = self.install_lib = basedir_observed
+
+ setattr(
+ install,
+ "install_purelib" if self.root_is_pure else "install_platlib",
+ basedir_observed,
+ )
+
+ log.info(f"installing to {self.bdist_dir}")
+
+ self.run_command("install")
+
+ impl_tag, abi_tag, plat_tag = self.get_tag()
+ archive_basename = f"{self.wheel_dist_name}-{impl_tag}-{abi_tag}-{plat_tag}"
+ if not self.relative:
+ archive_root = self.bdist_dir
+ else:
+ archive_root = os.path.join(
+ self.bdist_dir, self._ensure_relative(install.install_base)
+ )
+
+ self.set_undefined_options("install_egg_info", ("target", "egginfo_dir"))
+ distinfo_dirname = (
+ f"{safer_name(self.distribution.get_name())}-"
+ f"{safer_version(self.distribution.get_version())}.dist-info"
+ )
+ distinfo_dir = os.path.join(self.bdist_dir, distinfo_dirname)
+ self.egg2dist(self.egginfo_dir, distinfo_dir)
+
+ self.write_wheelfile(distinfo_dir)
+
+ # Make the archive
+ if not os.path.exists(self.dist_dir):
+ os.makedirs(self.dist_dir)
+
+ wheel_path = os.path.join(self.dist_dir, archive_basename + ".whl")
+ with WheelFile(wheel_path, "w", self.compression) as wf:
+ wf.write_files(archive_root)
+
+ # Add to 'Distribution.dist_files' so that the "upload" command works
+ getattr(self.distribution, "dist_files", []).append(
+ (
+ "bdist_wheel",
+ "{}.{}".format(*sys.version_info[:2]), # like 3.7
+ wheel_path,
+ )
+ )
+
+ if not self.keep_temp:
+ log.info(f"removing {self.bdist_dir}")
+ if not self.dry_run:
+ if sys.version_info < (3, 12):
+ rmtree(self.bdist_dir, onerror=remove_readonly)
+ else:
+ rmtree(self.bdist_dir, onexc=remove_readonly_exc)
+
+ def write_wheelfile(
+ self, wheelfile_base: str, generator: str = f"bdist_wheel ({wheel_version})"
+ ):
+ from email.message import Message
+
+ msg = Message()
+ msg["Wheel-Version"] = "1.0" # of the spec
+ msg["Generator"] = generator
+ msg["Root-Is-Purelib"] = str(self.root_is_pure).lower()
+ if self.build_number is not None:
+ msg["Build"] = self.build_number
+
+ # Doesn't work for bdist_wininst
+ impl_tag, abi_tag, plat_tag = self.get_tag()
+ for impl in impl_tag.split("."):
+ for abi in abi_tag.split("."):
+ for plat in plat_tag.split("."):
+ msg["Tag"] = "-".join((impl, abi, plat))
+
+ wheelfile_path = os.path.join(wheelfile_base, "WHEEL")
+ log.info(f"creating {wheelfile_path}")
+ with open(wheelfile_path, "wb") as f:
+ BytesGenerator(f, maxheaderlen=0).flatten(msg)
+
+ def _ensure_relative(self, path: str) -> str:
+ # copied from dir_util, deleted
+ drive, path = os.path.splitdrive(path)
+ if path[0:1] == os.sep:
+ path = drive + path[1:]
+ return path
+
+ @property
+ def license_paths(self) -> Iterable[str]:
+ if setuptools_major_version >= 57:
+ # Setuptools has resolved any patterns to actual file names
+ return self.distribution.metadata.license_files or ()
+
+ files: set[str] = set()
+ metadata = self.distribution.get_option_dict("metadata")
+ if setuptools_major_version >= 42:
+ # Setuptools recognizes the license_files option but does not do globbing
+ patterns = cast(Sequence[str], self.distribution.metadata.license_files)
+ else:
+ # Prior to those, wheel is entirely responsible for handling license files
+ if "license_files" in metadata:
+ patterns = metadata["license_files"][1].split()
+ else:
+ patterns = ()
+
+ if "license_file" in metadata:
+ warnings.warn(
+ 'The "license_file" option is deprecated. Use "license_files" instead.',
+ DeprecationWarning,
+ stacklevel=2,
+ )
+ files.add(metadata["license_file"][1])
+
+ if not files and not patterns and not isinstance(patterns, list):
+ patterns = ("LICEN[CS]E*", "COPYING*", "NOTICE*", "AUTHORS*")
+
+ for pattern in patterns:
+ for path in iglob(pattern):
+ if path.endswith("~"):
+ log.debug(
+ f'ignoring license file "{path}" as it looks like a backup'
+ )
+ continue
+
+ if path not in files and os.path.isfile(path):
+ log.info(
+ f'adding license file "{path}" (matched pattern "{pattern}")'
+ )
+ files.add(path)
+
+ return files
+
+ def egg2dist(self, egginfo_path: str, distinfo_path: str):
+ """Convert an .egg-info directory into a .dist-info directory"""
+
+ def adios(p: str) -> None:
+ """Appropriately delete directory, file or link."""
+ if os.path.exists(p) and not os.path.islink(p) and os.path.isdir(p):
+ shutil.rmtree(p)
+ elif os.path.exists(p):
+ os.unlink(p)
+
+ adios(distinfo_path)
+
+ if not os.path.exists(egginfo_path):
+ # There is no egg-info. This is probably because the egg-info
+ # file/directory is not named matching the distribution name used
+ # to name the archive file. Check for this case and report
+ # accordingly.
+ import glob
+
+ pat = os.path.join(os.path.dirname(egginfo_path), "*.egg-info")
+ possible = glob.glob(pat)
+ err = f"Egg metadata expected at {egginfo_path} but not found"
+ if possible:
+ alt = os.path.basename(possible[0])
+ err += f" ({alt} found - possible misnamed archive file?)"
+
+ raise ValueError(err)
+
+ if os.path.isfile(egginfo_path):
+ # .egg-info is a single file
+ pkg_info = pkginfo_to_metadata(egginfo_path, egginfo_path)
+ os.mkdir(distinfo_path)
+ else:
+ # .egg-info is a directory
+ pkginfo_path = os.path.join(egginfo_path, "PKG-INFO")
+ pkg_info = pkginfo_to_metadata(egginfo_path, pkginfo_path)
+
+ # ignore common egg metadata that is useless to wheel
+ shutil.copytree(
+ egginfo_path,
+ distinfo_path,
+ ignore=lambda x, y: {
+ "PKG-INFO",
+ "requires.txt",
+ "SOURCES.txt",
+ "not-zip-safe",
+ },
+ )
+
+ # delete dependency_links if it is only whitespace
+ dependency_links_path = os.path.join(distinfo_path, "dependency_links.txt")
+ with open(dependency_links_path, encoding="utf-8") as dependency_links_file:
+ dependency_links = dependency_links_file.read().strip()
+ if not dependency_links:
+ adios(dependency_links_path)
+
+ pkg_info_path = os.path.join(distinfo_path, "METADATA")
+ serialization_policy = EmailPolicy(
+ utf8=True,
+ mangle_from_=False,
+ max_line_length=0,
+ )
+ with open(pkg_info_path, "w", encoding="utf-8") as out:
+ Generator(out, policy=serialization_policy).flatten(pkg_info)
+
+ for license_path in self.license_paths:
+ filename = os.path.basename(license_path)
+ shutil.copy(license_path, os.path.join(distinfo_path, filename))
+
+ adios(egginfo_path)
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/_setuptools_logging.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/_setuptools_logging.py
new file mode 100644
index 0000000000000000000000000000000000000000..a1a2482ba29ac5290c8f7d7688452ec3faf59332
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/_setuptools_logging.py
@@ -0,0 +1,26 @@
+# copied from setuptools.logging, omitting monkeypatching
+from __future__ import annotations
+
+import logging
+import sys
+
+
+def _not_warning(record: logging.LogRecord) -> bool:
+ return record.levelno < logging.WARNING
+
+
+def configure() -> None:
+ """
+ Configure logging to emit warning and above to stderr
+ and everything else to stdout. This behavior is provided
+ for compatibility with distutils.log but may change in
+ the future.
+ """
+ err_handler = logging.StreamHandler()
+ err_handler.setLevel(logging.WARNING)
+ out_handler = logging.StreamHandler(sys.stdout)
+ out_handler.addFilter(_not_warning)
+ handlers = err_handler, out_handler
+ logging.basicConfig(
+ format="{message}", style="{", handlers=handlers, level=logging.DEBUG
+ )
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/bdist_wheel.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/bdist_wheel.py
new file mode 100644
index 0000000000000000000000000000000000000000..dd7b8629e5087fe35a2ea7ab6d3cbbb4cacf0031
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/bdist_wheel.py
@@ -0,0 +1,26 @@
+from typing import TYPE_CHECKING
+from warnings import warn
+
+warn(
+ "The 'wheel' package is no longer the canonical location of the 'bdist_wheel' "
+ "command, and will be removed in a future release. Please update to setuptools "
+ "v70.1 or later which contains an integrated version of this command.",
+ DeprecationWarning,
+ stacklevel=1,
+)
+
+if TYPE_CHECKING:
+ from ._bdist_wheel import bdist_wheel as bdist_wheel
+else:
+ try:
+ # Better integration/compatibility with setuptools:
+ # in the case new fixes or PEPs are implemented in setuptools
+ # there is no need to backport them to the deprecated code base.
+ # This is useful in the case of old packages in the ecosystem
+ # that are still used but have low maintenance.
+ from setuptools.command.bdist_wheel import bdist_wheel
+ except ImportError:
+ # Only used in the case of old setuptools versions.
+ # If the user wants to get the latest fixes/PEPs,
+ # they are encouraged to address the deprecation warning.
+ from ._bdist_wheel import bdist_wheel as bdist_wheel
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/macosx_libfile.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/macosx_libfile.py
new file mode 100644
index 0000000000000000000000000000000000000000..abdfc9eda1d4c1f33270c155e1610fe73bd54263
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/macosx_libfile.py
@@ -0,0 +1,482 @@
+"""
+This module contains function to analyse dynamic library
+headers to extract system information
+
+Currently only for MacOSX
+
+Library file on macosx system starts with Mach-O or Fat field.
+This can be distinguish by first 32 bites and it is called magic number.
+Proper value of magic number is with suffix _MAGIC. Suffix _CIGAM means
+reversed bytes order.
+Both fields can occur in two types: 32 and 64 bytes.
+
+FAT field inform that this library contains few version of library
+(typically for different types version). It contains
+information where Mach-O headers starts.
+
+Each section started with Mach-O header contains one library
+(So if file starts with this field it contains only one version).
+
+After filed Mach-O there are section fields.
+Each of them starts with two fields:
+cmd - magic number for this command
+cmdsize - total size occupied by this section information.
+
+In this case only sections LC_VERSION_MIN_MACOSX (for macosx 10.13 and earlier)
+and LC_BUILD_VERSION (for macosx 10.14 and newer) are interesting,
+because them contains information about minimal system version.
+
+Important remarks:
+- For fat files this implementation looks for maximum number version.
+ It not check if it is 32 or 64 and do not compare it with currently built package.
+ So it is possible to false report higher version that needed.
+- All structures signatures are taken form macosx header files.
+- I think that binary format will be more stable than `otool` output.
+ and if apple introduce some changes both implementation will need to be updated.
+- The system compile will set the deployment target no lower than
+ 11.0 for arm64 builds. For "Universal 2" builds use the x86_64 deployment
+ target when the arm64 target is 11.0.
+"""
+
+from __future__ import annotations
+
+import ctypes
+import os
+import sys
+from io import BufferedIOBase
+from typing import TYPE_CHECKING
+
+if TYPE_CHECKING:
+ from typing import Union
+
+ StrPath = Union[str, os.PathLike[str]]
+
+"""here the needed const and struct from mach-o header files"""
+
+FAT_MAGIC = 0xCAFEBABE
+FAT_CIGAM = 0xBEBAFECA
+FAT_MAGIC_64 = 0xCAFEBABF
+FAT_CIGAM_64 = 0xBFBAFECA
+MH_MAGIC = 0xFEEDFACE
+MH_CIGAM = 0xCEFAEDFE
+MH_MAGIC_64 = 0xFEEDFACF
+MH_CIGAM_64 = 0xCFFAEDFE
+
+LC_VERSION_MIN_MACOSX = 0x24
+LC_BUILD_VERSION = 0x32
+
+CPU_TYPE_ARM64 = 0x0100000C
+
+mach_header_fields = [
+ ("magic", ctypes.c_uint32),
+ ("cputype", ctypes.c_int),
+ ("cpusubtype", ctypes.c_int),
+ ("filetype", ctypes.c_uint32),
+ ("ncmds", ctypes.c_uint32),
+ ("sizeofcmds", ctypes.c_uint32),
+ ("flags", ctypes.c_uint32),
+]
+"""
+struct mach_header {
+ uint32_t magic; /* mach magic number identifier */
+ cpu_type_t cputype; /* cpu specifier */
+ cpu_subtype_t cpusubtype; /* machine specifier */
+ uint32_t filetype; /* type of file */
+ uint32_t ncmds; /* number of load commands */
+ uint32_t sizeofcmds; /* the size of all the load commands */
+ uint32_t flags; /* flags */
+};
+typedef integer_t cpu_type_t;
+typedef integer_t cpu_subtype_t;
+"""
+
+mach_header_fields_64 = mach_header_fields + [("reserved", ctypes.c_uint32)]
+"""
+struct mach_header_64 {
+ uint32_t magic; /* mach magic number identifier */
+ cpu_type_t cputype; /* cpu specifier */
+ cpu_subtype_t cpusubtype; /* machine specifier */
+ uint32_t filetype; /* type of file */
+ uint32_t ncmds; /* number of load commands */
+ uint32_t sizeofcmds; /* the size of all the load commands */
+ uint32_t flags; /* flags */
+ uint32_t reserved; /* reserved */
+};
+"""
+
+fat_header_fields = [("magic", ctypes.c_uint32), ("nfat_arch", ctypes.c_uint32)]
+"""
+struct fat_header {
+ uint32_t magic; /* FAT_MAGIC or FAT_MAGIC_64 */
+ uint32_t nfat_arch; /* number of structs that follow */
+};
+"""
+
+fat_arch_fields = [
+ ("cputype", ctypes.c_int),
+ ("cpusubtype", ctypes.c_int),
+ ("offset", ctypes.c_uint32),
+ ("size", ctypes.c_uint32),
+ ("align", ctypes.c_uint32),
+]
+"""
+struct fat_arch {
+ cpu_type_t cputype; /* cpu specifier (int) */
+ cpu_subtype_t cpusubtype; /* machine specifier (int) */
+ uint32_t offset; /* file offset to this object file */
+ uint32_t size; /* size of this object file */
+ uint32_t align; /* alignment as a power of 2 */
+};
+"""
+
+fat_arch_64_fields = [
+ ("cputype", ctypes.c_int),
+ ("cpusubtype", ctypes.c_int),
+ ("offset", ctypes.c_uint64),
+ ("size", ctypes.c_uint64),
+ ("align", ctypes.c_uint32),
+ ("reserved", ctypes.c_uint32),
+]
+"""
+struct fat_arch_64 {
+ cpu_type_t cputype; /* cpu specifier (int) */
+ cpu_subtype_t cpusubtype; /* machine specifier (int) */
+ uint64_t offset; /* file offset to this object file */
+ uint64_t size; /* size of this object file */
+ uint32_t align; /* alignment as a power of 2 */
+ uint32_t reserved; /* reserved */
+};
+"""
+
+segment_base_fields = [("cmd", ctypes.c_uint32), ("cmdsize", ctypes.c_uint32)]
+"""base for reading segment info"""
+
+segment_command_fields = [
+ ("cmd", ctypes.c_uint32),
+ ("cmdsize", ctypes.c_uint32),
+ ("segname", ctypes.c_char * 16),
+ ("vmaddr", ctypes.c_uint32),
+ ("vmsize", ctypes.c_uint32),
+ ("fileoff", ctypes.c_uint32),
+ ("filesize", ctypes.c_uint32),
+ ("maxprot", ctypes.c_int),
+ ("initprot", ctypes.c_int),
+ ("nsects", ctypes.c_uint32),
+ ("flags", ctypes.c_uint32),
+]
+"""
+struct segment_command { /* for 32-bit architectures */
+ uint32_t cmd; /* LC_SEGMENT */
+ uint32_t cmdsize; /* includes sizeof section structs */
+ char segname[16]; /* segment name */
+ uint32_t vmaddr; /* memory address of this segment */
+ uint32_t vmsize; /* memory size of this segment */
+ uint32_t fileoff; /* file offset of this segment */
+ uint32_t filesize; /* amount to map from the file */
+ vm_prot_t maxprot; /* maximum VM protection */
+ vm_prot_t initprot; /* initial VM protection */
+ uint32_t nsects; /* number of sections in segment */
+ uint32_t flags; /* flags */
+};
+typedef int vm_prot_t;
+"""
+
+segment_command_fields_64 = [
+ ("cmd", ctypes.c_uint32),
+ ("cmdsize", ctypes.c_uint32),
+ ("segname", ctypes.c_char * 16),
+ ("vmaddr", ctypes.c_uint64),
+ ("vmsize", ctypes.c_uint64),
+ ("fileoff", ctypes.c_uint64),
+ ("filesize", ctypes.c_uint64),
+ ("maxprot", ctypes.c_int),
+ ("initprot", ctypes.c_int),
+ ("nsects", ctypes.c_uint32),
+ ("flags", ctypes.c_uint32),
+]
+"""
+struct segment_command_64 { /* for 64-bit architectures */
+ uint32_t cmd; /* LC_SEGMENT_64 */
+ uint32_t cmdsize; /* includes sizeof section_64 structs */
+ char segname[16]; /* segment name */
+ uint64_t vmaddr; /* memory address of this segment */
+ uint64_t vmsize; /* memory size of this segment */
+ uint64_t fileoff; /* file offset of this segment */
+ uint64_t filesize; /* amount to map from the file */
+ vm_prot_t maxprot; /* maximum VM protection */
+ vm_prot_t initprot; /* initial VM protection */
+ uint32_t nsects; /* number of sections in segment */
+ uint32_t flags; /* flags */
+};
+"""
+
+version_min_command_fields = segment_base_fields + [
+ ("version", ctypes.c_uint32),
+ ("sdk", ctypes.c_uint32),
+]
+"""
+struct version_min_command {
+ uint32_t cmd; /* LC_VERSION_MIN_MACOSX or
+ LC_VERSION_MIN_IPHONEOS or
+ LC_VERSION_MIN_WATCHOS or
+ LC_VERSION_MIN_TVOS */
+ uint32_t cmdsize; /* sizeof(struct min_version_command) */
+ uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+ uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+};
+"""
+
+build_version_command_fields = segment_base_fields + [
+ ("platform", ctypes.c_uint32),
+ ("minos", ctypes.c_uint32),
+ ("sdk", ctypes.c_uint32),
+ ("ntools", ctypes.c_uint32),
+]
+"""
+struct build_version_command {
+ uint32_t cmd; /* LC_BUILD_VERSION */
+ uint32_t cmdsize; /* sizeof(struct build_version_command) plus */
+ /* ntools * sizeof(struct build_tool_version) */
+ uint32_t platform; /* platform */
+ uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+ uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
+ uint32_t ntools; /* number of tool entries following this */
+};
+"""
+
+
+def swap32(x: int) -> int:
+ return (
+ ((x << 24) & 0xFF000000)
+ | ((x << 8) & 0x00FF0000)
+ | ((x >> 8) & 0x0000FF00)
+ | ((x >> 24) & 0x000000FF)
+ )
+
+
+def get_base_class_and_magic_number(
+ lib_file: BufferedIOBase,
+ seek: int | None = None,
+) -> tuple[type[ctypes.Structure], int]:
+ if seek is None:
+ seek = lib_file.tell()
+ else:
+ lib_file.seek(seek)
+ magic_number = ctypes.c_uint32.from_buffer_copy(
+ lib_file.read(ctypes.sizeof(ctypes.c_uint32))
+ ).value
+
+ # Handle wrong byte order
+ if magic_number in [FAT_CIGAM, FAT_CIGAM_64, MH_CIGAM, MH_CIGAM_64]:
+ if sys.byteorder == "little":
+ BaseClass = ctypes.BigEndianStructure
+ else:
+ BaseClass = ctypes.LittleEndianStructure
+
+ magic_number = swap32(magic_number)
+ else:
+ BaseClass = ctypes.Structure
+
+ lib_file.seek(seek)
+ return BaseClass, magic_number
+
+
+def read_data(struct_class: type[ctypes.Structure], lib_file: BufferedIOBase):
+ return struct_class.from_buffer_copy(lib_file.read(ctypes.sizeof(struct_class)))
+
+
+def extract_macosx_min_system_version(path_to_lib: str):
+ with open(path_to_lib, "rb") as lib_file:
+ BaseClass, magic_number = get_base_class_and_magic_number(lib_file, 0)
+ if magic_number not in [FAT_MAGIC, FAT_MAGIC_64, MH_MAGIC, MH_MAGIC_64]:
+ return
+
+ if magic_number in [FAT_MAGIC, FAT_CIGAM_64]:
+
+ class FatHeader(BaseClass):
+ _fields_ = fat_header_fields
+
+ fat_header = read_data(FatHeader, lib_file)
+ if magic_number == FAT_MAGIC:
+
+ class FatArch(BaseClass):
+ _fields_ = fat_arch_fields
+
+ else:
+
+ class FatArch(BaseClass):
+ _fields_ = fat_arch_64_fields
+
+ fat_arch_list = [
+ read_data(FatArch, lib_file) for _ in range(fat_header.nfat_arch)
+ ]
+
+ versions_list: list[tuple[int, int, int]] = []
+ for el in fat_arch_list:
+ try:
+ version = read_mach_header(lib_file, el.offset)
+ if version is not None:
+ if el.cputype == CPU_TYPE_ARM64 and len(fat_arch_list) != 1:
+ # Xcode will not set the deployment target below 11.0.0
+ # for the arm64 architecture. Ignore the arm64 deployment
+ # in fat binaries when the target is 11.0.0, that way
+ # the other architectures can select a lower deployment
+ # target.
+ # This is safe because there is no arm64 variant for
+ # macOS 10.15 or earlier.
+ if version == (11, 0, 0):
+ continue
+ versions_list.append(version)
+ except ValueError:
+ pass
+
+ if len(versions_list) > 0:
+ return max(versions_list)
+ else:
+ return None
+
+ else:
+ try:
+ return read_mach_header(lib_file, 0)
+ except ValueError:
+ """when some error during read library files"""
+ return None
+
+
+def read_mach_header(
+ lib_file: BufferedIOBase,
+ seek: int | None = None,
+) -> tuple[int, int, int] | None:
+ """
+ This function parses a Mach-O header and extracts
+ information about the minimal macOS version.
+
+ :param lib_file: reference to opened library file with pointer
+ """
+ base_class, magic_number = get_base_class_and_magic_number(lib_file, seek)
+ arch = "32" if magic_number == MH_MAGIC else "64"
+
+ class SegmentBase(base_class):
+ _fields_ = segment_base_fields
+
+ if arch == "32":
+
+ class MachHeader(base_class):
+ _fields_ = mach_header_fields
+
+ else:
+
+ class MachHeader(base_class):
+ _fields_ = mach_header_fields_64
+
+ mach_header = read_data(MachHeader, lib_file)
+ for _i in range(mach_header.ncmds):
+ pos = lib_file.tell()
+ segment_base = read_data(SegmentBase, lib_file)
+ lib_file.seek(pos)
+ if segment_base.cmd == LC_VERSION_MIN_MACOSX:
+
+ class VersionMinCommand(base_class):
+ _fields_ = version_min_command_fields
+
+ version_info = read_data(VersionMinCommand, lib_file)
+ return parse_version(version_info.version)
+ elif segment_base.cmd == LC_BUILD_VERSION:
+
+ class VersionBuild(base_class):
+ _fields_ = build_version_command_fields
+
+ version_info = read_data(VersionBuild, lib_file)
+ return parse_version(version_info.minos)
+ else:
+ lib_file.seek(pos + segment_base.cmdsize)
+ continue
+
+
+def parse_version(version: int) -> tuple[int, int, int]:
+ x = (version & 0xFFFF0000) >> 16
+ y = (version & 0x0000FF00) >> 8
+ z = version & 0x000000FF
+ return x, y, z
+
+
+def calculate_macosx_platform_tag(archive_root: StrPath, platform_tag: str) -> str:
+ """
+ Calculate proper macosx platform tag basing on files which are included to wheel
+
+ Example platform tag `macosx-10.14-x86_64`
+ """
+ prefix, base_version, suffix = platform_tag.split("-")
+ base_version = tuple(int(x) for x in base_version.split("."))
+ base_version = base_version[:2]
+ if base_version[0] > 10:
+ base_version = (base_version[0], 0)
+ assert len(base_version) == 2
+ if "MACOSX_DEPLOYMENT_TARGET" in os.environ:
+ deploy_target = tuple(
+ int(x) for x in os.environ["MACOSX_DEPLOYMENT_TARGET"].split(".")
+ )
+ deploy_target = deploy_target[:2]
+ if deploy_target[0] > 10:
+ deploy_target = (deploy_target[0], 0)
+ if deploy_target < base_version:
+ sys.stderr.write(
+ "[WARNING] MACOSX_DEPLOYMENT_TARGET is set to a lower value ({}) than "
+ "the version on which the Python interpreter was compiled ({}), and "
+ "will be ignored.\n".format(
+ ".".join(str(x) for x in deploy_target),
+ ".".join(str(x) for x in base_version),
+ )
+ )
+ else:
+ base_version = deploy_target
+
+ assert len(base_version) == 2
+ start_version = base_version
+ versions_dict: dict[str, tuple[int, int]] = {}
+ for dirpath, _dirnames, filenames in os.walk(archive_root):
+ for filename in filenames:
+ if filename.endswith(".dylib") or filename.endswith(".so"):
+ lib_path = os.path.join(dirpath, filename)
+ min_ver = extract_macosx_min_system_version(lib_path)
+ if min_ver is not None:
+ min_ver = min_ver[0:2]
+ if min_ver[0] > 10:
+ min_ver = (min_ver[0], 0)
+ versions_dict[lib_path] = min_ver
+
+ if len(versions_dict) > 0:
+ base_version = max(base_version, max(versions_dict.values()))
+
+ # macosx platform tag do not support minor bugfix release
+ fin_base_version = "_".join([str(x) for x in base_version])
+ if start_version < base_version:
+ problematic_files = [k for k, v in versions_dict.items() if v > start_version]
+ problematic_files = "\n".join(problematic_files)
+ if len(problematic_files) == 1:
+ files_form = "this file"
+ else:
+ files_form = "these files"
+ error_message = (
+ "[WARNING] This wheel needs a higher macOS version than {} "
+ "To silence this warning, set MACOSX_DEPLOYMENT_TARGET to at least "
+ + fin_base_version
+ + " or recreate "
+ + files_form
+ + " with lower "
+ "MACOSX_DEPLOYMENT_TARGET: \n" + problematic_files
+ )
+
+ if "MACOSX_DEPLOYMENT_TARGET" in os.environ:
+ error_message = error_message.format(
+ "is set in MACOSX_DEPLOYMENT_TARGET variable."
+ )
+ else:
+ error_message = error_message.format(
+ "the version your Python interpreter is compiled against."
+ )
+
+ sys.stderr.write(error_message)
+
+ platform_tag = prefix + "_" + fin_base_version + "_" + suffix
+ return platform_tag
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/metadata.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/metadata.py
new file mode 100644
index 0000000000000000000000000000000000000000..b8098fa8599a1f142ee33ee551b7a874f5f98840
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/metadata.py
@@ -0,0 +1,183 @@
+"""
+Tools for converting old- to new-style metadata.
+"""
+
+from __future__ import annotations
+
+import functools
+import itertools
+import os.path
+import re
+import textwrap
+from email.message import Message
+from email.parser import Parser
+from typing import Generator, Iterable, Iterator, Literal
+
+from .vendored.packaging.requirements import Requirement
+
+
+def _nonblank(str: str) -> bool | Literal[""]:
+ return str and not str.startswith("#")
+
+
+@functools.singledispatch
+def yield_lines(iterable: Iterable[str]) -> Iterator[str]:
+ r"""
+ Yield valid lines of a string or iterable.
+ >>> list(yield_lines(''))
+ []
+ >>> list(yield_lines(['foo', 'bar']))
+ ['foo', 'bar']
+ >>> list(yield_lines('foo\nbar'))
+ ['foo', 'bar']
+ >>> list(yield_lines('\nfoo\n#bar\nbaz #comment'))
+ ['foo', 'baz #comment']
+ >>> list(yield_lines(['foo\nbar', 'baz', 'bing\n\n\n']))
+ ['foo', 'bar', 'baz', 'bing']
+ """
+ return itertools.chain.from_iterable(map(yield_lines, iterable))
+
+
+@yield_lines.register(str)
+def _(text: str) -> Iterator[str]:
+ return filter(_nonblank, map(str.strip, text.splitlines()))
+
+
+def split_sections(
+ s: str | Iterator[str],
+) -> Generator[tuple[str | None, list[str]], None, None]:
+ """Split a string or iterable thereof into (section, content) pairs
+ Each ``section`` is a stripped version of the section header ("[section]")
+ and each ``content`` is a list of stripped lines excluding blank lines and
+ comment-only lines. If there are any such lines before the first section
+ header, they're returned in a first ``section`` of ``None``.
+ """
+ section = None
+ content: list[str] = []
+ for line in yield_lines(s):
+ if line.startswith("["):
+ if line.endswith("]"):
+ if section or content:
+ yield section, content
+ section = line[1:-1].strip()
+ content = []
+ else:
+ raise ValueError("Invalid section heading", line)
+ else:
+ content.append(line)
+
+ # wrap up last segment
+ yield section, content
+
+
+def safe_extra(extra: str) -> str:
+ """Convert an arbitrary string to a standard 'extra' name
+ Any runs of non-alphanumeric characters are replaced with a single '_',
+ and the result is always lowercased.
+ """
+ return re.sub("[^A-Za-z0-9.-]+", "_", extra).lower()
+
+
+def safe_name(name: str) -> str:
+ """Convert an arbitrary string to a standard distribution name
+ Any runs of non-alphanumeric/. characters are replaced with a single '-'.
+ """
+ return re.sub("[^A-Za-z0-9.]+", "-", name)
+
+
+def requires_to_requires_dist(requirement: Requirement) -> str:
+ """Return the version specifier for a requirement in PEP 345/566 fashion."""
+ if requirement.url:
+ return " @ " + requirement.url
+
+ requires_dist: list[str] = []
+ for spec in requirement.specifier:
+ requires_dist.append(spec.operator + spec.version)
+
+ if requires_dist:
+ return " " + ",".join(sorted(requires_dist))
+ else:
+ return ""
+
+
+def convert_requirements(requirements: list[str]) -> Iterator[str]:
+ """Yield Requires-Dist: strings for parsed requirements strings."""
+ for req in requirements:
+ parsed_requirement = Requirement(req)
+ spec = requires_to_requires_dist(parsed_requirement)
+ extras = ",".join(sorted(safe_extra(e) for e in parsed_requirement.extras))
+ if extras:
+ extras = f"[{extras}]"
+
+ yield safe_name(parsed_requirement.name) + extras + spec
+
+
+def generate_requirements(
+ extras_require: dict[str | None, list[str]],
+) -> Iterator[tuple[str, str]]:
+ """
+ Convert requirements from a setup()-style dictionary to
+ ('Requires-Dist', 'requirement') and ('Provides-Extra', 'extra') tuples.
+
+ extras_require is a dictionary of {extra: [requirements]} as passed to setup(),
+ using the empty extra {'': [requirements]} to hold install_requires.
+ """
+ for extra, depends in extras_require.items():
+ condition = ""
+ extra = extra or ""
+ if ":" in extra: # setuptools extra:condition syntax
+ extra, condition = extra.split(":", 1)
+
+ extra = safe_extra(extra)
+ if extra:
+ yield "Provides-Extra", extra
+ if condition:
+ condition = "(" + condition + ") and "
+ condition += f"extra == '{extra}'"
+
+ if condition:
+ condition = " ; " + condition
+
+ for new_req in convert_requirements(depends):
+ canonical_req = str(Requirement(new_req + condition))
+ yield "Requires-Dist", canonical_req
+
+
+def pkginfo_to_metadata(egg_info_path: str, pkginfo_path: str) -> Message:
+ """
+ Convert .egg-info directory with PKG-INFO to the Metadata 2.1 format
+ """
+ with open(pkginfo_path, encoding="utf-8") as headers:
+ pkg_info = Parser().parse(headers)
+
+ pkg_info.replace_header("Metadata-Version", "2.1")
+ # Those will be regenerated from `requires.txt`.
+ del pkg_info["Provides-Extra"]
+ del pkg_info["Requires-Dist"]
+ requires_path = os.path.join(egg_info_path, "requires.txt")
+ if os.path.exists(requires_path):
+ with open(requires_path, encoding="utf-8") as requires_file:
+ requires = requires_file.read()
+
+ parsed_requirements = sorted(split_sections(requires), key=lambda x: x[0] or "")
+ for extra, reqs in parsed_requirements:
+ for key, value in generate_requirements({extra: reqs}):
+ if (key, value) not in pkg_info.items():
+ pkg_info[key] = value
+
+ description = pkg_info["Description"]
+ if description:
+ description_lines = pkg_info["Description"].splitlines()
+ dedented_description = "\n".join(
+ # if the first line of long_description is blank,
+ # the first line here will be indented.
+ (
+ description_lines[0].lstrip(),
+ textwrap.dedent("\n".join(description_lines[1:])),
+ "\n",
+ )
+ )
+ pkg_info.set_payload(dedented_description)
+ del pkg_info["Description"]
+
+ return pkg_info
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/util.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/util.py
new file mode 100644
index 0000000000000000000000000000000000000000..c928aa403b75e1ae392b4af5fe13147a095bbd30
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/util.py
@@ -0,0 +1,17 @@
+from __future__ import annotations
+
+import base64
+import logging
+
+log = logging.getLogger("wheel")
+
+
+def urlsafe_b64encode(data: bytes) -> bytes:
+ """urlsafe_b64encode without padding"""
+ return base64.urlsafe_b64encode(data).rstrip(b"=")
+
+
+def urlsafe_b64decode(data: bytes) -> bytes:
+ """urlsafe_b64decode without padding"""
+ pad = b"=" * (4 - (len(data) & 3))
+ return base64.urlsafe_b64decode(data + pad)
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/wheelfile.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/wheelfile.py
new file mode 100644
index 0000000000000000000000000000000000000000..0a0f4596c566420135991713ee75ca29c4cff3ed
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/wheel/wheelfile.py
@@ -0,0 +1,227 @@
+from __future__ import annotations
+
+import csv
+import hashlib
+import os.path
+import re
+import stat
+import time
+from io import StringIO, TextIOWrapper
+from typing import IO, TYPE_CHECKING, Literal
+from zipfile import ZIP_DEFLATED, ZipFile, ZipInfo
+
+from wheel.cli import WheelError
+from wheel.util import log, urlsafe_b64decode, urlsafe_b64encode
+
+if TYPE_CHECKING:
+ from typing import Protocol, Sized, Union
+
+ from typing_extensions import Buffer
+
+ StrPath = Union[str, os.PathLike[str]]
+
+ class SizedBuffer(Sized, Buffer, Protocol): ...
+
+
+# Non-greedy matching of an optional build number may be too clever (more
+# invalid wheel filenames will match). Separate regex for .dist-info?
+WHEEL_INFO_RE = re.compile(
+ r"""^(?P(?P[^\s-]+?)-(?P[^\s-]+?))(-(?P\d[^\s-]*))?
+ -(?P[^\s-]+?)-(?P[^\s-]+?)-(?P\S+)\.whl$""",
+ re.VERBOSE,
+)
+MINIMUM_TIMESTAMP = 315532800 # 1980-01-01 00:00:00 UTC
+
+
+def get_zipinfo_datetime(timestamp: float | None = None):
+ # Some applications need reproducible .whl files, but they can't do this without
+ # forcing the timestamp of the individual ZipInfo objects. See issue #143.
+ timestamp = int(os.environ.get("SOURCE_DATE_EPOCH", timestamp or time.time()))
+ timestamp = max(timestamp, MINIMUM_TIMESTAMP)
+ return time.gmtime(timestamp)[0:6]
+
+
+class WheelFile(ZipFile):
+ """A ZipFile derivative class that also reads SHA-256 hashes from
+ .dist-info/RECORD and checks any read files against those.
+ """
+
+ _default_algorithm = hashlib.sha256
+
+ def __init__(
+ self,
+ file: StrPath,
+ mode: Literal["r", "w", "x", "a"] = "r",
+ compression: int = ZIP_DEFLATED,
+ ):
+ basename = os.path.basename(file)
+ self.parsed_filename = WHEEL_INFO_RE.match(basename)
+ if not basename.endswith(".whl") or self.parsed_filename is None:
+ raise WheelError(f"Bad wheel filename {basename!r}")
+
+ ZipFile.__init__(self, file, mode, compression=compression, allowZip64=True)
+
+ self.dist_info_path = "{}.dist-info".format(
+ self.parsed_filename.group("namever")
+ )
+ self.record_path = self.dist_info_path + "/RECORD"
+ self._file_hashes: dict[str, tuple[None, None] | tuple[int, bytes]] = {}
+ self._file_sizes = {}
+ if mode == "r":
+ # Ignore RECORD and any embedded wheel signatures
+ self._file_hashes[self.record_path] = None, None
+ self._file_hashes[self.record_path + ".jws"] = None, None
+ self._file_hashes[self.record_path + ".p7s"] = None, None
+
+ # Fill in the expected hashes by reading them from RECORD
+ try:
+ record = self.open(self.record_path)
+ except KeyError:
+ raise WheelError(f"Missing {self.record_path} file") from None
+
+ with record:
+ for line in csv.reader(
+ TextIOWrapper(record, newline="", encoding="utf-8")
+ ):
+ path, hash_sum, size = line
+ if not hash_sum:
+ continue
+
+ algorithm, hash_sum = hash_sum.split("=")
+ try:
+ hashlib.new(algorithm)
+ except ValueError:
+ raise WheelError(
+ f"Unsupported hash algorithm: {algorithm}"
+ ) from None
+
+ if algorithm.lower() in {"md5", "sha1"}:
+ raise WheelError(
+ f"Weak hash algorithm ({algorithm}) is not permitted by "
+ f"PEP 427"
+ )
+
+ self._file_hashes[path] = (
+ algorithm,
+ urlsafe_b64decode(hash_sum.encode("ascii")),
+ )
+
+ def open(
+ self,
+ name_or_info: str | ZipInfo,
+ mode: Literal["r", "w"] = "r",
+ pwd: bytes | None = None,
+ ) -> IO[bytes]:
+ def _update_crc(newdata: bytes) -> None:
+ eof = ef._eof
+ update_crc_orig(newdata)
+ running_hash.update(newdata)
+ if eof and running_hash.digest() != expected_hash:
+ raise WheelError(f"Hash mismatch for file '{ef_name}'")
+
+ ef_name = (
+ name_or_info.filename if isinstance(name_or_info, ZipInfo) else name_or_info
+ )
+ if (
+ mode == "r"
+ and not ef_name.endswith("/")
+ and ef_name not in self._file_hashes
+ ):
+ raise WheelError(f"No hash found for file '{ef_name}'")
+
+ ef = ZipFile.open(self, name_or_info, mode, pwd)
+ if mode == "r" and not ef_name.endswith("/"):
+ algorithm, expected_hash = self._file_hashes[ef_name]
+ if expected_hash is not None:
+ # Monkey patch the _update_crc method to also check for the hash from
+ # RECORD
+ running_hash = hashlib.new(algorithm)
+ update_crc_orig, ef._update_crc = ef._update_crc, _update_crc
+
+ return ef
+
+ def write_files(self, base_dir: str):
+ log.info(f"creating '{self.filename}' and adding '{base_dir}' to it")
+ deferred: list[tuple[str, str]] = []
+ for root, dirnames, filenames in os.walk(base_dir):
+ # Sort the directory names so that `os.walk` will walk them in a
+ # defined order on the next iteration.
+ dirnames.sort()
+ for name in sorted(filenames):
+ path = os.path.normpath(os.path.join(root, name))
+ if os.path.isfile(path):
+ arcname = os.path.relpath(path, base_dir).replace(os.path.sep, "/")
+ if arcname == self.record_path:
+ pass
+ elif root.endswith(".dist-info"):
+ deferred.append((path, arcname))
+ else:
+ self.write(path, arcname)
+
+ deferred.sort()
+ for path, arcname in deferred:
+ self.write(path, arcname)
+
+ def write(
+ self,
+ filename: str,
+ arcname: str | None = None,
+ compress_type: int | None = None,
+ ) -> None:
+ with open(filename, "rb") as f:
+ st = os.fstat(f.fileno())
+ data = f.read()
+
+ zinfo = ZipInfo(
+ arcname or filename, date_time=get_zipinfo_datetime(st.st_mtime)
+ )
+ zinfo.external_attr = (stat.S_IMODE(st.st_mode) | stat.S_IFMT(st.st_mode)) << 16
+ zinfo.compress_type = compress_type or self.compression
+ self.writestr(zinfo, data, compress_type)
+
+ def writestr(
+ self,
+ zinfo_or_arcname: str | ZipInfo,
+ data: SizedBuffer | str,
+ compress_type: int | None = None,
+ ):
+ if isinstance(zinfo_or_arcname, str):
+ zinfo_or_arcname = ZipInfo(
+ zinfo_or_arcname, date_time=get_zipinfo_datetime()
+ )
+ zinfo_or_arcname.compress_type = self.compression
+ zinfo_or_arcname.external_attr = (0o664 | stat.S_IFREG) << 16
+
+ if isinstance(data, str):
+ data = data.encode("utf-8")
+
+ ZipFile.writestr(self, zinfo_or_arcname, data, compress_type)
+ fname = (
+ zinfo_or_arcname.filename
+ if isinstance(zinfo_or_arcname, ZipInfo)
+ else zinfo_or_arcname
+ )
+ log.info(f"adding '{fname}'")
+ if fname != self.record_path:
+ hash_ = self._default_algorithm(data)
+ self._file_hashes[fname] = (
+ hash_.name,
+ urlsafe_b64encode(hash_.digest()).decode("ascii"),
+ )
+ self._file_sizes[fname] = len(data)
+
+ def close(self):
+ # Write RECORD
+ if self.fp is not None and self.mode == "w" and self._file_hashes:
+ data = StringIO()
+ writer = csv.writer(data, delimiter=",", quotechar='"', lineterminator="\n")
+ writer.writerows(
+ (
+ (fname, algorithm + "=" + hash_, self._file_sizes[fname])
+ for fname, (algorithm, hash_) in self._file_hashes.items()
+ )
+ )
+ writer.writerow((format(self.record_path), "", ""))
+ self.writestr(self.record_path, data.getvalue())
+
+ ZipFile.close(self)
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/yarl/_parse.py b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/yarl/_parse.py
new file mode 100644
index 0000000000000000000000000000000000000000..cc259ea86dc89aa0766d0cd30945fd605743b7b0
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/yarl/_parse.py
@@ -0,0 +1,189 @@
+"""URL parsing utilities."""
+
+import re
+import unicodedata
+from functools import lru_cache
+from typing import Union
+from urllib.parse import scheme_chars, uses_netloc
+
+from ._quoters import QUOTER
+
+# Leading and trailing C0 control and space to be stripped per WHATWG spec.
+# == "".join([chr(i) for i in range(0, 0x20 + 1)])
+WHATWG_C0_CONTROL_OR_SPACE = (
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10"
+ "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f "
+)
+
+# Unsafe bytes to be removed per WHATWG spec
+UNSAFE_URL_BYTES_TO_REMOVE = ["\t", "\r", "\n"]
+USES_AUTHORITY = frozenset(uses_netloc)
+
+SplitURLType = tuple[str, str, str, str, str]
+
+
+def split_url(url: str) -> SplitURLType:
+ """Split URL into parts."""
+ # Adapted from urllib.parse.urlsplit
+ # Only lstrip url as some applications rely on preserving trailing space.
+ # (https://url.spec.whatwg.org/#concept-basic-url-parser would strip both)
+ url = url.lstrip(WHATWG_C0_CONTROL_OR_SPACE)
+ for b in UNSAFE_URL_BYTES_TO_REMOVE:
+ if b in url:
+ url = url.replace(b, "")
+
+ scheme = netloc = query = fragment = ""
+ i = url.find(":")
+ if i > 0 and url[0] in scheme_chars:
+ for c in url[1:i]:
+ if c not in scheme_chars:
+ break
+ else:
+ scheme, url = url[:i].lower(), url[i + 1 :]
+ has_hash = "#" in url
+ has_question_mark = "?" in url
+ if url[:2] == "//":
+ delim = len(url) # position of end of domain part of url, default is end
+ if has_hash and has_question_mark:
+ delim_chars = "/?#"
+ elif has_question_mark:
+ delim_chars = "/?"
+ elif has_hash:
+ delim_chars = "/#"
+ else:
+ delim_chars = "/"
+ for c in delim_chars: # look for delimiters; the order is NOT important
+ wdelim = url.find(c, 2) # find first of this delim
+ if wdelim >= 0 and wdelim < delim: # if found
+ delim = wdelim # use earliest delim position
+ netloc = url[2:delim]
+ url = url[delim:]
+ has_left_bracket = "[" in netloc
+ has_right_bracket = "]" in netloc
+ if (has_left_bracket and not has_right_bracket) or (
+ has_right_bracket and not has_left_bracket
+ ):
+ raise ValueError("Invalid IPv6 URL")
+ if has_left_bracket:
+ bracketed_host = netloc.partition("[")[2].partition("]")[0]
+ # Valid bracketed hosts are defined in
+ # https://www.rfc-editor.org/rfc/rfc3986#page-49
+ # https://url.spec.whatwg.org/
+ if bracketed_host[0] == "v":
+ if not re.match(r"\Av[a-fA-F0-9]+\..+\Z", bracketed_host):
+ raise ValueError("IPvFuture address is invalid")
+ elif ":" not in bracketed_host:
+ raise ValueError("An IPv4 address cannot be in brackets")
+ if has_hash:
+ url, _, fragment = url.partition("#")
+ if has_question_mark:
+ url, _, query = url.partition("?")
+ if netloc and not netloc.isascii():
+ _check_netloc(netloc)
+ return scheme, netloc, url, query, fragment
+
+
+def _check_netloc(netloc: str) -> None:
+ # Adapted from urllib.parse._checknetloc
+ # looking for characters like \u2100 that expand to 'a/c'
+ # IDNA uses NFKC equivalence, so normalize for this check
+
+ # ignore characters already included
+ # but not the surrounding text
+ n = netloc.replace("@", "").replace(":", "").replace("#", "").replace("?", "")
+ normalized_netloc = unicodedata.normalize("NFKC", n)
+ if n == normalized_netloc:
+ return
+ # Note that there are no unicode decompositions for the character '@' so
+ # its currently impossible to have test coverage for this branch, however if the
+ # one should be added in the future we want to make sure its still checked.
+ for c in "/?#@:": # pragma: no branch
+ if c in normalized_netloc:
+ raise ValueError(
+ f"netloc '{netloc}' contains invalid "
+ "characters under NFKC normalization"
+ )
+
+
+@lru_cache # match the same size as urlsplit
+def split_netloc(
+ netloc: str,
+) -> tuple[Union[str, None], Union[str, None], Union[str, None], Union[int, None]]:
+ """Split netloc into username, password, host and port."""
+ if "@" not in netloc:
+ username: Union[str, None] = None
+ password: Union[str, None] = None
+ hostinfo = netloc
+ else:
+ userinfo, _, hostinfo = netloc.rpartition("@")
+ username, have_password, password = userinfo.partition(":")
+ if not have_password:
+ password = None
+
+ if "[" in hostinfo:
+ _, _, bracketed = hostinfo.partition("[")
+ hostname, _, port_str = bracketed.partition("]")
+ _, _, port_str = port_str.partition(":")
+ else:
+ hostname, _, port_str = hostinfo.partition(":")
+
+ if not port_str:
+ return username or None, password, hostname or None, None
+
+ try:
+ port = int(port_str)
+ except ValueError:
+ raise ValueError("Invalid URL: port can't be converted to integer")
+ if not (0 <= port <= 65535):
+ raise ValueError("Port out of range 0-65535")
+ return username or None, password, hostname or None, port
+
+
+def unsplit_result(
+ scheme: str, netloc: str, url: str, query: str, fragment: str
+) -> str:
+ """Unsplit a URL without any normalization."""
+ if netloc or (scheme and scheme in USES_AUTHORITY) or url[:2] == "//":
+ if url and url[:1] != "/":
+ url = f"{scheme}://{netloc}/{url}" if scheme else f"{scheme}:{url}"
+ else:
+ url = f"{scheme}://{netloc}{url}" if scheme else f"//{netloc}{url}"
+ elif scheme:
+ url = f"{scheme}:{url}"
+ if query:
+ url = f"{url}?{query}"
+ return f"{url}#{fragment}" if fragment else url
+
+
+@lru_cache # match the same size as urlsplit
+def make_netloc(
+ user: Union[str, None],
+ password: Union[str, None],
+ host: Union[str, None],
+ port: Union[int, None],
+ encode: bool = False,
+) -> str:
+ """Make netloc from parts.
+
+ The user and password are encoded if encode is True.
+
+ The host must already be encoded with _encode_host.
+ """
+ if host is None:
+ return ""
+ ret = host
+ if port is not None:
+ ret = f"{ret}:{port}"
+ if user is None and password is None:
+ return ret
+ if password is not None:
+ if not user:
+ user = ""
+ elif encode:
+ user = QUOTER(user)
+ if encode:
+ password = QUOTER(password)
+ user = f"{user}:{password}"
+ elif user and encode:
+ user = QUOTER(user)
+ return f"{user}@{ret}" if user else ret
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/yarl/_quoting_c.pyx b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/yarl/_quoting_c.pyx
new file mode 100644
index 0000000000000000000000000000000000000000..067ba96e4efa297669b22fa407af500c7ea1e636
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/yarl/_quoting_c.pyx
@@ -0,0 +1,423 @@
+# cython: language_level=3
+
+from cpython.exc cimport PyErr_NoMemory
+from cpython.mem cimport PyMem_Free, PyMem_Malloc, PyMem_Realloc
+from cpython.unicode cimport (
+ PyUnicode_DATA,
+ PyUnicode_DecodeASCII,
+ PyUnicode_DecodeUTF8Stateful,
+ PyUnicode_GET_LENGTH,
+ PyUnicode_KIND,
+ PyUnicode_READ,
+)
+from libc.stdint cimport uint8_t, uint64_t
+from libc.string cimport memcpy, memset
+
+from string import ascii_letters, digits
+
+
+cdef str GEN_DELIMS = ":/?#[]@"
+cdef str SUB_DELIMS_WITHOUT_QS = "!$'()*,"
+cdef str SUB_DELIMS = SUB_DELIMS_WITHOUT_QS + '+?=;'
+cdef str RESERVED = GEN_DELIMS + SUB_DELIMS
+cdef str UNRESERVED = ascii_letters + digits + '-._~'
+cdef str ALLOWED = UNRESERVED + SUB_DELIMS_WITHOUT_QS
+cdef str QS = '+&=;'
+
+DEF BUF_SIZE = 8 * 1024 # 8KiB
+cdef char BUFFER[BUF_SIZE]
+
+cdef inline Py_UCS4 _to_hex(uint8_t v) noexcept:
+ if v < 10:
+ return (v+0x30) # ord('0') == 0x30
+ else:
+ return (v+0x41-10) # ord('A') == 0x41
+
+
+cdef inline int _from_hex(Py_UCS4 v) noexcept:
+ if '0' <= v <= '9':
+ return (v) - 0x30 # ord('0') == 0x30
+ elif 'A' <= v <= 'F':
+ return (v) - 0x41 + 10 # ord('A') == 0x41
+ elif 'a' <= v <= 'f':
+ return (v) - 0x61 + 10 # ord('a') == 0x61
+ else:
+ return -1
+
+
+cdef inline int _is_lower_hex(Py_UCS4 v) noexcept:
+ return 'a' <= v <= 'f'
+
+
+cdef inline Py_UCS4 _restore_ch(Py_UCS4 d1, Py_UCS4 d2):
+ cdef int digit1 = _from_hex(d1)
+ if digit1 < 0:
+ return -1
+ cdef int digit2 = _from_hex(d2)
+ if digit2 < 0:
+ return -1
+ return (digit1 << 4 | digit2)
+
+
+cdef uint8_t ALLOWED_TABLE[16]
+cdef uint8_t ALLOWED_NOTQS_TABLE[16]
+
+
+cdef inline bint bit_at(uint8_t array[], uint64_t ch) noexcept:
+ return array[ch >> 3] & (1 << (ch & 7))
+
+
+cdef inline void set_bit(uint8_t array[], uint64_t ch) noexcept:
+ array[ch >> 3] |= (1 << (ch & 7))
+
+
+memset(ALLOWED_TABLE, 0, sizeof(ALLOWED_TABLE))
+memset(ALLOWED_NOTQS_TABLE, 0, sizeof(ALLOWED_NOTQS_TABLE))
+
+for i in range(128):
+ if chr(i) in ALLOWED:
+ set_bit(ALLOWED_TABLE, i)
+ set_bit(ALLOWED_NOTQS_TABLE, i)
+ if chr(i) in QS:
+ set_bit(ALLOWED_NOTQS_TABLE, i)
+
+# ----------------- writer ---------------------------
+
+cdef struct Writer:
+ char *buf
+ Py_ssize_t size
+ Py_ssize_t pos
+ bint changed
+
+
+cdef inline void _init_writer(Writer* writer):
+ writer.buf = &BUFFER[0]
+ writer.size = BUF_SIZE
+ writer.pos = 0
+ writer.changed = 0
+
+
+cdef inline void _release_writer(Writer* writer):
+ if writer.buf != BUFFER:
+ PyMem_Free(writer.buf)
+
+
+cdef inline int _write_char(Writer* writer, Py_UCS4 ch, bint changed):
+ cdef char * buf
+ cdef Py_ssize_t size
+
+ if writer.pos == writer.size:
+ # reallocate
+ size = writer.size + BUF_SIZE
+ if writer.buf == BUFFER:
+ buf = PyMem_Malloc(size)
+ if buf == NULL:
+ PyErr_NoMemory()
+ return -1
+ memcpy(buf, writer.buf, writer.size)
+ else:
+ buf = PyMem_Realloc(writer.buf, size)
+ if buf == NULL:
+ PyErr_NoMemory()
+ return -1
+ writer.buf = buf
+ writer.size = size
+ writer.buf[writer.pos] = ch
+ writer.pos += 1
+ writer.changed |= changed
+ return 0
+
+
+cdef inline int _write_pct(Writer* writer, uint8_t ch, bint changed):
+ if _write_char(writer, '%', changed) < 0:
+ return -1
+ if _write_char(writer, _to_hex(ch >> 4), changed) < 0:
+ return -1
+ return _write_char(writer, _to_hex(ch & 0x0f), changed)
+
+
+cdef inline int _write_utf8(Writer* writer, Py_UCS4 symbol):
+ cdef uint64_t utf = symbol
+
+ if utf < 0x80:
+ return _write_pct(writer, utf, True)
+ elif utf < 0x800:
+ if _write_pct(writer, (0xc0 | (utf >> 6)), True) < 0:
+ return -1
+ return _write_pct(writer, (0x80 | (utf & 0x3f)), True)
+ elif 0xD800 <= utf <= 0xDFFF:
+ # surogate pair, ignored
+ return 0
+ elif utf < 0x10000:
+ if _write_pct(writer, (0xe0 | (utf >> 12)), True) < 0:
+ return -1
+ if _write_pct(writer, (0x80 | ((utf >> 6) & 0x3f)),
+ True) < 0:
+ return -1
+ return _write_pct(writer, (0x80 | (utf & 0x3f)), True)
+ elif utf > 0x10FFFF:
+ # symbol is too large
+ return 0
+ else:
+ if _write_pct(writer, (0xf0 | (utf >> 18)), True) < 0:
+ return -1
+ if _write_pct(writer, (0x80 | ((utf >> 12) & 0x3f)),
+ True) < 0:
+ return -1
+ if _write_pct(writer, (0x80 | ((utf >> 6) & 0x3f)),
+ True) < 0:
+ return -1
+ return _write_pct(writer, (0x80 | (utf & 0x3f)), True)
+
+
+# --------------------- end writer --------------------------
+
+
+cdef class _Quoter:
+ cdef bint _qs
+ cdef bint _requote
+
+ cdef uint8_t _safe_table[16]
+ cdef uint8_t _protected_table[16]
+
+ def __init__(
+ self, *, str safe='', str protected='', bint qs=False, bint requote=True,
+ ):
+ cdef Py_UCS4 ch
+
+ self._qs = qs
+ self._requote = requote
+
+ if not self._qs:
+ memcpy(self._safe_table,
+ ALLOWED_NOTQS_TABLE,
+ sizeof(self._safe_table))
+ else:
+ memcpy(self._safe_table,
+ ALLOWED_TABLE,
+ sizeof(self._safe_table))
+ for ch in safe:
+ if ord(ch) > 127:
+ raise ValueError("Only safe symbols with ORD < 128 are allowed")
+ set_bit(self._safe_table, ch)
+
+ memset(self._protected_table, 0, sizeof(self._protected_table))
+ for ch in protected:
+ if ord(ch) > 127:
+ raise ValueError("Only safe symbols with ORD < 128 are allowed")
+ set_bit(self._safe_table, ch)
+ set_bit(self._protected_table, ch)
+
+ def __call__(self, val):
+ if val is None:
+ return None
+ if type(val) is not str:
+ if isinstance(val, str):
+ # derived from str
+ val = str(val)
+ else:
+ raise TypeError("Argument should be str")
+ return self._do_quote_or_skip(val)
+
+ cdef str _do_quote_or_skip(self, str val):
+ cdef Py_UCS4 ch
+ cdef Py_ssize_t length = PyUnicode_GET_LENGTH(val)
+ cdef Py_ssize_t idx = length
+ cdef bint must_quote = 0
+ cdef Writer writer
+ cdef int kind = PyUnicode_KIND(val)
+ cdef const void *data = PyUnicode_DATA(val)
+
+ # If everything in the string is in the safe
+ # table and all ASCII, we can skip quoting
+ while idx:
+ idx -= 1
+ ch = PyUnicode_READ(kind, data, idx)
+ if ch >= 128 or not bit_at(self._safe_table, ch):
+ must_quote = 1
+ break
+
+ if not must_quote:
+ return val
+
+ _init_writer(&writer)
+ try:
+ return self._do_quote(val, length, kind, data, &writer)
+ finally:
+ _release_writer(&writer)
+
+ cdef str _do_quote(
+ self,
+ str val,
+ Py_ssize_t length,
+ int kind,
+ const void *data,
+ Writer *writer
+ ):
+ cdef Py_UCS4 ch
+ cdef int changed
+ cdef Py_ssize_t idx = 0
+
+ while idx < length:
+ ch = PyUnicode_READ(kind, data, idx)
+ idx += 1
+ if ch == '%' and self._requote and idx <= length - 2:
+ ch = _restore_ch(
+ PyUnicode_READ(kind, data, idx),
+ PyUnicode_READ(kind, data, idx + 1)
+ )
+ if ch != -1:
+ idx += 2
+ if ch < 128:
+ if bit_at(self._protected_table, ch):
+ if _write_pct(writer, ch, True) < 0:
+ raise
+ continue
+
+ if bit_at(self._safe_table, ch):
+ if _write_char(writer, ch, True) < 0:
+ raise
+ continue
+
+ changed = (_is_lower_hex(PyUnicode_READ(kind, data, idx - 2)) or
+ _is_lower_hex(PyUnicode_READ(kind, data, idx - 1)))
+ if _write_pct(writer, ch, changed) < 0:
+ raise
+ continue
+ else:
+ ch = '%'
+
+ if self._write(writer, ch) < 0:
+ raise
+
+ if not writer.changed:
+ return val
+ else:
+ return PyUnicode_DecodeASCII(writer.buf, writer.pos, "strict")
+
+ cdef inline int _write(self, Writer *writer, Py_UCS4 ch):
+ if self._qs:
+ if ch == ' ':
+ return _write_char(writer, '+', True)
+
+ if ch < 128 and bit_at(self._safe_table, ch):
+ return _write_char(writer, ch, False)
+
+ return _write_utf8(writer, ch)
+
+
+cdef class _Unquoter:
+ cdef str _ignore
+ cdef str _unsafe
+ cdef bint _qs
+ cdef _Quoter _quoter
+ cdef _Quoter _qs_quoter
+
+ def __init__(self, *, ignore="", unsafe="", qs=False):
+ self._ignore = ignore
+ self._unsafe = unsafe
+ self._qs = qs
+ self._quoter = _Quoter()
+ self._qs_quoter = _Quoter(qs=True)
+
+ def __call__(self, val):
+ if val is None:
+ return None
+ if type(val) is not str:
+ if isinstance(val, str):
+ # derived from str
+ val = str(val)
+ else:
+ raise TypeError("Argument should be str")
+ return self._do_unquote(val)
+
+ cdef str _do_unquote(self, str val):
+ cdef Py_ssize_t length = PyUnicode_GET_LENGTH(val)
+ if length == 0:
+ return val
+
+ cdef list ret = []
+ cdef char buffer[4]
+ cdef Py_ssize_t buflen = 0
+ cdef Py_ssize_t consumed
+ cdef str unquoted
+ cdef Py_UCS4 ch = 0
+ cdef Py_ssize_t idx = 0
+ cdef Py_ssize_t start_pct
+ cdef int kind = PyUnicode_KIND(val)
+ cdef const void *data = PyUnicode_DATA(val)
+ cdef bint changed = 0
+ while idx < length:
+ ch = PyUnicode_READ(kind, data, idx)
+ idx += 1
+ if ch == '%' and idx <= length - 2:
+ changed = 1
+ ch = _restore_ch(
+ PyUnicode_READ(kind, data, idx),
+ PyUnicode_READ(kind, data, idx + 1)
+ )
+ if ch != -1:
+ idx += 2
+ assert buflen < 4
+ buffer[buflen] = ch
+ buflen += 1
+ try:
+ unquoted = PyUnicode_DecodeUTF8Stateful(buffer, buflen,
+ NULL, &consumed)
+ except UnicodeDecodeError:
+ start_pct = idx - buflen * 3
+ buffer[0] = ch
+ buflen = 1
+ ret.append(val[start_pct : idx - 3])
+ try:
+ unquoted = PyUnicode_DecodeUTF8Stateful(buffer, buflen,
+ NULL, &consumed)
+ except UnicodeDecodeError:
+ buflen = 0
+ ret.append(val[idx - 3 : idx])
+ continue
+ if not unquoted:
+ assert consumed == 0
+ continue
+ assert consumed == buflen
+ buflen = 0
+ if self._qs and unquoted in '+=&;':
+ ret.append(self._qs_quoter(unquoted))
+ elif unquoted in self._unsafe or unquoted in self._ignore:
+ ret.append(self._quoter(unquoted))
+ else:
+ ret.append(unquoted)
+ continue
+ else:
+ ch = '%'
+
+ if buflen:
+ start_pct = idx - 1 - buflen * 3
+ ret.append(val[start_pct : idx - 1])
+ buflen = 0
+
+ if ch == '+':
+ if not self._qs or ch in self._unsafe:
+ ret.append('+')
+ else:
+ changed = 1
+ ret.append(' ')
+ continue
+
+ if ch in self._unsafe:
+ changed = 1
+ ret.append('%')
+ h = hex(ord(ch)).upper()[2:]
+ for ch in h:
+ ret.append(ch)
+ continue
+
+ ret.append(ch)
+
+ if not changed:
+ return val
+
+ if buflen:
+ ret.append(val[length - buflen * 3 : length])
+
+ return ''.join(ret)
diff --git a/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/yarl/py.typed b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/yarl/py.typed
new file mode 100644
index 0000000000000000000000000000000000000000..dcf2c804da5e19d617a03a6c68aa128d1d1f89a0
--- /dev/null
+++ b/Prism/LLaDA/LLaDA_Prism/.venv/lib/python3.12/site-packages/yarl/py.typed
@@ -0,0 +1 @@
+# Placeholder