Python
217,266 lines across 3,999 files. The most distinctive style in the estate, and the only one of the five languages with a written rule set behind it.
1. The complete example — everything in eleven lines
This file is quoted verbatim and entire. Nine conventions are visible in it, and the whole style follows from them.
sg_compute/catalog/schemas/Schema__Caller__IP.pyverbatim and entire · 01__python.md# ═══════════════════════════════════════════════════════════════════════════════
# SG/Compute — Schema__Caller__IP
# Response schema for GET /catalog/caller-ip.
# ═══════════════════════════════════════════════════════════════════════════════
from osbot_utils.type_safe.Type_Safe import Type_Safe
from sg_compute.primitives.Safe_Str__IP__Address import Safe_Str__IP__Address
class Schema__Caller__IP(Type_Safe):
ip : Safe_Str__IP__Address = Safe_Str__IP__Address()Apache-2.0 — quoted from the estate's own source, not covered by this site's CC BY 4.0. Counted 2026-08-24.
- A
═══banner header — product name, class name, one line of purpose. - The filename is the class name.
Schema__Caller__IP.py→class Schema__Caller__IP. - One class per file.
- Fully-qualified imports from the per-class path — never a package re-export.
importkeywords aligned to a column.Type_Safeas the base class.- A constrained primitive (
Safe_Str__IP__Address) rather thanstr. - The annotation colon aligned, with an instance as the default.
- No docstring. The banner does that job.
2. Naming
Prefix families — what the class is
| Prefix | Files | Meaning |
|---|---|---|
Schema__ | 614 | Pure data. No methods (rule 4) |
Safe_Str__ | 290 | A regex-constrained string type |
Enum__ | 185 | A fixed value set. Never a Literal (rule 3) |
Cli__ | 82 | A Typer command group |
Routes__ | 59 | A FastAPI route class. No logic (rule 19) |
Safe_Int__ | 18 | A bounded integer type |
Section__ | 15 | A shell fragment generator — see Bash |
Fast_API__ | 12 | An app assembly |
Suffix families — what the class does
__Builder 97 ·
__Helper 86 ·
__Client 77 ·
__Service 46 ·
__Mapper 39 ·
__Detector 23 ·
__Loader 17 ·
__Registry 14 ·
__Writer 14 ·
__Parser 10 ·
__Runner 9 ·
__Manager 7 ·
__Factory 4 ·
__Watchdog 2 ·
__Poller 1
The double-underscore rule
__ is the word separator inside a compound name; _ separates
words within one term. Schema__Image__Build__Request reads as
Schema · Image · Build · Request. Safe_Str__IP__Address keeps
Safe_Str as one term.
3,871 of
3,999 filenames contain __.
Rule 20 handles the one hard case: the spec uses names like SGraph-AI with a
hyphen, which is not a legal Python identifier. Class and module names use
SGraph_AI; repo roots and test filenames may keep the hyphen.
Why __init__.py stays empty
Rule 22, and it holds at 299/302 = 99%. Callers import from the fully-qualified per-class path; nothing is ever re-exported, so there is exactly one import path to any class. The rule carries its own warning, learned the hard way:
Never commit an empty__init__.pyin a folder that shares a name with a sibling.pymodule: Python's import system prefers the package, and every import under the module breaks.
3. Type_Safe — runtime validation instead of static typing
Type_Safe comes from osbot-utils,
Apache-2.0, under the owasp-sbot organisation. The convention is the estate's; the
mechanism is the dependency's, and on a site about attribution discipline that distinction is
worth stating plainly.
Rule 1 is that all classes extend it — no plain Python classes. The tooling rule is blunter: never use Pydantic, no Literals. Of 1,034 classes in the new tree:
| Base | Count |
|---|---|
Type_Safe | 506 |
TestCase | 169 |
Safe_Str | 78 |
str, Enum | 69 |
Fast_API__Routes (a Type_Safe descendant) | 46 |
Type_Safe__List | 44 |
Schema__Step__Base (a Type_Safe descendant) | 25 |
Safe_Int / Safe_UInt / Enum | 13 / 6 / 8 |
Do not publish “48% extend Type_Safe”. It is true and it is misleading.
Excluding tests and enums, essentially every class is in the Type_Safe lineage —
the rule holds, and the naive percentage does not show it. A style guide that reports the
flattering-looking number is doing the same thing in reverse.
What it buys: attributes are validated at construction, so a value that exists is a
value that is valid. There is no separate validation layer, no schema-parse step at the
boundary, and no isinstance checking scattered through the code. It is also why the
absence of a type-checker matters less here than it would elsewhere — though not as little as it
first appears. Q5: does runtime type safety replace
static analysis, or defer it? →
4. Constrained primitives — the type is the validation
Rule 2 is zero raw primitives — no str, int, float,
list or dict as attributes. One directory alone holds
27 of them, and the
pattern is uniform:
sg_compute/primitives/Safe_Str__IP__Address.pyverbatim and entire · 01__python.md# ═══════════════════════════════════════════════════════════════════════════════
# SG/Compute — Safe_Str__IP__Address
# IPv4 address string, e.g. "1.2.3.4". Empty = not yet assigned.
# ═══════════════════════════════════════════════════════════════════════════════
import re
from osbot_utils.type_safe.primitives.core.Safe_Str import Safe_Str
from osbot_utils.type_safe.primitives.core.enums.Enum__Safe_Str__Regex_Mode import Enum__Safe_Str__Regex_Mode
class Safe_Str__IP__Address(Safe_Str):
max_length = 45 # covers IPv4 + IPv6
regex = re.compile(r'^[0-9a-fA-F.:]*$')
regex_mode = Enum__Safe_Str__Regex_Mode.MATCH
strict_validation = True
allow_empty = TrueApache-2.0 — quoted from the estate's own source, not covered by this site's CC BY 4.0. Counted 2026-08-24.
Five class attributes, all aligned, and a trailing comment carrying the reasoning
(# covers IPv4 + IPv6) — which is this estate's substitute for a docstring.
The domain vocabulary is visible in the file list itself:
Safe_Str__AWS__Region, Safe_Str__Docker__Image,
Safe_Str__Instance__Type, Safe_Str__Node__Name,
Safe_Str__Pod__Name, Safe_Str__SSM__Path,
Safe_Str__Spec__Id, Safe_Int__Port,
Safe_Int__Max__Hours, Safe_Int__Exit__Code.
Naming a type is how a domain concept gets recorded.
A value of type Safe_Str__SSM__Path is a valid SSM path everywhere it appears,
forever, without a single check written at a call site. And the name tells a reader — or a
generator — what the value is, without a comment, a docstring or a lookup.
5. Layout and formatting
Banners. # ═ × 79, three content lines (product — class name — purpose),
# ═ × 79. Present on
3,120 of
3,999 files across the repo, and on
992 of
992 class-defining
files in the new tree — 100%.
Alignment. Schema attribute colons are
100%
aligned. Import keywords are
39%
— 321 of
817 files with two or
more from X import Y lines have every import at a single column. That is the
estate's least consistent formatting rule and the easiest to automate.
Why alignment at all →
Comments. Rule 8 is inline comments only — no docstrings, ever, and compliance is 989/992 = 99.7%. Trailing comments carry the reasoning; the banner carries the purpose.
Private methods. Rule 9 is no underscore prefix for private methods, and
compliance is 895/992 = 91% (97 violations).
The JavaScript uses _private universally, against the same rule. Either the rule is
Python-only and widely ignored, or it is being ignored in two languages, and the rule set does
not say which. Q2 →
6. Testing
Four rules, quoted in full on the rules page. The first is the strongest opinion in the whole set:
No mocks. No patches.
The alternative is real in-memory composition, which is only affordable because
Type_Safe objects are cheap to build. The type system and the testing philosophy
are the same decision. 169
classes extend TestCase, so tests are class-based, and 4,785 tests run in 81
seconds — which is the evidence that the no-mocks position is affordable rather than
aspirational.
Whether it generalises outside an estate with a cheap in-memory composition path is a genuinely open question, and this site does not assume it does. Q6 →
7. Responsibility boundaries — rules that name a single owner
Rules 16 to 19 are the most transferable thing in the rule set. Each names exactly one owner for a capability:
Step__Executoris the ONLY class that callspage.*Playwright methods — with aBrowser__Launchercarve-out for process lifecycle.Artefact__Writeris the ONLY class that writes to sinks.Request__Validatorcontains ALL cross-schema validation.- Routes have no logic — pure delegation to
Playwright__Service.
Rule 16 is described as being enforced by a CI guard that fails the build if a raw
browser.new_context( appears outside Page__Factory. That is the
model: a boundary rule with a test behind it. The other three have no such test — and the
guard behind rule 16 is not listed in the rule set's own table of CI guards, which is a
discrepancy this site can flag but not resolve.
What is claimed versus what is listed →
8. The dependencies
The osbot-* family, all Apache-2.0, all under the
owasp-sbot GitHub organisation:
osbot-utils (the source of Type_Safe and Safe_Str,
885 mentions across the corpus), osbot-aws, osbot-fast-api,
osbot-fast-api-serverless, memory_fs, mgraph-db,
mgraph-ai-service-cache.
Two hard rules govern their use — never use Pydantic, no Literals, and never use
boto3 directly, with a narrow documented exception for a Lambda Function URL
two-statement permission fix.
Note that the exception is documented rather than silent. That is a convention in itself and worth naming: a banned thing with one written carve-out beats a banned thing with quiet violations, because the first is a rule you can enforce and the second is a rule you can only argue about. Rule 21's registry carve-out is the same shape.