nds-mapviewer 2026.3.2.dev117__tar.gz → 2026.3.2.dev119__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.
- {nds_mapviewer-2026.3.2.dev117/src/nds_mapviewer.egg-info → nds_mapviewer-2026.3.2.dev119}/PKG-INFO +1 -1
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119/src/nds_mapviewer.egg-info}/PKG-INFO +1 -1
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/config.py +0 -85
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/tests/test_config.py +0 -140
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/.gitignore +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/CHANGELOG.md +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/README.md +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/pyproject.toml +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/setup.cfg +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/setup.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/nds_mapviewer.egg-info/SOURCES.txt +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/nds_mapviewer.egg-info/dependency_links.txt +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/nds_mapviewer.egg-info/entry_points.txt +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/nds_mapviewer.egg-info/requires.txt +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/nds_mapviewer.egg-info/top_level.txt +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/__init__.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/browser.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/cli.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/clipboard.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/container_runtime.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/docker_client.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/exceptions.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/tui.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/ui.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/viewer.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/tests/conftest.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/tests/test_cli.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/tests/test_clipboard.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/tests/test_docker_client.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/tests/test_tui.py +0 -0
- {nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/tests/test_viewer.py +0 -0
{nds_mapviewer-2026.3.2.dev117/src/nds_mapviewer.egg-info → nds_mapviewer-2026.3.2.dev119}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nds-mapviewer
|
|
3
|
-
Version: 2026.3.2.
|
|
3
|
+
Version: 2026.3.2.dev119
|
|
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
|
{nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119/src/nds_mapviewer.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nds-mapviewer
|
|
3
|
-
Version: 2026.3.2.
|
|
3
|
+
Version: 2026.3.2.dev119
|
|
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
|
{nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/config.py
RENAMED
|
@@ -26,9 +26,7 @@ FILESTORE_PATTERN = re.compile(r"^filestore:(.+)$")
|
|
|
26
26
|
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
|
-
STYLE_OPTION_PRESETS_ROOT = "/style-option-presets"
|
|
30
29
|
CUSTOM_BACKGROUNDS_ROOT = "/custom-backgrounds"
|
|
31
|
-
COORDINATE_LEGAL_TERMS_ROOT = "/coordinates-legal-terms"
|
|
32
30
|
|
|
33
31
|
# Default config for demo mode
|
|
34
32
|
DEFAULT_DEMO_CONFIG = {
|
|
@@ -480,34 +478,6 @@ def transform_config(
|
|
|
480
478
|
return container_dir
|
|
481
479
|
return f"{container_dir}/{suffix}"
|
|
482
480
|
|
|
483
|
-
def transform_coordinate_legal_terms(value: str) -> str:
|
|
484
|
-
"""Mount one local legal-terms document below its public static root."""
|
|
485
|
-
value = value.strip()
|
|
486
|
-
if not value or _is_explicit_browser_path(value, COORDINATE_LEGAL_TERMS_ROOT):
|
|
487
|
-
return value
|
|
488
|
-
host_file = _resolve_host_asset_path(value, base_dir)
|
|
489
|
-
return add_asset_volume(
|
|
490
|
-
host_file,
|
|
491
|
-
COORDINATE_LEGAL_TERMS_ROOT,
|
|
492
|
-
f"{COORDINATE_LEGAL_TERMS_ROOT}/{host_file.name}",
|
|
493
|
-
)
|
|
494
|
-
|
|
495
|
-
def transform_style_option_presets(value: str) -> str:
|
|
496
|
-
"""Mount one local preset document below its dedicated public root."""
|
|
497
|
-
value = value.strip()
|
|
498
|
-
if (
|
|
499
|
-
not value
|
|
500
|
-
or _is_external_or_bundle_url(value)
|
|
501
|
-
or _is_explicit_browser_path(value, STYLE_OPTION_PRESETS_ROOT)
|
|
502
|
-
):
|
|
503
|
-
return value
|
|
504
|
-
host_file = _resolve_host_asset_path(value, base_dir)
|
|
505
|
-
return add_asset_volume(
|
|
506
|
-
host_file,
|
|
507
|
-
STYLE_OPTION_PRESETS_ROOT,
|
|
508
|
-
f"{STYLE_OPTION_PRESETS_ROOT}/{host_file.name}",
|
|
509
|
-
)
|
|
510
|
-
|
|
511
481
|
erdblick = transformed.get("erdblick")
|
|
512
482
|
if isinstance(erdblick, dict):
|
|
513
483
|
additional_styles = erdblick.get("additionalStyles")
|
|
@@ -533,18 +503,6 @@ def transform_config(
|
|
|
533
503
|
for item in url_template
|
|
534
504
|
]
|
|
535
505
|
|
|
536
|
-
coordinate_legal_terms = erdblick.get("coordinates-legal-terms")
|
|
537
|
-
if isinstance(coordinate_legal_terms, str):
|
|
538
|
-
erdblick["coordinates-legal-terms"] = transform_coordinate_legal_terms(
|
|
539
|
-
coordinate_legal_terms
|
|
540
|
-
)
|
|
541
|
-
|
|
542
|
-
style_option_presets = erdblick.get("styleOptionPresets")
|
|
543
|
-
if isinstance(style_option_presets, str):
|
|
544
|
-
erdblick["styleOptionPresets"] = transform_style_option_presets(
|
|
545
|
-
style_option_presets
|
|
546
|
-
)
|
|
547
|
-
|
|
548
506
|
return TransformedConfig(config=transformed, volumes=volumes + asset_volumes)
|
|
549
507
|
|
|
550
508
|
|
|
@@ -667,49 +625,6 @@ def validate_paths(
|
|
|
667
625
|
f"Directory does not exist: {host_root}"
|
|
668
626
|
)
|
|
669
627
|
|
|
670
|
-
coordinate_legal_terms = erdblick.get("coordinates-legal-terms")
|
|
671
|
-
if isinstance(coordinate_legal_terms, str):
|
|
672
|
-
coordinate_legal_terms = coordinate_legal_terms.strip()
|
|
673
|
-
if (
|
|
674
|
-
coordinate_legal_terms
|
|
675
|
-
and not _is_explicit_browser_path(
|
|
676
|
-
coordinate_legal_terms, COORDINATE_LEGAL_TERMS_ROOT
|
|
677
|
-
)
|
|
678
|
-
):
|
|
679
|
-
host_file = _resolve_host_asset_path(coordinate_legal_terms, base_dir)
|
|
680
|
-
if host_file.suffix.lower() not in (".json", ".yaml", ".yml"):
|
|
681
|
-
errors.append(
|
|
682
|
-
"erdblick.coordinates-legal-terms: "
|
|
683
|
-
"File must use .json, .yaml, or .yml"
|
|
684
|
-
)
|
|
685
|
-
elif not host_file.is_file():
|
|
686
|
-
errors.append(
|
|
687
|
-
"erdblick.coordinates-legal-terms: "
|
|
688
|
-
f"File does not exist: {host_file}"
|
|
689
|
-
)
|
|
690
|
-
|
|
691
|
-
style_option_presets = erdblick.get("styleOptionPresets")
|
|
692
|
-
if isinstance(style_option_presets, str):
|
|
693
|
-
style_option_presets = style_option_presets.strip()
|
|
694
|
-
if (
|
|
695
|
-
style_option_presets
|
|
696
|
-
and not _is_external_or_bundle_url(style_option_presets)
|
|
697
|
-
and not _is_explicit_browser_path(
|
|
698
|
-
style_option_presets, STYLE_OPTION_PRESETS_ROOT
|
|
699
|
-
)
|
|
700
|
-
):
|
|
701
|
-
host_file = _resolve_host_asset_path(style_option_presets, base_dir)
|
|
702
|
-
if host_file.suffix.lower() not in (".yaml", ".yml"):
|
|
703
|
-
errors.append(
|
|
704
|
-
"erdblick.styleOptionPresets: "
|
|
705
|
-
"File must use .yaml or .yml"
|
|
706
|
-
)
|
|
707
|
-
elif not host_file.is_file():
|
|
708
|
-
errors.append(
|
|
709
|
-
"erdblick.styleOptionPresets: "
|
|
710
|
-
f"File does not exist: {host_file}"
|
|
711
|
-
)
|
|
712
|
-
|
|
713
628
|
return errors
|
|
714
629
|
|
|
715
630
|
|
|
@@ -453,90 +453,6 @@ class TestTransformConfig:
|
|
|
453
453
|
assert layers[2]["url"] == "service"
|
|
454
454
|
assert any(_same_path(vol.host_path, imagery_dir) for vol in result.volumes)
|
|
455
455
|
|
|
456
|
-
def test_erdblick_coordinate_legal_terms_are_mapped_from_config_dir(
|
|
457
|
-
self, temp_dir
|
|
458
|
-
):
|
|
459
|
-
"""Relative coordinate terms are mounted at the dedicated browser root."""
|
|
460
|
-
legal_dir = temp_dir / "legal"
|
|
461
|
-
legal_dir.mkdir()
|
|
462
|
-
legal_file = legal_dir / "coordinates.yaml"
|
|
463
|
-
legal_file.write_text("legal-terms: Test terms\n")
|
|
464
|
-
config = {
|
|
465
|
-
"sources": [],
|
|
466
|
-
"erdblick": {
|
|
467
|
-
"coordinates-enabled": True,
|
|
468
|
-
"coordinates-legal-terms": "legal/coordinates.yaml",
|
|
469
|
-
},
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
result = transform_config(config, base_dir=temp_dir)
|
|
473
|
-
|
|
474
|
-
assert result.config["erdblick"]["coordinates-enabled"] is True
|
|
475
|
-
assert result.config["erdblick"]["coordinates-legal-terms"] == (
|
|
476
|
-
"/coordinates-legal-terms/coordinates.yaml"
|
|
477
|
-
)
|
|
478
|
-
assert any(
|
|
479
|
-
_same_path(vol.host_path, legal_file)
|
|
480
|
-
and vol.container_path == "/coordinates-legal-terms/coordinates.yaml"
|
|
481
|
-
for vol in result.volumes
|
|
482
|
-
)
|
|
483
|
-
|
|
484
|
-
def test_explicit_coordinate_legal_terms_browser_path_is_preserved(self):
|
|
485
|
-
"""Raw-Docker browser paths do not create Python-managed mounts."""
|
|
486
|
-
config = {
|
|
487
|
-
"sources": [],
|
|
488
|
-
"erdblick": {
|
|
489
|
-
"coordinates-legal-terms": (
|
|
490
|
-
"/coordinates-legal-terms/manual.json"
|
|
491
|
-
)
|
|
492
|
-
},
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
result = transform_config(config)
|
|
496
|
-
|
|
497
|
-
assert result.config["erdblick"]["coordinates-legal-terms"] == (
|
|
498
|
-
"/coordinates-legal-terms/manual.json"
|
|
499
|
-
)
|
|
500
|
-
assert result.volumes == []
|
|
501
|
-
|
|
502
|
-
def test_style_option_presets_are_mapped_from_config_dir(self, temp_dir):
|
|
503
|
-
"""A relative preset YAML is mounted as one file at its dedicated root."""
|
|
504
|
-
presets_dir = temp_dir / "presets"
|
|
505
|
-
presets_dir.mkdir()
|
|
506
|
-
presets_file = presets_dir / "viewer.yaml"
|
|
507
|
-
presets_file.write_text("version: 1\npresets: []\n")
|
|
508
|
-
config = {
|
|
509
|
-
"sources": [],
|
|
510
|
-
"erdblick": {
|
|
511
|
-
"styleOptionPresets": "presets/viewer.yaml",
|
|
512
|
-
},
|
|
513
|
-
}
|
|
514
|
-
|
|
515
|
-
result = transform_config(config, base_dir=temp_dir)
|
|
516
|
-
|
|
517
|
-
assert result.config["erdblick"]["styleOptionPresets"] == (
|
|
518
|
-
"/style-option-presets/viewer.yaml"
|
|
519
|
-
)
|
|
520
|
-
assert any(
|
|
521
|
-
_same_path(volume.host_path, presets_file)
|
|
522
|
-
and volume.container_path == "/style-option-presets/viewer.yaml"
|
|
523
|
-
for volume in result.volumes
|
|
524
|
-
)
|
|
525
|
-
|
|
526
|
-
def test_style_option_preset_urls_are_preserved(self):
|
|
527
|
-
"""External, bundled, and explicit browser URLs do not create mounts."""
|
|
528
|
-
for value in (
|
|
529
|
-
"https://example.com/presets.yaml",
|
|
530
|
-
"bundle/styles/style-option-presets.yaml",
|
|
531
|
-
"/style-option-presets/manual.yaml",
|
|
532
|
-
):
|
|
533
|
-
result = transform_config({
|
|
534
|
-
"sources": [],
|
|
535
|
-
"erdblick": {"styleOptionPresets": value},
|
|
536
|
-
})
|
|
537
|
-
assert result.config["erdblick"]["styleOptionPresets"] == value
|
|
538
|
-
assert result.volumes == []
|
|
539
|
-
|
|
540
456
|
def test_existing_volume_mapping_is_reused(self, temp_dir):
|
|
541
457
|
"""Hot reloads keep container paths stable when entries are removed."""
|
|
542
458
|
first = temp_dir / "first"
|
|
@@ -698,62 +614,6 @@ class TestValidatePaths:
|
|
|
698
614
|
assert "erdblick.additionalStyles[0]" in errors[0]
|
|
699
615
|
assert "erdblick.backgroundLayers[0].urlTemplate[0]" in errors[1]
|
|
700
616
|
|
|
701
|
-
def test_coordinate_legal_terms_path_and_extension_are_validated(self, temp_dir):
|
|
702
|
-
"""Coordinate terms must be an existing JSON/YAML file."""
|
|
703
|
-
legal_file = temp_dir / "terms.json"
|
|
704
|
-
legal_file.write_text('{"legal-terms":"Text"}\n')
|
|
705
|
-
|
|
706
|
-
assert validate_paths(
|
|
707
|
-
{"erdblick": {"coordinates-legal-terms": "terms.json"}},
|
|
708
|
-
base_dir=temp_dir,
|
|
709
|
-
) == []
|
|
710
|
-
|
|
711
|
-
missing_errors = validate_paths(
|
|
712
|
-
{"erdblick": {"coordinates-legal-terms": "missing.yaml"}},
|
|
713
|
-
base_dir=temp_dir,
|
|
714
|
-
)
|
|
715
|
-
extension_errors = validate_paths(
|
|
716
|
-
{"erdblick": {"coordinates-legal-terms": "terms.txt"}},
|
|
717
|
-
base_dir=temp_dir,
|
|
718
|
-
)
|
|
719
|
-
|
|
720
|
-
assert len(missing_errors) == 1
|
|
721
|
-
assert "File does not exist" in missing_errors[0]
|
|
722
|
-
assert len(extension_errors) == 1
|
|
723
|
-
assert "File must use .json, .yaml, or .yml" in extension_errors[0]
|
|
724
|
-
|
|
725
|
-
def test_style_option_preset_path_and_extension_are_validated(self, temp_dir):
|
|
726
|
-
"""Preset configuration must point at an existing YAML file."""
|
|
727
|
-
presets_file = temp_dir / "presets.yaml"
|
|
728
|
-
presets_file.write_text("version: 1\npresets: []\n")
|
|
729
|
-
|
|
730
|
-
assert validate_paths(
|
|
731
|
-
{"erdblick": {"styleOptionPresets": "presets.yaml"}},
|
|
732
|
-
base_dir=temp_dir,
|
|
733
|
-
) == []
|
|
734
|
-
assert validate_paths(
|
|
735
|
-
{"erdblick": {"styleOptionPresets": "https://example.com/presets.yaml"}},
|
|
736
|
-
base_dir=temp_dir,
|
|
737
|
-
) == []
|
|
738
|
-
assert validate_paths(
|
|
739
|
-
{"erdblick": {"styleOptionPresets": "/style-option-presets/manual.yaml"}},
|
|
740
|
-
base_dir=temp_dir,
|
|
741
|
-
) == []
|
|
742
|
-
|
|
743
|
-
missing_errors = validate_paths(
|
|
744
|
-
{"erdblick": {"styleOptionPresets": "missing.yaml"}},
|
|
745
|
-
base_dir=temp_dir,
|
|
746
|
-
)
|
|
747
|
-
extension_errors = validate_paths(
|
|
748
|
-
{"erdblick": {"styleOptionPresets": "presets.json"}},
|
|
749
|
-
base_dir=temp_dir,
|
|
750
|
-
)
|
|
751
|
-
|
|
752
|
-
assert len(missing_errors) == 1
|
|
753
|
-
assert "File does not exist" in missing_errors[0]
|
|
754
|
-
assert len(extension_errors) == 1
|
|
755
|
-
assert "File must use .yaml or .yml" in extension_errors[0]
|
|
756
|
-
|
|
757
617
|
|
|
758
618
|
class TestWriteConfigToTemp:
|
|
759
619
|
"""Tests for write_config_to_temp()."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/__init__.py
RENAMED
|
File without changes
|
{nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/browser.py
RENAMED
|
File without changes
|
{nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/cli.py
RENAMED
|
File without changes
|
{nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/clipboard.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/exceptions.py
RENAMED
|
File without changes
|
{nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/tui.py
RENAMED
|
File without changes
|
|
File without changes
|
{nds_mapviewer-2026.3.2.dev117 → nds_mapviewer-2026.3.2.dev119}/src/ndslive/mapviewer/viewer.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|