polars-iptools


Namepolars-iptools JSON
Version 0.1.8 PyPI version JSON
download
home_pageNone
SummaryPolars extension for IP address parsing and enrichment including geolocation
upload_time2024-09-10 11:48:17
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseMIT
keywords polars dfir geoip
VCS
bugtrack_url
requirements polars maturin ruff pytest mypy
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Polars IPTools

Polars IPTools is a Rust-based extension to accelerates IP address manipulation and enrichment in Polars dataframes. This library includes various utility functions for working with IPv4 and IPv6 addresses and geoip and anonymization/proxy enrichment using MaxMind databases.

## Install

```shell
pip install polars-iptools
```

## Examples

### Simple enrichments

IPTools' Rust implementation gives you speedy answers to basic IP questions like "is this a private IP?"

```python
>>> import polars as pl
>>> import polars_iptools as ip
>>> df = pl.DataFrame({'ip': ['8.8.8.8', '2606:4700::1111', '192.168.100.100', '172.21.1.1', '172.34.5.5', 'a.b.c.d']})
>>> df.with_columns(ip.is_private(pl.col('ip')).alias('is_private'))
shape: (6, 2)
┌─────────────────┬────────────┐
│ ip              ┆ is_private │
│ ---             ┆ ---        │
│ str             ┆ bool       │
╞═════════════════╪════════════╡
│ 8.8.8.8         ┆ false      │
│ 2606:4700::1111 ┆ false      │
│ 192.168.100.100 ┆ true       │
│ 172.21.1.1      ┆ true       │
│ 172.34.5.5      ┆ false      │
│ a.b.c.d         ┆ false      │
└─────────────────┴────────────┘
```

### `is_in` but for network ranges

