Skip to content

Commit 1f62666

Browse files
committed
ogar-render-askama: render_python — Python import-shape emit PoC (SDK + package)
The Python counterpart of render_osm: same ruff → OGAR substrate, a language-pluggable emit back-end. Proves the pull-back side of the transpiler is not Rust-specific — OSM (and odoo) come out of the one substrate in Python import shape, just like Rust. Emits under python/: - osm/models.py — one @DataClass per THINK class; associations → typed id fields; each grounded model has CLASS_ID. - osm/controllers/<name>.py — the DO arm as a FAITHFUL mirror of app/controllers/, one module per source controller by its verbatim (snake) name — `osm.controllers.nodes.show(inp)`, standalone, not methods. No singularisation (mirrors the Rust `controllers` module). - osm/__init__.py — re-exports each controller at the package root (`osm.nodes` ≡ `osm.controllers.nodes`) + CLASS_IDS. - ogar_sdk.py — the substrate-pull SDK (Python mirror of Rust lance_graph_contract::ogar_codebook): CODEBOOK + class_id(concept) + render_classid(concept, prefix) (canon-high). Ships OSM (0x0F) AND odoo/commerce (0x02) — the pull is domain-agnostic. Verified: example builds clean; py_compile green on package + SDK; functional smoke — osm.controllers.nodes.show + re-exported osm.nodes.show both callable, class_id('osm_node')=0xf01, render_classid('account_move',0x0002)=0x2020002, osm.nodes.show({}) raises NotImplementedError('port Api::NodesController#show'). Stacks on #153 (the faithful-controllers / no-singulariser change) so the container module names are verbatim (nodes/searches/capabilities, not searche/capabilitie). Typed params (dict Input → typed) remain the ruff brick. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYvNjD8M8LMNYbRy3gq2FP
1 parent 5997b04 commit 1f62666

98 files changed

