nds-mapviewer 2026.3.2.dev151__tar.gz → 2026.3.2.dev153__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. {nds_mapviewer-2026.3.2.dev151/src/nds_mapviewer.egg-info → nds_mapviewer-2026.3.2.dev153}/PKG-INFO +3 -2
  2. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/README.md +2 -1
  3. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153/src/nds_mapviewer.egg-info}/PKG-INFO +3 -2
  4. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/ndslive/mapviewer/config.py +40 -0
  5. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/tests/test_config.py +70 -0
  6. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/.gitignore +0 -0
  7. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/CHANGELOG.md +0 -0
  8. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/pyproject.toml +0 -0
  9. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/setup.cfg +0 -0
  10. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/setup.py +0 -0
  11. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/nds_mapviewer.egg-info/SOURCES.txt +0 -0
  12. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/nds_mapviewer.egg-info/dependency_links.txt +0 -0
  13. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/nds_mapviewer.egg-info/entry_points.txt +0 -0
  14. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/nds_mapviewer.egg-info/requires.txt +0 -0
  15. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/nds_mapviewer.egg-info/top_level.txt +0 -0
  16. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/ndslive/mapviewer/__init__.py +0 -0
  17. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/ndslive/mapviewer/browser.py +0 -0
  18. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/ndslive/mapviewer/cli.py +0 -0
  19. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/ndslive/mapviewer/clipboard.py +0 -0
  20. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/ndslive/mapviewer/container_runtime.py +0 -0
  21. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/ndslive/mapviewer/docker_client.py +0 -0
  22. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/ndslive/mapviewer/exceptions.py +0 -0
  23. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/ndslive/mapviewer/tui.py +0 -0
  24. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/ndslive/mapviewer/ui.py +0 -0
  25. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/src/ndslive/mapviewer/viewer.py +0 -0
  26. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/tests/conftest.py +0 -0
  27. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/tests/test_cli.py +0 -0
  28. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/tests/test_clipboard.py +0 -0
  29. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/tests/test_docker_client.py +0 -0
  30. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/tests/test_tui.py +0 -0
  31. {nds_mapviewer-2026.3.2.dev151 → nds_mapviewer-2026.3.2.dev153}/tests/test_viewer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nds-mapviewer
3
- Version: 2026.3.2.dev151
3
+ Version: 2026.3.2.dev153
4
4
  Summary: CLI to run the NDS MapViewer Docker container for visualizing map data (NDS.Live, GeoJSON, and more)
5
5
  Author-email: NDS Association <support@nds-association.org>
6
6
  License: Proprietary
@@ -131,7 +131,8 @@ That mapped YAML is a disposable, one-way transformed copy. Map-preset catalogs
131
131
  configured under `erdblick.mapPresets` are passed through, but the browser marks
132
132
  their management surface read-only in CLI-launched sessions; edits are not written
133
133
  back to the original host config. Edit the host YAML and let the normal config sync
134
- reload it instead.
134
+ reload it instead. Enabling `allow-post-config` does not make this generated copy a
135
+ durable map-preset write target.
135
136
 
136
137
  ## Editions
137
138
 
@@ -98,7 +98,8 @@ That mapped YAML is a disposable, one-way transformed copy. Map-preset catalogs
98
98
  configured under `erdblick.mapPresets` are passed through, but the browser marks
99
99
  their management surface read-only in CLI-launched sessions; edits are not written
100
100
  back to the original host config. Edit the host YAML and let the normal config sync
101
- reload it instead.
101
+ reload it instead. Enabling `allow-post-config` does not make this generated copy a
102
+ durable map-preset write target.
102
103
 
103
104
  ## Editions
104
105
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nds-mapviewer
3
- Version: 2026.3.2.dev151
3
+ Version: 2026.3.2.dev153
4
4
  Summary: CLI to run the NDS MapViewer Docker container for visualizing map data (NDS.Live, GeoJSON, and more)
