figpack 0.3.1__tar.gz → 0.3.4__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.
- {figpack-0.3.1/figpack.egg-info → figpack-0.3.4}/PKG-INFO +2 -2
- {figpack-0.3.1 → figpack-0.3.4}/README.md +1 -1
- {figpack-0.3.1 → figpack-0.3.4}/figpack/__init__.py +1 -1
- {figpack-0.3.1 → figpack-0.3.4}/figpack/cli.py +2 -152
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_bundle_utils.py +11 -3
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_save_figure.py +17 -3
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_show_view.py +5 -2
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_upload_bundle.py +0 -40
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_view_figure.py +1 -3
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/figpack_view.py +14 -4
- figpack-0.3.4/figpack/figpack-figure-dist/assets/index-P3Ni9vtI.js +394 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/figpack-figure-dist/index.html +1 -1
- figpack-0.3.4/figpack/utils/__init__.py +24 -0
- figpack-0.3.4/figpack-serve/worker/container/app.py +249 -0
- {figpack-0.3.1 → figpack-0.3.4/figpack.egg-info}/PKG-INFO +2 -2
- {figpack-0.3.1 → figpack-0.3.4}/figpack.egg-info/SOURCES.txt +3 -1
- {figpack-0.3.1 → figpack-0.3.4}/figpack.egg-info/top_level.txt +1 -0
- {figpack-0.3.1 → figpack-0.3.4}/pyproject.toml +1 -1
- figpack-0.3.1/figpack/figpack-figure-dist/assets/index-ST_DU17U.js +0 -95
- {figpack-0.3.1 → figpack-0.3.4}/LICENSE +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/MANIFEST.in +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/__init__.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_file_handler.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_server_manager.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_zarr_consolidate.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/config.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/extension_view.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/figpack_extension.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/core/zarr.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/extensions.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/figpack-figure-dist/assets/index-V5m_wCvw.css +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/figpack-figure-dist/assets/neurosift-logo-CLsuwLMO.png +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Box.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/CaptionedView.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/DataFrame.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Gallery.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/GalleryItem.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Iframe.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Image.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/LayoutItem.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Markdown.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/MatplotlibFigure.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/MountainLayout.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/MountainLayoutItem.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/MultiChannelTimeseries.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/PlotlyExtension/PlotlyExtension.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/PlotlyExtension/__init__.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/PlotlyExtension/_plotly_extension.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/PlotlyExtension/plotly_view.js +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Spectrogram.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Splitter.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/TabLayout.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/TabLayoutItem.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/TimeseriesGraph.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack/views/__init__.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack.egg-info/dependency_links.txt +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack.egg-info/entry_points.txt +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/figpack.egg-info/requires.txt +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/setup.cfg +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_box.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_cli.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_core.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_dataframe.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_extension_system.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_figpack_view.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_file_handler.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_gallery.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_image.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_markdown.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_matplotlib_figure.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_multichannel_timeseries.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_plotly_figure.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_server_manager.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_spectrogram.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_splitter.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_tablayout.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_timeseries_graph.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_upload_bundle.py +0 -0
- {figpack-0.3.1 → figpack-0.3.4}/tests/test_view_figure.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: figpack
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.4
|
|
4
4
|
Summary: A Python package for creating shareable, interactive visualizations in the browser
|
|
5
5
|
Author-email: Jeremy Magland <jmagland@flatironinstitute.org>
|
|
6
6
|
License: Apache-2.0
|
|
@@ -133,7 +133,7 @@ If you use figpack in your research, please cite it:
|
|
|
133
133
|
|
|
134
134
|
Or in APA format:
|
|
135
135
|
|
|
136
|
-
> Magland, J. (2025). figpack (Version 0.3.
|
|
136
|
+
> Magland, J. (2025). figpack (Version 0.3.4) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.17419621
|
|
137
137
|
|
|
138
138
|
## Contributing
|
|
139
139
|
|
|
@@ -57,7 +57,7 @@ If you use figpack in your research, please cite it:
|
|
|
57
57
|
|
|
58
58
|
Or in APA format:
|
|
59
59
|
|
|
60
|
-
> Magland, J. (2025). figpack (Version 0.3.
|
|
60
|
+
> Magland, J. (2025). figpack (Version 0.3.4) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.17419621
|
|
61
61
|
|
|
62
62
|
## Contributing
|
|
63
63
|
|
|
@@ -16,9 +16,8 @@ from urllib.parse import urljoin
|
|
|
16
16
|
import requests
|
|
17
17
|
|
|
18
18
|
from . import __version__
|
|
19
|
-
from .core.
|
|
20
|
-
from .core.
|
|
21
|
-
from .core._upload_bundle import _upload_bundle, get_figure_by_source_url
|
|
19
|
+
from .core._view_figure import view_figure
|
|
20
|
+
from .core._upload_bundle import _upload_bundle
|
|
22
21
|
from .extensions import ExtensionManager
|
|
23
22
|
|
|
24
23
|
MAX_WORKERS_FOR_DOWNLOAD = 16
|
|
@@ -250,130 +249,6 @@ def handle_extensions_command(args):
|
|
|
250
249
|
print("Use 'figpack extensions <command> --help' for more information.")
|
|
251
250
|
|
|
252
251
|
|
|
253
|
-
def handle_upload_from_source_url(args) -> None:
|
|
254
|
-
"""
|
|
255
|
-
Handle the upload-from-source-url command
|
|
256
|
-
|
|
257
|
-
Downloads a tar.gz/tgz file from a URL, extracts it, and uploads it as a new figure
|
|
258
|
-
with the source URL set.
|
|
259
|
-
"""
|
|
260
|
-
import os
|
|
261
|
-
|
|
262
|
-
source_url = args.source_url
|
|
263
|
-
title = args.title if hasattr(args, "title") else None
|
|
264
|
-
|
|
265
|
-
# Get API key from environment variable
|
|
266
|
-
api_key = os.environ.get("FIGPACK_API_KEY")
|
|
267
|
-
if not api_key:
|
|
268
|
-
print(
|
|
269
|
-
"Error: FIGPACK_API_KEY environment variable must be set to upload figures."
|
|
270
|
-
)
|
|
271
|
-
sys.exit(1)
|
|
272
|
-
|
|
273
|
-
# Validate URL format
|
|
274
|
-
if not (source_url.endswith(".tar.gz") or source_url.endswith(".tgz")):
|
|
275
|
-
print(f"Error: Source URL must point to a .tar.gz or .tgz file: {source_url}")
|
|
276
|
-
sys.exit(1)
|
|
277
|
-
|
|
278
|
-
print(f"Downloading archive from: {source_url}")
|
|
279
|
-
|
|
280
|
-
try:
|
|
281
|
-
# Download the archive
|
|
282
|
-
response = requests.get(source_url, timeout=120, stream=True)
|
|
283
|
-
response.raise_for_status()
|
|
284
|
-
|
|
285
|
-
# Create temporary file for the archive
|
|
286
|
-
with tempfile.NamedTemporaryFile(
|
|
287
|
-
suffix=".tar.gz", delete=False
|
|
288
|
-
) as temp_archive:
|
|
289
|
-
archive_path = temp_archive.name
|
|
290
|
-
|
|
291
|
-
# Download with progress indication
|
|
292
|
-
total_size = int(response.headers.get("content-length", 0))
|
|
293
|
-
downloaded_size = 0
|
|
294
|
-
|
|
295
|
-
for chunk in response.iter_content(chunk_size=8192):
|
|
296
|
-
if chunk:
|
|
297
|
-
temp_archive.write(chunk)
|
|
298
|
-
downloaded_size += len(chunk)
|
|
299
|
-
if total_size > 0:
|
|
300
|
-
progress = (downloaded_size / total_size) * 100
|
|
301
|
-
print(
|
|
302
|
-
f"Downloaded: {downloaded_size / (1024*1024):.2f} MB ({progress:.1f}%)",
|
|
303
|
-
end="\r",
|
|
304
|
-
)
|
|
305
|
-
|
|
306
|
-
if total_size > 0:
|
|
307
|
-
print() # New line after progress
|
|
308
|
-
print(f"Download complete: {downloaded_size / (1024*1024):.2f} MB")
|
|
309
|
-
|
|
310
|
-
# Extract archive to temporary directory
|
|
311
|
-
print("Extracting archive...")
|
|
312
|
-
with tempfile.TemporaryDirectory() as extract_dir:
|
|
313
|
-
extract_path = pathlib.Path(extract_dir)
|
|
314
|
-
|
|
315
|
-
try:
|
|
316
|
-
with tarfile.open(archive_path, "r:gz") as tar:
|
|
317
|
-
tar.extractall(path=extract_path)
|
|
318
|
-
print(f"Extracted to temporary directory")
|
|
319
|
-
except Exception as e:
|
|
320
|
-
print(f"Error: Failed to extract archive: {e}")
|
|
321
|
-
sys.exit(1)
|
|
322
|
-
finally:
|
|
323
|
-
# Clean up downloaded archive
|
|
324
|
-
import os
|
|
325
|
-
|
|
326
|
-
try:
|
|
327
|
-
os.unlink(archive_path)
|
|
328
|
-
except Exception:
|
|
329
|
-
pass
|
|
330
|
-
|
|
331
|
-
# Upload the extracted files
|
|
332
|
-
print(f"Uploading figure with source URL: {source_url}")
|
|
333
|
-
try:
|
|
334
|
-
figure_url = _upload_bundle(
|
|
335
|
-
str(extract_path),
|
|
336
|
-
api_key=api_key,
|
|
337
|
-
title=title,
|
|
338
|
-
source_url=source_url,
|
|
339
|
-
)
|
|
340
|
-
print(f"\nFigure uploaded successfully!")
|
|
341
|
-
print(f"Figure URL: {figure_url}")
|
|
342
|
-
except Exception as e:
|
|
343
|
-
print(f"Error: Failed to upload figure: {e}")
|
|
344
|
-
sys.exit(1)
|
|
345
|
-
|
|
346
|
-
except requests.exceptions.RequestException as e:
|
|
347
|
-
print(f"Error: Failed to download archive from {source_url}: {e}")
|
|
348
|
-
sys.exit(1)
|
|
349
|
-
except Exception as e:
|
|
350
|
-
print(f"Error: {e}")
|
|
351
|
-
sys.exit(1)
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
def handle_find_by_source_url(args) -> None:
|
|
355
|
-
"""
|
|
356
|
-
Handle the find-by-source-url command
|
|
357
|
-
|
|
358
|
-
Queries the API for a figure URL by its source URL.
|
|
359
|
-
"""
|
|
360
|
-
source_url = args.source_url
|
|
361
|
-
|
|
362
|
-
print(f"Querying for figure with source URL: {source_url}")
|
|
363
|
-
|
|
364
|
-
try:
|
|
365
|
-
figure_url = get_figure_by_source_url(source_url)
|
|
366
|
-
|
|
367
|
-
if figure_url:
|
|
368
|
-
print(f"Figure found: {figure_url}")
|
|
369
|
-
else:
|
|
370
|
-
print(f"No figure found with source URL: {source_url}")
|
|
371
|
-
sys.exit(1)
|
|
372
|
-
except Exception as e:
|
|
373
|
-
print(f"Error: {e}")
|
|
374
|
-
sys.exit(1)
|
|
375
|
-
|
|
376
|
-
|
|
377
252
|
def download_and_view_archive(url: str, port: int = None) -> None:
|
|
378
253
|
"""
|
|
379
254
|
Download a tar.gz/tgz archive from a URL and view it
|
|
@@ -495,27 +370,6 @@ def main():
|
|
|
495
370
|
"extensions", nargs="+", help="Extension package names to uninstall"
|
|
496
371
|
)
|
|
497
372
|
|
|
498
|
-
# Upload from URL command
|
|
499
|
-
upload_from_source_url_parser = subparsers.add_parser(
|
|
500
|
-
"upload-from-source-url",
|
|
501
|
-
help="Download a tar.gz/tgz file and upload it as a new figure",
|
|
502
|
-
)
|
|
503
|
-
upload_from_source_url_parser.add_argument(
|
|
504
|
-
"source_url",
|
|
505
|
-
help="URL to the tar.gz or tgz file (will be set as the figure's source URL)",
|
|
506
|
-
)
|
|
507
|
-
upload_from_source_url_parser.add_argument(
|
|
508
|
-
"--title", help="Optional title for the figure"
|
|
509
|
-
)
|
|
510
|
-
|
|
511
|
-
# Find by source URL command
|
|
512
|
-
find_by_source_url_parser = subparsers.add_parser(
|
|
513
|
-
"find-by-source-url", help="Get the figure URL for a given source URL"
|
|
514
|
-
)
|
|
515
|
-
find_by_source_url_parser.add_argument(
|
|
516
|
-
"source_url", help="The source URL to search for"
|
|
517
|
-
)
|
|
518
|
-
|
|
519
373
|
args = parser.parse_args()
|
|
520
374
|
|
|
521
375
|
if args.command == "download":
|
|
@@ -528,10 +382,6 @@ def main():
|
|
|
528
382
|
view_figure(args.archive, port=args.port)
|
|
529
383
|
elif args.command == "extensions":
|
|
530
384
|
handle_extensions_command(args)
|
|
531
|
-
elif args.command == "upload-from-source-url":
|
|
532
|
-
handle_upload_from_source_url(args)
|
|
533
|
-
elif args.command == "find-by-source-url":
|
|
534
|
-
handle_find_by_source_url(args)
|
|
535
385
|
else:
|
|
536
386
|
parser.print_help()
|
|
537
387
|
|
|
@@ -15,7 +15,12 @@ thisdir = pathlib.Path(__file__).parent.resolve()
|
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
def prepare_figure_bundle(
|
|
18
|
-
view: FigpackView,
|
|
18
|
+
view: FigpackView,
|
|
19
|
+
tmpdir: str,
|
|
20
|
+
*,
|
|
21
|
+
title: str,
|
|
22
|
+
description: Optional[str] = None,
|
|
23
|
+
script: Optional[str] = None,
|
|
19
24
|
) -> None:
|
|
20
25
|
"""
|
|
21
26
|
Prepare a figure bundle in the specified temporary directory.
|
|
@@ -31,6 +36,7 @@ def prepare_figure_bundle(
|
|
|
31
36
|
tmpdir: The temporary directory to prepare the bundle in
|
|
32
37
|
title: Title for the figure (required)
|
|
33
38
|
description: Optional description for the figure (markdown supported)
|
|
39
|
+
script: Optional script text used to generate the figure
|
|
34
40
|
"""
|
|
35
41
|
html_dir = thisdir / ".." / "figpack-figure-dist"
|
|
36
42
|
if not os.path.exists(html_dir):
|
|
@@ -61,10 +67,12 @@ def prepare_figure_bundle(
|
|
|
61
67
|
zarr_group = Group(zarr_group)
|
|
62
68
|
view.write_to_zarr_group(zarr_group)
|
|
63
69
|
|
|
64
|
-
# Add title and description as attributes on the top-level zarr group
|
|
70
|
+
# Add title and description and script as attributes on the top-level zarr group
|
|
65
71
|
zarr_group.attrs["title"] = title
|
|
66
|
-
if description
|
|
72
|
+
if description:
|
|
67
73
|
zarr_group.attrs["description"] = description
|
|
74
|
+
if script:
|
|
75
|
+
zarr_group.attrs["script"] = script
|
|
68
76
|
|
|
69
77
|
# Discover and write extension JavaScript files
|
|
70
78
|
required_extensions = _discover_required_extensions(view)
|
|
@@ -6,7 +6,12 @@ from .figpack_view import FigpackView
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def _save_figure(
|
|
9
|
-
view: FigpackView,
|
|
9
|
+
view: FigpackView,
|
|
10
|
+
output_path: str,
|
|
11
|
+
*,
|
|
12
|
+
title: str,
|
|
13
|
+
description: str = "",
|
|
14
|
+
script: str = "",
|
|
10
15
|
) -> None:
|
|
11
16
|
"""
|
|
12
17
|
Save the figure to a folder or a .tar.gz file
|
|
@@ -14,6 +19,9 @@ def _save_figure(
|
|
|
14
19
|
Args:
|
|
15
20
|
view: FigpackView instance to save
|
|
16
21
|
output_path: Output path (destination folder or .tar.gz file path)
|
|
22
|
+
title: Title for the figure
|
|
23
|
+
description: Description text with markdown support
|
|
24
|
+
script: Optional script text used to generate the figure
|
|
17
25
|
"""
|
|
18
26
|
output_path_2 = pathlib.Path(output_path)
|
|
19
27
|
if (output_path_2.suffix == ".gz" and output_path_2.suffixes[-2] == ".tar") or (
|
|
@@ -21,7 +29,9 @@ def _save_figure(
|
|
|
21
29
|
):
|
|
22
30
|
# It's a .tar.gz file
|
|
23
31
|
with tempfile.TemporaryDirectory(prefix="figpack_save_") as tmpdir:
|
|
24
|
-
prepare_figure_bundle(
|
|
32
|
+
prepare_figure_bundle(
|
|
33
|
+
view, tmpdir, title=title, description=description, script=script
|
|
34
|
+
)
|
|
25
35
|
# Create tar.gz file
|
|
26
36
|
import tarfile
|
|
27
37
|
|
|
@@ -31,5 +41,9 @@ def _save_figure(
|
|
|
31
41
|
# It's a folder
|
|
32
42
|
output_path_2.mkdir(parents=True, exist_ok=True)
|
|
33
43
|
prepare_figure_bundle(
|
|
34
|
-
view,
|
|
44
|
+
view,
|
|
45
|
+
str(output_path_2),
|
|
46
|
+
title=title,
|
|
47
|
+
description=description,
|
|
48
|
+
script=script,
|
|
35
49
|
)
|
|
@@ -91,6 +91,7 @@ def _show_view(
|
|
|
91
91
|
ephemeral: bool,
|
|
92
92
|
title: str,
|
|
93
93
|
description: Union[str, None],
|
|
94
|
+
script: Union[str, None],
|
|
94
95
|
inline: bool,
|
|
95
96
|
inline_height: int,
|
|
96
97
|
wait_for_input: bool,
|
|
@@ -99,7 +100,9 @@ def _show_view(
|
|
|
99
100
|
if upload:
|
|
100
101
|
# Upload behavior: create temporary directory for this upload only
|
|
101
102
|
with tempfile.TemporaryDirectory(prefix="figpack_upload_") as tmpdir:
|
|
102
|
-
prepare_figure_bundle(
|
|
103
|
+
prepare_figure_bundle(
|
|
104
|
+
view, tmpdir, title=title, description=description, script=script
|
|
105
|
+
)
|
|
103
106
|
|
|
104
107
|
# Check for API key - required for regular uploads, optional for ephemeral
|
|
105
108
|
api_key = os.environ.get("FIGPACK_API_KEY")
|
|
@@ -143,7 +146,7 @@ def _show_view(
|
|
|
143
146
|
|
|
144
147
|
# Prepare the figure bundle in the subdirectory
|
|
145
148
|
prepare_figure_bundle(
|
|
146
|
-
view, str(figure_dir), title=title, description=description
|
|
149
|
+
view, str(figure_dir), title=title, description=description, script=script
|
|
147
150
|
)
|
|
148
151
|
|
|
149
152
|
# Start or get existing server
|
|
@@ -134,7 +134,6 @@ def _create_or_get_figure(
|
|
|
134
134
|
total_size: Optional[int] = None,
|
|
135
135
|
title: Optional[str] = None,
|
|
136
136
|
ephemeral: bool = False,
|
|
137
|
-
source_url: Optional[str] = None,
|
|
138
137
|
) -> dict:
|
|
139
138
|
"""
|
|
140
139
|
Create a new figure or get existing figure information
|
|
@@ -145,7 +144,6 @@ def _create_or_get_figure(
|
|
|
145
144
|
total_size: Optional total size of files
|
|
146
145
|
title: Optional title for the figure
|
|
147
146
|
ephemeral: Whether to create an ephemeral figure
|
|
148
|
-
source_url: Optional source URL for the figure (must be unique)
|
|
149
147
|
|
|
150
148
|
Returns:
|
|
151
149
|
dict: Figure information from the API
|
|
@@ -171,8 +169,6 @@ def _create_or_get_figure(
|
|
|
171
169
|
payload["title"] = title
|
|
172
170
|
if ephemeral:
|
|
173
171
|
payload["ephemeral"] = True
|
|
174
|
-
if source_url is not None:
|
|
175
|
-
payload["sourceUrl"] = source_url
|
|
176
172
|
|
|
177
173
|
# Use the same endpoint for both regular and ephemeral figures
|
|
178
174
|
url = f"{FIGPACK_API_BASE_URL}/figures/create"
|
|
@@ -242,7 +238,6 @@ def _upload_bundle(
|
|
|
242
238
|
title: Optional[str] = None,
|
|
243
239
|
ephemeral: bool = False,
|
|
244
240
|
use_consolidated_metadata_only: bool = False,
|
|
245
|
-
source_url: Optional[str] = None,
|
|
246
241
|
) -> str:
|
|
247
242
|
"""
|
|
248
243
|
Upload the prepared bundle to the cloud using the new database-driven approach
|
|
@@ -254,7 +249,6 @@ def _upload_bundle(
|
|
|
254
249
|
ephemeral: Whether to create an ephemeral figure
|
|
255
250
|
use_consolidated_metadata_only: If True, excludes individual zarr metadata files
|
|
256
251
|
(.zgroup, .zarray, .zattrs) since they are included in .zmetadata
|
|
257
|
-
source_url: Optional source URL for the figure (must be unique)
|
|
258
252
|
"""
|
|
259
253
|
tmpdir_path = pathlib.Path(tmpdir)
|
|
260
254
|
|
|
@@ -283,7 +277,6 @@ def _upload_bundle(
|
|
|
283
277
|
total_size,
|
|
284
278
|
title=title,
|
|
285
279
|
ephemeral=ephemeral,
|
|
286
|
-
source_url=source_url,
|
|
287
280
|
)
|
|
288
281
|
figure_info = result.get("figure", {})
|
|
289
282
|
figure_url = figure_info.get("figureUrl")
|
|
@@ -418,39 +411,6 @@ def _upload_bundle(
|
|
|
418
411
|
return figure_url
|
|
419
412
|
|
|
420
413
|
|
|
421
|
-
def get_figure_by_source_url(source_url: str) -> Optional[str]:
|
|
422
|
-
"""
|
|
423
|
-
Query the API for a figure URL by its source URL
|
|
424
|
-
|
|
425
|
-
Args:
|
|
426
|
-
source_url: The source URL to search for
|
|
427
|
-
|
|
428
|
-
Returns:
|
|
429
|
-
Optional[str]: The figure URL if found, None otherwise
|
|
430
|
-
"""
|
|
431
|
-
payload = {"sourceUrl": source_url}
|
|
432
|
-
|
|
433
|
-
response = requests.post(
|
|
434
|
-
f"{FIGPACK_API_BASE_URL}/figures/find-by-source-url", json=payload
|
|
435
|
-
)
|
|
436
|
-
|
|
437
|
-
if not response.ok:
|
|
438
|
-
if response.status_code == 404:
|
|
439
|
-
return None
|
|
440
|
-
try:
|
|
441
|
-
error_data = response.json()
|
|
442
|
-
error_msg = error_data.get("message", "Unknown error")
|
|
443
|
-
except:
|
|
444
|
-
error_msg = f"HTTP {response.status_code}"
|
|
445
|
-
raise Exception(f"Failed to query figure by source URL: {error_msg}")
|
|
446
|
-
|
|
447
|
-
response_data = response.json()
|
|
448
|
-
if not response_data.get("success"):
|
|
449
|
-
return None
|
|
450
|
-
|
|
451
|
-
return response_data.get("figureUrl")
|
|
452
|
-
|
|
453
|
-
|
|
454
414
|
def _determine_content_type(file_path: str) -> str:
|
|
455
415
|
"""
|
|
456
416
|
Determine content type for upload based on file extension
|
|
@@ -131,9 +131,7 @@ def view_figure(figure_path: str, port: Union[int, None] = None) -> None:
|
|
|
131
131
|
)
|
|
132
132
|
return
|
|
133
133
|
|
|
134
|
-
if not
|
|
135
|
-
figure_pathlib
|
|
136
|
-
).endswith(".tar.gz"):
|
|
134
|
+
if not figure_path.endswith(".tar.gz") and not figure_path.endswith(".tgz"):
|
|
137
135
|
print(f"Error: Archive file must be a .tar.gz file: {figure_path}")
|
|
138
136
|
sys.exit(1)
|
|
139
137
|
|
|
@@ -20,6 +20,7 @@ class FigpackView:
|
|
|
20
20
|
*,
|
|
21
21
|
title: str,
|
|
22
22
|
description: Optional[str] = None,
|
|
23
|
+
script: Optional[str] = None,
|
|
23
24
|
port: Optional[int] = None,
|
|
24
25
|
open_in_browser: Optional[bool] = None,
|
|
25
26
|
upload: Optional[bool] = None,
|
|
@@ -29,7 +30,7 @@ class FigpackView:
|
|
|
29
30
|
allow_origin: Optional[str] = None,
|
|
30
31
|
wait_for_input: Optional[bool] = None,
|
|
31
32
|
_dev: Optional[bool] = None,
|
|
32
|
-
)
|
|
33
|
+
):
|
|
33
34
|
"""
|
|
34
35
|
Display a figpack view component with intelligent environment detection and flexible display options.
|
|
35
36
|
See https://flatironinstitute.github.io/figpack/show_function.html for complete documentation.
|
|
@@ -41,6 +42,7 @@ class FigpackView:
|
|
|
41
42
|
Args:
|
|
42
43
|
title: Title for browser tab and figure (required)
|
|
43
44
|
description: Description text with markdown support (optional)
|
|
45
|
+
script: Optional script text used to generate the figure
|
|
44
46
|
port: Local server port, random if None
|
|
45
47
|
open_in_browser: Auto-open in browser, auto-detects by environment
|
|
46
48
|
upload: Upload figure to figpack servers, auto-detects by environment
|
|
@@ -161,7 +163,7 @@ class FigpackView:
|
|
|
161
163
|
)
|
|
162
164
|
print("")
|
|
163
165
|
|
|
164
|
-
_show_view(
|
|
166
|
+
return _show_view(
|
|
165
167
|
self,
|
|
166
168
|
port=port,
|
|
167
169
|
open_in_browser=open_in_browser,
|
|
@@ -170,21 +172,29 @@ class FigpackView:
|
|
|
170
172
|
ephemeral=ephemeral,
|
|
171
173
|
title=title,
|
|
172
174
|
description=description,
|
|
175
|
+
script=script,
|
|
173
176
|
inline=inline,
|
|
174
177
|
inline_height=inline_height,
|
|
175
178
|
wait_for_input=wait_for_input,
|
|
176
179
|
_local_figure_name=_local_figure_name if _dev else None,
|
|
177
180
|
)
|
|
178
181
|
|
|
179
|
-
def save(
|
|
182
|
+
def save(
|
|
183
|
+
self, output_path: str, *, title: str, description: str = "", script: str = ""
|
|
184
|
+
) -> None:
|
|
180
185
|
"""
|
|
181
186
|
Save as figure either to a folder or to a .tar.gz file
|
|
182
187
|
Args:
|
|
183
188
|
output_path: Output path (destination folder or .tar.gz file path)
|
|
189
|
+
title: Title for the figure
|
|
190
|
+
description: Description text with markdown support
|
|
191
|
+
script: Optional script text used to generate the figure
|
|
184
192
|
"""
|
|
185
193
|
from ._save_figure import _save_figure
|
|
186
194
|
|
|
187
|
-
_save_figure(
|
|
195
|
+
_save_figure(
|
|
196
|
+
self, output_path, title=title, description=description, script=script
|
|
197
|
+
)
|
|
188
198
|
|
|
189
199
|
def write_to_zarr_group(self, group: Group) -> None:
|
|
190
200
|
"""
|