Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 21 additions & 21 deletions .claude/harvest/osm-website-rs/python/osm/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, List, Optional
from typing import Any, ClassVar, List, Optional

@dataclass
class Acl:
Expand All @@ -15,7 +15,7 @@ class ApplicationRecord:

@dataclass
class Changeset:
CLASS_ID: int = 0x0F04 # canonical concept `osm_changeset`
CLASS_ID: ClassVar[int] = 0x0F04 # canonical concept `osm_changeset`
user: Optional[int] = None
changeset_tags: List[int] = field(default_factory=list)
nodes: List[int] = field(default_factory=list)
Expand Down Expand Up @@ -104,7 +104,7 @@ class ModerationZone:

@dataclass
class Node:
CLASS_ID: int = 0x0F01 # canonical concept `osm_node`
CLASS_ID: ClassVar[int] = 0x0F01 # canonical concept `osm_node`
changeset: Optional[int] = None
old_nodes: List[int] = field(default_factory=list)
way_nodes: List[int] = field(default_factory=list)
Expand All @@ -117,12 +117,12 @@ class Node:

@dataclass
class NodeTag:
CLASS_ID: int = 0x0F05 # canonical concept `osm_element_tag`
CLASS_ID: ClassVar[int] = 0x0F05 # canonical concept `osm_element_tag`
node: Optional[int] = None

@dataclass
class Note:
CLASS_ID: int = 0x0F08 # canonical concept `osm_note`
CLASS_ID: ClassVar[int] = 0x0F08 # canonical concept `osm_note`
author: Optional[int] = None
comments: List[int] = field(default_factory=list)
all_comments: List[int] = field(default_factory=list)
Expand All @@ -145,20 +145,20 @@ class Oauth2Application:

@dataclass
class OldNode:
CLASS_ID: int = 0x0F01 # canonical concept `osm_node`
CLASS_ID: ClassVar[int] = 0x0F01 # canonical concept `osm_node`
changeset: Optional[int] = None
redaction: Optional[int] = None
current_node: Optional[int] = None
old_tags: List[int] = field(default_factory=list)

@dataclass
class OldNodeTag:
CLASS_ID: int = 0x0F05 # canonical concept `osm_element_tag`
CLASS_ID: ClassVar[int] = 0x0F05 # canonical concept `osm_element_tag`
old_node: Optional[int] = None

@dataclass
class OldRelation:
CLASS_ID: int = 0x0F03 # canonical concept `osm_relation`
CLASS_ID: ClassVar[int] = 0x0F03 # canonical concept `osm_relation`
changeset: Optional[int] = None
redaction: Optional[int] = None
current_relation: Optional[int] = None
Expand All @@ -167,18 +167,18 @@ class OldRelation:

@dataclass
class OldRelationMember:
CLASS_ID: int = 0x0F06 # canonical concept `osm_relation_member`
CLASS_ID: ClassVar[int] = 0x0F06 # canonical concept `osm_relation_member`
old_relation: Optional[int] = None
member: Optional[int] = None

@dataclass
class OldRelationTag:
CLASS_ID: int = 0x0F05 # canonical concept `osm_element_tag`
CLASS_ID: ClassVar[int] = 0x0F05 # canonical concept `osm_element_tag`
old_relation: Optional[int] = None

@dataclass
class OldWay:
CLASS_ID: int = 0x0F02 # canonical concept `osm_way`
CLASS_ID: ClassVar[int] = 0x0F02 # canonical concept `osm_way`
changeset: Optional[int] = None
redaction: Optional[int] = None
current_way: Optional[int] = None
Expand All @@ -187,14 +187,14 @@ class OldWay:

@dataclass
class OldWayNode:
CLASS_ID: int = 0x0F07 # canonical concept `osm_way_node`
CLASS_ID: ClassVar[int] = 0x0F07 # canonical concept `osm_way_node`
old_way: Optional[int] = None
node: Optional[int] = None
way: Optional[int] = None

