Skip to main content

Tools for parsing, validating, normalizing, querying, and inspecting RFC 8805 geofeeds

Project description

geofeed-tools

geofeed-tools is a Python library and CLI for working with RFC 8805 geofeeds. It parses, validates, normalizes, queries, and summarizes geofeeds from local files, HTTP(S) sources, or directly from an IP address / CIDR prefix — in the IP/prefix case the geofeed URL is auto-discovered via RDAP before the operation runs.

Install

# Core library only
pip install geofeed-tools

# Library + CLI
pip install 'geofeed-tools[cli]'

# Library + async HTTP support for AsyncGeoFeed URL loading
pip install 'geofeed-tools[async]'

# Library + everything for development
pip install 'geofeed-tools[dev]'

Run the CLI under uv without installing:

uv tool run 'geofeed-tools[cli]' --help

Or via Docker (no Python needed on the host):

docker run --rm pythonmodules/geofeed-tools:latest doctor 31.133.128.1

Published images:

  • ghcr.io/python-modules/geofeed-tools
  • pythonmodules/geofeed-tools

Tags: python3, python3.11, python3.12, python3.13, and latest (tracks python3).

CLI quick start

# Discover a published geofeed for an IP via RDAP, then search it for the same IP
geofeed-tools query 31.133.128.1

# Same RDAP discovery, but show the full lookup metadata (trace, range, etc.)
geofeed-tools doctor 31.133.128.1

# Validate a geofeed source
geofeed-tools validate geofeeds.csv

# Show detailed info — works against a file, a URL, OR an IP/prefix (auto-RDAP-discovered)
geofeed-tools info geofeeds.csv
geofeed-tools info 31.133.128.1            # discovers the geofeed via RDAP, then info
geofeed-tools info https://example.com/geofeed.csv

# Query a geofeed for an IP or prefix
geofeed-tools query geofeeds.csv 192.0.2.200

# Filter records by country, region, prefix length, etc. (combinable)
geofeed-tools filter geofeeds.csv --country CA --family ipv4 --prefix-length 24 --longer

# Normalize the feed and write canonical CSV to a file
geofeed-tools normalize geofeeds.csv --output normalized.csv

# Validate in CI / pre-commit mode (machine-friendly exit codes + machine-readable output)
geofeed-tools validate geofeeds.csv --hook --strict

Per-command help is always available:

geofeed-tools --help
geofeed-tools doctor --help

Source argument: file, URL, or IP/prefix

Every command that takes a SOURCE (validate, dump, normalize, filter, query, info) accepts three input shapes:

