nds-mapviewer 2026.4.2.dev203__tar.gz → 2026.4.2.dev205__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.4.2.dev205/.gitignore +5 -0
  2. nds_mapviewer-2026.4.2.dev205/CHANGELOG.md +91 -0
  3. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/PKG-INFO +1 -1
  4. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/nds_mapviewer.egg-info/PKG-INFO +1 -1
  5. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/nds_mapviewer.egg-info/SOURCES.txt +3 -0
  6. nds_mapviewer-2026.4.2.dev205/tests/conftest.py +142 -0
  7. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/README.md +0 -0
  8. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/pyproject.toml +0 -0
  9. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/setup.cfg +0 -0
  10. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/setup.py +0 -0
  11. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/nds_mapviewer.egg-info/dependency_links.txt +0 -0
  12. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/nds_mapviewer.egg-info/entry_points.txt +0 -0
  13. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/nds_mapviewer.egg-info/requires.txt +0 -0
  14. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/nds_mapviewer.egg-info/top_level.txt +0 -0
  15. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/ndslive/mapviewer/__init__.py +0 -0
  16. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/ndslive/mapviewer/browser.py +0 -0
  17. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/ndslive/mapviewer/cli.py +0 -0
  18. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/ndslive/mapviewer/clipboard.py +0 -0
  19. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/ndslive/mapviewer/config.py +0 -0
  20. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/ndslive/mapviewer/container_runtime.py +0 -0
  21. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/ndslive/mapviewer/docker_client.py +0 -0
  22. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/ndslive/mapviewer/exceptions.py +0 -0
  23. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/ndslive/mapviewer/tui.py +0 -0
  24. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/ndslive/mapviewer/ui.py +0 -0
  25. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/src/ndslive/mapviewer/viewer.py +0 -0
  26. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/tests/test_cli.py +0 -0
  27. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/tests/test_clipboard.py +0 -0
  28. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/tests/test_config.py +0 -0
  29. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/tests/test_docker_client.py +0 -0
  30. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/tests/test_tui.py +0 -0
  31. {nds_mapviewer-2026.4.2.dev203 → nds_mapviewer-2026.4.2.dev205}/tests/test_viewer.py +0 -0