Pandas and Polars have `is_in` functions to perform membership lookups. IPTools extends this to enable IP address membership in IP _networks_. This function works seamlessly with both IPv4 and IPv6 addresses and converts the specified networks into a [Level-Compressed trie (LC-Trie)](https://github.com/Orange-OpenSource/iptrie) for fast, efficient lookups.

```python
>>> import polars as pl
>>> import polars_iptools as ip
>>> df = pl.DataFrame({'ip': ['8.8.8.8', '1.1.1.1', '2606:4700::1111']})
>>> networks = ['8.8.8.0/24', '2606:4700::/32']
>>> df.with_columns(ip.is_in(pl.col('ip'), networks).alias('is_in'))
shape: (3, 2)
┌─────────────────┬───────┐
│ ip              ┆ is_in │
│ ---             ┆ ---   │
│ str             ┆ bool  │
╞═════════════════╪═══════╡
│ 8.8.8.8         ┆ true  │
│ 1.1.1.1         ┆ false │
│ 2606:4700::1111 ┆ true  │
└─────────────────┴───────┘
```

### GeoIP enrichment

Using [MaxMind's](https://www.maxmind.com/en/geoip-databases) _GeoLite2-ASN.mmdb_ and _GeoLite2-City.mmdb_ databases, IPTools provides offline enrichment of network ownership and geolocation.

`ip.geoip.full` returns a Polars struct containing all available metadata parameters. If you just want the ASN and AS organization, you can use `ip.geoip.asn`.

```python
>>> import polars as pl
>>> import polars_iptools as ip

>>> df = pl.DataFrame({"ip":["8.8.8.8", "192.168.1.1", "2606:4700::1111", "999.abc.def.123"]})
>>> df.with_columns([ip.geoip.full(pl.col("ip")).alias("geoip")])

shape: (4, 2)
┌─────────────────┬─────────────────────────────────┐
│ ip              ┆ geoip                           │
│ ---             ┆ ---                             │
│ str             ┆ struct[11]                      │
╞═════════════════╪═════════════════════════════════╡
│ 8.8.8.8         ┆ {15169,"GOOGLE","","NA","","",… │
│ 192.168.1.1     ┆ {0,"","","","","","","",0.0,0.… │
│ 2606:4700::1111 ┆ {13335,"CLOUDFLARENET","","","… │
│ 999.abc.def.123 ┆ {null,null,null,null,null,null… │
└─────────────────┴─────────────────────────────────┘

>>> df.with_columns([ip.geoip.asn(pl.col("ip")).alias("asn")])
shape: (4, 2)
┌─────────────────┬───────────────────────┐
│ ip              ┆ asn                   │
│ ---             ┆ ---                   │
│ str             ┆ str                   │
╞═════════════════╪═══════════════════════╡
│ 8.8.8.8         ┆ AS15169 GOOGLE        │
│ 192.168.1.1     ┆                       │
│ 2606:4700::1111 ┆ AS13335 CLOUDFLARENET │
│ 999.abc.def.123 ┆                       │
└─────────────────┴───────────────────────┘
```

### Spur enrichment

[Spur](https://spur.us/) is a commercial service that provides "data to detect VPNs, residential proxies, and bots". One of its offerings is a [Maxmind mmdb format](https://docs.spur.us/feeds?id=feed-export-utility) of at most 2,000,000 "busiest" Anonymous or Anonymous+Residential ips.

`ip.spur.full` returns a Polars struct containing all available metadata parameters.

```python
>>> import polars as pl
>>> import polars_iptools as ip

>>> df = pl.DataFrame({"ip":["8.8.8.8", "192.168.1.1", "999.abc.def.123"]})
>>> df.with_columns([ip.spur.full(pl.col("ip")).alias("spur")])

shape: (3, 2)
┌─────────────────┬─────────────────────────────────┐
│ ip              ┆ geoip                           │
│ ---             ┆ ---                             │
│ str             ┆ struct[7]                       │
╞═════════════════╪═════════════════════════════════╡
│ 8.8.8.8         ┆ {0.0,"","","","","",null}       │
│ 192.168.1.1     ┆ {0.0,"","","","","",null}       │
│ 999.abc.def.123 ┆ {null,null,null,null,null,null… │
└─────────────────┴─────────────────────────────────┘
```

## Environment Configuration

IPTools uses two MaxMind databases: _GeoLite2-ASN.mmdb_ and _GeoLite2-City.mmdb_. You only need these files if you call the geoip functions.

Set the `MAXMIND_MMDB_DIR` environment variable to tell the extension where these files are located.

```shell
export MAXMIND_MMDB_DIR=/path/to/your/mmdb/files
# or Windows users
set MAXMIND_MMDB_DIR=c:\path\to\your\mmdb\files
````

If the environment is not set, polars_iptools will check two other common locations (on Mac/Linux):

```
/usr/local/share/GeoIP
/opt/homebrew/var/GeoIP
```

### Spur Environment

If you're a Spur customer, export the feed as `spur.mmdb` and specify its location using `SPUR_MMDB_DIR` environment variable.

```shell
export SPUR_MMDB_DIR=/path/to/spur/mmdb
# or Windows users
set SPUR_MMDB_DIR=c:\path\to\spur\mmdb
````

## Credit

Developing this extension was super easy by following Marco Gorelli's [tutorial](https://marcogorelli.github.io/polars-plugins-tutorial/) and [cookiecutter template](https://github.com/MarcoGorelli/cookiecutter-polars-plugins).


            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "polars-iptools",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "polars, dfir, geoip",
    "author": null,
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/a0/95/8681705050a97fd249d5b8a422d0e6d670372037f1009ea7b0780b37f29f/polars_iptools-0.1.8.tar.gz",
    "platform": null,
    "description": "# Polars IPTools\n\nPolars IPTools is a Rust-based extension to accelerates IP address manipulation and enrichment in Polars dataframes. This library includes various utility functions for working with IPv4 and IPv6 addresses and geoip and anonymization/proxy enrichment using MaxMind databases.\n\n## Install\n\n```shell\npip install polars-iptools\n```\n\n## Examples\n\n### Simple enrichments\n\nIPTools' Rust implementation gives you speedy answers to basic IP questions like \"is this a private IP?\"\n\n```python\n>>> import polars as pl\n>>> import polars_iptools as ip\n>>> df = pl.DataFrame({'ip': ['8.8.8.8', '2606:4700::1111', '192.168.100.100', '172.21.1.1', '172.34.5.5', 'a.b.c.d']})\n>>> df.with_columns(ip.is_private(pl.col('ip')).alias('is_private'))\nshape: (6, 2)\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 ip              \u2506 is_private \u2502\n\u2502 ---             \u2506 ---        \u2502\n\u2502 str             \u2506 bool       \u2502\n\u255e\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2561\n\u2502 8.8.8.8         \u2506 false      \u2502\n\u2502 2606:4700::1111 \u2506 false      \u2502\n\u2502 192.168.100.100 \u2506 true       \u2502\n\u2502 172.21.1.1      \u2506 true       \u2502\n\u2502 172.34.5.5      \u2506 false      \u2502\n\u2502 a.b.c.d         \u2506 false      \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n### `is_in` but for network ranges\n\nPandas and Polars have `is_in` functions to perform membership lookups. IPTools extends this to enable IP address membership in IP _networks_. This function works seamlessly with both IPv4 and IPv6 addresses and converts the specified networks into a [Level-Compressed trie (LC-Trie)](https://github.com/Orange-OpenSource/iptrie) for fast, efficient lookups.\n\n```python\n>>> import polars as pl\n>>> import polars_iptools as ip\n>>> df = pl.DataFrame({'ip': ['8.8.8.8', '1.1.1.1', '2606:4700::1111']})\n>>> networks = ['8.8.8.0/24', '2606:4700::/32']\n>>> df.with_columns(ip.is_in(pl.col('ip'), networks).alias('is_in'))\nshape: (3, 2)\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 ip              \u2506 is_in \u2502\n\u2502 ---             \u2506 ---   \u2502\n\u2502 str             \u2506 bool  \u2502\n\u255e\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2561\n\u2502 8.8.8.8         \u2506 true  \u2502\n\u2502 1.1.1.1         \u2506 false \u2502\n\u2502 2606:4700::1111 \u2506 true  \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n### GeoIP enrichment\n\nUsing [MaxMind's](https://www.maxmind.com/en/geoip-databases) _GeoLite2-ASN.mmdb_ and _GeoLite2-City.mmdb_ databases, IPTools provides offline enrichment of network ownership and geolocation.\n\n`ip.geoip.full` returns a Polars struct containing all available metadata parameters. If you just want the ASN and AS organization, you can use `ip.geoip.asn`.\n\n```python\n>>> import polars as pl\n>>> import polars_iptools as ip\n\n>>> df = pl.DataFrame({\"ip\":[\"8.8.8.8\", \"192.168.1.1\", \"2606:4700::1111\", \"999.abc.def.123\"]})\n>>> df.with_columns([ip.geoip.full(pl.col(\"ip\")).alias(\"geoip\")])\n\nshape: (4, 2)\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 ip              \u2506 geoip                           \u2502\n\u2502 ---             \u2506 ---                             \u2502\n\u2502 str             \u2506 struct[11]                      \u2502\n\u255e\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2561\n\u2502 8.8.8.8         \u2506 {15169,\"GOOGLE\",\"\",\"NA\",\"\",\"\",\u2026 \u2502\n\u2502 192.168.1.1     \u2506 {0,\"\",\"\",\"\",\"\",\"\",\"\",\"\",0.0,0.\u2026 \u2502\n\u2502 2606:4700::1111 \u2506 {13335,\"CLOUDFLARENET\",\"\",\"\",\"\u2026 \u2502\n\u2502 999.abc.def.123 \u2506 {null,null,null,null,null,null\u2026 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n>>> df.with_columns([ip.geoip.asn(pl.col(\"ip\")).alias(\"asn\")])\nshape: (4, 2)\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 ip              \u2506 asn                   \u2502\n\u2502 ---             \u2506 ---                   \u2502\n\u2502 str             \u2506 str                   \u2502\n\u255e\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2561\n\u2502 8.8.8.8         \u2506 AS15169 GOOGLE        \u2502\n\u2502 192.168.1.1     \u2506                       \u2502\n\u2502 2606:4700::1111 \u2506 AS13335 CLOUDFLARENET \u2502\n\u2502 999.abc.def.123 \u2506                       \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n### Spur enrichment\n\n[Spur](https://spur.us/) is a commercial service that provides \"data to detect VPNs, residential proxies, and bots\". One of its offerings is a [Maxmind mmdb format](https://docs.spur.us/feeds?id=feed-export-utility) of at most 2,000,000 \"busiest\" Anonymous or Anonymous+Residential ips.\n\n`ip.spur.full` returns a Polars struct containing all available metadata parameters.\n\n```python\n>>> import polars as pl\n>>> import polars_iptools as ip\n\n>>> df = pl.DataFrame({\"ip\":[\"8.8.8.8\", \"192.168.1.1\", \"999.abc.def.123\"]})\n>>> df.with_columns([ip.spur.full(pl.col(\"ip\")).alias(\"spur\")])\n\nshape: (3, 2)\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 ip              \u2506 geoip                           \u2502\n\u2502 ---             \u2506 ---                             \u2502\n\u2502 str             \u2506 struct[7]                       \u2502\n\u255e\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u256a\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2561\n\u2502 8.8.8.8         \u2506 {0.0,\"\",\"\",\"\",\"\",\"\",null}       \u2502\n\u2502 192.168.1.1     \u2506 {0.0,\"\",\"\",\"\",\"\",\"\",null}       \u2502\n\u2502 999.abc.def.123 \u2506 {null,null,null,null,null,null\u2026 \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n```\n\n## Environment Configuration\n\nIPTools uses two MaxMind databases: _GeoLite2-ASN.mmdb_ and _GeoLite2-City.mmdb_. You only need these files if you call the geoip functions.\n\nSet the `MAXMIND_MMDB_DIR` environment variable to tell the extension where these files are located.\n\n```shell\nexport MAXMIND_MMDB_DIR=/path/to/your/mmdb/files\n# or Windows users\nset MAXMIND_MMDB_DIR=c:\\path\\to\\your\\mmdb\\files\n````\n\nIf the environment is not set, polars_iptools will check two other common locations (on Mac/Linux):\n\n```\n/usr/local/share/GeoIP\n/opt/homebrew/var/GeoIP\n```\n\n### Spur Environment\n\nIf you're a Spur customer, export the feed as `spur.mmdb` and specify its location using `SPUR_MMDB_DIR` environment variable.\n\n```shell\nexport SPUR_MMDB_DIR=/path/to/spur/mmdb\n# or Windows users\nset SPUR_MMDB_DIR=c:\\path\\to\\spur\\mmdb\n````\n\n## Credit\n\nDeveloping this extension was super easy by following Marco Gorelli's [tutorial](https://marcogorelli.github.io/polars-plugins-tutorial/) and [cookiecutter template](https://github.com/MarcoGorelli/cookiecutter-polars-plugins).\n\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Polars extension for IP address parsing and enrichment including geolocation",
    "version": "0.1.8",
    "project_urls": {
        "Source Code": "https://github.com/erichutchins/polars_iptools"
    },
    "split_keywords": [
        "polars",
        " dfir",
        " geoip"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "2448f2bc882b941f2a15e136fc21ff489c355ab1ad5f59294dad949b858a2ed5",
                "md5": "4523f458a704cbf51d391d5f22bd6762",
                "sha256": "55a31af3cc6edc4bfbaaca3ac90f41db0bca8d76eecc0541c73720cfe90e9f1f"
            },
            "downloads": -1,
            "filename": "polars_iptools-0.1.8-cp38-abi3-macosx_10_12_x86_64.whl",
            "has_sig": false,
            "md5_digest": "4523f458a704cbf51d391d5f22bd6762",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 3202026,
            "upload_time": "2024-09-10T11:48:07",
            "upload_time_iso_8601": "2024-09-10T11:48:07.436986Z",
            "url": "https://files.pythonhosted.org/packages/24/48/f2bc882b941f2a15e136fc21ff489c355ab1ad5f59294dad949b858a2ed5/polars_iptools-0.1.8-cp38-abi3-macosx_10_12_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "61e346b3a69dd9f00d31340e4fb96c8ccd478741ef6d137a3840c01a331c0617",
                "md5": "74f4503a3e78868751b61f454d576c50",
                "sha256": "cd0a9c0d7ade0bad8e1f281ab8bbbd150d4bc8310130fb9e17c70eca019c5b7c"
            },
            "downloads": -1,
            "filename": "polars_iptools-0.1.8-cp38-abi3-macosx_11_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "74f4503a3e78868751b61f454d576c50",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 2836001,
            "upload_time": "2024-09-10T11:48:09",
            "upload_time_iso_8601": "2024-09-10T11:48:09.462372Z",
            "url": "https://files.pythonhosted.org/packages/61/e3/46b3a69dd9f00d31340e4fb96c8ccd478741ef6d137a3840c01a331c0617/polars_iptools-0.1.8-cp38-abi3-macosx_11_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "a6a2f043db553a2933c54f6dbc746d0e137ca2bbfbc9ad225ee2d599c703ae2c",
                "md5": "c6dcd87a2f4c4a33d72ee95b142764f4",
                "sha256": "dde32d75efc9be1a1cce42aeb736a6f255d143f56eeadf6d81ec00e6fd3b55cd"
            },
            "downloads": -1,
            "filename": "polars_iptools-0.1.8-cp38-abi3-manylinux_2_12_i686.manylinux2010_i686.whl",
            "has_sig": false,
            "md5_digest": "c6dcd87a2f4c4a33d72ee95b142764f4",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 3896882,
            "upload_time": "2024-09-10T11:48:11",
            "upload_time_iso_8601": "2024-09-10T11:48:11.417791Z",
            "url": "https://files.pythonhosted.org/packages/a6/a2/f043db553a2933c54f6dbc746d0e137ca2bbfbc9ad225ee2d599c703ae2c/polars_iptools-0.1.8-cp38-abi3-manylinux_2_12_i686.manylinux2010_i686.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d58360e23beb6ac391d42f4b16c55a17b110017a622109fbd933ccf1b2eac42a",
                "md5": "88258edb421c87f3094a83f0501e9cf5",
                "sha256": "4f6d0be5794d476c48eb729a3949939369cf65270fba92e117cada7ce32acd33"
            },
            "downloads": -1,
            "filename": "polars_iptools-0.1.8-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "has_sig": false,
            "md5_digest": "88258edb421c87f3094a83f0501e9cf5",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 3796361,
            "upload_time": "2024-09-10T11:48:13",
            "upload_time_iso_8601": "2024-09-10T11:48:13.522271Z",
            "url": "https://files.pythonhosted.org/packages/d5/83/60e23beb6ac391d42f4b16c55a17b110017a622109fbd933ccf1b2eac42a/polars_iptools-0.1.8-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "7e08285109382c52266129d19f3ac258ba8cc1f9f26d4e45ba125fc091fc8ea2",
                "md5": "2a88f60bc24d4797e21f89a79b424c6c",
                "sha256": "87dbaf08c58deba708df46ae370381ab71748d39cf508ef108e7eb59a8058d8d"
            },
            "downloads": -1,
            "filename": "polars_iptools-0.1.8-cp38-abi3-win_amd64.whl",
            "has_sig": false,
            "md5_digest": "2a88f60bc24d4797e21f89a79b424c6c",
            "packagetype": "bdist_wheel",
            "python_version": "cp38",
            "requires_python": ">=3.8",
            "size": 3512046,
            "upload_time": "2024-09-10T11:48:15",
            "upload_time_iso_8601": "2024-09-10T11:48:15.445402Z",
            "url": "https://files.pythonhosted.org/packages/7e/08/285109382c52266129d19f3ac258ba8cc1f9f26d4e45ba125fc091fc8ea2/polars_iptools-0.1.8-cp38-abi3-win_amd64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "a0958681705050a97fd249d5b8a422d0e6d670372037f1009ea7b0780b37f29f",
                "md5": "5107a56787682168e169e06b52ed6d4b",
                "sha256": "4210a58b89b279a74335ff28be3602f325cef3c18a825e0a8f0d969c44d8e77e"
            },
            "downloads": -1,
            "filename": "polars_iptools-0.1.8.tar.gz",
            "has_sig": false,
            "md5_digest": "5107a56787682168e169e06b52ed6d4b",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.8",
            "size": 48163,
            "upload_time": "2024-09-10T11:48:17",
            "upload_time_iso_8601": "2024-09-10T11:48:17.014689Z",
            "url": "https://files.pythonhosted.org/packages/a0/95/8681705050a97fd249d5b8a422d0e6d670372037f1009ea7b0780b37f29f/polars_iptools-0.1.8.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-09-10 11:48:17",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "erichutchins",
    "github_project": "polars_iptools",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "requirements": [
        {
            "name": "polars",
            "specs": []
        },
        {
            "name": "maturin",
            "specs": []
        },
        {
            "name": "ruff",
            "specs": []
        },
        {
            "name": "pytest",
            "specs": []
        },
        {
            "name": "mypy",
            "specs": []
        }
    ],
    "lcname": "polars-iptools"
}
        
Elapsed time: 0.32284s