lets-plot 4.8.1rc1__cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl

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 (97) hide show
  1. lets_plot/__init__.py +382 -0
  2. lets_plot/_global_settings.py +192 -0
  3. lets_plot/_kbridge.py +197 -0
  4. lets_plot/_type_utils.py +133 -0
  5. lets_plot/_version.py +6 -0
  6. lets_plot/bistro/__init__.py +16 -0
  7. lets_plot/bistro/_plot2d_common.py +106 -0
  8. lets_plot/bistro/corr.py +448 -0
  9. lets_plot/bistro/im.py +196 -0
  10. lets_plot/bistro/joint.py +192 -0
  11. lets_plot/bistro/qq.py +207 -0
  12. lets_plot/bistro/residual.py +341 -0
  13. lets_plot/bistro/waterfall.py +332 -0
  14. lets_plot/export/__init__.py +6 -0
  15. lets_plot/export/ggsave_.py +172 -0
  16. lets_plot/frontend_context/__init__.py +8 -0
  17. lets_plot/frontend_context/_configuration.py +140 -0
  18. lets_plot/frontend_context/_dynamic_configure_html.py +115 -0
  19. lets_plot/frontend_context/_frontend_ctx.py +16 -0
  20. lets_plot/frontend_context/_html_contexts.py +223 -0
  21. lets_plot/frontend_context/_intellij_python_json_ctx.py +38 -0
  22. lets_plot/frontend_context/_isolated_webview_panel_ctx.py +81 -0
  23. lets_plot/frontend_context/_json_contexts.py +39 -0
  24. lets_plot/frontend_context/_jupyter_notebook_ctx.py +82 -0
  25. lets_plot/frontend_context/_mime_types.py +7 -0
  26. lets_plot/frontend_context/_static_html_page_ctx.py +76 -0
  27. lets_plot/frontend_context/_static_svg_ctx.py +26 -0
  28. lets_plot/frontend_context/_webbr_html_page_ctx.py +29 -0
  29. lets_plot/frontend_context/sandbox.py +5 -0
  30. lets_plot/geo_data/__init__.py +19 -0
  31. lets_plot/geo_data/core.py +335 -0
  32. lets_plot/geo_data/geocoder.py +988 -0
  33. lets_plot/geo_data/geocodes.py +512 -0
  34. lets_plot/geo_data/gis/__init__.py +0 -0
  35. lets_plot/geo_data/gis/fluent_dict.py +201 -0
  36. lets_plot/geo_data/gis/geocoding_service.py +42 -0
  37. lets_plot/geo_data/gis/geometry.py +91 -0
  38. lets_plot/geo_data/gis/json_request.py +232 -0
  39. lets_plot/geo_data/gis/json_response.py +308 -0
  40. lets_plot/geo_data/gis/request.py +492 -0
  41. lets_plot/geo_data/gis/response.py +247 -0
  42. lets_plot/geo_data/livemap_helper.py +65 -0
  43. lets_plot/geo_data/to_geo_data_frame.py +141 -0
  44. lets_plot/geo_data/type_assertion.py +34 -0
  45. lets_plot/geo_data_internals/__init__.py +4 -0
  46. lets_plot/geo_data_internals/constants.py +13 -0
  47. lets_plot/geo_data_internals/utils.py +33 -0
  48. lets_plot/mapping.py +115 -0
  49. lets_plot/package_data/lets-plot.min.js +3 -0
  50. lets_plot/plot/__init__.py +64 -0
  51. lets_plot/plot/_global_theme.py +14 -0
  52. lets_plot/plot/annotation.py +290 -0
  53. lets_plot/plot/coord.py +242 -0
  54. lets_plot/plot/core.py +1071 -0
  55. lets_plot/plot/expand_limits_.py +78 -0
  56. lets_plot/plot/facet.py +210 -0
  57. lets_plot/plot/font_features.py +71 -0
  58. lets_plot/plot/geom.py +9146 -0
  59. lets_plot/plot/geom_extras.py +53 -0
  60. lets_plot/plot/geom_function_.py +219 -0
  61. lets_plot/plot/geom_imshow_.py +393 -0
  62. lets_plot/plot/geom_livemap_.py +343 -0
  63. lets_plot/plot/ggbunch_.py +96 -0
  64. lets_plot/plot/gggrid_.py +139 -0
  65. lets_plot/plot/ggtb_.py +81 -0
  66. lets_plot/plot/guide.py +231 -0
  67. lets_plot/plot/label.py +187 -0
  68. lets_plot/plot/marginal_layer.py +181 -0
  69. lets_plot/plot/plot.py +245 -0
  70. lets_plot/plot/pos.py +344 -0
  71. lets_plot/plot/sampling.py +338 -0
  72. lets_plot/plot/sandbox_.py +26 -0
  73. lets_plot/plot/scale.py +3580 -0
  74. lets_plot/plot/scale_colormap_mpl.py +300 -0
  75. lets_plot/plot/scale_convenience.py +155 -0
  76. lets_plot/plot/scale_identity_.py +653 -0
  77. lets_plot/plot/scale_position.py +1342 -0
  78. lets_plot/plot/series_meta.py +209 -0
  79. lets_plot/plot/stat.py +585 -0
  80. lets_plot/plot/subplots.py +331 -0
  81. lets_plot/plot/subplots_util.py +24 -0
  82. lets_plot/plot/theme_.py +790 -0
  83. lets_plot/plot/theme_set.py +418 -0
  84. lets_plot/plot/tooltip.py +486 -0
  85. lets_plot/plot/util.py +267 -0
  86. lets_plot/settings_utils.py +244 -0
  87. lets_plot/tilesets.py +429 -0
  88. lets_plot-4.8.1rc1.dist-info/METADATA +221 -0
  89. lets_plot-4.8.1rc1.dist-info/RECORD +97 -0
  90. lets_plot-4.8.1rc1.dist-info/WHEEL +6 -0
  91. lets_plot-4.8.1rc1.dist-info/licenses/LICENSE +21 -0
  92. lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.FreeType +166 -0
  93. lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.ImageMagick +106 -0
  94. lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.expat +21 -0
  95. lets_plot-4.8.1rc1.dist-info/licenses/licenses/LICENSE.fontconfig +200 -0
  96. lets_plot-4.8.1rc1.dist-info/top_level.txt +2 -0
  97. lets_plot_kotlin_bridge.cpython-311-x86_64-linux-gnu.so +0 -0
