Skip to main content

self-healing-whois

This is my project for trying AI-assisted repair in a Python library. It is a fork of python-whois, which looks up domain registration information.

The original library already does the WHOIS lookup and most of the parsing. My addition handles one particular problem: what happens when the response has an expiration date, but the parser does not recognize its label?

For example, a parser might understand Expiry Date: but miss Domain valid until:. This project sends the failed response to an AI provider, asks for a repair, checks it against old examples, and uses it if the checks pass.

This is still an experimental project. I have tested normal domain lookups and a deliberately changed label with a real AI provider. That does not mean it can fix every registry format.

What I added

  • A background worker that asks an AI provider for an expiration-date regex repair.
  • Checks against historical WHOIS examples before accepting a repair.
  • An API for passing the key, model name, and endpoint directly.
  • An in-memory cache so accepted repairs can be reused in the same process.
  • An offline demo, a real AI verification script, and tests.

I did not write the original WHOIS client or all the domain parsers. Those come from python-whois, and the original license is kept in this repository.

How it works

Look up a domain
    |
Try the existing parser
    |
    +-- Expiration found --> return the result
    |
    +-- Expiration missing --> ask AI for a repair
                                  |
                            check old examples
                                  |
                            accept or reject

With healing enabled, a normal successful parse does not call AI. If the expiration date is missing, the default behavior is to wait for a checked repair. If that fails, the library raises WhoisHealingError instead of pretending it found a date.

The repair runs in a background thread, but waiting for it still makes that lookup slower. You can use wait_for_repair=False to get a partial result immediately. In that mode, keep the process running and do another lookup after the repair finishes.

Installation

You need Python 3.12 or newer.

Version 0.1.1 has been installed and tested from TestPyPI in a separate Codespaces environment:

python -m pip install python-dateutil
python -m pip install --index-url https://test.pypi.org/simple/ --no-deps self-healing-whois==0.1.1

To work on the code, clone or download this repository, open a terminal in its folder, and run:

python -m venv .venv

Activate it on Windows PowerShell:

.\.venv\Scripts\Activate.ps1

Or on Linux/macOS:

source .venv/bin/activate

Then install the project and development tools:

python -m pip install -e ".[dev]"

The package name is self-healing-whois, but the Python import is self_healing_whois. This keeps it separate from the original library's whois import.

Basic lookup

You do not need an AI key for a normal lookup:

import self_healing_whois

result = self_healing_whois.whois("thispersondoesnotexist.com")
print(result)
print(result.expiration_date)

WHOIS lookups need internet access. Some servers or networks may block or limit requests.

Using AI repair

Pass all three settings yourself. The library does not choose a default provider.

from getpass import getpass
import self_healing_whois

client = self_healing_whois.enable_healing(
    api_key=getpass("API key: "),
    model=input("Model ID: ").strip(),
    endpoint=input("Full chat-completions endpoint: ").strip(),
)

try:
    result = self_healing_whois.whois("example.com")
    print(result)
except self_healing_whois.WhoisHealingError as error:
    print("Could not repair the expiration date:", error)
finally:
    self_healing_whois.disable_healing()

You can also pass strings or values from your application's environment variables. The prompts above are just one way to provide them. Do not put real keys in code that you upload to GitHub.

The endpoint must support the chat-completions request format used by this project. The library does not automatically work with every provider's API format. Network and WHOIS errors can still happen separately from repair errors.

Call enable_healing() once when your application starts and disable_healing() when it finishes. Configuration is shared within that Python process. You do not need a separate worker terminal.

Printing the result does not show the demo's before/after messages. Only expiration dates are repaired; other fields can still be empty. You can inspect the original response using result.text.

Optional settings

Setting Default What it does
wait_for_repair True Wait for repair when the expiration date is missing
repair_timeout 150 seconds How long the caller waits for repair
timeout 120 seconds AI request socket timeout, up to 120 seconds
queue_size 256 Maximum number of waiting samples
max_scopes 128 Maximum parser/domain-suffix groups with cached repairs
corpus_path Included JSON file Optional replacement set of historical examples

