geovizpy 0.1.5__py3-none-any.whl → 0.1.6__py3-none-any.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.
- geovizpy/renderer.py +81 -23
- {geovizpy-0.1.5.dist-info → geovizpy-0.1.6.dist-info}/METADATA +6 -5
- {geovizpy-0.1.5.dist-info → geovizpy-0.1.6.dist-info}/RECORD +5 -5
- {geovizpy-0.1.5.dist-info → geovizpy-0.1.6.dist-info}/WHEEL +0 -0
- {geovizpy-0.1.5.dist-info → geovizpy-0.1.6.dist-info}/top_level.txt +0 -0
geovizpy/renderer.py
CHANGED
|
@@ -4,6 +4,9 @@ import json
|
|
|
4
4
|
import tempfile
|
|
5
5
|
import os
|
|
6
6
|
import time
|
|
7
|
+
import html
|
|
8
|
+
import sys
|
|
9
|
+
import subprocess
|
|
7
10
|
|
|
8
11
|
class RendererMixin:
|
|
9
12
|
"""Mixin class for rendering the map."""
|
|
@@ -33,14 +36,14 @@ class RendererMixin:
|
|
|
33
36
|
"""Return the configuration as a JSON string."""
|
|
34
37
|
return json.dumps(self.get_config())
|
|
35
38
|
|
|
36
|
-
def
|
|
37
|
-
"""
|
|
39
|
+
def _get_html_content(self):
|
|
40
|
+
"""Generate the full HTML content string."""
|
|
38
41
|
json_commands = self.to_json()
|
|
39
42
|
|
|
40
43
|
layer_control_js = self._get_layer_control_js()
|
|
41
44
|
export_control_js = self._get_export_control_js()
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
return f"""
|
|
44
47
|
<!DOCTYPE html>
|
|
45
48
|
<html>
|
|
46
49
|
<head>
|
|
@@ -49,7 +52,7 @@ class RendererMixin:
|
|
|
49
52
|
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
|
|
50
53
|
<script src="https://cdn.jsdelivr.net/npm/geoviz@0.9.8"></script>
|
|
51
54
|
<style>
|
|
52
|
-
body {{ margin: 0; padding: 0; }}
|
|
55
|
+
body {{ margin: 0; padding: 0; overflow: hidden; }}
|
|
53
56
|
button {{ background: #f8f9fa; border: 1px solid #ddd; border-radius: 3px; }}
|
|
54
57
|
button:hover {{ background: #e2e6ea; }}
|
|
55
58
|
</style>
|
|
@@ -111,10 +114,35 @@ class RendererMixin:
|
|
|
111
114
|
</body>
|
|
112
115
|
</html>
|
|
113
116
|
"""
|
|
117
|
+
|
|
118
|
+
def render_html(self, filename="map.html"):
|
|
119
|
+
"""Render the map to an HTML file."""
|
|
120
|
+
html_content = self._get_html_content()
|
|
114
121
|
with open(filename, "w") as f:
|
|
115
122
|
f.write(html_content)
|
|
116
123
|
print(f"Map saved to {filename}")
|
|
117
124
|
|
|
125
|
+
def show(self, width=800, height=600):
|
|
126
|
+
"""
|
|
127
|
+
Display the map in a Jupyter notebook using an IFrame.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
width (int/str): Width of the display area (default 800).
|
|
131
|
+
height (int/str): Height of the display area (default 600).
|
|
132
|
+
"""
|
|
133
|
+
try:
|
|
134
|
+
from IPython.display import IFrame
|
|
135
|
+
import base64
|
|
136
|
+
except ImportError:
|
|
137
|
+
print("IPython is required to display the map. Please install it with 'pip install ipython'.")
|
|
138
|
+
return
|
|
139
|
+
|
|
140
|
+
html_content = self._get_html_content()
|
|
141
|
+
b64_content = base64.b64encode(html_content.encode('utf-8')).decode('utf-8')
|
|
142
|
+
data_uri = f"data:text/html;base64,{b64_content}"
|
|
143
|
+
|
|
144
|
+
return IFrame(src=data_uri, width=width, height=height)
|
|
145
|
+
|
|
118
146
|
def save(self, filename="map.html"):
|
|
119
147
|
"""
|
|
120
148
|
Save the map to a file.
|
|
@@ -134,39 +162,69 @@ class RendererMixin:
|
|
|
134
162
|
print("Error: filename must end with .html, .png, or .svg")
|
|
135
163
|
|
|
136
164
|
def _save_image(self, filename):
|
|
137
|
-
"""Internal method to save as PNG or SVG using Playwright."""
|
|
165
|
+
"""Internal method to save as PNG or SVG using Playwright via a subprocess."""
|
|
166
|
+
|
|
167
|
+
# Check if playwright is installed
|
|
138
168
|
try:
|
|
139
|
-
|
|
169
|
+
import playwright
|
|
140
170
|
except ImportError:
|
|
141
171
|
print("Error: Playwright is required for image export.")
|
|
142
172
|
print("Please install it with: pip install geovizpy[export] && playwright install")
|
|
143
173
|
return
|
|
144
174
|
|
|
175
|
+
# Create a temporary HTML file
|
|
145
176
|
with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".html") as tmp_file:
|
|
146
177
|
self.render_html(tmp_file.name)
|
|
147
178
|
tmp_path = tmp_file.name
|
|
148
179
|
|
|
180
|
+
# Create a temporary Python script to run Playwright
|
|
181
|
+
# This isolates Playwright from the current asyncio loop (Jupyter)
|
|
182
|
+
script_content = f"""
|
|
183
|
+
import os
|
|
184
|
+
from playwright.sync_api import sync_playwright
|
|
185
|
+
|
|
186
|
+
def run():
|
|
187
|
+
try:
|
|
188
|
+
with sync_playwright() as p:
|
|
189
|
+
browser = p.chromium.launch()
|
|
190
|
+
page = browser.new_page(viewport={{"width": 1000, "height": 800}})
|
|
191
|
+
page.goto(f"file://{{os.path.abspath('{tmp_path}')}}")
|
|
192
|
+
page.wait_for_timeout(2000)
|
|
193
|
+
|
|
194
|
+
if "{filename}".endswith(".svg"):
|
|
195
|
+
svg_outer = page.locator("svg").first.evaluate("el => el.outerHTML")
|
|
196
|
+
with open("{filename}", "w") as f:
|
|
197
|
+
f.write(svg_outer)
|
|
198
|
+
else:
|
|
199
|
+
page.locator("svg").first.screenshot(path="{filename}")
|
|
200
|
+
|
|
201
|
+
browser.close()
|
|
202
|
+
print(f"Image saved to {filename}")
|
|
203
|
+
except Exception as e:
|
|
204
|
+
print(f"Error in subprocess: {{e}}")
|
|
205
|
+
exit(1)
|
|
206
|
+
|
|
207
|
+
if __name__ == "__main__":
|
|
208
|
+
run()
|
|
209
|
+
"""
|
|
210
|
+
|
|
211
|
+
with tempfile.NamedTemporaryFile(mode="w", delete=False, suffix=".py") as tmp_script:
|
|
212
|
+
tmp_script.write(script_content)
|
|
213
|
+
tmp_script_path = tmp_script.name
|
|
214
|
+
|
|
149
215
|
try:
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
if filename.endswith(".svg"):
|
|
157
|
-
svg_outer = page.locator("svg").first.evaluate("el => el.outerHTML")
|
|
158
|
-
with open(filename, "w") as f:
|
|
159
|
-
f.write(svg_outer)
|
|
160
|
-
else: # .png
|
|
161
|
-
page.locator("svg").first.screenshot(path=filename)
|
|
162
|
-
|
|
163
|
-
browser.close()
|
|
164
|
-
print(f"Image saved to {filename}")
|
|
165
|
-
except Exception as e:
|
|
166
|
-
print(f"Error saving image: {e}")
|
|
216
|
+
# Run the script in a subprocess
|
|
217
|
+
result = subprocess.run([sys.executable, tmp_script_path], capture_output=True, text=True)
|
|
218
|
+
if result.returncode != 0:
|
|
219
|
+
print(f"Error saving image: {result.stderr}")
|
|
220
|
+
else:
|
|
221
|
+
print(result.stdout.strip())
|
|
167
222
|
finally:
|
|
223
|
+
# Cleanup
|
|
168
224
|
if os.path.exists(tmp_path):
|
|
169
225
|
os.remove(tmp_path)
|
|
226
|
+
if os.path.exists(tmp_script_path):
|
|
227
|
+
os.remove(tmp_script_path)
|
|
170
228
|
|
|
171
229
|
def _get_layer_control_js(self):
|
|
172
230
|
if not self.layer_control_config:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: geovizpy
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: A Python wrapper for the geoviz JavaScript library
|
|
5
5
|
Author: fbxyz
|
|
6
6
|
Project-URL: Source, https://codeberg.org/fbxyz/geovizpy
|
|
@@ -24,7 +24,9 @@ Dynamic: summary
|
|
|
24
24
|
|
|
25
25
|
**geovizpy** is a Python wrapper for the `geoviz` JavaScript library, designed to bring the power of D3.js-based thematic mapping to Python. It allows you to create high-quality, interactive maps directly from Python scripts or Jupyter notebooks.
|
|
26
26
|
|
|
27
|
-
This library is a wrapper around the
|
|
27
|
+
This library is a wrapper around the `geoviz` library. For detailed information on the underlying mapping logic, please refer to the [original geoviz documentation](https://github.com/neocarto/geoviz).
|
|
28
|
+
|
|
29
|
+

|
|
28
30
|
|
|
29
31
|
## Features
|
|
30
32
|
|
|
@@ -53,7 +55,7 @@ pip install git+https://codeberg.org/fbxyz/geovizpy.git
|
|
|
53
55
|
|
|
54
56
|
### For Image Export
|
|
55
57
|
|
|
56
|
-
To save maps as PNG or SVG files directly from Python, you need to install the optional `export` dependencies
|
|
58
|
+
To save maps as PNG or SVG files directly from Python, you need to install the optional `export` dependencies:
|
|
57
59
|
|
|
58
60
|
1. **Install the extra dependencies:**
|
|
59
61
|
|
|
@@ -113,5 +115,4 @@ viz.save("my_map.html") # Renders an interactive HTML file
|
|
|
113
115
|
|
|
114
116
|
## Documentation
|
|
115
117
|
|
|
116
|
-
For more detailed information on all available methods and parameters, please see the [full documentation](https://
|
|
117
|
-
|
|
118
|
+
For more detailed information on all available methods and parameters, please see the [full documentation](https://geovizpy.readthedocs.io/en/latest/).
|
|
@@ -5,8 +5,8 @@ geovizpy/geoviz.py,sha256=bG1A5AQIhsfIJ9RQ4RJteG9HRuu70k2xI9l_eydQTH0,1415
|
|
|
5
5
|
geovizpy/legends.py,sha256=IPn_1drQ9MkmJlQ54XwBqAlTRSyq98sm8gzgE-ATRog,2218
|
|
6
6
|
geovizpy/marks.py,sha256=xqwf8ELY05lnrrXGQljMe-mm315vUt_-qOmdFAsYhwA,5520
|
|
7
7
|
geovizpy/plots.py,sha256=EVjPPBFyUFQpXH7sAuxCz_sctonJVUxoi8edbehKrpI,3089
|
|
8
|
-
geovizpy/renderer.py,sha256=
|
|
9
|
-
geovizpy-0.1.
|
|
10
|
-
geovizpy-0.1.
|
|
11
|
-
geovizpy-0.1.
|
|
12
|
-
geovizpy-0.1.
|
|
8
|
+
geovizpy/renderer.py,sha256=ql9eaRGo-274MEA6ZXcLY4QpidJdmHlt65IuHiwAbko,16543
|
|
9
|
+
geovizpy-0.1.6.dist-info/METADATA,sha256=l9WRhOd_vESt9qOK071kioRARK4OTvpCymOEtXRbHhE,3463
|
|
10
|
+
geovizpy-0.1.6.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
11
|
+
geovizpy-0.1.6.dist-info/top_level.txt,sha256=3D5AFdMd9bWEvGQUWDy6jccJamUwdKmchgCmxLHaAYs,9
|
|
12
|
+
geovizpy-0.1.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|