Skip to content

Commit 89f6b18

Browse files
committed
ogar-render-askama: render_python — Python import-shape emit PoC
The Python counterpart of render_osm: same ruff → OGAR substrate, a language-pluggable emit back-end. Proves OGAR is a bidirectional per-class transpiler whose pull-back side is not Rust-specific. Emits under python/osm/: - models.py — one @DataClass per THINK class; associations become typed id fields (belongs_to/has_one → Optional[int], has_many/ habtm → List[int]); each grounded model carries its CLASS_ID. - <part_of>.py — the DO arm: `osm.node.show(inp)` free functions (part_of = module, is_a = function), never methods on the model; all colliding source controllers cited. - __init__.py — package re-exports + CLASS_IDS map. Plus python/ogar_sdk.py — the substrate-pull SDK (Python mirror of Rust lance_graph_contract::ogar_codebook): CODEBOOK dict + class_id(concept) + render_classid(concept, prefix) (canon-high `(concept<<16)|prefix`). Ships OSM (0x0F) AND odoo/commerce (0x02) concepts — the pull is domain-agnostic, so `osm`/`odoo` come out of the same substrate the same way. Verified: example builds clean; py_compile green on the package + SDK; functional smoke — class_id('osm_node')=0xf01, render_classid('account_move', 0x0002)=0x2020002, Node.CLASS_ID=0xf01, osm.node.show({}) raises NotImplementedError('port Api::NodesController#show'). Note: container module names inherit main's naïve singulariser (capabilitie.py / companie.py); the real inflector is PR #153 (claude/osm-render-ergonomics) — regen after both merge cleans the names. Typed params (dict Input → typed) remain the ruff param-harvest brick. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EYvNjD8M8LMNYbRy3gq2FP
1 parent 5d29a22 commit 89f6b18

97 files changed