@dataclass
class OldWayTag:
CLASS_ID: int = 0x0F05 # canonical concept `osm_element_tag`
CLASS_ID: ClassVar[int] = 0x0F05 # canonical concept `osm_element_tag`
old_way: Optional[int] = None

@dataclass
Expand All @@ -206,7 +206,7 @@ class Redaction:

@dataclass
class Relation:
CLASS_ID: int = 0x0F03 # canonical concept `osm_relation`
CLASS_ID: ClassVar[int] = 0x0F03 # canonical concept `osm_relation`
changeset: Optional[int] = None
old_relations: List[int] = field(default_factory=list)
relation_members: List[int] = field(default_factory=list)
Expand All @@ -216,13 +216,13 @@ class Relation:

@dataclass
class RelationMember:
CLASS_ID: int = 0x0F06 # canonical concept `osm_relation_member`
CLASS_ID: ClassVar[int] = 0x0F06 # canonical concept `osm_relation_member`
relation: Optional[int] = None
member: Optional[int] = None

@dataclass
class RelationTag:
CLASS_ID: int = 0x0F05 # canonical concept `osm_element_tag`
CLASS_ID: ClassVar[int] = 0x0F05 # canonical concept `osm_element_tag`
relation: Optional[int] = None

@dataclass
Expand All @@ -240,7 +240,7 @@ class SpammyPhrase:

@dataclass
class Trace:
CLASS_ID: int = 0x0F09 # canonical concept `osm_gpx_trace`
CLASS_ID: ClassVar[int] = 0x0F09 # canonical concept `osm_gpx_trace`
user: Optional[int] = None
tags: List[int] = field(default_factory=list)
points: List[int] = field(default_factory=list)
Expand All @@ -255,7 +255,7 @@ class Tracetag:

@dataclass
class User:
CLASS_ID: int = 0x0F0A # canonical concept `osm_user`
CLASS_ID: ClassVar[int] = 0x0F0A # canonical concept `osm_user`
traces: List[int] = field(default_factory=list)
diary_entries: List[int] = field(default_factory=list)
diary_comments: List[int] = field(default_factory=list)
Expand Down Expand Up @@ -315,7 +315,7 @@ class UserRole:

@dataclass
class Way:
CLASS_ID: int = 0x0F02 # canonical concept `osm_way`
CLASS_ID: ClassVar[int] = 0x0F02 # canonical concept `osm_way`
changeset: Optional[int] = None
old_ways: List[int] = field(default_factory=list)
way_nodes: List[int] = field(default_factory=list)
Expand All @@ -326,12 +326,12 @@ class Way:

@dataclass
class WayNode:
CLASS_ID: int = 0x0F07 # canonical concept `osm_way_node`
CLASS_ID: ClassVar[int] = 0x0F07 # canonical concept `osm_way_node`
way: Optional[int] = None
node: Optional[int] = None

@dataclass
class WayTag:
CLASS_ID: int = 0x0F05 # canonical concept `osm_element_tag`
CLASS_ID: ClassVar[int] = 0x0F05 # canonical concept `osm_element_tag`
way: Optional[int] = None

