Skip to content

Commit 596d994

Browse files
committed
Add callbacks instead of printing to stdout when a data issue is found
This is useful for osrd-data, where such issues are usually reported through the errdb mechanism, allowing more precise statistics. Signed-off-by: Younes Khoudli <younes.khoudli@epita.fr>
1 parent e02a6b5 commit 596d994

14 files changed

Lines changed: 140 additions & 25 deletions

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "liblrs"
3-
version = "0.4.3"
3+
version = "0.5.0"
44
edition = "2024"
55
description = "Library to manipulate linear referencing systems"
66
license = "MIT"

python/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "liblrs_python"
33
description = "Python bindings for liblrs: a library to work with linear referencing systems"
4-
version = "0.4.3"
4+
version = "0.5.0"
55
edition = "2024"
66
license = "MIT"
77
repository = "https://github.com/OpenRailAssociation/liblrs/"

python/liblrs_python.pyi

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

python/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "liblrs_python"
3-
version = "0.4.3"
3+
version = "0.5.0"
44
requires-python = ">=3.12"
55
dependencies = ["pip>=25.2"]
66

python/src/lib.rs

Lines changed: 60 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ fn liblrs_python(_py: Python, m: &Bound<'_, PyModule>) -> PyResult<()> {
2727
m.add_class::<AnchorOnLrm>()?;
2828
m.add_class::<SegmentOfTraversal>()?;
2929
m.add_class::<Builder>()?;
30+
m.add_class::<DataIssueReporter>()?;
3031
Ok(())
3132
}
3233

@@ -576,15 +577,22 @@ impl Builder {
576577
/// Read the topology from an OpenStreetMap source
577578
///
578579
/// It reads the nodes, segments and traversals.
579-
pub fn read_from_osm(
580+
pub fn read_from_osm<'py>(
580581
&mut self,
581582
input_osm_file: PathBuf,
582583
lrm_tag: String,
583584
required: Vec<(String, String)>,
584585
to_reject: Vec<(String, String)>,
586+
reporter: Bound<'py, DataIssueReporter>,
585587
) {
586-
self.inner
587-
.read_from_osm(&input_osm_file, &lrm_tag, required, to_reject)
588+
let mut reporter = PythonDataIssueReporter(reporter);
589+
self.inner.read_from_osm(
590+
&input_osm_file,
591+
&lrm_tag,
592+
required,
593+
to_reject,
594+
Some(&mut reporter),
595+
)
588596
}
589597

590598
/// Save the lrs to a file
@@ -656,3 +664,52 @@ impl Builder {
656664
}
657665

658666
define_stub_info_gatherer!(stub_info);
667+
668+
#[gen_stub_pyclass]
669+
#[pyclass(subclass)]
670+
struct DataIssueReporter {}
671+
672+
#[pymethods]
673+
impl DataIssueReporter {
674+
#[new]
675+
fn new() -> Self {
676+
Self {}
677+
}
678+
}
679+
680+
#[allow(unused_variables)]
681+
#[gen_stub_pymethods]
682+
impl liblrs::DataIssueReporter for DataIssueReporter {
683+
fn report_ignoring_traversal_edges(
684+
&mut self,
685+
traversal_ref: &str,
686+
ignored_count: usize,
687+
total_count: usize,
688+
first_node: i64,
689+
last_node: i64,
690+
) {
691+
}
692+
}
693+
694+
struct PythonDataIssueReporter<'a>(Bound<'a, DataIssueReporter>);
695+
impl liblrs::DataIssueReporter for PythonDataIssueReporter<'_> {
696+
fn report_ignoring_traversal_edges(
697+
&mut self,
698+
traversal_ref: &str,
699+
ignored_count: usize,
700+
total_count: usize,
701+
first_node: i64,
702+
last_node: i64,
703+
) {
704+
let _ = self.0.call_method1(
705+
"report_ignoring_traversal_edges",
706+
(
707+
traversal_ref,
708+
ignored_count,
709+
total_count,
710+
first_node,
711+
last_node,
712+
),
713+
);
714+
}
715+
}

python/uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/builder.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use crate::lrs::Properties;
1313
use crate::lrs_ext::ExtLrs;
1414
use crate::lrs_generated::{self, *};
1515
use crate::osm_helpers::sort_edges;
16-
use crate::properties;
16+
use crate::{DataIssueReporter, properties};
1717

1818
/// The linear position of an [`Anchor`] doesn’t always match the measured distance.
1919
/// For example if a road was transformed into a bypass, resulting in a longer road,
@@ -436,7 +436,10 @@ impl<'fbb> Builder<'fbb> {
436436
lrm_tag: &str,
437437
required: Vec<(String, String)>,
438438
to_reject: Vec<(String, String)>,
439+
reporter: Option<&mut dyn DataIssueReporter>,
439440
) {
441+
let mut default_reporter = ();
442+
let reporter = reporter.unwrap_or(&mut default_reporter);
440443
let mut reader = osm4routing::Reader::new().merge_ways().read_tag(lrm_tag);
441444

442445
for (key, value) in required.iter() {
@@ -479,7 +482,7 @@ impl<'fbb> Builder<'fbb> {
479482

480483
// Sort the traversals
481484
for (srv_ref, edges) in traversals.into_iter() {
482-
let segments: Vec<_> = sort_edges(edges, &srv_ref)
485+
let segments: Vec<_> = sort_edges(edges, &srv_ref, reporter)
483486
.into_iter()
484487
.map(|(edge, reversed)| SegmentOfTraversal {
485488
segment_index: edges_map[&edge.id],

src/geometry_from_osm.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ fn main() {
4444
&cli_args.lrm_tag,
4545
required,
4646
to_reject,
47+
Some(&mut liblrs::LoggingDataIssueReporter),
4748
);
4849

4950
builder.save(

src/lib.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,46 @@ pub mod lrs_ext;
2121
#[deny(missing_docs)]
2222
pub mod builder;
2323

24+
pub trait DataIssueReporter {
25+
fn report_ignoring_traversal_edges(
26+
&mut self,
27+
traversal_ref: &str,
28+
ignored_count: usize,
29+
total_count: usize,
30+
first_node: i64,
31+
last_node: i64,
32+
);
33+
}
34+
35+
pub struct LoggingDataIssueReporter;
36+
37+
impl DataIssueReporter for LoggingDataIssueReporter {
38+
fn report_ignoring_traversal_edges(
39+
&mut self,
40+
traversal_ref: &str,
41+
ignored_count: usize,
42+
total_count: usize,
43+
first_node: i64,
44+
last_node: i64,
45+
) {
46+
println!(
47+
"[WARN] on traversal {traversal_ref}, ignoring {ignored_count} edges out of {total_count}. Sorted from {first_node} to {last_node}"
48+
);
49+
}
50+
}
51+
52+
impl DataIssueReporter for () {
53+
fn report_ignoring_traversal_edges(
54+
&mut self,
55+
_traversal_ref: &str,
56+
_ignored_count: usize,
57+
_total_count: usize,
58+
_first_node: i64,
59+
_last_node: i64,
60+
) {
61+
}
62+
}
63+
2464
#[test]
2565
fn read_and_write_lrs() {
2666
use builder::*;

0 commit comments

Comments
 (0)