geodeploy 1.3.0__tar.gz → 1.4.0__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.
- {geodeploy-1.3.0/geodeploy.egg-info → geodeploy-1.4.0}/PKG-INFO +1 -1
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/__init__.py +1 -1
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/_common.py +22 -4
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/layers.py +5 -2
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/portals.py +13 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/styles.py +27 -4
- {geodeploy-1.3.0 → geodeploy-1.4.0/geodeploy.egg-info}/PKG-INFO +1 -1
- {geodeploy-1.3.0 → geodeploy-1.4.0}/LICENSE +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/MANIFEST.in +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/NOTICE +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/PYPI.md +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/README.md +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/__main__.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/admin.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/catalog.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/__init__.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/__init__.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/admin.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/auth.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/browse.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/catalog.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/imports.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/jobs.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/portals.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/sources.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/upload.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/main.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/output.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/client.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/config.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/errors.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/imports.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/jobs.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/layers.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/py.typed +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/sources.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/transport.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/uploads.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy.egg-info/SOURCES.txt +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy.egg-info/dependency_links.txt +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy.egg-info/entry_points.txt +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy.egg-info/requires.txt +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy.egg-info/top_level.txt +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/pyproject.toml +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/setup.cfg +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/conftest.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_cli.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_config.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_layers_portals.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_output.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_styles_jobs.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_transport.py +0 -0
- {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_uploads.py +0 -0
|
@@ -14,7 +14,7 @@ from __future__ import annotations
|
|
|
14
14
|
# The CLI's version tracks the GeoDeploy release it ships with. A PyPI version can never be
|
|
15
15
|
# re-uploaded, so a number is only spent once the release it names exists: 1.3.0b1 proved the
|
|
16
16
|
# packaging against the real index, and this is the release it was rehearsing for.
|
|
17
|
-
__version__ = "1.
|
|
17
|
+
__version__ = "1.4.0"
|
|
18
18
|
|
|
19
19
|
from .client import Client # noqa: E402 (after __version__ — the user agent reads it)
|
|
20
20
|
from .errors import ( # noqa: E402
|
|
@@ -27,8 +27,9 @@ def add_style_args(parser, raster: bool = True) -> None:
|
|
|
27
27
|
single.add_argument("--outline-color",
|
|
28
28
|
help="outline colour, or 'none' for no outline at all")
|
|
29
29
|
single.add_argument("--outline-width", type=float,
|
|
30
|
-
help="
|
|
31
|
-
"— a wide one on a small marker is how a ring is drawn"
|
|
30
|
+
help="outline width. On POINTS a fraction of the radius (0-1, default "
|
|
31
|
+
"0.28) — a wide one on a small marker is how a ring is drawn. On "
|
|
32
|
+
"POLYGONS a width in px (default 1)")
|
|
32
33
|
single.add_argument("--line-width", type=float, help="line width in px")
|
|
33
34
|
single.add_argument("--radius", type=float, help="point radius in px")
|
|
34
35
|
single.add_argument("--marker", choices=MARKERS, help="point marker shape")
|
|
@@ -77,9 +78,25 @@ def add_style_args(parser, raster: bool = True) -> None:
|
|
|
77
78
|
if raster:
|
|
78
79
|
rast = parser.add_argument_group("raster")
|
|
79
80
|
rast.add_argument("--colormap", help="TiTiler colormap, e.g. viridis (see `layers colormaps`)")
|
|
81
|
+
rast.add_argument("--reverse-colormap", dest="colormap_reverse", action="store_true",
|
|
82
|
+
default=None,
|
|
83
|
+
help="flip the palette (low values take the colour high values had)")
|
|
84
|
+
rast.add_argument("--no-reverse-colormap", dest="colormap_reverse", action="store_false",
|
|
85
|
+
help="undo --reverse-colormap")
|
|
80
86
|
rast.add_argument("--rescale", help="stretch as 'min,max' (see `layers stats` for a suggestion)")
|
|
81
|
-
rast.add_argument("--algorithm", help="
|
|
87
|
+
rast.add_argument("--algorithm", help="hillshade or contours (single-band)")
|
|
82
88
|
rast.add_argument("--zfactor", type=float, help="hillshade vertical exaggeration")
|
|
89
|
+
# Contours colours the data across its range with a built-in terrain ramp and draws the
|
|
90
|
+
# lines on that, so --rescale is not decoration here: without it the whole raster renders
|
|
91
|
+
# as one flat band. See services/titiler._contour_params.
|
|
92
|
+
rast.add_argument("--increment", type=float,
|
|
93
|
+
help="contour interval, in the raster's own units (default 35)")
|
|
94
|
+
rast.add_argument("--thickness", type=int,
|
|
95
|
+
help="contour line width in pixels (default 1)")
|
|
96
|
+
rast.add_argument("--minz", type=float,
|
|
97
|
+
help="low end of the contour colour range (defaults to --rescale)")
|
|
98
|
+
rast.add_argument("--maxz", type=float,
|
|
99
|
+
help="high end of the contour colour range (defaults to --rescale)")
|
|
83
100
|
rast.add_argument("--bidx", help="band selection: '1' or '3,2,1' for an RGB composite")
|
|
84
101
|
|
|
85
102
|
parser.add_argument("--style-json",
|
|
@@ -112,7 +129,8 @@ def style_from_args(args, client=None, layer_ref: Optional[Any] = None,
|
|
|
112
129
|
|
|
113
130
|
kwargs = {} # type: Dict[str, Any]
|
|
114
131
|
for name in ("color", "fill_opacity", "outline_color", "outline_width", "line_width",
|
|
115
|
-
"radius", "marker", "line_type", "colormap", "
|
|
132
|
+
"radius", "marker", "line_type", "colormap", "colormap_reverse",
|
|
133
|
+
"rescale", "algorithm", "zfactor", "increment", "thickness", "minz", "maxz",
|
|
116
134
|
"color_field", "color_mode", "size_field", "other_color", "size_stops",
|
|
117
135
|
"extrude_field", "extrude_scale", "extrude_base", "extrude_color",
|
|
118
136
|
"extrude_opacity", "extrude_radius"):
|
|
@@ -12,6 +12,7 @@ import sys
|
|
|
12
12
|
from ...errors import GeoDeployError, NotFoundError, ValidationError
|
|
13
13
|
from ..main import add_command, group_parser
|
|
14
14
|
from ..output import EXIT_GENERIC, EXIT_OK, human_size
|
|
15
|
+
from ...styles import RASTER_STYLE_KEYS
|
|
15
16
|
from ._common import (add_style_args, confirm, layer_ref_arg, parse_fields, resolve_layer,
|
|
16
17
|
style_from_args, write_json_file)
|
|
17
18
|
|
|
@@ -58,6 +59,7 @@ examples:
|
|
|
58
59
|
geodeploy layers style sites --marker star --radius 6 --outline-color none
|
|
59
60
|
geodeploy layers style parcels --color-field pop --classify jenks --classes 6 --ramp magma
|
|
60
61
|
geodeploy layers style dem --colormap terrain --rescale 0,2400
|
|
62
|
+
geodeploy layers style depth --colormap blues --reverse-colormap
|
|
61
63
|
""")
|
|
62
64
|
layer_ref_arg(style)
|
|
63
65
|
style.add_argument("--popup-fields", help="comma-separated attribute names for popups")
|
|
@@ -190,7 +192,8 @@ def cmd_legend(ctx, args) -> int:
|
|
|
190
192
|
ctx.out.json(legend)
|
|
191
193
|
return EXIT_OK
|
|
192
194
|
if legend.get("ramp"):
|
|
193
|
-
ctx.out.record(legend, ["layer", "colormap", "
|
|
195
|
+
ctx.out.record(legend, ["layer", "colormap", "colormap_reverse", "rescale", "algorithm",
|
|
196
|
+
"zfactor", "increment", "thickness", "bidx", "band_count"])
|
|
194
197
|
ctx.out.info("A raster legend is a continuous ramp, so there are no swatches to list.")
|
|
195
198
|
return EXIT_OK
|
|
196
199
|
ctx.out.out(ctx.out.bold(legend.get("layer") or ""))
|
|
@@ -467,7 +470,7 @@ def cmd_style(ctx, args) -> int:
|
|
|
467
470
|
else:
|
|
468
471
|
# The raster default-style body is flat: colormap/rescale/algorithm live at the top level.
|
|
469
472
|
body = {"opacity": body["opacity"]}
|
|
470
|
-
for key in
|
|
473
|
+
for key in RASTER_STYLE_KEYS:
|
|
471
474
|
if style.get(key) is not None:
|
|
472
475
|
body[key] = style[key]
|
|
473
476
|
|
|
@@ -136,6 +136,19 @@ class Portals(object):
|
|
|
136
136
|
|
|
137
137
|
# ── layers on a portal ──────────────────────────────────────────────────────────────────────
|
|
138
138
|
|
|
139
|
+
def upload_thumbnail(self, portal_id: Any, path: str) -> Dict[str, Any]:
|
|
140
|
+
"""The card image for this portal — the picture shown wherever it is listed.
|
|
141
|
+
|
|
142
|
+
The dashboard captures its map canvas at publish time; anything else that publishes a
|
|
143
|
+
portal has to supply its own, or the card stays blank. Separate from `upload_asset`: a
|
|
144
|
+
portal has exactly one thumbnail, and the server replaces the previous one.
|
|
145
|
+
"""
|
|
146
|
+
from .transport import MultipartBody
|
|
147
|
+
body = MultipartBody(file_path=path, filename=os.path.basename(path))
|
|
148
|
+
return self._c.request("POST", "/portals/{0}/thumbnail".format(int(portal_id)),
|
|
149
|
+
body=body, content_type=body.content_type,
|
|
150
|
+
timeout=self._c.upload_timeout)
|
|
151
|
+
|
|
139
152
|
def layers(self, portal: Any) -> List[Dict[str, Any]]:
|
|
140
153
|
"""The portal's layer configs, top of the list first."""
|
|
141
154
|
doc = portal if isinstance(portal, dict) else self.get(portal)
|
|
@@ -31,6 +31,14 @@ COLOR_MODES = ("single", "graduated", "categorized")
|
|
|
31
31
|
#: what an uninitialised colour input produces and would silently turn outlines off.
|
|
32
32
|
NO_OUTLINE = "none"
|
|
33
33
|
|
|
34
|
+
#: Every key a RASTER style is made of — the twin of `services/titiler.STYLE_KEYS` and of
|
|
35
|
+
#: `ui/src/lib/mapStyle.RASTER_STYLE_KEYS`. `opacity` is not one of them: the map applies it, the
|
|
36
|
+
#: tile server does not. Named once because the same list, written out by hand, had already fallen
|
|
37
|
+
#: behind in four UI components, seven API call sites and this CLI — and a key that is merely
|
|
38
|
+
#: FORGOTTEN does not fail. It quietly serves the layer in a style nobody chose.
|
|
39
|
+
RASTER_STYLE_KEYS = ("colormap", "colormap_reverse", "rescale", "algorithm", "zfactor", "bidx",
|
|
40
|
+
"color_classes", "increment", "thickness", "minz", "maxz")
|
|
41
|
+
|
|
34
42
|
#: CLI/keyword name → the key the style dict actually uses. Only `line_type` differs, and it
|
|
35
43
|
#: differs because the stored key is camelCase (`lineType`) for historical reasons.
|
|
36
44
|
_SIMPLE_KEYS = (
|
|
@@ -46,6 +54,11 @@ _SIMPLE_KEYS = (
|
|
|
46
54
|
("rescale", "rescale"),
|
|
47
55
|
("algorithm", "algorithm"),
|
|
48
56
|
("zfactor", "zfactor"),
|
|
57
|
+
# Contours: spacing, line width, and the range its background relief is coloured over.
|
|
58
|
+
("increment", "increment"),
|
|
59
|
+
("thickness", "thickness"),
|
|
60
|
+
("minz", "minz"),
|
|
61
|
+
("maxz", "maxz"),
|
|
49
62
|
("bidx", "bidx"),
|
|
50
63
|
("other_color", "other_color"),
|
|
51
64
|
("color_field", "color_field"),
|
|
@@ -255,10 +268,20 @@ def _validate(style: Dict[str, Any]) -> None:
|
|
|
255
268
|
mode = style.get("color_mode")
|
|
256
269
|
if mode is not None and mode not in COLOR_MODES:
|
|
257
270
|
raise ValidationError(400, "Colour mode must be one of {0}.".format(", ".join(COLOR_MODES)))
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
271
|
+
value = style.get("fill_opacity")
|
|
272
|
+
if value is not None and not 0 <= float(value) <= 1:
|
|
273
|
+
raise ValidationError(400, "fill_opacity is a fraction between 0 and 1.")
|
|
274
|
+
# `outline_width` MEANS TWO THINGS and this validator cannot see the geometry: on a POINT it is
|
|
275
|
+
# a fraction of the radius (0-1), on a POLYGON a width in CSS pixels. Refusing anything above 1
|
|
276
|
+
# made a polygon border impossible to set from here at all — "outline_width is a fraction
|
|
277
|
+
# between 0 and 1" for a perfectly ordinary 3 px edge. The renderers clamp for their own
|
|
278
|
+
# geometry (a marker ratio is capped at 1, a polygon width at 40), so the check here is only a
|
|
279
|
+
# sanity bound on a number that has no single unit.
|
|
280
|
+
value = style.get("outline_width")
|
|
281
|
+
if value is not None and not 0 <= float(value) <= 40:
|
|
282
|
+
raise ValidationError(
|
|
283
|
+
400, "outline_width is a fraction of the radius on points (0-1) and a width in pixels "
|
|
284
|
+
"on polygons (up to 40).")
|
|
262
285
|
|
|
263
286
|
|
|
264
287
|
class Style(object):
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|