nonconform


Namenonconform JSON
Version 0.9.12 PyPI version JSON
download
home_pageNone
SummaryConformal Anomaly Detection
upload_time2025-07-24 09:19:12
maintainerNone
docs_urlNone
authorNone
requires_python>=3.12
licenseBSD 3-Clause License Copyright (c) 2024, Oliver Hennhöfer 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.
keywords anomaly detection conformal anomaly detection conformal inference false discovery rate uncertainty quantification
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            **nonconform** is a Python library that enhances anomaly detection by providing uncertainty quantification. It acts as a wrapper around most detectors from the popular [*PyOD*](https://pyod.readthedocs.io/en/latest/) library (see [Supported Estimators](#supported-estimators)). By leveraging one-class classification principles and **conformal inference**, **nonconform** enables **statistically rigorous anomaly detection**.

# Key Features

*   **Uncertainty Quantification:** Go beyond simple anomaly scores; get statistically valid _p_-values.
*   **Error Control:** Reliably control metrics like the False Discovery Rate (FDR).
*   **Broad PyOD Compatibility:** Works with a wide range of PyOD estimators (see [Supported Estimators](#supported-estimators)).
*   **Flexible Strategies:** Implements various conformal strategies like Split-Conformal and Bootstrap-after-Jackknife+ (JaB+).

# Getting Started

```sh
pip install nonconform
```

_For additional features, you might need optional dependencies:_
- `pip install nonconform[data]` - Includes pyarrow for loading example data (via remote download)
- `pip install nonconform[deep]` - Includes deep learning dependencies (PyTorch)
- `pip install nonconform[fdr]` - Includes advanced FDR control methods (online-fdr)
- `pip install nonconform[dev]` - Includes development tools (black, ruff, pre-commit)
- `pip install nonconform[docs]` - Includes documentation building tools (sphinx, furo, etc.)
- `pip install nonconform[all]` - Includes all optional dependencies

_Please refer to the [pyproject.toml](https://github.com/OliverHennhoefer/nonconform/blob/main/pyproject.toml) for details._

## Split-Conformal (also _Inductive_) Approach

Using a _Gaussian Mixture Model_ on the _Shuttle_ dataset:

> **Note:** The examples below use the built-in datasets. Install with `pip install nonconform[data]` to run these examples.

```python
from pyod.models.gmm import GMM
from scipy.stats import false_discovery_control

from nonconform.strategy import Split
from nonconform.estimation import StandardConformalDetector
from nonconform.utils.data import load_shuttle
from nonconform.utils.stat import false_discovery_rate, statistical_power

x_train, x_test, y_test = load_shuttle(setup=True)

ce = StandardConformalDetector(
    detector=GMM(),
    strategy=Split(calib_size=1_000)
)

ce.fit(x_train)
estimates = ce.predict(x_test)

decisions = false_discovery_control(estimates, method='bh') <= 0.2

print(f"Empirical FDR: {false_discovery_rate(y=y_test, y_hat=decisions)}")
print(f"Empirical Power: {statistical_power(y=y_test, y_hat=decisions)}")
```

Output:
```text
Empirical FDR: 0.108
Empirical Power: 0.99
```

# Advanced Usage

## Bootstrap-after-Jackknife+ (JaB+)

The `BootstrapConformal()` strategy allows to set 2 of the 3 parameters `resampling_ratio`, `n_boostraps` and `n_calib`.
For either combination, the remaining parameter will be filled automatically. This allows exact control of the
calibration procedure when using a bootstrap strategy.

```python
from pyod.models.iforest import IForest
from scipy.stats import false_discovery_control

from nonconform.estimation import StandardConformalDetector
from nonconform.strategy import Bootstrap
from nonconform.utils.data import load_shuttle
from nonconform.utils.stat import false_discovery_rate, statistical_power

x_train, x_test, y_test = load_shuttle(setup=True)

ce = StandardConformalDetector(
    detector=IForest(behaviour="new"),
    strategy=Bootstrap(resampling_ratio=0.99, n_bootstraps=20, plus=True)
)

ce.fit(x_train)
estimates = ce.predict(x_test)

decisions = false_discovery_control(estimates, method='bh') <= 0.1

print(f"Empirical FDR: {false_discovery_rate(y=y_test, y_hat=decisions)}")
print(f"Empirical Power: {statistical_power(y=y_test, y_hat=decisions)}")
```

Output:
```text
Empirical FDR: 0.067
Empirical Power: 0.98
```

## Weighted Conformal Anomaly Detection

The statistical validity of conformal anomaly detection depends on data *exchangability* (weaker than i.i.d.). This assumption can be slightly relaxed by computing weighted conformal _p_-values.

```python
from pyod.models.iforest import IForest
from scipy.stats import false_discovery_control

from nonconform.utils.data import load_shuttle
from nonconform.estimation import WeightedConformalDetector
from nonconform.strategy import Split
from nonconform.utils.stat import false_discovery_rate, statistical_power

x_train, x_test, y_test = load_shuttle(setup=True)

model = IForest(behaviour="new")
strategy = Split(calib_size=1_000)

ce = WeightedConformalDetector(detector=model, strategy=strategy)
ce.fit(x_train)
estimates = ce.predict(x_test)

decisions = false_discovery_control(estimates, method='bh') <= 0.1

print(f"Empirical FDR: {false_discovery_rate(y=y_test, y_hat=decisions)}")
print(f"Empirical Power: {statistical_power(y=y_test, y_hat=decisions)}")
```

Output:
```text
Empirical FDR: 0.077
Empirical Power: 0.96
```

# Citation

If you find this repository useful for your research, please cite following papers:

##### Leave-One-Out-, Bootstrap- and Cross-Conformal Anomaly Detectors
```text
@inproceedings{Hennhofer2024,
	title        = {{ Leave-One-Out-, Bootstrap- and Cross-Conformal Anomaly Detectors }},
	author       = {Hennhofer, Oliver and Preisach, Christine},
	year         = 2024,
	month        = {Dec},
	booktitle    = {2024 IEEE International Conference on Knowledge Graph (ICKG)},
	publisher    = {IEEE Computer Society},
	address      = {Los Alamitos, CA, USA},
	pages        = {110--119},
	doi          = {10.1109/ICKG63256.2024.00022},
	url          = {https://doi.ieeecomputersociety.org/10.1109/ICKG63256.2024.00022}
}
```

##### Testing for outliers with conformal p-values
```text
@article{Bates2023,
	title        = {Testing for outliers with conformal p-values},
	author       = {Bates,  Stephen and Candès,  Emmanuel and Lei,  Lihua and Romano,  Yaniv and Sesia,  Matteo},
	year         = 2023,
	month        = feb,
	journal      = {The Annals of Statistics},
	publisher    = {Institute of Mathematical Statistics},
	volume       = 51,
	number       = 1,
	doi          = {10.1214/22-aos2244},
	issn         = {0090-5364},
	url          = {http://dx.doi.org/10.1214/22-AOS2244}
}
```
##### Model-free selective inference under covariate shift via weighted conformal p-values
```text
@inproceedings{Jin2023,
	title        = {Model-free selective inference under covariate shift via weighted conformal p-values},
	author       = {Ying Jin and Emmanuel J. Cand{\`e}s},
	year         = 2023,
	url          = {https://api.semanticscholar.org/CorpusID:259950903}
}
```

# Supported Estimators

The package only supports anomaly estimators that are suitable for unsupervised one-class classification. As respective
detectors are therefore exclusively fitted on *normal* (or *non-anomalous*) data, parameters like *threshold* are internally
set to the smallest possible values.

Models that are **currently supported** include:

* Angle-Based Outlier Detection (**ABOD**)
* Autoencoder (**AE**)
* Cook's Distance (**CD**)
* Copula-based Outlier Detector (**COPOD**)
* Deep Isolation Forest (**DIF**)
* Empirical-Cumulative-distribution-based Outlier Detection (**ECOD**)
* Gaussian Mixture Model (**GMM**)
* Histogram-based Outlier Detection (**HBOS**)
* Isolation-based Anomaly Detection using Nearest-Neighbor Ensembles (**INNE**)
* Isolation Forest (**IForest**)
* Kernel Density Estimation (**KDE**)
* *k*-Nearest Neighbor (***k*NN**)
* Kernel Principal Component Analysis (**KPCA**)
* Linear Model Deviation-base Outlier Detection (**LMDD**)
* Local Outlier Factor (**LOF**)
* Local Correlation Integral (**LOCI**)
* Lightweight Online Detector of Anomalies (**LODA**)
* Locally Selective Combination of Parallel Outlier Ensembles (**LSCP**)
* GNN-based Anomaly Detection Method (**LUNAR**)
* Median Absolute Deviation (**MAD**)
* Minimum Covariance Determinant (**MCD**)
* One-Class SVM (**OCSVM**)
* Principal Component Analysis (**PCA**)
* Quasi-Monte Carlo Discrepancy Outlier Detection (**QMCD**)
* Rotation-based Outlier Detection (**ROD**)
* Subspace Outlier Detection (**SOD**)
* Scalable Unsupervised Outlier Detection (**SUOD**)

# Contact
**Bug reporting:** [https://github.com/OliverHennhoefer/nonconform/issues](https://github.com/OliverHennhoefer/nonconform/issues)

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "nonconform",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": "Oliver Hennhoefer <oliver.hennhoefer@mail.de>",
    "keywords": "anomaly detection, conformal anomaly detection, conformal inference, false discovery rate, uncertainty quantification",
    "author": null,
    "author_email": "Oliver Hennhoefer <oliver.hennhoefer@mail.de>",
    "download_url": "https://files.pythonhosted.org/packages/9b/74/df4702113629f7cb944c1553fa47607fea00501cc47909c3729e0bf1b7f0/nonconform-0.9.12.tar.gz",
    "platform": null,
    "description": "**nonconform** is a Python library that enhances anomaly detection by providing uncertainty quantification. It acts as a wrapper around most detectors from the popular [*PyOD*](https://pyod.readthedocs.io/en/latest/) library (see [Supported Estimators](#supported-estimators)). By leveraging one-class classification principles and **conformal inference**, **nonconform** enables **statistically rigorous anomaly detection**.\n\n# Key Features\n\n*   **Uncertainty Quantification:** Go beyond simple anomaly scores; get statistically valid _p_-values.\n*   **Error Control:** Reliably control metrics like the False Discovery Rate (FDR).\n*   **Broad PyOD Compatibility:** Works with a wide range of PyOD estimators (see [Supported Estimators](#supported-estimators)).\n*   **Flexible Strategies:** Implements various conformal strategies like Split-Conformal and Bootstrap-after-Jackknife+ (JaB+).\n\n# Getting Started\n\n```sh\npip install nonconform\n```\n\n_For additional features, you might need optional dependencies:_\n- `pip install nonconform[data]` - Includes pyarrow for loading example data (via remote download)\n- `pip install nonconform[deep]` - Includes deep learning dependencies (PyTorch)\n- `pip install nonconform[fdr]` - Includes advanced FDR control methods (online-fdr)\n- `pip install nonconform[dev]` - Includes development tools (black, ruff, pre-commit)\n- `pip install nonconform[docs]` - Includes documentation building tools (sphinx, furo, etc.)\n- `pip install nonconform[all]` - Includes all optional dependencies\n\n_Please refer to the [pyproject.toml](https://github.com/OliverHennhoefer/nonconform/blob/main/pyproject.toml) for details._\n\n## Split-Conformal (also _Inductive_) Approach\n\nUsing a _Gaussian Mixture Model_ on the _Shuttle_ dataset:\n\n> **Note:** The examples below use the built-in datasets. Install with `pip install nonconform[data]` to run these examples.\n\n```python\nfrom pyod.models.gmm import GMM\nfrom scipy.stats import false_discovery_control\n\nfrom nonconform.strategy import Split\nfrom nonconform.estimation import StandardConformalDetector\nfrom nonconform.utils.data import load_shuttle\nfrom nonconform.utils.stat import false_discovery_rate, statistical_power\n\nx_train, x_test, y_test = load_shuttle(setup=True)\n\nce = StandardConformalDetector(\n    detector=GMM(),\n    strategy=Split(calib_size=1_000)\n)\n\nce.fit(x_train)\nestimates = ce.predict(x_test)\n\ndecisions = false_discovery_control(estimates, method='bh') <= 0.2\n\nprint(f\"Empirical FDR: {false_discovery_rate(y=y_test, y_hat=decisions)}\")\nprint(f\"Empirical Power: {statistical_power(y=y_test, y_hat=decisions)}\")\n```\n\nOutput:\n```text\nEmpirical FDR: 0.108\nEmpirical Power: 0.99\n```\n\n# Advanced Usage\n\n## Bootstrap-after-Jackknife+ (JaB+)\n\nThe `BootstrapConformal()` strategy allows to set 2 of the 3 parameters `resampling_ratio`, `n_boostraps` and `n_calib`.\nFor either combination, the remaining parameter will be filled automatically. This allows exact control of the\ncalibration procedure when using a bootstrap strategy.\n\n```python\nfrom pyod.models.iforest import IForest\nfrom scipy.stats import false_discovery_control\n\nfrom nonconform.estimation import StandardConformalDetector\nfrom nonconform.strategy import Bootstrap\nfrom nonconform.utils.data import load_shuttle\nfrom nonconform.utils.stat import false_discovery_rate, statistical_power\n\nx_train, x_test, y_test = load_shuttle(setup=True)\n\nce = StandardConformalDetector(\n    detector=IForest(behaviour=\"new\"),\n    strategy=Bootstrap(resampling_ratio=0.99, n_bootstraps=20, plus=True)\n)\n\nce.fit(x_train)\nestimates = ce.predict(x_test)\n\ndecisions = false_discovery_control(estimates, method='bh') <= 0.1\n\nprint(f\"Empirical FDR: {false_discovery_rate(y=y_test, y_hat=decisions)}\")\nprint(f\"Empirical Power: {statistical_power(y=y_test, y_hat=decisions)}\")\n```\n\nOutput:\n```text\nEmpirical FDR: 0.067\nEmpirical Power: 0.98\n```\n\n## Weighted Conformal Anomaly Detection\n\nThe statistical validity of conformal anomaly detection depends on data *exchangability* (weaker than i.i.d.). This assumption can be slightly relaxed by computing weighted conformal _p_-values.\n\n```python\nfrom pyod.models.iforest import IForest\nfrom scipy.stats import false_discovery_control\n\nfrom nonconform.utils.data import load_shuttle\nfrom nonconform.estimation import WeightedConformalDetector\nfrom nonconform.strategy import Split\nfrom nonconform.utils.stat import false_discovery_rate, statistical_power\n\nx_train, x_test, y_test = load_shuttle(setup=True)\n\nmodel = IForest(behaviour=\"new\")\nstrategy = Split(calib_size=1_000)\n\nce = WeightedConformalDetector(detector=model, strategy=strategy)\nce.fit(x_train)\nestimates = ce.predict(x_test)\n\ndecisions = false_discovery_control(estimates, method='bh') <= 0.1\n\nprint(f\"Empirical FDR: {false_discovery_rate(y=y_test, y_hat=decisions)}\")\nprint(f\"Empirical Power: {statistical_power(y=y_test, y_hat=decisions)}\")\n```\n\nOutput:\n```text\nEmpirical FDR: 0.077\nEmpirical Power: 0.96\n```\n\n# Citation\n\nIf you find this repository useful for your research, please cite following papers:\n\n##### Leave-One-Out-, Bootstrap- and Cross-Conformal Anomaly Detectors\n```text\n@inproceedings{Hennhofer2024,\n\ttitle        = {{ Leave-One-Out-, Bootstrap- and Cross-Conformal Anomaly Detectors }},\n\tauthor       = {Hennhofer, Oliver and Preisach, Christine},\n\tyear         = 2024,\n\tmonth        = {Dec},\n\tbooktitle    = {2024 IEEE International Conference on Knowledge Graph (ICKG)},\n\tpublisher    = {IEEE Computer Society},\n\taddress      = {Los Alamitos, CA, USA},\n\tpages        = {110--119},\n\tdoi          = {10.1109/ICKG63256.2024.00022},\n\turl          = {https://doi.ieeecomputersociety.org/10.1109/ICKG63256.2024.00022}\n}\n```\n\n##### Testing for outliers with conformal p-values\n```text\n@article{Bates2023,\n\ttitle        = {Testing for outliers with conformal p-values},\n\tauthor       = {Bates,  Stephen and Cand\u00e8s,  Emmanuel and Lei,  Lihua and Romano,  Yaniv and Sesia,  Matteo},\n\tyear         = 2023,\n\tmonth        = feb,\n\tjournal      = {The Annals of Statistics},\n\tpublisher    = {Institute of Mathematical Statistics},\n\tvolume       = 51,\n\tnumber       = 1,\n\tdoi          = {10.1214/22-aos2244},\n\tissn         = {0090-5364},\n\turl          = {http://dx.doi.org/10.1214/22-AOS2244}\n}\n```\n##### Model-free selective inference under covariate shift via weighted conformal p-values\n```text\n@inproceedings{Jin2023,\n\ttitle        = {Model-free selective inference under covariate shift via weighted conformal p-values},\n\tauthor       = {Ying Jin and Emmanuel J. Cand{\\`e}s},\n\tyear         = 2023,\n\turl          = {https://api.semanticscholar.org/CorpusID:259950903}\n}\n```\n\n# Supported Estimators\n\nThe package only supports anomaly estimators that are suitable for unsupervised one-class classification. As respective\ndetectors are therefore exclusively fitted on *normal* (or *non-anomalous*) data, parameters like *threshold* are internally\nset to the smallest possible values.\n\nModels that are **currently supported** include:\n\n* Angle-Based Outlier Detection (**ABOD**)\n* Autoencoder (**AE**)\n* Cook's Distance (**CD**)\n* Copula-based Outlier Detector (**COPOD**)\n* Deep Isolation Forest (**DIF**)\n* Empirical-Cumulative-distribution-based Outlier Detection (**ECOD**)\n* Gaussian Mixture Model (**GMM**)\n* Histogram-based Outlier Detection (**HBOS**)\n* Isolation-based Anomaly Detection using Nearest-Neighbor Ensembles (**INNE**)\n* Isolation Forest (**IForest**)\n* Kernel Density Estimation (**KDE**)\n* *k*-Nearest Neighbor (***k*NN**)\n* Kernel Principal Component Analysis (**KPCA**)\n* Linear Model Deviation-base Outlier Detection (**LMDD**)\n* Local Outlier Factor (**LOF**)\n* Local Correlation Integral (**LOCI**)\n* Lightweight Online Detector of Anomalies (**LODA**)\n* Locally Selective Combination of Parallel Outlier Ensembles (**LSCP**)\n* GNN-based Anomaly Detection Method (**LUNAR**)\n* Median Absolute Deviation (**MAD**)\n* Minimum Covariance Determinant (**MCD**)\n* One-Class SVM (**OCSVM**)\n* Principal Component Analysis (**PCA**)\n* Quasi-Monte Carlo Discrepancy Outlier Detection (**QMCD**)\n* Rotation-based Outlier Detection (**ROD**)\n* Subspace Outlier Detection (**SOD**)\n* Scalable Unsupervised Outlier Detection (**SUOD**)\n\n# Contact\n**Bug reporting:** [https://github.com/OliverHennhoefer/nonconform/issues](https://github.com/OliverHennhoefer/nonconform/issues)\n",
    "bugtrack_url": null,
    "license": "BSD 3-Clause License\n        \n        Copyright (c) 2024, Oliver Hennh\u00f6fer\n        \n        Redistribution and use in source and binary forms, with or without\n        modification, are permitted provided that the following conditions are met:\n        \n        1. Redistributions of source code must retain the above copyright notice, this\n           list of conditions and the following disclaimer.\n        \n        2. Redistributions in binary form must reproduce the above copyright notice,\n           this list of conditions and the following disclaimer in the documentation\n           and/or other materials provided with the distribution.\n        \n        3. Neither the name of the copyright holder nor the names of its\n           contributors may be used to endorse or promote products derived from\n           this software without specific prior written permission.\n        \n        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n        AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n        IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n        DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n        FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n        DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n        SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n        CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n        OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n        OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.",
    "summary": "Conformal Anomaly Detection",
    "version": "0.9.12",
    "project_urls": {
        "Bugs": "https://github.com/OliverHennhoefer/nonconform/issues",
        "Homepage": "https://github.com/OliverHennhoefer/nonconform"
    },
    "split_keywords": [
        "anomaly detection",
        " conformal anomaly detection",
        " conformal inference",
        " false discovery rate",
        " uncertainty quantification"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "bc7c8e9872a62bac037ef7bb95b604d5ccf80da5f365c8c6202b8556327d5cdb",
                "md5": "a662000735579d6b13c64d3be50edefa",
                "sha256": "48afce8eb53f1e6cff926293ebd68f54ae3a3b4b77ddfa02f1fe9d7491b85731"
            },
            "downloads": -1,
            "filename": "nonconform-0.9.12-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "a662000735579d6b13c64d3be50edefa",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 50293,
            "upload_time": "2025-07-24T09:19:10",
            "upload_time_iso_8601": "2025-07-24T09:19:10.798923Z",
            "url": "https://files.pythonhosted.org/packages/bc/7c/8e9872a62bac037ef7bb95b604d5ccf80da5f365c8c6202b8556327d5cdb/nonconform-0.9.12-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "9b74df4702113629f7cb944c1553fa47607fea00501cc47909c3729e0bf1b7f0",
                "md5": "43cd486e910935849bf53fc6f6ab76bb",
                "sha256": "984006f3c8cfae866ae3f59a947bd3a7b6d5911e5638dc8ae1f9a6b47959f794"
            },
            "downloads": -1,
            "filename": "nonconform-0.9.12.tar.gz",
            "has_sig": false,
            "md5_digest": "43cd486e910935849bf53fc6f6ab76bb",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 130708,
            "upload_time": "2025-07-24T09:19:12",
            "upload_time_iso_8601": "2025-07-24T09:19:12.720031Z",
            "url": "https://files.pythonhosted.org/packages/9b/74/df4702113629f7cb944c1553fa47607fea00501cc47909c3729e0bf1b7f0/nonconform-0.9.12.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-07-24 09:19:12",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "OliverHennhoefer",
    "github_project": "nonconform",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "nonconform"
}
        
Elapsed time: 1.48612s