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.
- geofeed-tools
# 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]' --helpOr via Docker (no Python needed on the host):
docker run --rm pythonmodules/geofeed-tools:latest doctor 31.133.128.1Published images:
ghcr.io/python-modules/geofeed-toolspythonmodules/geofeed-tools
Tags: python3, python3.11, python3.12, python3.13, and latest (tracks python3).
# 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 --strictPer-command help is always available:
geofeed-tools --help
geofeed-tools doctor --helpEvery 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.
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 injsonmode (the emptymatchesarray 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.
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.
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.
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. |
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 grepgeofeed-tools query SOURCE [QUERY] [--format ...] [--all] [--longer]
[--rdap-method rdap.org|iana-bootstrap] [-v]Look up an IP or CIDR in a geofeed.
SOURCEis the geofeed source (file path, URL, or IP/prefix to auto-discover via RDAP).QUERYis the IP or CIDR to look up. It's optional whenSOURCEis itself an IP/prefix —geofeed-tools query 1.1.1.1discovers the geofeed for1.1.1.1and searches it for the same address. This replaces the previouslookupsubcommand.--allreturns every match instead of only the most specific one.--longerincludes more-specific prefixes contained by a queried prefix.--rdap-methodcontrols which RDAP method is used when discovering a geofeed from an IP/prefixSOURCE(rdap.orgby default; also acceptsiana-bootstrap).
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.
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 // 256for IPv4 andsum_addresses // 2^80for 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
The library is fully usable from Python without the CLI dependencies installed.
Sync:
fromgeofeed_toolsimportGeoFeedgeofeed=GeoFeed("https://api.cloudflare.com/local-ip-ranges.csv")
records=geofeed.parse() # list[GeofeedRecord]records_json=geofeed.parse(output="json") # JSON stringreport=geofeed.validate(check_aggregation=True) # ValidationReportcanonical_csv=geofeed.normalize(output="csv") # strmatch=geofeed.query("192.0.2.1") # QueryResultdeep=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 RDAPdiscovered=GeoFeed("1.1.1.1") # RDAP-discovers + loadsdiscovered.discovery.geofeed_url# where it landeddiscovered.original_source# "1.1.1.1"discovered.source# resolved URL after RDAPmatches=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 renderinggrep=geofeed.info(output="grep") # str — key=value lines# Eager constructor alternative (symmetric with AsyncGeoFeed.from_source)loaded=GeoFeed.from_source("geofeeds.csv")Async:
fromgeofeed_toolsimportAsyncGeoFeedgeofeed=AsyncGeoFeed("https://api.cloudflare.com/local-ip-ranges.csv")
# Loading is lazy by default; the first awaited operation fetches the source.records=awaitgeofeed.parse()
report=awaitgeofeed.validate(check_aggregation=True)
summary=awaitgeofeed.info()
# RDAP discovery does not require an instancediagnosis=awaitAsyncGeoFeed.doctor("31.133.128.1")
# Same as the CLI's ``query 1.1.1.1`` — discover then searchdiscovered=awaitAsyncGeoFeed.from_source("1.1.1.1")
matches=awaitdiscovered.query("1.1.1.1")
# Eager-load factorypreloaded=awaitAsyncGeoFeed.from_source("https://api.cloudflare.com/local-ip-ranges.csv")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, withinclude_validation=True, marked invalid. Withnormalize=True, source line numbers are not preserved.normalize():aggregate=Trueimplies dedupe within each metadata group.fix_host_bits=Falseskips rows like192.0.2.5/24instead of coercing them.query(): for IP queries the default returns the most specific covering prefix.return_all=Truereturns every match ordered most-specific first;include_longer=Truealso includes more-specific prefixes contained by the queried CIDR.
AsyncGeoFeed(source: str, *, cache_query_index: bool=True, rdap_method: str="rdap.org")
awaitAsyncGeoFeed.from_source(source: str, *, cache_query_index: bool=True, rdap_method: str="rdap.org") ->AsyncGeoFeedMirrors 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.
GeoFeed.doctor(query, *, return_all=False, include_longer=False, rdap_method="rdap.org", output="objects") ->DoctorResult|strawaitAsyncGeoFeed.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://….
All public dataclasses are exported from geofeed_tools. Every one provides an as_dict() method.
| 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. |
| 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. |
| 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. |
| Field | Type | Meaning |
|---|---|---|
query | str | Original query. |
matches | tuple[GeofeedRecord, ...] | Matching records, most-specific first. |
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. |
| Field | Type | Meaning |
|---|---|---|
query | str | Original query string. |
lookup | DoctorLookup | RDAP discovery metadata. |
matches | tuple[GeofeedRecord, ...] | Matching geofeed rows. |
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. |
| 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. |
fromgeofeed_toolsimportGeoFeedfromgeofeed_tools.loaderimportFetchErrortry:
geofeed=GeoFeed("https://example.com/geofeed.csv")
report=geofeed.validate(check_content_type=True)
exceptFetchErrorasexc:
print(f"fetch failed: {exc}")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 geofeedon:
pull_request:
paths: ["path/to/geofeed.csv"]push:
branches: [main]paths: ["path/to/geofeed.csv"]workflow_dispatch:
permissions:
contents: readjobs:
geofeed-validation:
uses: python-modules/geofeed-tools/.github/workflows/geofeed-validation.yml@mainwith:
geofeed_path: path/to/geofeed.csvstrict: false # set true to fail on warnings as well as errorsmake test# unit tests (no network)
make test-integration # real HTTP fetches
make test-html # writes reports/pytest-report.htmlEquivalent direct invocations:
pytest -m "not integration"
pytest -m integrationpytest-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.
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.