scrutipy


Namescrutipy JSON
Version 0.1.11 PyPI version JSON
download
home_pageNone
SummaryA toolset for detecting inconsistencies in summary data.
upload_time2025-08-28 13:29:49
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords statistics diagnostics fraud detection error detection summary data replication
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # scrutiPy v0.1.11: Scientific error detection in Python

A library for scientific error checking and fraud detection, based on the R Scrutiny library by Lukas Jung. Frontend API in Python 3, backend in Rust with PyO3 bindings. 

Currently in early development. Presently available functions include:

grim_scalar(): Implements the GRIM test on single observations. 

```
from scrutipy import grim_scalar

grim_scalar("5.19", 40)
# False
```

grim_map() Implements the GRIM test on Pandas dataframes. Use the variant grim_map_pl() for Polars dataframes. Both functions require Polars, which can be enabled using `pip install scrutipy[polars]` or `pip install polars`.

```
import pandas as pd
from scrutipy import grim_map 

df = pd.read_csv("data/pigs1.csv")
# it may be necessary to explicitly convert your x column to string type in order to avoid losing trailing zeros. In the event that trailing zeros may be lost, the function will throw a warning 
df["x"] = df["x"].astype(str) 
bools, errors = grim_map(df, 1, 2)

print(bools)
# list([True, False, False, False, False, True, False, True, False, False, True, False])

print(errors)
# None
```

grimmer() Implements the GRIMMER test on 1d iterables.

```
from scrutipy import grimmer
results = grimmer(["1.03", "52.13", "9.42375"], ["0.41", "2.26", "3.86"], [40, 30, 59], items = [1, 1, 1])

print(results)
# list(False, True, False) 

```

debit() implements the DEBIT test on 1d iterables (lists and arrays). 

```
from scrutipy import debit

results = debit(["0.36", "0.11", "0.118974"], ["0.11", "0.31", "0.6784"], [20, 40, 100])
print(results)
# list([False, True, False])
```

debit_map() implements the DEBIT test on Pandas dataframes. Use the variant debit_map_pl() for Polars dataframes. Both functions require Polars, which can be enabled using `pip install scrutipy[polars]` or `pip install polars`.

```
from scrutipy import debit_map 

df = pd.read_csv("data/debit_data.csv")
df["xs"] = df["xs"].astype(str) # ensuring that these columns are string types to silence a warning
df["sds"] = df["sds"].astype(str) # it can also be silenced with silence_numeric_warning = True.
results, errors = debit_map(df, 1, 2, 3)

print(bools)
# list([True, True, True, False, True, True, True])

print(errors)
# None
```

closure(): Implements the CLOSURE algorithm for recovering integer data from summary statistics. Any data which can be represented as integers on a bounded range, such as Likert scores, can be provably reconstructed using the mean, standard deviation, count, and range. 
This function replaces the CORVIDS algorithm, which relied on more advanced mathematics packages, with a simpler and faster algorithm. 
Note that even with CLOSURE's performance gains, the necessary time and compute to reconstruct data increases rapidly as range and count increase. 

```
# reconstruct possible datasets with a mean of 3.5, sd of 0.57, n = 100, 
# and inclusive range from 0 to 7. 
# We set the rounding error for the mean to 0.05 and for sd to 0.005

from scrutipy import closure
results = closure(3.5, 1.2, 50, 0, 7, 0.05, 0.005) 

len(results)
# 7980 
# indicates there are 7980 possible datasets with these characteristics.
```

calculate_snspn(): Calculates all possible confusion matries which could be produced from a sample size, and compares the calculated sensitivity and specificity to the input values. It returns a list of dictionaries containing the records for each possibility, as well as a total error and whether the total error is less than a certain tolerance. 
The dictionaries are ordered from least to greatest total error. For larger sample sizes, it is recommended to use a top_n argument to limit the number of returned values. The return can be trivially turned into a pandas or polars dataframe as seen below.
This is based on an application by Rod Whitely.
```
import pandas as pd
import scrutipy as s
vals = s.calculate_snspn(0.8, 0.70588, 20, top_n=5)
df = pd.DataFrame(vals)
df
   TP  TN  FP  FN  Calculated_Sensitivity  Calculated_Specificity  Sensitivity_Error  Specificity_Error  Total_Error  Exact_Match
0   8   7   3   2                0.800000                0.700000           0.000000           0.005880     0.005880        False
1   4  11   4   1                0.800000                0.733333           0.000000           0.027453     0.027453        False
2  10   5   2   3                0.769231                0.714286           0.030769           0.008406     0.039175        False
3   4  10   5   1                0.800000                0.666667           0.000000           0.039213     0.039213        False
4   5  10   4   1                0.833333                0.714286           0.033333           0.008406     0.041739        False
```