32 changes: 19 additions & 13 deletions crates/ogar-render-askama/examples/render_osm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,28 +288,34 @@ fn main() {
"pub mod {} {{\n use super::{{Input, Output}};\n",
rustify(part_of)
));
let mut seen = std::collections::HashSet::new();
// Distinct is_a rail keys can normalise to the SAME Rust fn name (`foo?`
// and `foo` both → `foo`). Group by the emitted name and MERGE their
// sources + labels into one fn, so no rail tile silently vanishes
// (a `continue` here dropped the collider — codex/Bugbot on the Python
// sibling #154; the Rust emitter had the same latent drop).
let mut by_fname: std::collections::BTreeMap<String, (Vec<String>, Vec<String>)> =
std::collections::BTreeMap::new();
for (is_a, sources) in isas {
let fname = rustify(is_a);
if !seen.insert(fname.clone()) {
continue;
}
// All source controllers that collapse onto this canonical tile,
// deduped + sorted, cited so no route is lost from the docs.
let mut srcs: Vec<String> = sources
.iter()
.map(|(c, a)| format!("{c}#{a}"))
.collect();
let entry = by_fname.entry(rustify(is_a)).or_default();
entry.0.push(is_a.clone());
entry
.1
.extend(sources.iter().map(|(c, a)| format!("{c}#{a}")));
}
for (fname, (mut labels, mut srcs)) in by_fname {
labels.sort();
labels.dedup();
srcs.sort();
srcs.dedup();
let primary = &srcs[0];
let is_a_disp = labels.join(", ");
let primary = srcs[0].clone();
let source_line = if srcs.len() == 1 {
format!("Source: `{primary}`.")
} else {
format!("Sources (canonical tile): `{}`.", srcs.join("`, `"))
};
acts.push_str(&format!(
" /// `{part_of}:{is_a}` — DO arm. {source_line}\n \
" /// `{part_of}:{is_a_disp}` — DO arm. {source_line}\n \
pub fn {fname}(input: Input) -> Output {{\n \
let _ = input;\n todo!(\"port {primary}\")\n }}\n"
));
Expand Down
26 changes: 16 additions & 10 deletions crates/ogar-render-askama/examples/render_python.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ fn main() {
"\"\"\"@generated by ogar-render-askama render_python — ruff → OGAR (THINK arm).\n\
OSM domain models as dataclasses; associations become typed id fields.\n\"\"\"\n\
from __future__ import annotations\nfrom dataclasses import dataclass, field\n\
from typing import Any, List, Optional\n\n",
from typing import Any, ClassVar, List, Optional\n\n",
);
let mut class_ids: Vec<(String, u16)> = Vec::new();
for c in &classes {
Expand All @@ -136,7 +136,7 @@ fn main() {
if let Some(concept) = &c.canonical_concept {
if let Some(id) = canonical_concept_id(concept) {
models.push_str(&format!(
" CLASS_ID: int = 0x{id:04X} # canonical concept `{concept}`\n"
" CLASS_ID: ClassVar[int] = 0x{id:04X} # canonical concept `{concept}`\n"
));
class_ids.push((cls.clone(), id));
}
Expand Down Expand Up @@ -207,24 +207,30 @@ fn main() {
Input = dict # the Rails params bag; typed params are the next ruff brick\n\
Output = Any\n\n",
);
let mut seen = std::collections::HashSet::new();
// Distinct is_a rail keys can normalise to the SAME Python identifier
// (`foo?` and `foo` both → `foo`). Group by the emitted name and MERGE
// their sources + labels into one stub, so no rail tile silently
// vanishes (Bugbot #154).
let mut by_fname: BTreeMap<String, (Vec<String>, Vec<String>)> = BTreeMap::new();
for (is_a, sources) in isas {
let fname = pyify(is_a);
if !seen.insert(fname.clone()) {
continue;
}
let mut srcs: Vec<String> =
sources.iter().map(|(c, a)| format!("{c}#{a}")).collect();
let entry = by_fname.entry(pyify(is_a)).or_default();
entry.0.push(is_a.clone());
entry.1.extend(sources.iter().map(|(c, a)| format!("{c}#{a}")));
}
for (fname, (mut labels, mut srcs)) in by_fname {
labels.sort();
labels.dedup();
srcs.sort();
srcs.dedup();
let is_a_disp = labels.join(", ");
let cite = if srcs.len() == 1 {
format!("Source: {}", srcs[0])
} else {
format!("Sources (canonical tile): {}", srcs.join(", "))
};
body.push_str(&format!(
"def {fname}(inp: Input) -> Output:\n \
\"\"\"`{part_of}:{is_a}` — DO arm. {cite}.\"\"\"\n \
\"\"\"`{part_of}:{is_a_disp}` — DO arm. {cite}.\"\"\"\n \
raise NotImplementedError(\"port {}\")\n\n",
srcs[0]
));
Expand Down
Loading