Lines changed: 2903 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: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
"""@generated OSM package (ruff → OGAR, Python import shape).
2+
Models: `from osm.models import Node`. DO arm: `import osm.node; osm.node.show(inp)`.
3+
"""
4+
from . import models as models
5+
from . import account as account
6+
from . import active_list as active_list
7+
from . import advanced_preference as advanced_preference
8+
from . import api as api
9+
from . import application as application
10+
from . import basic_preference as basic_preference
11+
from . import capabilitie as capabilitie
12+
from . import changeset as changeset
13+
from . import changeset_comment as changeset_comment
14+
from . import changeset_subscription as changeset_subscription
15+
from . import close as close
16+
from . import companie as companie
17+
from . import confirmation as confirmation
18+
from . import dashboard as dashboard
19+
from . import data as data
20+
from . import deletion as deletion
21+
from . import description as description
22+
from . import diary_comment as diary_comment
23+
from . import diary_entrie as diary_entrie
24+
from . import direction as direction
25+
from . import download as download
26+
from . import error as error
27+
from . import export as export
28+
from . import feature_querie as feature_querie
29+
from . import feed as feed
30+
from . import follow as follow
31+
from . import heatmap as heatmap
32+
from . import home as home
33+
from . import icon as icon
34+
from . import image as image
35+
from . import inboxe as inboxe
36+
from . import issue as issue
37+
from . import issue_comment as issue_comment
38+
from . import issued_block as issued_block
39+
from . import languages_pane as languages_pane
40+
from . import latlon_querie as latlon_querie
41+
from . import layers_pane as layers_pane
42+
from . import legend_pane as legend_pane
43+
from . import link as link
44+
from . import list as list
45+
from . import location as location
46+
from . import mailboxe as mailboxe
47+
from . import map as map
48+
from . import message as message
49+
from . import mute as mute
50+
from . import muted_inboxe as muted_inboxe
51+
from . import node as node
52+
from . import nominatim_querie as nominatim_querie
53+
from . import nominatim_reverse_querie as nominatim_reverse_querie
54+
from . import note as note
55+
from . import note_subscription as note_subscription
56+
from . import notification_preference as notification_preference
57+
from . import oauth2_application as oauth2_application
58+
from . import old_element as old_element
59+
from . import old_node as old_node
60+
from . import old_relation as old_relation
61+
from . import old_relation_member as old_relation_member
62+
from . import old_way as old_way
63+
from . import outboxe as outboxe
64+
from . import password as password
65+
from . import pd_declaration as pd_declaration
66+
from . import permission as permission
67+
from . import picture as picture
68+
from . import preference as preference
69+
from . import profile_section as profile_section
70+
from . import querie as querie
71+
from . import read_mark as read_mark
72+
from . import received_block as received_block
73+
from . import redaction as redaction
74+
from . import relation as relation
75+
from . import relation_member as relation_member
76+
from . import replie as replie
77+
from . import report as report
78+
from . import reporter as reporter
79+
from . import searche as searche
80+
from . import session as session
81+
from . import share_pane as share_pane
82+
from . import site as site
83+
from . import statuse as statuse
84+
from . import term as term
85+
from . import trace as trace
86+
from . import tracepoint as tracepoint
87+
from . import upload as upload
88+
from . import user as user
89+
from . import user_block as user_block
90+
from . import user_mute as user_mute
91+
from . import user_preference as user_preference
92+
from . import user_role as user_role
93+
from . import version as version
94+
from . import visibilitie as visibilitie
95+
from . import way as way
96+
from . import webgl_error_pane as webgl_error_pane
97+
98+
CLASS_IDS = {
99+
"Changeset": 0x0F04,
100+
"Node": 0x0F01,
101+
"NodeTag": 0x0F05,
102+
"Note": 0x0F08,
103+
"OldNode": 0x0F01,
104+
"OldNodeTag": 0x0F05,
105+
"OldRelation": 0x0F03,
106+
"OldRelationMember": 0x0F06,
107+
"OldRelationTag": 0x0F05,
108+
"OldWay": 0x0F02,
109+
"OldWayNode": 0x0F07,
110+
"OldWayTag": 0x0F05,
111+
"Relation": 0x0F03,
112+
"RelationMember": 0x0F06,
113+
"RelationTag": 0x0F05,
114+
"Trace": 0x0F09,
115+
"User": 0x0F0A,
116+
"Way": 0x0F02,
117+
"WayNode": 0x0F07,
118+
"WayTag": 0x0F05,
119+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""@generated DO-arm — `osm.account.<is_a>(inp)` free functions.
2+
part_of = this module, is_a = the function (standalone, not methods on
3+
the model — per OGAR's ActionDef rule). Call: `osm.account.show(inp)`.
4+
"""
5+
from typing import Any
6+
7+
Input = dict # the Rails params bag; typed params are the next ruff brick
8+
Output = Any
9+
10+
def delete(inp: Input) -> Output:
11+
"""`account:delete` — DO arm. Source: AccountsController#destroy."""
12+
raise NotImplementedError("port AccountsController#destroy")
13+
14+
def show(inp: Input) -> Output:
15+
"""`account:show` — DO arm. Source: AccountsController#show."""
16+
raise NotImplementedError("port AccountsController#show")
17+
18+
def update(inp: Input) -> Output:
19+
"""`account:update` — DO arm. Source: AccountsController#update."""
20+
raise NotImplementedError("port AccountsController#update")
21+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""@generated DO-arm — `osm.active_list.<is_a>(inp)` free functions.
2+
part_of = this module, is_a = the function (standalone, not methods on
3+
the model — per OGAR's ActionDef rule). Call: `osm.active_list.show(inp)`.
4+
"""
5+
from typing import Any
6+
7+
Input = dict # the Rails params bag; typed params are the next ruff brick
8+
Output = Any
9+
10+
def show(inp: Input) -> Output:
11+
"""`active_list:show` — DO arm. Source: Api::UserBlocks::ActiveListsController#show."""
12+
raise NotImplementedError("port Api::UserBlocks::ActiveListsController#show")
13+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""@generated DO-arm — `osm.advanced_preference.<is_a>(inp)` free functions.
2+
part_of = this module, is_a = the function (standalone, not methods on
3+
the model — per OGAR's ActionDef rule). Call: `osm.advanced_preference.show(inp)`.
4+
"""
5+
from typing import Any
6+
7+
Input = dict # the Rails params bag; typed params are the next ruff brick
8+
Output = Any
9+
10+
def update_preferences(inp: Input) -> Output:
11+
"""`advanced_preference:update_preferences` — DO arm. Source: Preferences::AdvancedPreferencesController#update_preferences."""
12+
raise NotImplementedError("port Preferences::AdvancedPreferencesController#update_preferences")
13+
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""@generated DO-arm — `osm.api.<is_a>(inp)` free functions.
2+
part_of = this module, is_a = the function (standalone, not methods on
3+
the model — per OGAR's ActionDef rule). Call: `osm.api.show(inp)`.
4+
"""
5+
from typing import Any
6+
7+
Input = dict # the Rails params bag; typed params are the next ruff brick
8+
Output = Any
9+
10+
def api_call_handle_error(inp: Input) -> Output:
11+
"""`api:api_call_handle_error` — DO arm. Source: ApiController#api_call_handle_error."""
12+
raise NotImplementedError("port ApiController#api_call_handle_error")
13+
14+
def api_call_timeout(inp: Input) -> Output:
15+
"""`api:api_call_timeout` — DO arm. Source: ApiController#api_call_timeout."""
16+
raise NotImplementedError("port ApiController#api_call_timeout")
17+
18+
def authorize(inp: Input) -> Output:
19+
"""`api:authorize` — DO arm. Source: ApiController#authorize."""
20+
raise NotImplementedError("port ApiController#authorize")
21+
22+
def check_rate_limit(inp: Input) -> Output:
23+
"""`api:check_rate_limit` — DO arm. Source: ApiController#check_rate_limit."""
24+
raise NotImplementedError("port ApiController#check_rate_limit")
25+
26+
def current_ability(inp: Input) -> Output:
27+
"""`api:current_ability` — DO arm. Source: ApiController#current_ability."""
28+
raise NotImplementedError("port ApiController#current_ability")
29+
30+
def deny_access(inp: Input) -> Output:
31+
"""`api:deny_access` — DO arm. Source: ApiController#deny_access."""
32+
raise NotImplementedError("port ApiController#deny_access")
33+
34+
def gpx_status(inp: Input) -> Output:
35+
"""`api:gpx_status` — DO arm. Source: ApiController#gpx_status."""
36+
raise NotImplementedError("port ApiController#gpx_status")
37+
38+
def scope_enabled(inp: Input) -> Output:
39+
"""`api:scope_enabled?` — DO arm. Source: ApiController#scope_enabled?."""
40+
raise NotImplementedError("port ApiController#scope_enabled?")
41+
42+
def set_request_formats(inp: Input) -> Output:
43+
"""`api:set_request_formats` — DO arm. Source: ApiController#set_request_formats."""
44+
raise NotImplementedError("port ApiController#set_request_formats")
45+
46+
def setup_user_auth(inp: Input) -> Output:
47+
"""`api:setup_user_auth` — DO arm. Source: ApiController#setup_user_auth."""
48+
raise NotImplementedError("port ApiController#setup_user_auth")
49+
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
"""@generated DO-arm — `osm.application.<is_a>(inp)` free functions.
2+
part_of = this module, is_a = the function (standalone, not methods on
3+
the model — per OGAR's ActionDef rule). Call: `osm.application.show(inp)`.
4+
"""
5+
from typing import Any
6+
7+
Input = dict # the Rails params bag; typed params are the next ruff brick
8+
Output = Any
9+
10+
def api_status(inp: Input) -> Output:
11+
"""`application:api_status` — DO arm. Source: ApplicationController#api_status."""
12+
raise NotImplementedError("port ApplicationController#api_status")
13+
14+
def authorize_web(inp: Input) -> Output:
15+
"""`application:authorize_web` — DO arm. Source: ApplicationController#authorize_web."""
16+
raise NotImplementedError("port ApplicationController#authorize_web")
17+
18+
def check_api_readable(inp: Input) -> Output:
19+
"""`application:check_api_readable` — DO arm. Source: ApplicationController#check_api_readable."""
20+
raise NotImplementedError("port ApplicationController#check_api_readable")
21+
22+
def check_api_writable(inp: Input) -> Output:
23+
"""`application:check_api_writable` — DO arm. Source: ApplicationController#check_api_writable."""
24+
raise NotImplementedError("port ApplicationController#check_api_writable")
25+
26+
def check_database_readable(inp: Input) -> Output:
27+
"""`application:check_database_readable` — DO arm. Source: ApplicationController#check_database_readable."""
28+
raise NotImplementedError("port ApplicationController#check_database_readable")
29+
30+
def check_database_writable(inp: Input) -> Output:
31+
"""`application:check_database_writable` — DO arm. Source: ApplicationController#check_database_writable."""
32+
raise NotImplementedError("port ApplicationController#check_database_writable")
33+
34+
def close_body(inp: Input) -> Output:
35+
"""`application:close_body` — DO arm. Source: ApplicationController#close_body."""
36+
raise NotImplementedError("port ApplicationController#close_body")
37+
38+
def current_ability(inp: Input) -> Output:
39+
"""`application:current_ability` — DO arm. Source: ApplicationController#current_ability."""
40+
raise NotImplementedError("port ApplicationController#current_ability")
41+
42+
def database_status(inp: Input) -> Output:
43+
"""`application:database_status` — DO arm. Source: ApplicationController#database_status."""
44+
raise NotImplementedError("port ApplicationController#database_status")
45+
46+
def deny_access(inp: Input) -> Output:
47+
"""`application:deny_access` — DO arm. Source: ApplicationController#deny_access."""
48+
raise NotImplementedError("port ApplicationController#deny_access")
49+
50+
def invalid_parameter(inp: Input) -> Output:
51+
"""`application:invalid_parameter` — DO arm. Source: ApplicationController#invalid_parameter."""
52+
raise NotImplementedError("port ApplicationController#invalid_parameter")
53+
54+
def map_layout(inp: Input) -> Output:
55+
"""`application:map_layout` — DO arm. Source: ApplicationController#map_layout."""
56+
raise NotImplementedError("port ApplicationController#map_layout")
57+
58+
def preferred_editor(inp: Input) -> Output:
59+
"""`application:preferred_editor` — DO arm. Source: ApplicationController#preferred_editor."""
60+
raise NotImplementedError("port ApplicationController#preferred_editor")
61+
62+
def preferred_languages(inp: Input) -> Output:
63+
"""`application:preferred_languages` — DO arm. Source: ApplicationController#preferred_languages."""
64+
raise NotImplementedError("port ApplicationController#preferred_languages")
65+
66+
def report_error(inp: Input) -> Output:
67+
"""`application:report_error` — DO arm. Source: ApplicationController#report_error."""
68+
raise NotImplementedError("port ApplicationController#report_error")
69+
70+
def require_cookies(inp: Input) -> Output:
71+
"""`application:require_cookies` — DO arm. Source: ApplicationController#require_cookies."""
72+
raise NotImplementedError("port ApplicationController#require_cookies")
73+
74+
def require_oauth(inp: Input) -> Output:
75+
"""`application:require_oauth` — DO arm. Source: ApplicationController#require_oauth."""
76+
raise NotImplementedError("port ApplicationController#require_oauth")
77+
78+
def require_public_data(inp: Input) -> Output:
79+
"""`application:require_public_data` — DO arm. Source: ApplicationController#require_public_data."""
80+
raise NotImplementedError("port ApplicationController#require_public_data")
81+
82+
def require_user(inp: Input) -> Output:
83+
"""`application:require_user` — DO arm. Source: ApplicationController#require_user."""
84+
raise NotImplementedError("port ApplicationController#require_user")
85+
86+
def respond_to_timeout(inp: Input) -> Output:
87+
"""`application:respond_to_timeout` — DO arm. Source: ApplicationController#respond_to_timeout."""
88+
raise NotImplementedError("port ApplicationController#respond_to_timeout")
89+
90+
def safe_referer(inp: Input) -> Output:
91+
"""`application:safe_referer` — DO arm. Source: ApplicationController#safe_referer."""
92+
raise NotImplementedError("port ApplicationController#safe_referer")
93+
94+
def set_locale(inp: Input) -> Output:
95+
"""`application:set_locale` — DO arm. Source: ApplicationController#set_locale."""
96+
raise NotImplementedError("port ApplicationController#set_locale")
97+
98+
def site_layout(inp: Input) -> Output:
99+
"""`application:site_layout` — DO arm. Source: ApplicationController#site_layout."""
100+
raise NotImplementedError("port ApplicationController#site_layout")
101+
102+
def update_totp(inp: Input) -> Output:
103+
"""`application:update_totp` — DO arm. Source: ApplicationController#update_totp."""
104+
raise NotImplementedError("port ApplicationController#update_totp")
105+
106+
def web_timeout(inp: Input) -> Output:
107+
"""`application:web_timeout` — DO arm. Source: ApplicationController#web_timeout."""
108+
raise NotImplementedError("port ApplicationController#web_timeout")
109+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""@generated DO-arm — `osm.basic_preference.<is_a>(inp)` free functions.
2+
part_of = this module, is_a = the function (standalone, not methods on
3+
the model — per OGAR's ActionDef rule). Call: `osm.basic_preference.show(inp)`.
4+
"""
5+
from typing import Any
6+
7+
Input = dict # the Rails params bag; typed params are the next ruff brick
8+
Output = Any
9+
10+
def update_preferences(inp: Input) -> Output:
11+
"""`basic_preference:update_preferences` — DO arm. Source: Preferences::BasicPreferencesController#update_preferences."""
12+
raise NotImplementedError("port Preferences::BasicPreferencesController#update_preferences")
13+

0 commit comments

Comments
 (0)