Input Behavior
Local file path (./geofeeds.csv) Read from disk.
HTTP(S) URL (https://example.com/foo.csv) Fetch and use directly.
IP address or CIDR prefix (1.1.1.1, 2001:db8::/32) RDAP-discover the published geofeed URL (rdap.org by default), then load and run on it.

Discovery failures (no geofeed URL published for the IP/prefix) exit 1 with a friendly message. The same auto-discovery works in the Python API — GeoFeed("1.1.1.1").info() does the right thing.

The query and doctor commands take a separate QUERY argument (always an IP or prefix). query also accepts a single-argument form — geofeed-tools query 1.1.1.1 — which auto-discovers the geofeed via RDAP and searches it for that same IP, replacing the previous lookup subcommand.

Output formats

Every command supports --format / -f with four values:

Format Best for Notes
rich terminal (default) Colored panels, trees, and tables
plain redirected to file or scrollback Same content, no colors, no box-drawing characters
grep piping to grep/awk/scripting One record per line, no headers or summary lines
json piping to jq or programmatic Stable structured JSON identical to the matching output="json" API

Examples:

geofeed-tools validate geofeeds.csv --format grep | grep error
geofeed-tools info geofeeds.csv --format grep | grep ^errors=
geofeed-tools doctor 31.133.128.1 --format json | jq .lookup.geofeed_url
geofeed-tools query geofeeds.csv 192.0.2.1 --format json | jq '.matches[0]'

Exit codes follow the most useful semantic per format:

  • validate (with or without --hook): exit 1 when errors are found (or warnings with --strict), regardless of format.
  • query: exit 1 on no match in any non-JSON format; exit 0 in json mode (the empty matches array is the answer). Exit 1 if an IP/prefix source can't be resolved via RDAP.
  • doctor: exit 1 when no geofeed is discovered or no record matches, regardless of format.
  • dump / normalize / filter / info: exit 0 on success; exit 1 when an IP/prefix source can't be resolved via RDAP.

CLI command reference

validate

geofeed-tools validate SOURCE [--format ...] [--strict] [--hook] [--show-issues/--no-issues]
                              [--check-aggregation] [--no-sort-check] [--no-content-type-check] [-v]

Validate a geofeed and report issues. Add --hook for CI/CD integration — it renders machine-friendly hook output (issues table / status line on stderr in rich mode, path:line:severity:code:message rows on stdout in grep mode) while keeping the same exit-code policy.

Option Default Meaning
--format, -f rich Output format.
--strict off Exit 1 when warnings are present, not just errors.
--hook off CI-friendly rendering (status line + issues), same exit codes.
--show-issues/--no-issues on In --hook mode, print individual validation issues. Ignored otherwise.
--check-aggregation off Warn for prefixes that could be safely aggregated.
--no-sort-check off Disable sort-order warnings.
--no-content-type-check off Disable Content-Type warnings for URL sources.
-v, --verbose 0 Increase log verbosity (-v INFO, -vv DEBUG, -vvv TRACE).

--format grep emits one line per issue in path:line:severity:code:message form, identical to GCC/grep style for easy pipeline use. The standalone hook subcommand was removed in 0.2.0 — use validate --hook instead.

dump

geofeed-tools dump SOURCE [--format ...] [--normalize] [--no-validation] [-v]

Dump parsed records in the chosen format. --normalize rebuilds rows from normalized output; --no-validation strips the valid / validation_messages columns from rich, plain, and JSON output. The grep format always emits 5-column geofeed CSV without validation columns.

normalize

geofeed-tools normalize SOURCE [--format ...] [--output FILE] [--no-uppercase] [--no-sort] [--no-aggregate] [--no-dedupe] [--no-host-bit-fix] [-v]

Normalize a geofeed. --output FILE always writes canonical CSV regardless of --format because that is the only useful payload to persist.

Option Default Meaning
--no-uppercase off Do not uppercase country and region fields.
--no-sort off Do not sort by IP family and prefix.
--no-aggregate off Do not collapse compatible prefixes into larger prefixes.
--no-dedupe off Do not remove exact duplicate rows when aggregation is disabled.
--no-host-bit-fix off Do not coerce prefixes with host bits set to their containing network.

filter

geofeed-tools filter SOURCE [--format ...]
                            [--prefix CIDR] [--country CC] [--region SUB]
                            [--city NAME] [--postal-code PC]
                            [--family ipv4|ipv6]
                            [--prefix-length N]
                            [--longer]
                            [-v]

Return records matching every supplied predicate (AND).

Option Default Meaning
--prefix CIDR prefix. Exact match unless --longer is set.
--country ISO 3166-1 alpha-2 code (case-insensitive).
--region ISO 3166-2 subdivision code (case-insensitive).
--city City name (case-insensitive).
--postal-code Postal code (case-insensitive).
--family both Restrict to ipv4 or ipv6.
--prefix-length Filter by CIDR length. Exact match unless --longer is set.
--longer off For --prefix, also match subnets contained by it. For --prefix-length, match length >= N.

Filters combine. Examples:

# All Canadian IPv4 records covering /24-or-longer
geofeed-tools filter geofeeds.csv --country CA --family ipv4 --prefix-length 24 --longer

# Records inside 192.0.2.0/24 in Ontario, Canada
geofeed-tools filter geofeeds.csv --country CA --region CA-ON --prefix 192.0.2.0/24 --longer

# All IPv6 records for a specific city, as raw CSV
geofeed-tools filter geofeeds.csv --family ipv6 --city Toronto --format grep

query

geofeed-tools query SOURCE [QUERY] [--format ...] [--all] [--longer]
                                    [--rdap-method rdap.org|iana-bootstrap] [-v]

Look up an IP or CIDR in a geofeed.

  • SOURCE is the geofeed source (file path, URL, or IP/prefix to auto-discover via RDAP).
  • QUERY is the IP or CIDR to look up. It's optional when SOURCE is itself an IP/prefix — geofeed-tools query 1.1.1.1 discovers the geofeed for 1.1.1.1 and searches it for the same address. This replaces the previous lookup subcommand.
  • --all returns every match instead of only the most specific one.
  • --longer includes more-specific prefixes contained by a queried prefix.
  • --rdap-method controls which RDAP method is used when discovering a geofeed from an IP/prefix SOURCE (rdap.org by default; also accepts iana-bootstrap).

doctor

geofeed-tools doctor QUERY [--format ...] [--all] [--longer] [--rdap-method rdap.org|iana-bootstrap] [-v]

Discover the published geofeed for an IP or prefix via RDAP, fetch it, and query it. The rich format renders the RDAP trace as a tree plus a "Geofeed discovery" panel (green ✓ when found, yellow ✗ when not). The plain format prints the same information as labeled lines.

--rdap-method rdap.org (default) uses the rdap.org proxy for fast lookups. --rdap-method iana-bootstrap reads IANA bootstrap data and queries the selected RIR endpoint directly.

info

geofeed-tools info SOURCE [--format ...] [--top-n N] [-v]

Comprehensive geofeed analysis. SOURCE may be a file, URL, or IP/prefix (RDAP auto-discovered). The command runs the feed through parsing, validation, and a virtual normalize pass and reports:

  • Overview — total prefixes, unique prefixes, duplicates, errors and warnings.
  • /24- and /48-equivalents — total address coverage measured as sum_addresses // 256 for IPv4 and sum_addresses // 2^80 for IPv6. Prefixes shorter than the divisor contribute whole multiples (a /23 = 2 /24s); fragments smaller than the divisor (a lone /25) round down to zero.
  • Geography summary — distinct counts of countries, regions, cities, and postal codes.
  • Per-country breakdown — prefix and slash counts split by IP version, sorted by total prefix count.
  • Prefix-length histograms — sorted ascending for IPv4 and IPv6.
  • Top regions and top cities — sized by --top-n (default 20).
  • If normalized — projected prefix counts, /24- and /48-equivalents, the number of invalid rows that would be dropped, and the number of rows merged by aggregation/dedupe.

The library info() method also exposes the plain and grep renderings directly via output="text" and output="grep", so consumers without rich installed can produce the same human/machine output as the CLI.

The grep format emits one key=value line per metric, including the normalize preview and ranked keys for top regions/cities:

prefixes_total=3
unique_prefixes=3
slash_24s=1
slash_48s=65536
unique_countries=1
country.US.prefixes_v4=2
normalized.prefixes_total=2
normalized.invalid_removed=0
normalized.aggregated=1
top_city.1.name="San Francisco"
top_city.1.count=2

Python API

The library is fully usable from Python without the CLI dependencies installed.

Python API quick start

Sync:

from geofeed_tools import GeoFeed

geofeed = GeoFeed("https://api.cloudflare.com/local-ip-ranges.csv")

records = geofeed.parse()                              # list[GeofeedRecord]
records_json = geofeed.parse(output="json")            # JSON string

report = geofeed.validate(check_aggregation=True)      # ValidationReport
canonical_csv = geofeed.normalize(output="csv")        # str

match = geofeed.query("192.0.2.1")                     # QueryResult
deep = geofeed.query("192.0.2.0/24", return_all=True, include_longer=True)

# Filter records by any combination of fields (all kwargs optional, AND'd)
canada = geofeed.filter(country="CA")
narrow = geofeed.filter(country="CA", region="CA-ON", prefix="192.0.2.0/24")
small_v4 = geofeed.filter(family="ipv4", prefix_length=24, include_longer=True)

# IP/prefix source: GeoFeed auto-discovers the published geofeed via RDAP
discovered = GeoFeed("1.1.1.1")                        # RDAP-discovers + loads
discovered.discovery.geofeed_url                       # where it landed
discovered.original_source                             # "1.1.1.1"
discovered.source                                      # resolved URL after RDAP
matches = discovered.query("1.1.1.1")                  # QueryResult — same code path as CLI: query 1.1.1.1

# RDAP discovery static helper (instance-less convenience wrapper for the full lookup metadata)
diagnosis = GeoFeed.doctor("31.133.128.1")             # DoctorResult (RDAP trace + matches)

summary = geofeed.info()                               # GeoFeedInfo (incl. normalize preview)
text = geofeed.info(output="text")                     # str — human-readable plain rendering
grep = geofeed.info(output="grep")                     # str — key=value lines

# Eager constructor alternative (symmetric with AsyncGeoFeed.from_source)
loaded = GeoFeed.from_source("geofeeds.csv")

Async:

from geofeed_tools import AsyncGeoFeed

geofeed = AsyncGeoFeed("https://api.cloudflare.com/local-ip-ranges.csv")

# Loading is lazy by default; the first awaited operation fetches the source.
records = await geofeed.parse()
report = await geofeed.validate(check_aggregation=True)
summary = await geofeed.info()

# RDAP discovery does not require an instance
diagnosis = await AsyncGeoFeed.doctor("31.133.128.1")

# Same as the CLI's ``query 1.1.1.1`` — discover then search
discovered = await AsyncGeoFeed.from_source("1.1.1.1")
matches = await discovered.query("1.1.1.1")

# Eager-load factory
preloaded = await AsyncGeoFeed.from_source("https://api.cloudflare.com/local-ip-ranges.csv")

GeoFeed class

GeoFeed(source: str, *, auto_load: bool = True, cache_query_index: bool = True, rdap_method: str = "rdap.org")
GeoFeed.from_source(source: str, *, cache_query_index: bool = True, rdap_method: str = "rdap.org") -> GeoFeed
Argument Default Meaning
source Local file path, HTTP(S) URL, or IP/prefix (auto-RDAP-discovered).
auto_load True If True, load the source immediately; otherwise lazily on first operation.
cache_query_index True Cache the parsed query index between query() calls for repeated lookups.
rdap_method "rdap.org" RDAP discovery method used when source is an IP/prefix. "iana-bootstrap" is also accepted.

When source is an IP or CIDR prefix, the first load triggers an RDAP discovery. The resolved geofeed URL is then loaded and used for every operation; subsequent reload() calls reuse the discovered URL without re-resolving. Raises GeoFeedDiscoveryError if no geofeed URL is published for the input.

After loading: source, raw, content_type, and text are populated. When discovery happened, original_source holds the input IP/prefix and discovery: DoctorLookup holds the full RDAP metadata. For file/URL sources, original_source == source and discovery is None.

Parsed records (and their networks) are also cached on the instance and shared across parse(), filter(), info(), etc.; the cache is invalidated by reload().

Methods (every method also accepts output="objects" (default), "json", and, where applicable, "csv" or "text"):

Method Return Notes
reload() None Re-fetch / re-read the source.
parse(*, include_validation, normalize) list[GeofeedRecord] | str Records, optionally annotated with valid/validation_messages.
validate(*, check_sort, check_content_type, check_aggregation) ValidationReport | str Structured validation report.
normalize(*, uppercase, sort, aggregate, dedupe, fix_host_bits) list[GeofeedRecord] | str Canonical normalized records.
query(query, *, return_all, include_longer) QueryResult | str Longest-prefix match (default) or all matches.
filter(*, prefix=None, country=None, region=None, city=None, postal_code=None, family=None, prefix_length=None, include_longer=False) list[GeofeedRecord] | str Records matching every supplied predicate (AND). See filter CLI section for semantics.
info(*, top_n=20) GeoFeedInfo | str Detailed breakdowns: counts, geography, per-country prefixes/slash counts, length histogram, top regions/cities, and a normalize preview. Also supports output="text" (human plain text) and output="grep" (key=value lines) in addition to "objects" / "json".

Behavior notes:

  • parse(): malformed CSV rows and rows with empty prefixes are skipped. Rows with invalid CIDRs are still returned and, with include_validation=True, marked invalid. With normalize=True, source line numbers are not preserved.
  • normalize(): aggregate=True implies dedupe within each metadata group. fix_host_bits=False skips rows like 192.0.2.5/24 instead of coercing them.
  • query(): for IP queries the default returns the most specific covering prefix. return_all=True returns every match ordered most-specific first; include_longer=True also includes more-specific prefixes contained by the queried CIDR.

AsyncGeoFeed class

AsyncGeoFeed(source: str, *, cache_query_index: bool = True, rdap_method: str = "rdap.org")
await AsyncGeoFeed.from_source(source: str, *, cache_query_index: bool = True, rdap_method: str = "rdap.org") -> AsyncGeoFeed

Mirrors GeoFeed but loads, parses, validates, normalizes, queries, and computes info asynchronously. CPU-bound work runs in a worker thread so the event loop stays responsive. URL fetches use httpx and require the geofeed-tools[async] extra; local file reads are offloaded via asyncio.to_thread. RDAP discovery for IP/prefix sources runs asynchronously via httpx as well. AsyncGeoFeed has no auto_load flag — use from_source for one-step construction + load.

Static doctor helper

GeoFeed.doctor(query, *, return_all=False, include_longer=False, rdap_method="rdap.org", output="objects") -> DoctorResult | str
await AsyncGeoFeed.doctor(...)

doctor() returns the full DoctorResult (RDAP trace + matches, filtered to the RIR-published address range). For a plain "find the geofeed for this IP and search it" use case, construct a GeoFeed/AsyncGeoFeed with the IP/prefix as the source and call query() on it directly — that's what the CLI's query 1.1.1.1 form does. RDAP discovery raises GeoFeedDiscoveryError when no geofeed URL is published.

rdap_method Behavior
"rdap.org" Default. Fast gateway lookups via the rdap.org proxy.
"iana-bootstrap" Reads IANA bootstrap data and queries the selected RIR service directly.

Discovery walks rdap-up parents and supports both direct rel=geofeed links and remarks/comments containing Geofeed: https://….

Data models

All public dataclasses are exported from geofeed_tools. Every one provides an as_dict() method.

GeofeedRecord

Field Type Meaning
prefix str Network prefix.
country str ISO 3166-1 alpha-2 code.
region str ISO 3166-2 subdivision code.
city str City field.
postal_code str Postal code field.
line int Source line number (0 for synthesized normalized records).
raw_line str | None Original source line when available.
valid bool True when no validation errors attached.
validation_messages tuple[str, ...] Record-level validation messages.

ValidationIssue

Field Type Meaning
severity str Usually "error" or "warning".
line int | None Source line, or None for file-level issues.
code str Stable machine-readable code (invalid-prefix, etc.).
message str Human-readable message.
raw_line str | None Original line text when available.

ValidationReport

Field Type Meaning
source str Original path or URL.
records int Number of records processed.
errors int Error count.
warnings int Warning count.
valid bool True when errors == 0.
issues tuple[ValidationIssue, ...] Full issue list.

QueryResult

Field Type Meaning
query str Original query.
matches tuple[GeofeedRecord, ...] Matching records, most-specific first.

DoctorLookup

RDAP discovery metadata returned inside DoctorResult.lookup.

Field Type Meaning
lookup_strategy str "ip-address" or "prefix-network-address".
rdap_method str "rdap.org" or "iana-bootstrap".
rdap_query str IP address used for the RDAP lookup.
bootstrap_url str First RDAP URL queried.
bootstrap_source_url str | None Bootstrap source (rdap.org or an IANA JSON file).
resolved_urls tuple[str,…] RDAP URLs visited, ordered most-specific to broader.
referring_handle str | None Handle of the RDAP object that published the geofeed.
referring_range str | None IP range of the referring RDAP object.
geofeed_url str | None Published geofeed URL or None if not found.
geofeed_discovered_via str | None How the reference was found (link / remarks / comments).
geofeed_reference_url str | None RDAP URL where the geofeed reference appears.

DoctorResult

Field Type Meaning
query str Original query string.
lookup DoctorLookup RDAP discovery metadata.
matches tuple[GeofeedRecord, ...] Matching geofeed rows.

GeoFeedInfo / CountryStatistics / NormalizationPreview

Returned by GeoFeed.info() and AsyncGeoFeed.info().

GeoFeedInfo:

Field Type Meaning
source str Original path or URL.
prefixes_v4 int IPv4 prefix count.
prefixes_v6 int IPv6 prefix count.
unique_prefixes int Distinct prefix string count.
duplicates int prefixes_total - unique_prefixes.
slash_24s int IPv4 address space in /24-equivalents (sum_addresses // 256).
slash_48s int IPv6 address space in /48-equivalents (sum_addresses // 2**80).
unique_countries int Distinct country count.
unique_regions int Distinct region count.
unique_cities int Distinct city count.
unique_postal_codes int Distinct postal-code count.
errors int Validation error count.
warnings int Validation warning count.
by_country tuple[CountryStatistics, ...] Per-country breakdown, sorted by descending total prefix count.
prefix_length_v4 tuple[tuple[int, int], ...] Sorted (prefixlen, count) histogram for IPv4.
prefix_length_v6 tuple[tuple[int, int], ...] Sorted (prefixlen, count) histogram for IPv6.
top_regions tuple[tuple[str, int], ...] Top-top_n (region, count) pairs by prefix count.
top_cities tuple[tuple[str, int], ...] Top-top_n (city, count) pairs by prefix count.
normalized NormalizationPreview | None Projected state after a default normalize(); None if the builder was called without text input.
metadata dict[str, object] Reserved for extensible metadata.

Properties: prefixes_total (= prefixes_v4 + prefixes_v6) and total_records (alias of prefixes_total).

CountryStatistics (one row in by_country):

Field Type Meaning
country str ISO 3166-1 alpha-2 code, uppercased.
prefixes_v4 int IPv4 prefix count for this country.
prefixes_v6 int IPv6 prefix count for this country.
slash_24s int IPv4 coverage in /24-equivalents.
slash_48s int IPv6 coverage in /48-equivalents.

Properties: prefixes_total.

NormalizationPreview (the normalized field of GeoFeedInfo):

Field Type Meaning
prefixes_total int Projected total prefix count after normalize().
prefixes_v4 int Projected IPv4 prefix count.
prefixes_v6 int Projected IPv6 prefix count.
slash_24s int Projected IPv4 /24-equivalents.
slash_48s int Projected IPv6 /48-equivalents.
invalid_removed int Rows dropped because their prefix could not be parsed (even with host-bit fixing).
aggregated int Rows folded into a supernet or removed as exact duplicates during aggregation/dedupe.

Error handling

Exception Raised when
ValueError Invalid output mode or unparseable query string.
geofeed_tools.GeoFeedDiscoveryError GeoFeed(ip) (or any CLI command with an IP/prefix source) finds no published geofeed URL.
geofeed_tools.loader.FetchError Remote HTTP(S) or RDAP fetch failure.
FileNotFoundError / OSError Local file read failure.
from geofeed_tools import GeoFeed
from geofeed_tools.loader import FetchError

try:
    geofeed = GeoFeed("https://example.com/geofeed.csv")
    report = geofeed.validate(check_content_type=True)
except FetchError as exc:
    print(f"fetch failed: {exc}")

GitHub Actions integration

The validate --hook command is designed as a CI quality gate. This repository publishes a reusable workflow at .github/workflows/geofeed-validation.yml and a caller example at examples/github-actions/geofeed-validation.yml.

Minimal caller workflow:

name: Validate geofeed

on:
  pull_request:
    paths: ["path/to/geofeed.csv"]
  push:
    branches: [main]
    paths: ["path/to/geofeed.csv"]
  workflow_dispatch:

permissions:
  contents: read

jobs:
  geofeed-validation:
    uses: python-modules/geofeed-tools/.github/workflows/geofeed-validation.yml@main
    with:
      geofeed_path: path/to/geofeed.csv
      strict: false   # set true to fail on warnings as well as errors

Testing

make test                # unit tests (no network)
make test-integration    # real HTTP fetches
make test-html           # writes reports/pytest-report.html

Equivalent direct invocations:

pytest -m "not integration"
pytest -m integration

pytest-html is wired up in pyproject.toml; running pytest always produces a self-contained reports/pytest-report.html.

Integration tests depend on HTTP access to well-known public geofeed files. Their contents may change at any time and produce test failures unrelated to code changes.

Configuration

All tuneable defaults and external endpoints live in src/geofeed_tools/config.py. Most users never need to touch them; the most relevant are:

Constant Default Purpose
FETCH_TIMEOUT 30 HTTP timeout in seconds.
USER_AGENT geofeed-tools/<version> User-Agent header.
DEFAULT_RDAP_METHOD "rdap.org" RDAP method used when none is specified.
MAX_RDAP_DEPTH 8 RDAP redirect hop cap.
LRU_COUNTRY_CACHE_SIZE 512 ISO 3166-1 lookup cache size.
LRU_SUBDIVISION_CACHE_SIZE 4096 ISO 3166-2 lookup cache size.
TRACE_LEVEL 5 Numeric level below DEBUG used by -vvv.

See the source file for the full list and inline docstrings.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

geofeed_tools-0.2.0.tar.gz (1.0 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

geofeed_tools-0.2.0-py3-none-any.whl (66.6 kB view details)

Uploaded Python 3

File details

Details for the file geofeed_tools-0.2.0.tar.gz.

File metadata

  • Download URL: geofeed_tools-0.2.0.tar.gz
  • Upload date:
  • Size: 1.0 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for geofeed_tools-0.2.0.tar.gz
Algorithm Hash digest
SHA256 29ab2d395c8202039203e0c3df6b3b0f894f70d9b905154c9547c45515800abf
MD5 adfff43e617faacd9b9c2bdf456d294c
BLAKE2b-256 72a48be7cf2e566989c31a1dcf3d3a8a46bd3b3e6015d549fd123970a6f711b8

See more details on using hashes here.

Provenance

The following attestation bundles were made for geofeed_tools-0.2.0.tar.gz:

Publisher: publish-to-pypi.yml on python-modules/geofeed-tools

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file geofeed_tools-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: geofeed_tools-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 66.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for geofeed_tools-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 70fbc9896e2c9ed440973e6088f4ab4cee22c4e12e1e672e9e16e0953af99c6e
MD5 05d6cc4169d88fe919479bd9783e6e80
BLAKE2b-256 89848364e60e303e9c3cb207cc954292a71d599e5b75838516d5583825037990

See more details on using hashes here.

Provenance

The following attestation bundles were made for geofeed_tools-0.2.0-py3-none-any.whl:

Publisher: publish-to-pypi.yml on python-modules/geofeed-tools

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page