Skip to main content

isomorphism

Reversible anonymisation of Swiss personal data for Python. It replaces AHV numbers, IBANs, UID numbers, phone numbers, emails, names, addresses, companies, dates of birth, card and account numbers with placeholders before a text goes to a language model, and puts the real values back into the answer.

  • Local only. No network calls, no telemetry, no dependencies, nothing downloaded at runtime.
  • Reversible. anonymize(text) returns the text with placeholders and a mapping, restore(text, mapping) undoes it, also for an answer that arrives in pieces.
  • Same value, same placeholder. The model can follow that [PERSON_1] appears three times.
  • Checksums. AHV (EAN-13), IBAN (mod 97), UID (mod 11), cards (Luhn) and PostFinance accounts (mod 10) are verified. Numbers that look right but fail the check are reported anyway, with lower confidence.
  • Audit-friendly. Every hit comes back as kind, position, confidence and recogniser, without the value.
  • German, French, Italian and English in one pass, including Swiss spellings.

Python 3.12 or newer. MIT license.

pip install isomorphism
from isomorphism import anonymize, restore

text = "Hr. Keller, Musterstrasse 12, 9000 St. Gallen, AHV 756.1234.5678.97, Tel. 071 123 45 67"
safe, mapping = anonymize(text)
# '[PERSON_1], [ADDRESS_1], AHV [AHV_1], Tel. [PHONE_1]'

answer = call_your_model(safe)  # the model only sees placeholders
print(restore(answer, mapping))  # real values are back

The mapping holds the real values. This package never logs or stores it; keeping it (in memory, per request) is up to you. repr(mapping) shows only the number of placeholders.

What it finds

Kind Placeholder Formats Check
AHV number [AHV_n] 756.1234.5678.97, with spaces or without separators prefix 756, EAN-13
IBAN (CH, LI) [IBAN_n] with or without spaces, upper or lower case mod 97
UID number [UID_n] CHE-123.456.788, CHE123456788; MWST/TVA/IVA/HR stay in the text mod 11
Phone (Switzerland) [PHONE_n] +41 71 123 45 67, 0041 …, +41 (0)71 …, 071 123 45 67, 071/123 45 67, (071) …, 0711234567 format
Email [EMAIL_n] format
Person [PERSON_n] Hr. Keller, Frau Dr. Müller, M. Jean Dupont, signora Bianchi, Anna Muster, Muster, Anna; the same surname or a first name alone later in the text titles, first-name list
Company [ORG_n] name before AG, GmbH, SA, Sàrl, Sagl, KlG, KG, Ltd, Inc, LLC … legal form
Address [ADDRESS_n] Musterstrasse 12, 9000 St. Gallen, Rue de Lausanne 12, 1003 Lausanne, Via Nassa 8, 6900 Lugano, 12 Baker Street, CH-9000 St. Gallen street words, postcode
Date of birth [DOB_n] a date after geb., Geburtsdatum, né le, nata il, date of birth … context word
Card number [CARD_n] 16 digits (4111 1111 1111 1111), Amex Luhn
Account [ACCOUNT_n] PostFinance 80-12345-6; digits after Konto, compte, conto, account mod 10 / context word

detect(text) returns the hits without changing the text.

  • Exceptions: keep=["info@gemeinde.example", re.compile(r".*@gemeinde\.example")] leaves exact values (case-insensitive) or values matching a pattern untouched.
  • Authorities: names such as "Steueramt St. Gallen" or "Handelsregisteramt Zürich" are not replaced (protect_authorities=True, the default).
  • Streaming: restore_stream(chunks, mapping) or Restorer(mapping) restore an answer that arrives in pieces, also when a placeholder is split between two pieces.
  • Presidio (optional): anonymize(text, detectors=[presidio_detector(analyzer, language="de")]) adds names in running text from Microsoft Presidio. Presidio is not a dependency and runs locally.

Measured on the test cases

tests/cases.py holds invented Swiss texts (payslip extract, client email, receipt, tax query, French and Italian letters, English mail, written-out variants, numbers with wrong check digits, and a text full of look-alikes that must not match). The numbers below come from python -m tests.measure. A test fails if the table is out of date, if a listed value slips through, or if the false alarms exceed what is listed here.

Kind Expected Found Missed False alarms
AHV 10 10 0 0
IBAN 10 10 0 0
UID 9 9 0 0
PHONE 15 15 0 0
EMAIL 6 6 0 0
PERSON 10 10 0 0
ORG 4 4 0 0
ADDRESS 9 9 0 2
DOB 6 6 0 0
CARD 6 6 0 0
ACCOUNT 3 3 0 0

Read it as follows:

  • "Missed" is zero for every kind: no value in these texts gets through.
  • The two address false alarms are 4500 Euro and 1200 Meter after a comma: a four-digit number followed by a capitalised word looks like a postcode and a place. They are reported with low confidence (0.55), so you can filter by confidence.
  • Names, companies and addresses are heuristics (titles, a list of about 440 first names, legal forms, street words). They find less than a language model would and can over-report. A person written two ways (Anna Muster, then Muster) gets two placeholders.
  • This is a small invented set, not a benchmark on real documents. Test with your own (invented) samples before you rely on it.

Limits

lang ("de", "fr", "it", "en") is accepted and checked but has no effect: all four languages are always active, because Swiss texts mix them. Foreign IBANs, the old 11-digit AHV format and service numbers such as 0800 … are not recognised. Names of other origins than the first-name list are found with a title or through Presidio.

No tool finds all personal data. Treat the result as one protective layer, not as a guarantee of anonymity.

Development

uv venv && uv pip install -e . pytest ruff mypy
ruff check . && ruff format --check . && mypy && pytest

Docs: https://packages.sweber.dev/isomorphism/docs

Metadata

Release files for isomorphism 0.2.0

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

Source distribution (sdist)

Source distribution for isomorphism 0.2.0
File Size Uploaded Provenance Actions
isomorphism-0.2.0.tar.gz 27.1 kB With provenance Details for isomorphism-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for isomorphism 0.2.0
File Interpreter ABI Platform Actions
isomorphism-0.2.0-py3-none-any.whl Python 3 none any Details for isomorphism-0.2.0-py3-none-any.whl

Total release size: 44.9 kB

Release files / isomorphism-0.2.0.tar.gz

Download URL isomorphism-0.2.0.tar.gz
Size 27.1 kB
Tags Source
SHA-256 checksum
How to use checksums
9d5799b445ca4fcf63b9581f428e3d06e1564915738b41f3228bdc5ac63ee388
BLAKE2b-256 checksum
How to use checksums
15e446a886567691c6bc11bbb4bf3c8feeb1eb922a2ef5f2ebd561fc299e1e2e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Release files / isomorphism-0.2.0-py3-none-any.whl

Download URL isomorphism-0.2.0-py3-none-any.whl
Size 17.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f517c15595aeb9345695348ddde2eac4fd61c230248d611e5c1f5b1e4c49756f
BLAKE2b-256 checksum
How to use checksums
5c475613e166cf9440b60c65d1e03aae4f5f9afba8c1ea524e79e4219428b774
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

Security for isomorphism 0.2.0

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for isomorphism-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 2, 2026.

Transparency log

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.2.0 This release

2 release files Full 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