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.
Files changed (53) hide show
  1. {geodeploy-1.3.0/geodeploy.egg-info → geodeploy-1.4.0}/PKG-INFO +1 -1
  2. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/__init__.py +1 -1
  3. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/_common.py +22 -4
  4. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/layers.py +5 -2
  5. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/portals.py +13 -0
  6. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/styles.py +27 -4
  7. {geodeploy-1.3.0 → geodeploy-1.4.0/geodeploy.egg-info}/PKG-INFO +1 -1
  8. {geodeploy-1.3.0 → geodeploy-1.4.0}/LICENSE +0 -0
  9. {geodeploy-1.3.0 → geodeploy-1.4.0}/MANIFEST.in +0 -0
  10. {geodeploy-1.3.0 → geodeploy-1.4.0}/NOTICE +0 -0
  11. {geodeploy-1.3.0 → geodeploy-1.4.0}/PYPI.md +0 -0
  12. {geodeploy-1.3.0 → geodeploy-1.4.0}/README.md +0 -0
  13. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/__main__.py +0 -0
  14. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/admin.py +0 -0
  15. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/catalog.py +0 -0
  16. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/__init__.py +0 -0
  17. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/__init__.py +0 -0
  18. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/admin.py +0 -0
  19. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/auth.py +0 -0
  20. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/browse.py +0 -0
  21. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/catalog.py +0 -0
  22. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/imports.py +0 -0
  23. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/jobs.py +0 -0
  24. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/portals.py +0 -0
  25. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/sources.py +0 -0
  26. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/commands/upload.py +0 -0
  27. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/main.py +0 -0
  28. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/cli/output.py +0 -0
  29. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/client.py +0 -0
  30. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/config.py +0 -0
  31. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/errors.py +0 -0
  32. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/imports.py +0 -0
  33. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/jobs.py +0 -0
  34. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/layers.py +0 -0
  35. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/py.typed +0 -0
  36. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/sources.py +0 -0
  37. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/transport.py +0 -0
  38. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy/uploads.py +0 -0
  39. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy.egg-info/SOURCES.txt +0 -0
  40. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy.egg-info/dependency_links.txt +0 -0
  41. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy.egg-info/entry_points.txt +0 -0
  42. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy.egg-info/requires.txt +0 -0
  43. {geodeploy-1.3.0 → geodeploy-1.4.0}/geodeploy.egg-info/top_level.txt +0 -0
  44. {geodeploy-1.3.0 → geodeploy-1.4.0}/pyproject.toml +0 -0
  45. {geodeploy-1.3.0 → geodeploy-1.4.0}/setup.cfg +0 -0
  46. {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/conftest.py +0 -0
  47. {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_cli.py +0 -0
  48. {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_config.py +0 -0
  49. {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_layers_portals.py +0 -0
  50. {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_output.py +0 -0
  51. {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_styles_jobs.py +0 -0
  52. {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_transport.py +0 -0
  53. {geodeploy-1.3.0 → geodeploy-1.4.0}/tests/test_uploads.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: geodeploy
3
- Version: 1.3.0
3
+ Version: 1.4.0
4
4
  Summary: Command-line client and Python API for GeoDeploy — upload spatial data, build and publish portals.
5
5
  Author: Koffi Dodji Noumonvi
6
6
  License-Expression: Apache-2.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.3.0"
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="point outline width as a FRACTION of the radius (0-1, default 0.28) "
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="e.g. hillshade (single-band)")
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", "rescale", "algorithm", "zfactor",
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", "rescale", "algorithm", "bidx", "band_count"])
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 ("colormap", "rescale", "algorithm", "zfactor", "bidx"):
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
- for key in ("fill_opacity", "outline_width"):
259
- value = style.get(key)
260
- if value is not None and not 0 <= float(value) <= 1:
261
- raise ValidationError(400, "{0} is a fraction between 0 and 1.".format(key))
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):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: geodeploy
3
- Version: 1.3.0
3
+ Version: 1.4.0
4
4
  Summary: Command-line client and Python API for GeoDeploy — upload spatial data, build and publish portals.
5
5
  Author: Koffi Dodji Noumonvi
6
6
  License-Expression: Apache-2.0
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