It is also recommended to use the n_positive argument (previously called n_pathology), which limits the search range only to those sets where the number of true positives and false negatives equal the input value, if this information is available.

```
vals = s.calculate_snspn(0.8, 0.70588, 20, n_positive=10, top_n=5)
df = pd.DataFrame(vals)
df
   TP  TN  FP  FN  Calculated_Sensitivity  Calculated_Specificity  Sensitivity_Error  Specificity_Error  Total_Error  Exact_Match
0   8   7   3   2                     0.8                     0.7                0.0            0.00588      0.00588        False
1   8   8   2   2                     0.8                     0.8                0.0            0.09412      0.09412        False
2   8   6   4   2                     0.8                     0.6                0.0            0.10588      0.10588        False
3   9   7   3   1                     0.9                     0.7                0.1            0.00588      0.10588        False
4   7   7   3   3                     0.7                     0.7                0.1            0.00588      0.10588        False
```

calculate_ppvnpv(): Calculates all possible confusion matries which could be produced from a sample size, and compares the calculated PPV and NPV to the input values. See calculate_snspn() above for some other details of recommended use for this family of functions.

```
>>> import pandas as pd
>>> import scrutipy as s
>>> vals = s.calculate_ppvnpv(0.8, 0.70588, 20, top_n=5)
>>> df = pd.DataFrame(vals)
>>> df
   TP  TN  FP  FN  Calculated_PPV  Calculated_NPV  PPV_Error  NPV_Error  Total_Error  Exact_Match
0   8   7   2   3        0.800000        0.700000   0.000000   0.005880     0.005880        False
1   4  11   1   4        0.800000        0.733333   0.000000   0.027453     0.027453        False
2  10   5   3   2        0.769231        0.714286   0.030769   0.008406     0.039175        False
3   4  10   1   5        0.800000        0.666667   0.000000   0.039213     0.039213        False
4   5  10   1   4        0.833333        0.714286   0.033333   0.008406     0.041739        False
```



calculate_likelihoodratios(): Calculates all possible confusion matries which could be produced from a sample size, and compares the calculated likelihood ratios to the input values. See calculate_snspn() above for some other details of recommended use for this family of functions.

```
l = s.calculate_likelihoodratios(0.234, 0.687, 56, top_n = 5)
df = pd.DataFrame(l)
df
   TP  TN  FP  FN  Calculated_PLR  Calculated_NLR  PLR_Error  NLR_Error  Total_Error  Exact_Match
0  20   9  22   5        0.232258        0.688889   0.001742   0.001889     0.003631        False
1  12  12  29   3        0.234146        0.683333   0.000146   0.003667     0.003813        False
2   4  15  36   1        0.235294        0.680000   0.001294   0.007000     0.008294        False
3  31   5  12   8        0.233786        0.697436   0.000214   0.010436     0.010650        False
4  23   8  19   6        0.234994        0.698276   0.000994   0.011276     0.012269        False

```

calculate_metrics_from_counts(): Calculates sensitivity, specificity, PPV, NPV, Positive Likelihood Ratio and Negative Likelihood Ratio from input counts of true/false positives/negatives.

```
import pandas as pd
import scrutipy as s
l = s.calculate_metrics_from_counts(34, 88, 94, 234)
df = pd.DataFrame([l])
   Sensitivity  Specificity       PPV       NPV       +LR       -LR
0     0.126866     0.483516  0.265625  0.273292  0.245634  1.805801

```

# Roadmap

Expand documentation

Test and document user-side GRIMMER function 

Tidy up return types as dataframes

Implicitly maintain x_col as str when appropriate

Implement SPRITE


# Acknowledgements

Lukas Jung

Nick Brown

James Heathers

Jordan Anaya

Aurelien Allard