5
5
  Author-email: NDS Association <support@nds-association.org>
6
6
  License: Proprietary
@@ -131,7 +131,8 @@ That mapped YAML is a disposable, one-way transformed copy. Map-preset catalogs
131
131
  configured under `erdblick.mapPresets` are passed through, but the browser marks
132
132
  their management surface read-only in CLI-launched sessions; edits are not written
133
133
  back to the original host config. Edit the host YAML and let the normal config sync
134
- reload it instead.
134
+ reload it instead. Enabling `allow-post-config` does not make this generated copy a
135
+ durable map-preset write target.
135
136
 
136
137
  ## Editions
137
138
 
@@ -27,6 +27,7 @@ FOLDER_URI_PATTERN = re.compile(r"^folder:(.+)$")
27
27
  LOCALHOST_PATTERN = re.compile(r"^(localhost|127\.0\.0\.1)(:\d+)?$")
28
28
  CUSTOM_STYLES_ROOT = "/custom-styles"
29
29
  CUSTOM_BACKGROUNDS_ROOT = "/custom-backgrounds"
30
+ COORDINATE_LEGAL_TERMS_ROOT = "/coordinates-legal-terms"
30
31
 
31
32
  # Default config for demo mode
32
33
  DEFAULT_DEMO_CONFIG = {
@@ -484,6 +485,18 @@ def transform_config(
484
485
  return container_dir
485
486
  return f"{container_dir}/{suffix}"
486
487
 
488
+ def transform_coordinate_legal_terms(value: str) -> str:
489
+ """Mount one local legal-terms document below its public static root."""
490
+ value = value.strip()
491
+ if not value or _is_explicit_browser_path(value, COORDINATE_LEGAL_TERMS_ROOT):
492
+ return value
493
+ host_file = _resolve_host_asset_path(value, base_dir)
494
+ return add_asset_volume(
495
+ host_file,
496
+ COORDINATE_LEGAL_TERMS_ROOT,
497
+ f"{COORDINATE_LEGAL_TERMS_ROOT}/{host_file.name}",
498
+ )
499
+
487
500
  erdblick = transformed.get("erdblick")
488
501
  if isinstance(erdblick, dict):
489
502
  additional_styles = erdblick.get("additionalStyles")
@@ -509,6 +522,12 @@ def transform_config(
509
522
  for item in url_template
510
523
  ]
511
524
 
525
+ coordinate_legal_terms = erdblick.get("coordinates-legal-terms")
526
+ if isinstance(coordinate_legal_terms, str):
527
+ erdblick["coordinates-legal-terms"] = transform_coordinate_legal_terms(
528
+ coordinate_legal_terms
529
+ )
530
+
512
531
  return TransformedConfig(config=transformed, volumes=volumes + asset_volumes)
513
532
 
514
533
 
@@ -631,6 +650,27 @@ def validate_paths(
631
650
  f"Directory does not exist: {host_root}"
632
651
  )
633
652
 
653
+ coordinate_legal_terms = erdblick.get("coordinates-legal-terms")
654
+ if isinstance(coordinate_legal_terms, str):
655
+ coordinate_legal_terms = coordinate_legal_terms.strip()
656
+ if (
657
+ coordinate_legal_terms
658
+ and not _is_explicit_browser_path(
659
+ coordinate_legal_terms, COORDINATE_LEGAL_TERMS_ROOT
660
+ )
661
+ ):
662
+ host_file = _resolve_host_asset_path(coordinate_legal_terms, base_dir)
663
+ if host_file.suffix.lower() not in (".json", ".yaml", ".yml"):
664
+ errors.append(
665
+ "erdblick.coordinates-legal-terms: "
666
+ "File must use .json, .yaml, or .yml"
667
+ )
668
+ elif not host_file.is_file():
669
+ errors.append(
670
+ "erdblick.coordinates-legal-terms: "
671
+ f"File does not exist: {host_file}"
672
+ )
673
+
634
674
  return errors
635
675
 
636
676
 
@@ -472,6 +472,52 @@ class TestTransformConfig:
472
472
  assert layers[2]["url"] == "service"
473
473
  assert any(_same_path(vol.host_path, imagery_dir) for vol in result.volumes)
474
474
 
475
+ def test_erdblick_coordinate_legal_terms_are_mapped_from_config_dir(
476
+ self, temp_dir
477
+ ):
478
+ """Relative coordinate terms are mounted at the dedicated browser root."""
479
+ legal_dir = temp_dir / "legal"
480
+ legal_dir.mkdir()
481
+ legal_file = legal_dir / "coordinates.yaml"
482
+ legal_file.write_text("legal-terms: Test terms\n")
483
+ config = {
484
+ "sources": [],
485
+ "erdblick": {
486
+ "coordinates-enabled": True,
487
+ "coordinates-legal-terms": "legal/coordinates.yaml",
488
+ },
489
+ }
490
+
491
+ result = transform_config(config, base_dir=temp_dir)
492
+
493
+ assert result.config["erdblick"]["coordinates-enabled"] is True
494
+ assert result.config["erdblick"]["coordinates-legal-terms"] == (
495
+ "/coordinates-legal-terms/coordinates.yaml"
496
+ )
497
+ assert any(
498
+ _same_path(vol.host_path, legal_file)
499
+ and vol.container_path == "/coordinates-legal-terms/coordinates.yaml"
500
+ for vol in result.volumes
501
+ )
502
+
503
+ def test_explicit_coordinate_legal_terms_browser_path_is_preserved(self):
504
+ """Raw-Docker browser paths do not create Python-managed mounts."""
505
+ config = {
506
+ "sources": [],
507
+ "erdblick": {
508
+ "coordinates-legal-terms": (
509
+ "/coordinates-legal-terms/manual.json"
510
+ )
511
+ },
512
+ }
513
+
514
+ result = transform_config(config)
515
+
516
+ assert result.config["erdblick"]["coordinates-legal-terms"] == (
517
+ "/coordinates-legal-terms/manual.json"
518
+ )
519
+ assert result.volumes == []
520
+
475
521
  def test_existing_volume_mapping_is_reused(self, temp_dir):
476
522
  """Hot reloads keep container paths stable when entries are removed."""
477
523
  first = temp_dir / "first"
@@ -633,6 +679,30 @@ class TestValidatePaths:
633
679
  assert "erdblick.additionalStyles[0]" in errors[0]
634
680
  assert "erdblick.backgroundLayers[0].urlTemplate[0]" in errors[1]
635
681
 
682
+ def test_coordinate_legal_terms_path_and_extension_are_validated(self, temp_dir):
683
+ """Coordinate terms must be an existing JSON/YAML file."""
684
+ legal_file = temp_dir / "terms.json"
685
+ legal_file.write_text('{"legal-terms":"Text"}\n')
686
+
687
+ assert validate_paths(
688
+ {"erdblick": {"coordinates-legal-terms": "terms.json"}},
689
+ base_dir=temp_dir,
690
+ ) == []
691
+
692
+ missing_errors = validate_paths(
693
+ {"erdblick": {"coordinates-legal-terms": "missing.yaml"}},
694
+ base_dir=temp_dir,
695
+ )
696
+ extension_errors = validate_paths(
697
+ {"erdblick": {"coordinates-legal-terms": "terms.txt"}},
698
+ base_dir=temp_dir,
699
+ )
700
+
701
+ assert len(missing_errors) == 1
702
+ assert "File does not exist" in missing_errors[0]
703
+ assert len(extension_errors) == 1
704
+ assert "File must use .json, .yaml, or .yml" in extension_errors[0]
705
+
636
706
 
637
707
  class TestWriteConfigToTemp:
638
708
  """Tests for write_config_to_temp()."""