Lines changed: 3114 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
__pycache__/
2+
*.pyc
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""ogar_sdk — thin Python client over the OGAR codebook substrate.
2+
3+
The Python mirror of Rust `lance_graph_contract::ogar_codebook`: pull a concept's
4+
stable classid, or compose a render-classid with an app prefix. Domain-agnostic —
5+
OSM (0x0F) and odoo/commerce (0x02) pull identically.
6+
7+
>>> from ogar_sdk import class_id, render_classid
8+
>>> class_id("osm_node")
9+
3841
10+
>>> hex(render_classid("account_move", 0x0002)) # odoo, canon-high
11+
'0x2020002'
12+
"""
13+
from typing import Optional
14+
15+
# The pulled substrate — a subset of ogar-vocab's CODEBOOK (concept -> u16 id).
16+
CODEBOOK = {
17+
# 0x0F — Geo (OpenStreetMap)
18+
"osm_node": 0x0F01, "osm_way": 0x0F02, "osm_relation": 0x0F03,
19+
"osm_changeset": 0x0F04, "osm_element_tag": 0x0F05, "osm_relation_member": 0x0F06,
20+
"osm_way_node": 0x0F07, "osm_note": 0x0F08, "osm_gpx_trace": 0x0F09, "osm_user": 0x0F0A,
21+
# 0x02 — Commerce (odoo / ERP) — same pull, different domain
22+
"commercial_document": 0x0202, "product": 0x0207, "accounting_account": 0x0208,
23+
}
24+
# Convenience alias used in the odoo docstring example.
25+
CODEBOOK["account_move"] = CODEBOOK["commercial_document"]
26+
27+
28+
def class_id(concept: str) -> Optional[int]:
29+
"""Resolve a canonical-concept string to its stable u16 codebook id."""
30+
return CODEBOOK.get(concept)
31+
32+
33+
def render_classid(concept: str, app_prefix: int) -> Optional[int]:
34+
"""Compose a 32-bit render classid: canon (concept) HIGH, custom (prefix) LOW.
35+
36+
Mirrors the post-2026-07-02 canon-high flip: `(concept << 16) | prefix`.
37+
"""
38+
cid = class_id(concept)
39+
if cid is None:
40+
return None
41+
return (cid << 16) | (app_prefix & 0xFFFF)
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
"""@generated OSM package (ruff → OGAR, Python import shape).
2+
Models: `from osm.models import Node`.
3+
DO arm (faithful): `osm.controllers.nodes.show(inp)`.
4+
DO arm (re-exported): `osm.nodes.show(inp)`.
5+
"""
6+
from . import models as models
7+
from . import controllers as controllers
8+
from .controllers import accounts as accounts
9+
from .controllers import active_lists as active_lists
10+
from .controllers import advanced_preferences as advanced_preferences
11+
from .controllers import api as api
12+
from .controllers import application as application
13+
from .controllers import basic_preferences as basic_preferences
14+
from .controllers import capabilities as capabilities
15+
from .controllers import changeset_comments as changeset_comments
16+
from .controllers import changeset_subscriptions as changeset_subscriptions
17+
from .controllers import changesets as changesets
18+
from .controllers import closes as closes
19+
from .controllers import companies as companies
20+
from .controllers import confirmations as confirmations
21+
from .controllers import dashboards as dashboards
22+
from .controllers import data as data
23+
from .controllers import deletions as deletions
24+
from .controllers import descriptions as descriptions
25+
from .controllers import diary_comments as diary_comments
26+
from .controllers import diary_entries as diary_entries
27+
from .controllers import directions as directions
28+
from .controllers import downloads as downloads
29+
from .controllers import errors as errors
30+
from .controllers import export as export
31+
from .controllers import feature_queries as feature_queries
32+
from .controllers import feeds as feeds
33+
from .controllers import follows as follows
34+
from .controllers import heatmaps as heatmaps
35+
from .controllers import homes as homes
36+
from .controllers import icons as icons
37+
from .controllers import images as images
38+
from .controllers import inboxes as inboxes
39+
from .controllers import issue_comments as issue_comments
40+
from .controllers import issued_blocks as issued_blocks
41+
from .controllers import issues as issues
42+
from .controllers import languages_panes as languages_panes
43+
from .controllers import latlon_queries as latlon_queries
44+
from .controllers import layers_panes as layers_panes
45+
from .controllers import legend_panes as legend_panes
46+
from .controllers import links as links
47+
from .controllers import lists as lists
48+
from .controllers import locations as locations
49+
from .controllers import mailboxes as mailboxes
50+
from .controllers import maps as maps
51+
from .controllers import messages as messages
52+
from .controllers import muted_inboxes as muted_inboxes
53+
from .controllers import mutes as mutes
54+
from .controllers import nodes as nodes
55+
from .controllers import nominatim_queries as nominatim_queries
56+
from .controllers import nominatim_reverse_queries as nominatim_reverse_queries
57+
from .controllers import note_subscriptions as note_subscriptions
58+
from .controllers import notes as notes
59+
from .controllers import notification_preferences as notification_preferences
60+
from .controllers import oauth2_applications as oauth2_applications
61+
from .controllers import old_elements as old_elements
62+
from .controllers import old_nodes as old_nodes
63+
from .controllers import old_relation_members as old_relation_members
64+
from .controllers import old_relations as old_relations
65+
from .controllers import old_ways as old_ways
66+
from .controllers import outboxes as outboxes
67+
from .controllers import passwords as passwords
68+
from .controllers import pd_declarations as pd_declarations
69+
from .controllers import permissions as permissions
70+
from .controllers import pictures as pictures
71+
from .controllers import preferences as preferences
72+
from .controllers import profile_sections as profile_sections
73+
from .controllers import queries as queries
74+
from .controllers import read_marks as read_marks
75+
from .controllers import received_blocks as received_blocks
76+
from .controllers import redactions as redactions
77+
from .controllers import relation_members as relation_members
78+
from .controllers import relations as relations
79+
from .controllers import replies as replies
80+
from .controllers import reporters as reporters
81+
from .controllers import reports as reports
82+
from .controllers import searches as searches
83+
from .controllers import sessions as sessions
84+
from .controllers import share_panes as share_panes
85+
from .controllers import site as site
86+
from .controllers import statuses as statuses
87+
from .controllers import terms as terms
88+
from .controllers import tracepoints as tracepoints
89+
from .controllers import traces as traces
90+
from .controllers import uploads as uploads
91+
from .controllers import user_blocks as user_blocks
92+
from .controllers import user_mutes as user_mutes
93+
from .controllers import user_preferences as user_preferences
94+
from .controllers import user_roles as user_roles
95+
from .controllers import users as users
96+
from .controllers import versions as versions
97+
from .controllers import visibilities as visibilities
98+
from .controllers import ways as ways
99+
from .controllers import webgl_error_panes as webgl_error_panes
100+
101+
CLASS_IDS = {
102+
"Changeset": 0x0F04,
103+
"Node": 0x0F01,
104+
"NodeTag": 0x0F05,
105+
"Note": 0x0F08,
106+
"OldNode": 0x0F01,
107+
"OldNodeTag": 0x0F05,
108+
"OldRelation": 0x0F03,
109+
"OldRelationMember": 0x0F06,
110+
"OldRelationTag": 0x0F05,
111+
"OldWay": 0x0F02,
112+
"OldWayNode": 0x0F07,
113+
"OldWayTag": 0x0F05,
114+
"Relation": 0x0F03,
115+
"RelationMember": 0x0F06,
116+
"RelationTag": 0x0F05,
117+
"Trace": 0x0F09,
118+
"User": 0x0F0A,
119+
"Way": 0x0F02,
120+
"WayNode": 0x0F07,
121+
"WayTag": 0x0F05,
122+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
"""@generated `controllers` subpackage — faithful 1:1 mirror of
2+
`app/controllers/`, each module named by its controller (verbatim).
3+
"""
4+
from . import accounts as accounts
5+
from . import active_lists as active_lists
6+
from . import advanced_preferences as advanced_preferences
7+
from . import api as api
8+
from . import application as application
9+
from . import basic_preferences as basic_preferences
10+
from . import capabilities as capabilities
11+
from . import changeset_comments as changeset_comments
12+
from . import changeset_subscriptions as changeset_subscriptions
13+
from . import changesets as changesets
14+
from . import closes as closes
15+
from . import companies as companies
16+
from . import confirmations as confirmations
17+
from . import dashboards as dashboards
18+
from . import data as data
19+
from . import deletions as deletions
20+
from . import descriptions as descriptions
21+
from . import diary_comments as diary_comments
22+
from . import diary_entries as diary_entries
23+
from . import directions as directions
24+
from . import downloads as downloads
25+
from . import errors as errors
26+
from . import export as export
27+
from . import feature_queries as feature_queries
28+
from . import feeds as feeds
29+
from . import follows as follows
30+
from . import heatmaps as heatmaps
31+
from . import homes as homes
32+
from . import icons as icons
33+
from . import images as images
34+
from . import inboxes as inboxes
35+
from . import issue_comments as issue_comments
36+
from . import issued_blocks as issued_blocks
37+
from . import issues as issues
38+
from . import languages_panes as languages_panes
39+
from . import latlon_queries as latlon_queries
40+
from . import layers_panes as layers_panes
41+
from . import legend_panes as legend_panes
42+
from . import links as links
43+
from . import lists as lists
44+
from . import locations as locations
45+
from . import mailboxes as mailboxes
46+
from . import maps as maps
47+
from . import messages as messages
48+
from . import muted_inboxes as muted_inboxes
49+
from . import mutes as mutes
50+
from . import nodes as nodes
51+
from . import nominatim_queries as nominatim_queries
52+
from . import nominatim_reverse_queries as nominatim_reverse_queries
53+
from . import note_subscriptions as note_subscriptions
54+
from . import notes as notes
55+
from . import notification_preferences as notification_preferences
56+
from . import oauth2_applications as oauth2_applications
57+
from . import old_elements as old_elements
58+
from . import old_nodes as old_nodes
59+
from . import old_relation_members as old_relation_members
60+
from . import old_relations as old_relations
61+
from . import old_ways as old_ways
62+
from . import outboxes as outboxes
63+
from . import passwords as passwords
64+
from . import pd_declarations as pd_declarations
65+
from . import permissions as permissions
66+
from . import pictures as pictures
67+
from . import preferences as preferences
68+
from . import profile_sections as profile_sections
69+
from . import queries as queries
70+
from . import read_marks as read_marks
71+
from . import received_blocks as received_blocks
72+
from . import redactions as redactions
73+
from . import relation_members as relation_members
74+
from . import relations as relations
75+
from . import replies as replies
76+
from . import reporters as reporters
77+
from . import reports as reports
78+
from . import searches as searches
79+
from . import sessions as sessions
80+
from . import share_panes as share_panes
81+
from . import site as site
82+
from . import statuses as statuses
83+
from . import terms as terms
84+
from . import tracepoints as tracepoints
85+
from . import traces as traces
86+
from . import uploads as uploads
87+
from . import user_blocks as user_blocks
88+
from . import user_mutes as user_mutes
89+
from . import user_preferences as user_preferences
90+
from . import user_roles as user_roles
91+
from . import users as users
92+
from . import versions as versions
93+
from . import visibilities as visibilities
94+
from . import ways as ways
95+
from . import webgl_error_panes as webgl_error_panes
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""@generated DO arm — faithful mirror of the `accounts` controller.
2+
`osm.controllers.accounts.<is_a>(inp)` free functions (re-exported as
3+
`osm.accounts`); standalone, not methods on the model. Call:
4+
`osm.controllers.accounts.show(inp)`.
5+
"""
6+
from typing import Any
7+
8+
Input = dict # the Rails params bag; typed params are the next ruff brick
9+
Output = Any
10+
11+
def delete(inp: Input) -> Output:
12+
"""`accounts:delete` — DO arm. Source: AccountsController#destroy."""
13+
raise NotImplementedError("port AccountsController#destroy")
14+
15+
def show(inp: Input) -> Output:
16+
"""`accounts:show` — DO arm. Source: AccountsController#show."""
17+
raise NotImplementedError("port AccountsController#show")
18+
19+
def update(inp: Input) -> Output:
20+
"""`accounts:update` — DO arm. Source: AccountsController#update."""
21+
raise NotImplementedError("port AccountsController#update")
22+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""@generated DO arm — faithful mirror of the `active_lists` controller.
2+
`osm.controllers.active_lists.<is_a>(inp)` free functions (re-exported as
3+
`osm.active_lists`); standalone, not methods on the model. Call:
4+
`osm.controllers.active_lists.show(inp)`.
5+
"""
6+
from typing import Any
7+
8+
Input = dict # the Rails params bag; typed params are the next ruff brick
9+
Output = Any
10+
11+
def show(inp: Input) -> Output:
12+
"""`active_lists:show` — DO arm. Source: Api::UserBlocks::ActiveListsController#show."""
13+
raise NotImplementedError("port Api::UserBlocks::ActiveListsController#show")
14+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""@generated DO arm — faithful mirror of the `advanced_preferences` controller.
2+
`osm.controllers.advanced_preferences.<is_a>(inp)` free functions (re-exported as
3+
`osm.advanced_preferences`); standalone, not methods on the model. Call:
4+
`osm.controllers.advanced_preferences.show(inp)`.
5+
"""
6+
from typing import Any
7+
8+
Input = dict # the Rails params bag; typed params are the next ruff brick
9+
Output = Any
10+
11+
def update_preferences(inp: Input) -> Output:
12+
"""`advanced_preferences:update_preferences` — DO arm. Source: Preferences::AdvancedPreferencesController#update_preferences."""
13+
raise NotImplementedError("port Preferences::AdvancedPreferencesController#update_preferences")
14+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"""@generated DO arm — faithful mirror of the `api` controller.
2+
`osm.controllers.api.<is_a>(inp)` free functions (re-exported as
3+
`osm.api`); standalone, not methods on the model. Call:
4+
`osm.controllers.api.show(inp)`.
5+
"""
6+
from typing import Any
7+
8+
Input = dict # the Rails params bag; typed params are the next ruff brick
9+
Output = Any
10+
11+
def api_call_handle_error(inp: Input) -> Output:
12+
"""`api:api_call_handle_error` — DO arm. Source: ApiController#api_call_handle_error."""
13+
raise NotImplementedError("port ApiController#api_call_handle_error")
14+
15+
def api_call_timeout(inp: Input) -> Output:
16+
"""`api:api_call_timeout` — DO arm. Source: ApiController#api_call_timeout."""
17+
raise NotImplementedError("port ApiController#api_call_timeout")
18+
19+
def authorize(inp: Input) -> Output:
20+
"""`api:authorize` — DO arm. Source: ApiController#authorize."""
21+
raise NotImplementedError("port ApiController#authorize")
22+
23+
def check_rate_limit(inp: Input) -> Output:
24+
"""`api:check_rate_limit` — DO arm. Source: ApiController#check_rate_limit."""
25+
raise NotImplementedError("port ApiController#check_rate_limit")
26+
27+
def current_ability(inp: Input) -> Output:
28+
"""`api:current_ability` — DO arm. Source: ApiController#current_ability."""
29+
raise NotImplementedError("port ApiController#current_ability")
30+
31+
def deny_access(inp: Input) -> Output:
32+
"""`api:deny_access` — DO arm. Source: ApiController#deny_access."""
33+
raise NotImplementedError("port ApiController#deny_access")
34+
35+
def gpx_status(inp: Input) -> Output:
36+
"""`api:gpx_status` — DO arm. Source: ApiController#gpx_status."""
37+
raise NotImplementedError("port ApiController#gpx_status")
38+
39+
def scope_enabled(inp: Input) -> Output:
40+
"""`api:scope_enabled?` — DO arm. Source: ApiController#scope_enabled?."""
41+
raise NotImplementedError("port ApiController#scope_enabled?")
42+
43+
def set_request_formats(inp: Input) -> Output:
44+
"""`api:set_request_formats` — DO arm. Source: ApiController#set_request_formats."""
45+
raise NotImplementedError("port ApiController#set_request_formats")
46+
47+
def setup_user_auth(inp: Input) -> Output:
48+
"""`api:setup_user_auth` — DO arm. Source: ApiController#setup_user_auth."""
49+
raise NotImplementedError("port ApiController#setup_user_auth")
50+

0 commit comments

Comments
 (0)