Rod Whitely


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "scrutipy",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": "Nicolas Roman Posner <nrposner@uchicago.edu>",
    "keywords": "statistics, diagnostics, fraud detection, error detection, summary data, replication",
    "author": null,
    "author_email": "Nicolas Roman Posner <nrposner@uchicago.edu>",
    "download_url": "https://files.pythonhosted.org/packages/c2/73/04819d5bd9f5f89d330f40540bf5d6b2ebe12c13abc2b33a9fd5a3236450/scrutipy-0.1.11.tar.gz",
    "platform": null,
    "description": "# scrutiPy v0.1.11: Scientific error detection in Python\n\nA library for scientific error checking and fraud detection, based on the R Scrutiny library by Lukas Jung. Frontend API in Python 3, backend in Rust with PyO3 bindings. \n\nCurrently in early development. Presently available functions include:\n\ngrim_scalar(): Implements the GRIM test on single observations. \n\n```\nfrom scrutipy import grim_scalar\n\ngrim_scalar(\"5.19\", 40)\n# False\n```\n\ngrim_map() Implements the GRIM test on Pandas dataframes. Use the variant grim_map_pl() for Polars dataframes. Both functions require Polars, which can be enabled using `pip install scrutipy[polars]` or `pip install polars`.\n\n```\nimport pandas as pd\nfrom scrutipy import grim_map \n\ndf = pd.read_csv(\"data/pigs1.csv\")\n# it may be necessary to explicitly convert your x column to string type in order to avoid losing trailing zeros. In the event that trailing zeros may be lost, the function will throw a warning \ndf[\"x\"] = df[\"x\"].astype(str) \nbools, errors = grim_map(df, 1, 2)\n\nprint(bools)\n# list([True, False, False, False, False, True, False, True, False, False, True, False])\n\nprint(errors)\n# None\n```\n\ngrimmer() Implements the GRIMMER test on 1d iterables.\n\n```\nfrom scrutipy import grimmer\nresults = grimmer([\"1.03\", \"52.13\", \"9.42375\"], [\"0.41\", \"2.26\", \"3.86\"], [40, 30, 59], items = [1, 1, 1])\n\nprint(results)\n# list(False, True, False) \n\n```\n\ndebit() implements the DEBIT test on 1d iterables (lists and arrays). \n\n```\nfrom scrutipy import debit\n\nresults = debit([\"0.36\", \"0.11\", \"0.118974\"], [\"0.11\", \"0.31\", \"0.6784\"], [20, 40, 100])\nprint(results)\n# list([False, True, False])\n```\n\ndebit_map() implements the DEBIT test on Pandas dataframes. Use the variant debit_map_pl() for Polars dataframes. Both functions require Polars, which can be enabled using `pip install scrutipy[polars]` or `pip install polars`.\n\n```\nfrom scrutipy import debit_map \n\ndf = pd.read_csv(\"data/debit_data.csv\")\ndf[\"xs\"] = df[\"xs\"].astype(str) # ensuring that these columns are string types to silence a warning\ndf[\"sds\"] = df[\"sds\"].astype(str) # it can also be silenced with silence_numeric_warning = True.\nresults, errors = debit_map(df, 1, 2, 3)\n\nprint(bools)\n# list([True, True, True, False, True, True, True])\n\nprint(errors)\n# None\n```\n\nclosure(): Implements the CLOSURE algorithm for recovering integer data from summary statistics. Any data which can be represented as integers on a bounded range, such as Likert scores, can be provably reconstructed using the mean, standard deviation, count, and range. \nThis function replaces the CORVIDS algorithm, which relied on more advanced mathematics packages, with a simpler and faster algorithm. \nNote that even with CLOSURE's performance gains, the necessary time and compute to reconstruct data increases rapidly as range and count increase. \n\n```\n# reconstruct possible datasets with a mean of 3.5, sd of 0.57, n = 100, \n# and inclusive range from 0 to 7. \n# We set the rounding error for the mean to 0.05 and for sd to 0.005\n\nfrom scrutipy import closure\nresults = closure(3.5, 1.2, 50, 0, 7, 0.05, 0.005) \n\nlen(results)\n# 7980 \n# indicates there are 7980 possible datasets with these characteristics.\n```\n\ncalculate_snspn(): Calculates all possible confusion matries which could be produced from a sample size, and compares the calculated sensitivity and specificity to the input values. It returns a list of dictionaries containing the records for each possibility, as well as a total error and whether the total error is less than a certain tolerance. \nThe dictionaries are ordered from least to greatest total error. For larger sample sizes, it is recommended to use a top_n argument to limit the number of returned values. The return can be trivially turned into a pandas or polars dataframe as seen below.\nThis is based on an application by Rod Whitely.\n```\nimport pandas as pd\nimport scrutipy as s\nvals = s.calculate_snspn(0.8, 0.70588, 20, top_n=5)\ndf = pd.DataFrame(vals)\ndf\n   TP  TN  FP  FN  Calculated_Sensitivity  Calculated_Specificity  Sensitivity_Error  Specificity_Error  Total_Error  Exact_Match\n0   8   7   3   2                0.800000                0.700000           0.000000           0.005880     0.005880        False\n1   4  11   4   1                0.800000                0.733333           0.000000           0.027453     0.027453        False\n2  10   5   2   3                0.769231                0.714286           0.030769           0.008406     0.039175        False\n3   4  10   5   1                0.800000                0.666667           0.000000           0.039213     0.039213        False\n4   5  10   4   1                0.833333                0.714286           0.033333           0.008406     0.041739        False\n```\n\nIt is also recommended to use the n_positive argument (previously called n_pathology), which limits the search range only to those sets where the number of true positives and false negatives equal the input value, if this information is available.\n\n```\nvals = s.calculate_snspn(0.8, 0.70588, 20, n_positive=10, top_n=5)\ndf = pd.DataFrame(vals)\ndf\n   TP  TN  FP  FN  Calculated_Sensitivity  Calculated_Specificity  Sensitivity_Error  Specificity_Error  Total_Error  Exact_Match\n0   8   7   3   2                     0.8                     0.7                0.0            0.00588      0.00588        False\n1   8   8   2   2                     0.8                     0.8                0.0            0.09412      0.09412        False\n2   8   6   4   2                     0.8                     0.6                0.0            0.10588      0.10588        False\n3   9   7   3   1                     0.9                     0.7                0.1            0.00588      0.10588        False\n4   7   7   3   3                     0.7                     0.7                0.1            0.00588      0.10588        False\n```\n\ncalculate_ppvnpv(): Calculates all possible confusion matries which could be produced from a sample size, and compares the calculated PPV and NPV to the input values. See calculate_snspn() above for some other details of recommended use for this family of functions.\n\n```\n>>> import pandas as pd\n>>> import scrutipy as s\n>>> vals = s.calculate_ppvnpv(0.8, 0.70588, 20, top_n=5)\n>>> df = pd.DataFrame(vals)\n>>> df\n   TP  TN  FP  FN  Calculated_PPV  Calculated_NPV  PPV_Error  NPV_Error  Total_Error  Exact_Match\n0   8   7   2   3        0.800000        0.700000   0.000000   0.005880     0.005880        False\n1   4  11   1   4        0.800000        0.733333   0.000000   0.027453     0.027453        False\n2  10   5   3   2        0.769231        0.714286   0.030769   0.008406     0.039175        False\n3   4  10   1   5        0.800000        0.666667   0.000000   0.039213     0.039213        False\n4   5  10   1   4        0.833333        0.714286   0.033333   0.008406     0.041739        False\n```\n\n\n\ncalculate_likelihoodratios(): Calculates all possible confusion matries which could be produced from a sample size, and compares the calculated likelihood ratios to the input values. See calculate_snspn() above for some other details of recommended use for this family of functions.\n\n```\nl = s.calculate_likelihoodratios(0.234, 0.687, 56, top_n = 5)\ndf = pd.DataFrame(l)\ndf\n   TP  TN  FP  FN  Calculated_PLR  Calculated_NLR  PLR_Error  NLR_Error  Total_Error  Exact_Match\n0  20   9  22   5        0.232258        0.688889   0.001742   0.001889     0.003631        False\n1  12  12  29   3        0.234146        0.683333   0.000146   0.003667     0.003813        False\n2   4  15  36   1        0.235294        0.680000   0.001294   0.007000     0.008294        False\n3  31   5  12   8        0.233786        0.697436   0.000214   0.010436     0.010650        False\n4  23   8  19   6        0.234994        0.698276   0.000994   0.011276     0.012269        False\n\n```\n\ncalculate_metrics_from_counts(): Calculates sensitivity, specificity, PPV, NPV, Positive Likelihood Ratio and Negative Likelihood Ratio from input counts of true/false positives/negatives.\n\n```\nimport pandas as pd\nimport scrutipy as s\nl = s.calculate_metrics_from_counts(34, 88, 94, 234)\ndf = pd.DataFrame([l])\n   Sensitivity  Specificity       PPV       NPV       +LR       -LR\n0     0.126866     0.483516  0.265625  0.273292  0.245634  1.805801\n\n```\n\n# Roadmap\n\nExpand documentation\n\nTest and document user-side GRIMMER function \n\nTidy up return types as dataframes\n\nImplicitly maintain x_col as str when appropriate\n\nImplement SPRITE\n\n\n# Acknowledgements\n\nLukas Jung\n\nNick Brown\n\nJames Heathers\n\nJordan Anaya\n\nAurelien Allard\n\nRod Whitely\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A toolset for detecting inconsistencies in summary data.",
    "version": "0.1.11",
    "project_urls": null,
    "split_keywords": [
        "statistics",
        " diagnostics",
        " fraud detection",
        " error detection",
        " summary data",
        " replication"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "8871acd586694c0f601d0595e2b2f0067ad48231d16b0250daeae18b03c64b23",
                "md5": "13fad1c2345815040c3d3685da4da101",
                "sha256": "8634759ed7853b7c64d707adc768ea584b90a70c5bce5342b9fe67747ea3efec"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11-cp310-cp310-macosx_10_12_x86_64.whl",
            "has_sig": false,
            "md5_digest": "13fad1c2345815040c3d3685da4da101",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.8",
            "size": 3971983,
            "upload_time": "2025-08-28T13:29:33",
            "upload_time_iso_8601": "2025-08-28T13:29:33.103139Z",
            "url": "https://files.pythonhosted.org/packages/88/71/acd586694c0f601d0595e2b2f0067ad48231d16b0250daeae18b03c64b23/scrutipy-0.1.11-cp310-cp310-macosx_10_12_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "87c63b61ad677c7ee2411d542ab41f42c8c068ea04bf5db067db7e355ad3a48d",
                "md5": "24d064dc59a40cb91045dfe29c26e8fe",
                "sha256": "66ed3e0073fa730ce64929568a96a7d319fddd56be66c4533655cd0540f735fc"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11-cp310-cp310-macosx_11_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "24d064dc59a40cb91045dfe29c26e8fe",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.8",
            "size": 3639093,
            "upload_time": "2025-08-28T13:29:35",
            "upload_time_iso_8601": "2025-08-28T13:29:35.601967Z",
            "url": "https://files.pythonhosted.org/packages/87/c6/3b61ad677c7ee2411d542ab41f42c8c068ea04bf5db067db7e355ad3a48d/scrutipy-0.1.11-cp310-cp310-macosx_11_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "44a6d507a4eaab74bdf2663df9732a709f3b26e3fb5e61128d90f515a3686dda",
                "md5": "3c03c8b1561857e70c8d850be93c0817",
                "sha256": "9eb15a9b03ba77042efc70fcbdc29ee36854ed94a684b17e8a3cc9c120c97a93"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11-cp310-cp310-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "3c03c8b1561857e70c8d850be93c0817",
            "packagetype": "bdist_wheel",
            "python_version": "cp310",
            "requires_python": ">=3.8",
            "size": 4407720,
            "upload_time": "2025-08-28T13:41:03",
            "upload_time_iso_8601": "2025-08-28T13:41:03.722266Z",
            "url": "https://files.pythonhosted.org/packages/44/a6/d507a4eaab74bdf2663df9732a709f3b26e3fb5e61128d90f515a3686dda/scrutipy-0.1.11-cp310-cp310-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "8f3269807fc18311ee01747bb17d22f579ae8283d1da9b7d16bc7b919b1f69c1",
                "md5": "048873206de55dab8dcbb56ce00a809d",
                "sha256": "7bd2448cbb01f181f6de26386d9e44e2f40277035ca0e45f3575144e6ddf090c"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11-cp311-cp311-macosx_10_12_x86_64.whl",
            "has_sig": false,
            "md5_digest": "048873206de55dab8dcbb56ce00a809d",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.8",
            "size": 3972097,
            "upload_time": "2025-08-28T13:29:37",
            "upload_time_iso_8601": "2025-08-28T13:29:37.452108Z",
            "url": "https://files.pythonhosted.org/packages/8f/32/69807fc18311ee01747bb17d22f579ae8283d1da9b7d16bc7b919b1f69c1/scrutipy-0.1.11-cp311-cp311-macosx_10_12_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "2ae579202aec785b6fa946be118923bc41e925a48fb9e167aba1c0812f56195a",
                "md5": "8ee15b28ea1c7671d22cfc4862296c7e",
                "sha256": "6b394ecda795eacc7ba7cb7c7092bc9dabe9d11c4cd296baafa098ace88fbeb9"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11-cp311-cp311-macosx_11_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "8ee15b28ea1c7671d22cfc4862296c7e",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.8",
            "size": 3639583,
            "upload_time": "2025-08-28T13:29:39",
            "upload_time_iso_8601": "2025-08-28T13:29:39.413021Z",
            "url": "https://files.pythonhosted.org/packages/2a/e5/79202aec785b6fa946be118923bc41e925a48fb9e167aba1c0812f56195a/scrutipy-0.1.11-cp311-cp311-macosx_11_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f2b5e8164f44c57bf85bf7e399fe443ba71f19f869b17b90127ff40c5d9eb91f",
                "md5": "99bf04ef139e4e38fc2dcda292d9159a",
                "sha256": "e177b6651693aab1028d86362482d8e7b462b1d3a3cc2676c95786303c52c7fb"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11-cp311-cp311-manylinux_2_28_x86_64.whl",
            "has_sig": false,
            "md5_digest": "99bf04ef139e4e38fc2dcda292d9159a",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.8",
            "size": 4261100,
            "upload_time": "2025-08-28T13:46:40",
            "upload_time_iso_8601": "2025-08-28T13:46:40.858360Z",
            "url": "https://files.pythonhosted.org/packages/f2/b5/e8164f44c57bf85bf7e399fe443ba71f19f869b17b90127ff40c5d9eb91f/scrutipy-0.1.11-cp311-cp311-manylinux_2_28_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "eeab92c35bbeb5463868280b472877e762b1ab22c8b61f1b3319b8025a763ea4",
                "md5": "c1f5698db5f537370ffd716a0cfe5a73",
                "sha256": "eab86a46ceddf9bcab88a4070a4a019e3abe5df32e2b5c89ee261e34c734fcf9"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11-cp311-cp311-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "c1f5698db5f537370ffd716a0cfe5a73",
            "packagetype": "bdist_wheel",
            "python_version": "cp311",
            "requires_python": ">=3.8",
            "size": 4407751,
            "upload_time": "2025-08-28T13:41:05",
            "upload_time_iso_8601": "2025-08-28T13:41:05.514756Z",
            "url": "https://files.pythonhosted.org/packages/ee/ab/92c35bbeb5463868280b472877e762b1ab22c8b61f1b3319b8025a763ea4/scrutipy-0.1.11-cp311-cp311-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "e010980f82cf6df23f59ccef618101b1cfe19515a8e1249d252c0cff768f8e41",
                "md5": "840049bf9f8b670fd46c62054020f67b",
                "sha256": "3157088d54e82d66998de873f70300e07fdf049260bb3d25061eeb3706235afc"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11-cp312-cp312-macosx_10_12_x86_64.whl",
            "has_sig": false,
            "md5_digest": "840049bf9f8b670fd46c62054020f67b",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.8",
            "size": 3970453,
            "upload_time": "2025-08-28T13:29:41",
            "upload_time_iso_8601": "2025-08-28T13:29:41.275172Z",
            "url": "https://files.pythonhosted.org/packages/e0/10/980f82cf6df23f59ccef618101b1cfe19515a8e1249d252c0cff768f8e41/scrutipy-0.1.11-cp312-cp312-macosx_10_12_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "3484a3fd558a48cd7cbd5d97c4e0e001e1ed46f022c6a8010aa96ebcdda9c2b0",
                "md5": "2e8b8e85ec00c2ad0ab19c7e72781748",
                "sha256": "165e11631420424f488dc06930967422addeacab094e64a39624f271edbf61f6"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11-cp312-cp312-macosx_11_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "2e8b8e85ec00c2ad0ab19c7e72781748",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.8",
            "size": 3635741,
            "upload_time": "2025-08-28T13:29:43",
            "upload_time_iso_8601": "2025-08-28T13:29:43.385793Z",
            "url": "https://files.pythonhosted.org/packages/34/84/a3fd558a48cd7cbd5d97c4e0e001e1ed46f022c6a8010aa96ebcdda9c2b0/scrutipy-0.1.11-cp312-cp312-macosx_11_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "ef8d5209656b026ed053d7cd17b7f67967196fdae4f0ba2af298cf8db5701399",
                "md5": "cb30711a2aa53c307ebbf5473795f103",
                "sha256": "bdbbf38c362d0e33fec53d21bf73e565edfd4073f03ab4012565f6b45c16b404"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11-cp312-cp312-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "cb30711a2aa53c307ebbf5473795f103",
            "packagetype": "bdist_wheel",
            "python_version": "cp312",
            "requires_python": ">=3.8",
            "size": 4409905,
            "upload_time": "2025-08-28T13:41:07",
            "upload_time_iso_8601": "2025-08-28T13:41:07.196359Z",
            "url": "https://files.pythonhosted.org/packages/ef/8d/5209656b026ed053d7cd17b7f67967196fdae4f0ba2af298cf8db5701399/scrutipy-0.1.11-cp312-cp312-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "a1a53ef01a3d3c84ac3dbbb2729c6684eae290390f01d4d2e3a57637d8cec62f",
                "md5": "7534f7d97982faa618e33a5a25a7f86b",
                "sha256": "34edff81759a3a3d404a7a07736f04e82b89a073b359e20dd699a6b7dd7e9ecf"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11-cp313-cp313-macosx_10_12_x86_64.whl",
            "has_sig": false,
            "md5_digest": "7534f7d97982faa618e33a5a25a7f86b",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.8",
            "size": 3970456,
            "upload_time": "2025-08-28T13:29:45",
            "upload_time_iso_8601": "2025-08-28T13:29:45.430023Z",
            "url": "https://files.pythonhosted.org/packages/a1/a5/3ef01a3d3c84ac3dbbb2729c6684eae290390f01d4d2e3a57637d8cec62f/scrutipy-0.1.11-cp313-cp313-macosx_10_12_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f4350169051908cc6bfef35ddbad1998089d2274d3be847a83c931823704f27e",
                "md5": "4101d1d57bbf2b217cfca9589bd3786b",
                "sha256": "6b395a072f2a96818a04581f2d4ce7f8e9a6aa6540ebd991de62877be20ed886"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11-cp313-cp313-macosx_11_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "4101d1d57bbf2b217cfca9589bd3786b",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.8",
            "size": 3635390,
            "upload_time": "2025-08-28T13:29:47",
            "upload_time_iso_8601": "2025-08-28T13:29:47.378962Z",
            "url": "https://files.pythonhosted.org/packages/f4/35/0169051908cc6bfef35ddbad1998089d2274d3be847a83c931823704f27e/scrutipy-0.1.11-cp313-cp313-macosx_11_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f10aadfe4245dcd581f85b9e20900fe877827e44563deccbe94541ca39101cc3",
                "md5": "a63a41b22dc558876d4a345aa53f8a26",
                "sha256": "17686bb31f8400c2c300df2a26c94751d9160deb3dfc4b118c08f49d640797c9"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11-cp313-cp313-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "a63a41b22dc558876d4a345aa53f8a26",
            "packagetype": "bdist_wheel",
            "python_version": "cp313",
            "requires_python": ">=3.8",
            "size": 4409461,
            "upload_time": "2025-08-28T13:41:08",
            "upload_time_iso_8601": "2025-08-28T13:41:08.999042Z",
            "url": "https://files.pythonhosted.org/packages/f1/0a/adfe4245dcd581f85b9e20900fe877827e44563deccbe94541ca39101cc3/scrutipy-0.1.11-cp313-cp313-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "c27304819d5bd9f5f89d330f40540bf5d6b2ebe12c13abc2b33a9fd5a3236450",
                "md5": "246d8901ff13f53fe2ecf3c4d3525736",
                "sha256": "5e9dd2628a77d32b3c3b186879af43c46ef6634ac1d88418baf90b1fe41acf81"
            },
            "downloads": -1,
            "filename": "scrutipy-0.1.11.tar.gz",
            "has_sig": false,
            "md5_digest": "246d8901ff13f53fe2ecf3c4d3525736",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 56423,
            "upload_time": "2025-08-28T13:29:49",
            "upload_time_iso_8601": "2025-08-28T13:29:49.035781Z",
            "url": "https://files.pythonhosted.org/packages/c2/73/04819d5bd9f5f89d330f40540bf5d6b2ebe12c13abc2b33a9fd5a3236450/scrutipy-0.1.11.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-28 13:29:49",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "scrutipy"
}
        
Elapsed time: 1.08985s