The WHOIS request has its own timeout, which you pass to whois(). The low-level WhoisEntry.load() method does not wait for background repair. For that use case, call client.finish_lookup(entry) explicitly.

Trying the demos

Run these commands from the repository folder with the virtual environment activated.

Offline demo

python examples/demo_healing.py

This uses a fake AI provider, so it needs no API key. It shows a missing date becoming a parsed date:

Before: None
After:  2030-01-02 00:00:00+00:00

Real AI test

Copy .env.example to .env if you do not already have one. Fill in your settings:

WHOIS_LLM_ENDPOINT=https://YOUR_PROVIDER/chat/completions
WHOIS_LLM_MODEL=model_name
WHOIS_LLM_API_KEY=YOUR_API_KEY

Then run:

python scripts/verify_ai_repair.py

This script reads .env from the project folder. Existing environment variables take priority. The library itself does not require a .env file.

The script changes a known expiration label, makes one real AI request, and checks that:

  • The expected date is restored.
  • The repair also works for a different date.
  • The original label still works.

A successful run ends with:

Repair status: accepted
After repair: 2031-04-05 00:00:00+00:00
PASS: known date restored, unseen date parsed, original parsing preserved.

This is a controlled test, not proof that a live registry changed its format. Provider usage limits and charges still apply. A normal website lookup might not call AI at all because the existing parser already works.

Where the repairs are stored

Everything learned at runtime stays in memory. There is no SQLite database or runtime storage file.

When you stop the process or disable healing, the learned repairs are cleared. Different processes do not share repairs. The included healing_corpus.json contains historical examples for checking candidates; live lookups do not update it.

For debugging, client.job_status(result) reports the job status, attempt count, and error type. A result that did not need repair has no job.

Tests

python -m pytest -q

The default tests run offline. They cover parsing, repair validation, waiting, rejected repairs, malformed provider responses, and cleanup. You do not need a real API key to run them.

The latest local run passed 57 tests. The repository also keeps upstream tests that need network access; those are not part of the default run. The GitHub Actions workflow is set up to run the offline tests, demo, and build on Python 3.12 and 3.13.

To build the package:

python -m build

Files in this project

This is a fork, so some files belong to the original library. Here is what the main files do and what should go on GitHub.

Path Purpose Commit?
README.md Setup, usage, limitations, and this guide Yes
LICENSE.txt Original MIT license and attribution Yes; preserve it
setup.py Package metadata, dependencies, Python requirement, dev extras Yes
pyproject.toml Build backend and default offline pytest configuration Yes
MANIFEST.in Data, docs, examples, and tests included in source packages Yes
requirements.txt Upstream pinned dateutil dependency Yes
.gitignore Excludes credentials, databases, caches, and environments Yes
.env.example Provider-neutral template without credentials Yes
.github/workflows/python-package.yml Automated tests and build Yes
.vscode/settings.json, .vscode/tasks.json Interpreter, tests, and task shortcuts Optional
self_healing_whois/__init__.py Public lookup API and healing exports Yes
self_healing_whois/whois.py Upstream WHOIS network client Yes
self_healing_whois/parser.py TLD parsers and failure-observation hook Yes
self_healing_whois/exceptions.py Lookup errors and WhoisHealingError Yes
self_healing_whois/time_zones.py Date/time-zone parsing data Yes
self_healing_whois/data/public_suffix_list.dat Domain suffix data Yes
self_healing_whois/healing.py In-memory queue, bounded rule/history cache, worker, waiting, lifecycle Yes
self_healing_whois/healing_worker.py Provider transport and pure regression validation Yes
self_healing_whois/healing_config.py Small .env loader for the live verification tool Yes
self_healing_whois/healing_corpus.json Historical WHOIS examples used to check repairs Yes
examples/demo_healing.py Offline demonstration with a fake model Yes
scripts/verify_ai_repair.py Real-provider verification with known expected dates Yes
scripts/build_healing_corpus.py Rebuilds corpus from upstream fixtures Yes
docs/SELF_HEALING.md Architecture, validation, operations, troubleshooting Yes
docs/PUBLISHING.md Release checks and publishing instructions Yes
docs/UPSTREAM_README.md Preserved original upstream README Yes
test/test_parser.py Upstream parser and date tests Yes
test/test_healing.py Validation, memory bounds, deduplication, and shutdown tests Yes
test/test_library_healing.py Direct-key API and transparent repair tests Yes
test/test_healing_config.py .env loading and precedence test Yes
test/test_verify_ai_repair.py Tests for the verification tool and provider responses Yes
test/test_main.py, test/test_query.py Upstream extraction/live tests; some require network Yes
test/test_ipv6.py, test/test_nicclient.py Upstream network-client behavior tests Yes
test/__init__.py, test/samples/ Test package and raw/expected fixtures Yes
.env Your real API credentials No
.venv/ Installed Python environment No
__pycache__/, .pytest_cache/, *.egg-info/, build/, dist/ Generated files No
.git/ Local repository metadata managed by Git Never upload manually