lets_plot/__init__.py ADDED
@@ -0,0 +1,382 @@
1
+ #
2
+ # Copyright (c) 2019. JetBrains s.r.o.
3
+ # Use of this source code is governed by the MIT license that can be found in the LICENSE file.
4
+ #
5
+ from pkgutil import extend_path
6
+ from typing import Dict, Union
7
+
8
+ # To handle the situation when the 'lets_plot' package is shared by modules in different locations.
9
+ __path__ = extend_path(__path__, __name__)
10
+
11
+ from ._version import __version__
12
+ from ._global_settings import _settings, is_production, get_global_bool
13
+ from ._global_settings import NO_JS, OFFLINE
14
+
15
+ from .plot import *
16
+ from .export import *
17
+ from .frontend_context import *
18
+ from .mapping import *
19
+ from .settings_utils import *
20
+ from .plot._global_theme import _set_global_theme
21
+
22
+ __all__ = (plot.__all__ +
23
+ frontend_context.__all__ +
24
+ mapping.__all__ +
25
+ settings_utils.__all__ +
26
+ export.__all__ +
27
+ ['LetsPlot'])
28
+
29
+ from .frontend_context import _configuration as cfg
30
+
31
+
32
+ class LetsPlot:
33
+ """
34
+ Initialize the library and its options.
35
+ """
36
+
37
+ @classmethod
38
+ def setup_html(cls, *,
39
+ isolated_frame: bool = None,
40
+ offline: bool = None,
41
+ no_js: bool = None,
42
+ show_status: bool = False,
43
+ **kwargs) -> None:
44
+ """
45
+ Configure Lets-Plot HTML output.
46
+ This method should typically be called before rendering any plots.
47
+ Depending on the usage, Lets-Plot generates different HTML to show plots.
48
+ In most cases Lets-Plot will detect the type of the environment automatically.
49
+ Use this method to adjust or override the autoconfigured output mode.
50
+
51
+ Parameters
52
+ ----------
53
+ isolated_frame : bool
54
+ True - generate HTML which can be used in iframe or in a standalone HTML document.
55
+ False - preload Lets-Plot JS library. Notebook cell output will only consist
56
+ of HTML for the plot rendering. Default: auto-detect.
57
+ offline : bool
58
+ True - full Lets-Plot JS bundle will be added to the notebook.
59
+ Use this option if you would like to work with a notebook without the Internet connection.
60
+ False - load Lets-Plot JS library from CDN.
61
+ Default: 'connected' mode in the production environment, 'offline' mode in the dev environment.
62
+ no_js : bool, default=False
63
+ True - do not generate HTML+JS as an output - just static SVG image.
64
+ Note that without JS interactive maps and tooltips don't work!
65
+ show_status : bool, default=False
66
+ Whether to show the Lets-Plot JS library loading status.
67
+ Only applicable when the Lets-Plot JS library is preloaded.
68
+ **kwargs
69
+ Advanced display options for developers testing in new environments
70
+ or debugging rendering behavior. These options control the underlying
71
+ HTML rendering:
72
+
73
+ - isolated_webview_panel : bool
74
+ If True, generates HTML for an isolated webview panel with dynamic script loading.
75
+ When enabled, the 'isolated_frame' parameter is ignored.
76
+ - width_mode : str
77
+ Plot width sizing mode: 'fixed', 'min', 'fit', or 'scaled'.
78
+ Requires height_mode to also be specified.
79
+ - height_mode : str
80
+ Plot height sizing mode: 'fixed', 'min', 'fit', or 'scaled'.
81
+ Requires width_mode to also be specified.
82
+ - width : float
83
+ Explicit width value in px (used with certain sizing modes).
84
+ - height : float
85
+ Explicit height value in px (used with certain sizing modes).
86
+ - force_immediate_render : bool
87
+ Controls the timing of plot rendering.
88
+ If True, renders plot immediately.
89
+ If False, waits for the ResizeObserver event to ensure proper DOM layout.
90
+ - responsive : bool
91
+ If True, the plot automatically resizes when the container is resized.
92
+ - height100pct : bool
93
+ If True, sets the plot container div height to 100%.
94
+
95
+ Sizing modes:
96
+
97
+ - 'fixed': Uses specified width/height or default size (not responsive)
98
+ - 'min': Uses smallest of: default size, specified size, and container size
99
+ - 'fit': Uses container size or specified size if provided
100
+ - 'scaled': Adjusts to preserve the aspect ratio
101
+
102
+
103
+ Examples
104
+ --------
105
+ .. jupyter-execute::
106
+ :linenos:
107
+ :emphasize-lines: 2
108
+
109
+ from lets_plot import *
110
+ LetsPlot.setup_html()
111
+ ggplot({'x': [0], 'y': [0]}, aes('x', 'y')) + geom_point()
112
+
113
+ |
114
+
115
+ .. jupyter-execute::
116
+ :linenos:
117
+ :emphasize-lines: 2-3
118
+
119
+ from lets_plot import *
120
+ LetsPlot.setup_html(isolated_frame=False, offline=True, \\
121
+ no_js=True, show_status=True)
122
+ ggplot({'x': [0], 'y': [0]}, aes('x', 'y')) + geom_point()
123
+
124
+ """
125
+ if not (isinstance(isolated_frame, bool) or isolated_frame is None):
126
+ raise ValueError("'isolated' argument is not boolean: {}".format(type(isolated_frame)))
127
+ if not (isinstance(offline, bool) or offline is None):
128
+ raise ValueError("'offline' argument is not boolean: {}".format(type(offline)))
129
+ if not (isinstance(no_js, bool) or no_js is None):
130
+ raise ValueError("'no_js' argument is not boolean: {}".format(type(no_js)))
131
+ if not isinstance(show_status, bool):
132
+ raise ValueError("'show_status' argument is not boolean: {}".format(type(show_status)))
133
+
134
+ # Validate dev options
135
+ if kwargs:
136
+ supported_keys = {'width_mode', 'height_mode', 'width', 'height',
137
+ 'responsive', 'force_immediate_render', 'height100pct', 'isolated_webview_panel'}
138
+ unsupported_keys = set(kwargs.keys()) - supported_keys
139
+ if unsupported_keys:
140
+ raise ValueError(
141
+ "Unsupported parameter(s): {}".format(', '.join(sorted(unsupported_keys)))
142
+ )
143
+
144
+ has_width_mode = 'width_mode' in kwargs
145
+ has_height_mode = 'height_mode' in kwargs
146
+ if has_width_mode != has_height_mode:
147
+ raise ValueError(
148
+ "Both 'width_mode' and 'height_mode' must be specified together. "
149
+ "Got: width_mode={}, height_mode={}".format(
150
+ kwargs.get('width_mode', 'not specified'),
151
+ kwargs.get('height_mode', 'not specified')
152
+ )
153
+ )
154
+
155
+ if has_width_mode:
156
+ valid_modes = ['fixed', 'min', 'fit', 'scaled']
157
+ width_mode = kwargs['width_mode']
158
+ if not isinstance(width_mode, str):
159
+ raise ValueError("'width_mode' must be a string, got: {}".format(type(width_mode)))
160
+ if width_mode.lower() not in valid_modes:
161
+ raise ValueError(
162
+ "'width_mode' must be one of {}, got: '{}'".format(valid_modes, width_mode)
163
+ )
164
+
165
+ if has_height_mode:
166
+ valid_modes = ['fixed', 'min', 'fit', 'scaled']
167
+ height_mode = kwargs['height_mode']
168
+ if not isinstance(height_mode, str):
169
+ raise ValueError("'height_mode' must be a string, got: {}".format(type(height_mode)))
170
+ if height_mode.lower() not in valid_modes:
171
+ raise ValueError(
172
+ "'height_mode' must be one of {}, got: '{}'".format(valid_modes, height_mode)
173
+ )
174
+
175
+ if 'width' in kwargs:
176
+ width = kwargs['width']
177
+ if not isinstance(width, (int, float)):
178
+ raise ValueError("'width' must be a number, got: {}".format(type(width)))
179
+
180
+ if 'height' in kwargs:
181
+ height = kwargs['height']
182
+ if not isinstance(height, (int, float)):
183
+ raise ValueError("'height' must be a number, got: {}".format(type(height)))
184
+
185
+ # Validate boolean options
186
+ for bool_option in ['responsive', 'force_immediate_render', 'height100pct', 'isolated_webview_panel']:
187
+ if bool_option in kwargs and not isinstance(kwargs[bool_option], bool):
188
+ raise ValueError("'{}' must be a boolean, got: {}".format(
189
+ bool_option, type(kwargs[bool_option])
190
+ ))
191
+
192
+ # Warn if isolated_webview_panel is True
193
+ if kwargs.get('isolated_webview_panel'):
194
+ print("WARNING: 'isolated_webview_panel=True' - using isolated webview panel context. "
195
+ "The 'isolated_frame' parameter will be ignored.")
196
+
197
+ offline = offline if offline is not None else get_global_bool(OFFLINE)
198
+ no_js = no_js if no_js is not None else get_global_bool(NO_JS)
199
+
200
+ cfg._setup_html_context(isolated_frame=isolated_frame,
201
+ offline=offline,
202
+ no_js=no_js,
203
+ show_status=show_status,
204
+ dev_options=kwargs)
205
+
206
+ @classmethod
207
+ def set(cls, settings: Dict):
208
+ """
209
+ Set up library options.
210
+ For more info see `Configuring Globally <https://lets-plot.org/python/pages/basemap_tiles.html#configuring-globally>`__.
211
+
212
+ Parameters
213
+ ----------
214
+ settings : dict
215
+ Dictionary of settings.
216
+
217
+ Notes
218
+ -----
219
+ List of possible settings:
220
+
221
+ - html_isolated_frame : preload Lets-Plot JS library or not (bool). Do not use this parameter explicitly. Instead you should call `LetsPlot.setup_html() <https://lets-plot.org/python/pages/api/lets_plot.LetsPlot.html#lets_plot.LetsPlot.setup_html>`__.
222
+ - offline : to work with notebook without the Internet connection (bool). Do not use this parameter explicitly. Instead you should call `LetsPlot.setup_html() <https://lets-plot.org/python/pages/api/lets_plot.LetsPlot.html#lets_plot.LetsPlot.setup_html>`__.
223
+ - no_js : do not generate HTML+JS as an output (bool). Do not use this parameter explicitly. Instead you should call `LetsPlot.setup_html() <https://lets-plot.org/python/pages/api/lets_plot.LetsPlot.html#lets_plot.LetsPlot.setup_html>`__. Also note that without JS interactive maps and tooltips doesn't work!
224
+
225
+ Interactive map settings could also be specified:
226
+
227
+ - maptiles_kind : kind of the tiles, could be 'raster_zxy' or 'vector_lets_plot'. Do not use this parameter explicitly. Instead you should construct it with functions `maptiles_zxy() <https://lets-plot.org/python/pages/api/lets_plot.maptiles_zxy.html>`__ and `maptiles_lets_plot() <https://lets-plot.org/python/pages/api/lets_plot.maptiles_lets_plot.html>`__.
228
+ - maptiles_url : address of the tile server (str). Do not use this parameter explicitly. Instead you should construct it with functions `maptiles_zxy() <https://lets-plot.org/python/pages/api/lets_plot.maptiles_zxy.html>`__ and `maptiles_lets_plot() <https://lets-plot.org/python/pages/api/lets_plot.maptiles_lets_plot.html>`__.
229
+ - maptiles_theme : tiles theme, could be 'color', 'light' or 'dark'. Do not use this parameter explicitly. Instead you should construct it with function `maptiles_lets_plot() <https://lets-plot.org/python/pages/api/lets_plot.maptiles_lets_plot.html>`__.
230
+ - maptiles_attribution : an attribution or a copyright notice to display on the map as required by the tile license (str, supports HTML links). Do not use this parameter explicitly. Instead you should construct it with function `maptiles_zxy() <https://lets-plot.org/python/pages/api/lets_plot.maptiles_zxy.html>`__.
231
+ - maptiles_min_zoom : minimal zoom limit (int). Do not use this parameter explicitly. Instead you should construct it with function `maptiles_zxy() <https://lets-plot.org/python/pages/api/lets_plot.maptiles_zxy.html>`__.
232
+ - maptiles_max_zoom : maximal zoom limit (int). Do not use this parameter explicitly. Instead you should construct it with function `maptiles_zxy() <https://lets-plot.org/python/pages/api/lets_plot.maptiles_zxy.html>`__.
233
+
234
+ Examples
235
+ --------
236
+ .. jupyter-execute::
237
+ :linenos:
238
+ :emphasize-lines: 4
239
+
240
+ from lets_plot import *
241
+ from lets_plot import tilesets
242
+ LetsPlot.setup_html()
243
+ LetsPlot.set(tilesets.LETS_PLOT_LIGHT)
244
+ ggplot() + geom_livemap()
245
+
246
+ |
247
+
248
+ .. jupyter-execute::
249
+ :linenos:
250
+ :emphasize-lines: 4
251
+
252
+ from lets_plot import *
253
+ from lets_plot import tilesets
254
+ LetsPlot.setup_html()
255
+ LetsPlot.set(tilesets.LETS_PLOT_BW)
256
+ ggplot() + geom_livemap()
257
+
258
+ """
259
+ if is_production():
260
+ _settings.update(settings)
261
+ else:
262
+ _settings.update({'dev_' + key: value for key, value in settings.items()})
263
+
264
+ @classmethod
265
+ def set_theme(cls, theme: Union['core.FeatureSpec', 'core.FeatureSpecArray']):
266
+ """
267
+ Set up global theme.
268
+
269
+ Parameters
270
+ ----------
271
+ theme : spec
272
+ Theme spec provided by `theme(...) <https://lets-plot.org/python/pages/api/lets_plot.theme.html>`__, ``theme_xxx()``, ``flavor_xxx()`` functions, or their sum.
273
+
274
+ """
275
+ if theme is None:
276
+ _set_global_theme(None)
277
+ return
278
+
279
+ if theme.kind != 'theme' and not (theme.kind == 'feature-list' and all(f.kind == 'theme' for f in theme)):
280
+ raise ValueError("Only `theme(...)`, `theme_xxx()`, `flavor_xxx()`, or a sum of them are supported")
281
+
282
+ _set_global_theme(theme)
283
+
284
+ @classmethod
285
+ def setup_show_ext(cls, *,
286
+ exec: str = None,
287
+ new: bool = False) -> None:
288
+ """
289
+ Configure Lets-Plot to show its HTML output in an external browser.
290
+
291
+ When the "show externally" is set up, an invocation of ``figire.show()`` will
292
+ - generate HTML output
293
+ - save it to a temporary file
294
+ - open the file in the default web browser or in a web browser specified by the ``exec`` parameter.
295
+
296
+ Parameters
297
+ ----------
298
+ exec : str, optional
299
+ Specify an app to open the generated temporary HTML file.
300
+ If not specified, the default browser will be used.
301
+ new : bool, default=False
302
+ If True, the URL is opened in a new window of the web browser.
303
+ If False, the URL is opened in the already opened web browser window.
304
+ The ``new`` parameter is only applicable when the ``exec`` parameter is not specified.
305
+ Please note that the ``new`` parameter is not supported by all web browsers and all OS-s.
306
+
307
+ Examples
308
+ --------
309
+ .. code-block::
310
+ :linenos:
311
+ :emphasize-lines: 3
312
+
313
+ # Show the plot in the default web browser.
314
+ from lets_plot import *
315
+ LetsPlot.setup_show_ext()
316
+ p = ggplot() + geom_point(x=0, y=0)
317
+ p.show()
318
+
319
+ |
320
+
321
+ .. code-block::
322
+ :linenos:
323
+ :emphasize-lines: 3
324
+
325
+ # Show the plot in the new window of the default web browser if possible.
326
+ from lets_plot import *
327
+ LetsPlot.setup_show_ext(new=True)
328
+ p = ggplot() + geom_point(x=0, y=0)
329
+ p.show()
330
+
331
+ |
332
+
333
+ .. code-block::
334
+ :linenos:
335
+ :emphasize-lines: 4
336
+
337
+ # Show the plot in the Chrome web browser for Windows.
338
+ # This is the default setup path. Replace the file path with your own if it differs.
339
+ from lets_plot import *
340
+ LetsPlot.setup_show_ext(exec='C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe --app=%s')
341
+ p = ggplot() + geom_point(x=0, y=0)
342
+ p.show()
343
+
344
+ |
345
+
346
+ .. code-block::
347
+ :linenos:
348
+ :emphasize-lines: 3
349
+
350
+ # Show the plot in the Safari web browser for macOS.
351
+ from lets_plot import *
352
+ LetsPlot.setup_show_ext(exec='open -a safari %s')
353
+ p = ggplot() + geom_point(x=0, y=0)
354
+ p.show()
355
+
356
+ |
357
+
358
+ .. code-block::
359
+ :linenos:
360
+ :emphasize-lines: 4
361
+
362
+ # Show the plot in the Chrome web browser for macOS in the application mode.
363
+ # This is the default setup path. Replace the path with your own if it differs.
364
+ from lets_plot import *
365
+ LetsPlot.setup_show_ext(exec='/Applications/Google\\ Chrome.app/Contents/MacOS/Google\\ Chrome --app=%s')
366
+ p = ggplot() + geom_point(x=0, y=0)
367
+ p.show()
368
+
369
+ |
370
+
371
+ .. code-block::
372
+ :linenos:
373
+ :emphasize-lines: 3
374
+
375
+ # Show the plot in the Chrome web browser for Linux.
376
+ from lets_plot import *
377
+ LetsPlot.setup_show_ext(exec='google-chrome --app=%s')
378
+ p = ggplot() + geom_point(x=0, y=0)
379
+ p.show()
380
+
381
+ """
382
+ cfg._setup_wb_html_context(exec=exec, new=new)
@@ -0,0 +1,192 @@
1
+ #
2
+ # Copyright (c) 2019. JetBrains s.r.o.
3
+ # Use of this source code is governed by the MIT license that can be found in the LICENSE file.
4
+ #
5
+ import os
6
+ from typing import Any
7
+
8
+ from ._version import __version__
9
+
10
+ # Supported environment variables.
11
+ # 'bool' variables accept values:
12
+ # True: 'true', '1', 't', 'y', 'yes'
13
+ # False: 'false', '0', 'f', 'n', 'no'
14
+ #
15
+ # Production mode env variables:
16
+ ENV_HTML_ISOLATED_FRAME = 'LETS_PLOT_HTML_ISOLATED_FRAME' # bool
17
+ ENV_OFFLINE = 'LETS_PLOT_OFFLINE' # bool
18
+ ENV_NO_JS = 'LETS_PLOT_NO_JS' # bool
19
+ ENV_MAX_WIDTH = 'LETS_PLOT_MAX_WIDTH'
20
+ ENV_MAX_HEIGHT = 'LETS_PLOT_MAX_HEIGHT'
21
+ ENV_MAPTILES_KIND = 'LETS_PLOT_MAPTILES_KIND'
22
+ ENV_MAPTILES_URL = 'LETS_PLOT_MAPTILES_URL'
23
+ ENV_MAPTILES_THEME = 'LETS_PLOT_MAPTILES_THEME'
24
+ ENV_GEOCODING_URL = 'LETS_PLOT_GEOCODING_URL'
25
+
26
+ # Dev mode env variables have 'LETS_PLOT_DEV_' prefix instead of 'LETS_PLOT_'.
27
+ ENV_DEV_HTML_ISOLATED_FRAME = 'LETS_PLOT_DEV_HTML_ISOLATED_FRAME' # bool
28
+ ENV_DEV_OFFLINE = 'LETS_PLOT_DEV_OFFLINE' # bool
29
+ ENV_DEV_NO_JS = 'LETS_PLOT_DEV_NO_JS' # bool
30
+ ENV_DEV_MAX_WIDTH = 'LETS_PLOT_DEV_MAX_WIDTH'
31
+ ENV_DEV_MAX_HEIGHT = 'LETS_PLOT_DEV_MAX_HEIGHT'
32
+ ENV_DEV_MAGICK_EXPORT = 'LETS_PLOT_DEV_MAGICK_EXPORT' # bool
33
+ ENV_DEV_MAPTILES_KIND = 'LETS_PLOT_DEV_MAPTILES_KIND'
34
+ ENV_DEV_MAPTILES_URL = 'LETS_PLOT_DEV_MAPTILES_URL'
35
+ ENV_DEV_MAPTILES_THEME = 'LETS_PLOT_DEV_MAPTILES_THEME'
36
+ ENV_DEV_GEOCODING_URL = 'LETS_PLOT_DEV_GEOCODING_URL'
37
+
38
+ # Options
39
+
40
+ HTML_ISOLATED_FRAME = 'html_isolated_frame'
41
+ OFFLINE = 'offline'
42
+ NO_JS = 'no_js'
43
+ JS_BASE_URL = 'js_base_url'
44
+ JS_PATH_TO_FILE = 'js_path_to_file'
45
+ JS_NAME = 'js_name'
46
+ JS_URL_MANUAL = 'js_url_manual'
47
+ MAX_WIDTH = 'max_width'
48
+ MAX_HEIGHT = 'max_height'
49
+
50
+ MAPTILES_KIND = 'maptiles_kind'
51
+ MAPTILES_URL = 'maptiles_url'
52
+ MAPTILES_THEME = 'maptiles_theme'
53
+ MAPTILES_ATTRIBUTION = 'maptiles_attribution'
54
+ MAPTILES_MIN_ZOOM = 'maptiles_min_zoom'
55
+ MAPTILES_MAX_ZOOM = 'maptiles_max_zoom'
56
+ MAPTILES_SOLID_FILL_COLOR = 'maptiles_fill_color'
57
+ TILES_VECTOR_LETS_PLOT = 'vector_lets_plot'
58
+ TILES_RASTER_ZXY = 'raster_zxy'
59
+ TILES_SOLID = 'solid'
60
+ TILES_CHESSBOARD = 'chessboard'
61
+ GEOCODING_PROVIDER_URL = 'geocoding_url'
62
+ GEOCODING_ROUTE = '/map_data/geocoding'
63
+ FRAGMENTS_ENABLED = 'fragments_enabled'
64
+
65
+ _DATALORE_TILES_SERVICE = 'wss://tiles.datalore.jetbrains.com'
66
+ _DATALORE_TILES_ATTRIBUTION = '<a href="https://lets-plot.org">\u00a9 Lets-Plot</a>, map data: <a href="https://www.openstreetmap.org/copyright">\u00a9 OpenStreetMap contributors</a>.'
67
+ _DATALORE_TILES_THEME = 'color'
68
+ _DATALORE_TILES_MIN_ZOOM = 1
69
+ _DATALORE_TILES_MAX_ZOOM = 15
70
+ _DATALORE_GEOCODING_SERVICE = 'https://geo2.datalore.jetbrains.com'
71
+
72
+
73
+ def _init_value(actual_name: str, def_val: Any) -> Any:
74
+ env_val = _get_env_val(actual_name)
75
+ return env_val if env_val else def_val
76
+
77
+
78
+ def _get_env_val(actual_name: str) -> Any:
79
+ env_name = "LETS_PLOT_{}".format(actual_name.upper())
80
+ return os.environ.get(env_name)
81
+
82
+
83
+ _settings = {
84
+ OFFLINE: _init_value(OFFLINE, False), # default: download from CDN
85
+ NO_JS: _init_value(NO_JS, False),
86
+ # JS_BASE_URL: 'https://dl.bintray.com/jetbrains/lets-plot',
87
+ # JS_BASE_URL: "https://cdnjs.cloudflare.com/ajax/libs/lets-plot",
88
+ JS_BASE_URL: "https://cdn.jsdelivr.net/gh/JetBrains/lets-plot@v{version}".format(version=__version__),
89
+ JS_PATH_TO_FILE: "js-package/distr",
90
+ JS_NAME: '', # default: lets-plot.min.js
91
+ GEOCODING_PROVIDER_URL: _init_value(GEOCODING_PROVIDER_URL, _DATALORE_GEOCODING_SERVICE),
92
+ MAPTILES_KIND: _init_value(MAPTILES_KIND, TILES_VECTOR_LETS_PLOT),
93
+ MAPTILES_URL: _init_value(MAPTILES_URL, _DATALORE_TILES_SERVICE),
94
+ MAPTILES_ATTRIBUTION: _init_value(MAPTILES_ATTRIBUTION, _DATALORE_TILES_ATTRIBUTION),
95
+ MAPTILES_THEME: _init_value(MAPTILES_THEME, _DATALORE_TILES_THEME),
96
+ MAPTILES_MIN_ZOOM: _init_value(MAPTILES_MIN_ZOOM, _DATALORE_TILES_MIN_ZOOM),
97
+ MAPTILES_MAX_ZOOM: _init_value(MAPTILES_MAX_ZOOM, _DATALORE_TILES_MAX_ZOOM),
98
+
99
+ 'dev_' + OFFLINE: _init_value('dev_' + OFFLINE, True), # default: embed js into the notebook
100
+ 'dev_' + NO_JS: _init_value('dev_' + NO_JS, False),
101
+ # We don't publish "dev" version, it must be served on localhost:
102
+ # $ cd lets-plot
103
+ # ./gradlew js-package:jsBrowserDevelopmentWebpack
104
+ # $ python -m http.server 8080
105
+ 'dev_' + JS_BASE_URL: "http://127.0.0.1:8080",
106
+ 'dev_' + JS_PATH_TO_FILE: "js-package/build/dist/js/developmentExecutable",
107
+ 'dev_' + JS_NAME: '', # default: lets-plot.js
108
+ 'dev_' + GEOCODING_PROVIDER_URL: _init_value('dev_' + GEOCODING_PROVIDER_URL, _DATALORE_GEOCODING_SERVICE),
109
+ 'dev_' + MAPTILES_KIND: _init_value('dev_' + MAPTILES_KIND, TILES_VECTOR_LETS_PLOT),
110
+ 'dev_' + MAPTILES_URL: _init_value('dev_' + MAPTILES_URL, _DATALORE_TILES_SERVICE),
111
+ 'dev_' + MAPTILES_ATTRIBUTION: _init_value('dev_' + MAPTILES_ATTRIBUTION, _DATALORE_TILES_ATTRIBUTION),
112
+ 'dev_' + MAPTILES_THEME: _init_value('dev_' + MAPTILES_THEME, _DATALORE_TILES_THEME),
113
+ 'dev_' + MAPTILES_MIN_ZOOM: _init_value('dev_' + MAPTILES_MIN_ZOOM, _DATALORE_TILES_MIN_ZOOM),
114
+ 'dev_' + MAPTILES_MAX_ZOOM: _init_value('dev_' + MAPTILES_MAX_ZOOM, _DATALORE_TILES_MAX_ZOOM),
115
+ }
116
+
117
+
118
+ def _to_actual_name(name: str) -> str:
119
+ if name.startswith("dev_"):
120
+ return name
121
+
122
+ return name if is_production() else 'dev_' + name
123
+
124
+
125
+ def _get_global_val_intern(actual_name: str) -> Any:
126
+ # `settings` dict has precedence over environment variables.
127
+ env_val = _get_env_val(actual_name)
128
+ return _settings.get(actual_name, env_val)
129
+
130
+
131
+ def is_production() -> bool:
132
+ return 'dev' not in __version__
133
+
134
+
135
+ def get_js_cdn_url() -> str:
136
+ if has_global_value(JS_URL_MANUAL):
137
+ return get_global_str(JS_URL_MANUAL)
138
+
139
+ base_url = get_global_str(JS_BASE_URL)
140
+
141
+ js_path_to_file = get_global_str(JS_PATH_TO_FILE)
142
+
143
+ if has_global_value(JS_NAME):
144
+ name = get_global_str(JS_NAME)
145
+ else:
146
+ name = "lets-plot.min.js" if is_production() else "lets-plot.js".format(version=__version__)
147
+ # name = "lets-plot-{version}.{suffix}".format(version=__version__, suffix=suffix)
148
+ # name = "lets-plot.{suffix}".format(suffix=suffix)
149
+
150
+ # url = "{base_url}/{name}".format(base_url=base_url, name=name)
151
+ url = "{base_url}/{js_path_to_file}/{name}".format(base_url=base_url, js_path_to_file=js_path_to_file, name=name)
152
+ return url
153
+
154
+
155
+ def has_global_value(name: str) -> bool:
156
+ val = _get_global_val_intern(_to_actual_name(name))
157
+
158
+ if isinstance(val, bool):
159
+ return True
160
+ if isinstance(val, str) and not val.strip():
161
+ return False
162
+ return bool(val)
163
+
164
+
165
+ def get_global_val(name: str) -> Any:
166
+ if not has_global_value(name):
167
+ raise ValueError("Not defined '{}'".format(_to_actual_name(name)))
168
+
169
+ return _get_global_val_intern(_to_actual_name(name))
170
+
171
+
172
+ def get_global_str(name: str) -> str:
173
+ val = get_global_val(name)
174
+ if not isinstance(val, str):
175
+ raise ValueError("Not string value: ['{}'] : {}".format(_to_actual_name(name), type(val)))
176
+ return val
177
+
178
+
179
+ def get_global_bool(name: str) -> bool:
180
+ val = get_global_val(name)
181
+ if isinstance(val, bool):
182
+ return val
183
+
184
+ if isinstance(val, str):
185
+ if val.lower() in ['true', '1', 't', 'y', 'yes']:
186
+ return True
187
+ elif val.lower() in ['false', '0', 'f', 'n', 'no']:
188
+ return False
189
+ else:
190
+ raise ValueError("Can't convert str to boolean : ['{}'] : {}".format(_to_actual_name(name), val))
191
+
192
+ raise ValueError("Not boolean value: ['{}'] : {}".format(_to_actual_name(name), type(val)))