@@ -0,0 +1,5 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.egg-info/
4
+ dist/
5
+ build/
@@ -0,0 +1,91 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ### Added
11
+
12
+ - `--debug` flag to enable container debug logging (sets `HTTP_LOG_LEVEL=debug`)
13
+ - `--env KEY=VALUE` (repeatable, short `-E`) to pass custom environment
14
+ variables into the container; overrides `--debug` on key collision
15
+ - `--network NAME` to attach the container to a specific network (e.g. `host`);
16
+ in `host` mode port publishing is skipped and the viewer is reached on the
17
+ container's internal port
18
+ - Run screen now shows a config line below the info banner with the source
19
+ (config file or directly-passed data-source path, e.g. a `*.ndslive`
20
+ filestore) and the mapped config mounted into the container
21
+ - Accept an http(s) service URL directly as a source (e.g.
22
+ `mapviewer https://my-host/openapi.json`), turned into a
23
+ `SmartLayerTileService`; the bare-URL form configures no auth — use
24
+ ndslive-server as a proxy or a config.yaml with `http-settings` for
25
+ authenticated services
26
+ - Default Docker image version pinned to package (`--image-version` defaults to
27
+ matching calver instead of `"latest"`)
28
+ - SCM-based versioning — package version derived from MapViewer git tags
29
+
30
+ ### Fixed
31
+
32
+ - Clipboard copy in the Docker screen now uses the native OS clipboard
33
+ (`clip.exe` / `pbcopy` / `wl-copy`/`xclip`/`xsel`) instead of relying on the
34
+ OSC 52 terminal escape, which is unreliable on Windows; warns when a copy
35
+ cannot be confirmed
36
+ - Quitting the TUI no longer hangs — the log-follow stream is torn down by
37
+ terminating the process before closing pipes, and container shutdown is
38
+ bounded so the terminal is always returned to the user
39
+ - `localhost`/`127.0.0.1` in service `uri` values and `http-settings` `scope`
40
+ values are now translated to `host.docker.internal`, so a service running on
41
+ the host machine is reachable from the container without `--network host`
42
+ - Container readiness check uses log sentinel before HTTP polling to avoid
43
+ startup crash (mapget#151)
44
+
45
+ ### Changed
46
+
47
+ - Version scheme: package now follows MapViewer calver (e.g. 2025.6.2)
48
+ with post-release dev builds between releases
49
+
50
+ ## [0.1.0] - Unreleased
51
+
52
+ ### Added
53
+
54
+ - **CLI Commands**
55
+ - `setup` - Interactive setup wizard for Docker, registry auth, and image download
56
+ - `run` - Run MapViewer with a local path, saved config, or `--demo` mode
57
+ - `connect` - Interactive connection picker / wizard for saved or new data sources
58
+ - `update` - Check for and pull newer MapViewer Docker images
59
+ - Shorthand: `mapviewer <path>` resolves `.ndslive` files, SmartLayer folders, or saved config names
60
+
61
+ - **Python API**
62
+ - `MapViewer` class for programmatic container lifecycle management
63
+ - Context manager support for automatic cleanup
64
+ - `start()` / `stop()` / `restart()` for container control
65
+ - `connect()` class method to attach to a running container by name
66
+ - `logs()` with real-time streaming and severity filtering
67
+ - `status()` and `get_datasources()` for runtime introspection
68
+ - `open_browser()` to launch the viewer in a system or bundled browser
69
+
70
+ - **Configuration**
71
+ - Automatic path transformation (host paths to container mount points)
72
+ - Volume mount generation with read-only mounts and parent-directory deduplication
73
+ - Localhost translation to `host.docker.internal`
74
+ - YAML config creation helpers for filestores, SmartLayer folders, and remote services
75
+ - Saved connections stored under `~/.nds/configs/`
76
+ - Default config at `~/.nds/config.yaml` — shared across NDS tools, auto-loaded when no args given
77
+
78
+ - **Authentication**
79
+ - Six methods: API key, query parameters, basic auth, bearer token, OAuth2 client credentials, and none
80
+ - Optional proxy support with authentication
81
+
82
+ - **Browser Integration**
83
+ - Multi-platform system browser detection (Chrome, Chromium, Edge, Brave)
84
+ - Optional bundled Chromium via Playwright (`[browser]` extra)
85
+ - Automatic browser launch on `run` and `connect`
86
+
87
+ - **Setup & Diagnostics**
88
+ - Interactive setup wizard with Docker daemon and registry checks
89
+ - Image pull with progress display
90
+ - `--dry` mode for walkthroughs without Docker access
91
+ - Edition selection (community / member)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nds-mapviewer
3
- Version: 2026.4.2.dev203
3
+ Version: 2026.4.2.dev205
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nds-mapviewer
3
- Version: 2026.4.2.dev203
3
+ Version: 2026.4.2.dev205
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
@@ -1,3 +1,5 @@
1
+ .gitignore
2
+ CHANGELOG.md
1
3
  README.md
2
4
  pyproject.toml
3
5
  setup.py
@@ -18,6 +20,7 @@ src/ndslive/mapviewer/exceptions.py
18
20
  src/ndslive/mapviewer/tui.py
19
21
  src/ndslive/mapviewer/ui.py
20
22
  src/ndslive/mapviewer/viewer.py
23
+ tests/conftest.py
21
24
  tests/test_cli.py
22
25
  tests/test_clipboard.py
23
26
  tests/test_config.py
@@ -0,0 +1,142 @@
1
+ """Shared pytest fixtures and container-runtime availability check."""
2
+
3
+ import shutil
4
+ import tempfile
5
+ from pathlib import Path
6
+
7
+ import pytest
8
+ import yaml
9
+
10
+
11
+ # Default edition for tests
12
+ DEFAULT_EDITION = "member"
13
+
14
+
15
+ @pytest.fixture(scope="session")
16
+ def docker_client():
17
+ """Verify the container runtime is available, skipping tests otherwise.
18
+
19
+ Returns ``None`` — the fixture is kept for backward compatibility with
20
+ tests that declare it as a dependency to gate on runtime availability.
21
+ """
22
+ from ndslive.mapviewer import docker_client as dc
23
+ from ndslive.mapviewer.exceptions import RuntimeNotInstalled, RuntimeNotRunning
24
+
25
+ try:
26
+ dc.get_docker_client()
27
+ return None # runtime OK
28
+ except RuntimeNotInstalled:
29
+ pytest.skip("No container runtime installed (Docker/Podman)")
30
+ except RuntimeNotRunning:
31
+ pytest.skip("Container runtime is not running")
32
+
33
+
34
+ @pytest.fixture(scope="session")
35
+ def edition():
36
+ """Default edition for tests."""
37
+ return DEFAULT_EDITION
38
+
39
+
40
+ @pytest.fixture
41
+ def temp_dir():
42
+ """Create a temporary directory for test files."""
43
+ path = Path(tempfile.mkdtemp(prefix="mapviewer-test-"))
44
+ yield path
45
+ shutil.rmtree(path, ignore_errors=True)
46
+
47
+
48
+ @pytest.fixture
49
+ def sample_config(temp_dir):
50
+ """Create a sample config file with HTTP-only sources (no local paths)."""
51
+ config = {
52
+ "http-settings": [
53
+ {
54
+ "scope": "https://api.nds.live/*",
55
+ "api-key": "test-key",
56
+ }
57
+ ],
58
+ "sources": [
59
+ {
60
+ "type": "SmartLayerTileService",
61
+ "uri": "https://api.nds.live/island6/openapi.json",
62
+ "mapId": "Test Island",
63
+ }
64
+ ],
65
+ }
66
+ config_path = temp_dir / "config.yaml"
67
+ with open(config_path, "w") as f:
68
+ yaml.dump(config, f)
69
+ return config_path
70
+
71
+
72
+ @pytest.fixture
73
+ def sample_config_with_local_path(temp_dir):
74
+ """Create a sample config with a local path that needs volume mounting."""
75
+ data_dir = temp_dir / "data" / "maps"
76
+ data_dir.mkdir(parents=True)
77
+ (data_dir / "dummy.db").touch()
78
+
79
+ config = {
80
+ "sources": [
81
+ {
82
+ "type": "ClassicFolder",
83
+ "folder": str(data_dir),
84
+ "mapId": "Local Data",
85
+ }
86
+ ],
87
+ }
88
+ config_path = temp_dir / "config.yaml"
89
+ with open(config_path, "w") as f:
90
+ yaml.dump(config, f)
91
+ return config_path, data_dir
92
+
93
+
94
+ @pytest.fixture
95
+ def sample_config_filestore(temp_dir):
96
+ """Create a sample config with filestore: URI."""
97
+ data_dir = temp_dir / "filestore"
98
+ data_dir.mkdir(parents=True)
99
+ (data_dir / "test.nds").touch()
100
+
101
+ config = {
102
+ "sources": [
103
+ {
104
+ "type": "SmartLayerTileService",
105
+ "uri": f"filestore:{data_dir}",
106
+ "mapId": "Filestore Test",
107
+ }
108
+ ],
109
+ }
110
+ config_path = temp_dir / "config.yaml"
111
+ with open(config_path, "w") as f:
112
+ yaml.dump(config, f)
113
+ return config_path, data_dir
114
+
115
+
116
+ @pytest.fixture
117
+ def container_name():
118
+ """Generate a unique container name for test isolation."""
119
+ import uuid
120
+ return f"mapviewer-test-{uuid.uuid4().hex[:8]}"
121
+
122
+
123
+ @pytest.fixture
124
+ def cleanup_container(docker_client, container_name):
125
+ """Ensure test container is cleaned up after test."""
126
+ from ndslive.mapviewer import container_runtime as rt
127
+ yield container_name
128
+ try:
129
+ rt.run("stop", container_name, check=False, timeout=10)
130
+ rt.run("rm", container_name, check=False, timeout=10)
131
+ except Exception:
132
+ pass
133
+
134
+
135
+ def pytest_configure(config):
136
+ """Register custom markers."""
137
+ config.addinivalue_line(
138
+ "markers", "docker: mark test as requiring Docker"
139
+ )
140
+ config.addinivalue_line(
141
+ "markers", "slow: mark test as slow-running"
142
+ )