Keep setup.py, pyproject.toml, and MANIFEST.in. They are part of how the package is built and installed with its data files. requirements.txt keeps the upstream pinned dependency; normal package installation uses the dependencies in setup.py.

Things it cannot do yet

  • It only repairs expiration-date extraction, not all WHOIS fields.
  • It accepts a limited set of English expiration labels and regex shapes. It does not run arbitrary AI-generated Python or regex.
  • If the response has no expiration date, AI should not invent one.
  • Repairs need historical examples for the relevant parser and domain suffix. Missing coverage or conflicting dates cause rejection.
  • Passing the checks does not guarantee a repair will work on every future response.
  • Large responses over 32 KiB are skipped. Queues and caches also have size limits.
  • A retained failed job gets one AI attempt. There is no automatic retry loop. Restarting healing clears that state.
  • An AI request already in progress cannot be cancelled immediately during shutdown, but it cannot publish a repair after shutdown.

The failed WHOIS response is sent to the provider you configure. It can contain contact details. This project does not save it to disk, but the provider has its own data policies.

Publishing and GitHub

See docs/PUBLISHING.md for the release steps. TestPyPI installation and the AI repair test have passed for 0.1.1; a main PyPI release is a separate upload.

Before pushing, check that .env, .venv, caches, and build output are not included. .env.example is safe to commit because it only contains placeholders. Ignoring a file does not remove it from earlier commits if it was already tracked.

Credits

This project is based on Richard Penman's python-whois, starting from commit f686713155810ba125d59a30e962a38933f12dfe.

The original README is kept in docs/UPSTREAM_README.md, and the original MIT license and attribution are in LICENSE.txt.

Metadata

Release files for self-healing-whois 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for self-healing-whois 0.1.1
File Size Uploaded Provenance Actions
self_healing_whois-0.1.1.tar.gz 252.6 kB Without provenance Details for self_healing_whois-0.1.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for self-healing-whois 0.1.1
File Interpreter ABI Platform Actions
self_healing_whois-0.1.1-py3-none-any.whl Python 3 none any Details for self_healing_whois-0.1.1-py3-none-any.whl

Total release size: 425.9 kB

Release files / self_healing_whois-0.1.1.tar.gz

Download URL self_healing_whois-0.1.1.tar.gz
Size 252.6 kB
Tags Source
SHA-256 checksum
How to use checksums
5353bff1e7fe027c5181399099cebf3f7b899ad9a81b2d0dfd70d2d35df316aa
BLAKE2b-256 checksum
How to use checksums
742e4d082f940690d7b289895e5d78a8466605ac8f0145f7cbddf2f74a3bbc1f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / self_healing_whois-0.1.1-py3-none-any.whl

Download URL self_healing_whois-0.1.1-py3-none-any.whl
Size 173.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8417378e8d5e52db46a5aaa8a8aef36524bf4872e8fac8d2a1154e73740cf04a
BLAKE2b-256 checksum
How to use checksums
c27faa5640637ff08d9572ef8926362cfce045a5b7cba9c53880979144921ff8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Security for self-healing-whois 0.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page