A toolkit for validating and working with Sri Lankan data.
Project description
Helakit
A toolkit for validating and working with Sri Lankan data.
Helakit is a small, dependency-free Python library for validating and parsing Sri Lankan identifiers — NIC numbers, phone numbers, postal codes, and more. Each identifier lives in its own self-contained subpackage and shares a single result type, so adding a new validator is a matter of dropping in a folder.
For usage and API reference, see the docs. This page is a tour of how the project is laid out — useful if you want to contribute, audit, or fork.
Design principles
- Modular monolith. Every validation domain (
nic,phone,postal, …) is a self-contained subpackage. Adding a new domain is adding a new folder; no plugin system or registry to wire up. - Zero runtime dependencies. The library itself uses only the Python standard library. Dev and docs tools are kept in extras.
- Data as Python dicts. Lookup tables (provinces, districts,
mobile prefixes, NIC encoding rules) live as module-level
dictconstants in.pyfiles, not JSON / Parquet / SQLite. Lookups are O(1) and cost nothing after import. - One result shape, two entry points. Every validator exposes
both a rich
validate_X(value) -> ValidationResultand a booleanis_valid_X(value) -> bool.ValidationResultis truthy when valid, so the rich form drops intoifstatements naturally. src/layout. Tests run against the installed package, not the source tree, so packaging mistakes can't masquerade as passing tests.- Strict typing end to end. A
py.typedmarker ships with the wheel and CI runsmypy --strict. Type hints use modern syntax (X | Y,list[X],dict[K, V]).
Repository layout
src/helakit/
├── __init__.py # public API surface + __version__
├── py.typed # PEP 561 marker
├── _core/ # shared primitives, no domain logic
│ ├── result.py # ValidationResult + ValidationError dataclasses
│ ├── base.py # Validator Protocol
│ └── exceptions.py # HelakitError hierarchy
├── _data/ # cross-domain lookup tables (provinces, districts, …)
└── <domain>/ # one folder per identifier type
├── __init__.py # re-exports validate_X / is_valid_X
├── validator.py # the actual rules
├── exceptions.py # domain-specific exceptions
└── _data.py # domain-specific lookup tables (optional)
Domains currently in the tree: nic/, phone/, postal/. The
underscore-prefixed packages (_core/, _data/) are private —
nothing outside the package should import from them.
Around the source:
tests/ # mirror of src/helakit/, one folder per domain
docs/ # MkDocs site (Material theme, mike for versioning)
.github/workflows/ # ci.yml, docs.yml, release.yml
pyproject.toml # hatchling build, ruff, mypy, pytest, coverage config
How a domain is structured
Each domain is independent. The contract:
validate_X(value: str) -> ValidationResult— full validation, returns parsed fields inresult.dataand structured errors inresult.errors.is_valid_X(value: str) -> bool— boolean shorthand.- A domain-specific
XErrorexception class inheriting fromHelakitError, for unrecoverable misuse (not validation failures — those go throughValidationResult). - A
_data.pyfor any tables only that domain cares about.
The __init__.py re-exports the two functions and the exception, and
the top-level helakit/__init__.py re-exports them again so users can
write from helakit import validate_nic without thinking about layout.
Validators
| Validator | Function | Status |
|---|---|---|
| NIC | validate_nic |
In progress |
| Phone | validate_phone |
Planned |
| Postal | validate_postal |
Planned |
| Passport | (planned) | Planned |
| Vehicle | (planned) | Planned |
More (driving licence numbers, BR numbers, …) will follow. Stubs for
unimplemented validators raise NotImplementedError so call-sites
written against the planned API don't silently no-op.
Adding a new validator
- Create
src/helakit/<domain>/mirroring the layout above. - Add a
tests/test_<domain>/folder with at least one test for the happy path and one for each error class. - Add a
docs/validators/<domain>.mdpage. - Re-export the public functions from
src/helakit/__init__.py. - Add a
## [Unreleased]entry toCHANGELOG.md.
See CONTRIBUTING.md for the dev-environment setup and the PR checklist.
Data contributions
A lot of helakit's value lives in its lookup tables. Adding or
correcting entries (postal codes, mobile prefixes, district names) is
the easiest way to contribute and doesn't require deep Python — each
table is a plain dict in src/helakit/_data/ or
src/helakit/<domain>/_data.py. Cite a source in the PR description
so we can verify it.
Documentation
Docs are versioned with mike and published in three flavours:
/dev/— built from every push tomain. Tracks in-progress work./<MAJOR>.<MINOR>/— built from each release tag. Frozen./latest/— alias for the most recent release.
The bare site URL (Aswikinz.github.io/Helakit)
redirects to /latest/ once a release exists, and to /dev/ until then.
Links: docs · dev · changelog · contributing.
Install
pip install helakit
Requires Python 3.10+.
Status
Helakit is alpha software. The public API may change before 1.0; pin versions accordingly.
License
Apache License 2.0 — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file helakit-0.1.0.tar.gz.
File metadata
- Download URL: helakit-0.1.0.tar.gz
- Upload date:
- Size: 12.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
655048f716589d5d4e279e722a7d4d48df348d51d6604c0f9d80a36398dd6833
|
|
| MD5 |
34a49241748fb860f52120eacb6c8627
|
|
| BLAKE2b-256 |
bb9e7b7c8dca48c50cdfc041122f02f3360339d2239de8bc78560193bb3fd254
|
Provenance
The following attestation bundles were made for helakit-0.1.0.tar.gz:
Publisher:
release.yml on Aswikinz/Helakit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
helakit-0.1.0.tar.gz -
Subject digest:
655048f716589d5d4e279e722a7d4d48df348d51d6604c0f9d80a36398dd6833 - Sigstore transparency entry: 1402522884
- Sigstore integration time:
-
Permalink:
Aswikinz/Helakit@55aa3f0124dad7082f2c4f5b1ad635d59d4c7130 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Aswikinz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@55aa3f0124dad7082f2c4f5b1ad635d59d4c7130 -
Trigger Event:
push
-
Statement type:
File details
Details for the file helakit-0.1.0-py3-none-any.whl.
File metadata
- Download URL: helakit-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e2f624df22ec84ea270651a25a3205a2af94630cb82d5900cfe275ab9d61e094
|
|
| MD5 |
33b2b258c1a5cf97fe3a03e7fc6358ed
|
|
| BLAKE2b-256 |
ab2267b35c9ef14957577cfaf36f191d518bdff4bd534eea538777fe137b6e76
|
Provenance
The following attestation bundles were made for helakit-0.1.0-py3-none-any.whl:
Publisher:
release.yml on Aswikinz/Helakit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
helakit-0.1.0-py3-none-any.whl -
Subject digest:
e2f624df22ec84ea270651a25a3205a2af94630cb82d5900cfe275ab9d61e094 - Sigstore transparency entry: 1402522949
- Sigstore integration time:
-
Permalink:
Aswikinz/Helakit@55aa3f0124dad7082f2c4f5b1ad635d59d4c7130 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/Aswikinz
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@55aa3f0124dad7082f2c4f5b1ad635d59d4c7130 -
Trigger Event:
push
-
Statement type: