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.
Files changed (79) hide show
  1. {figpack-0.3.1/figpack.egg-info → figpack-0.3.4}/PKG-INFO +2 -2
  2. {figpack-0.3.1 → figpack-0.3.4}/README.md +1 -1
  3. {figpack-0.3.1 → figpack-0.3.4}/figpack/__init__.py +1 -1
  4. {figpack-0.3.1 → figpack-0.3.4}/figpack/cli.py +2 -152
  5. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_bundle_utils.py +11 -3
  6. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_save_figure.py +17 -3
  7. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_show_view.py +5 -2
  8. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_upload_bundle.py +0 -40
  9. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_view_figure.py +1 -3
  10. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/figpack_view.py +14 -4
  11. figpack-0.3.4/figpack/figpack-figure-dist/assets/index-P3Ni9vtI.js +394 -0
  12. {figpack-0.3.1 → figpack-0.3.4}/figpack/figpack-figure-dist/index.html +1 -1
  13. figpack-0.3.4/figpack/utils/__init__.py +24 -0
  14. figpack-0.3.4/figpack-serve/worker/container/app.py +249 -0
  15. {figpack-0.3.1 → figpack-0.3.4/figpack.egg-info}/PKG-INFO +2 -2
  16. {figpack-0.3.1 → figpack-0.3.4}/figpack.egg-info/SOURCES.txt +3 -1
  17. {figpack-0.3.1 → figpack-0.3.4}/figpack.egg-info/top_level.txt +1 -0
  18. {figpack-0.3.1 → figpack-0.3.4}/pyproject.toml +1 -1
  19. figpack-0.3.1/figpack/figpack-figure-dist/assets/index-ST_DU17U.js +0 -95
  20. {figpack-0.3.1 → figpack-0.3.4}/LICENSE +0 -0
  21. {figpack-0.3.1 → figpack-0.3.4}/MANIFEST.in +0 -0
  22. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/__init__.py +0 -0
  23. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_file_handler.py +0 -0
  24. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_server_manager.py +0 -0
  25. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/_zarr_consolidate.py +0 -0
  26. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/config.py +0 -0
  27. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/extension_view.py +0 -0
  28. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/figpack_extension.py +0 -0
  29. {figpack-0.3.1 → figpack-0.3.4}/figpack/core/zarr.py +0 -0
  30. {figpack-0.3.1 → figpack-0.3.4}/figpack/extensions.py +0 -0
  31. {figpack-0.3.1 → figpack-0.3.4}/figpack/figpack-figure-dist/assets/index-V5m_wCvw.css +0 -0
  32. {figpack-0.3.1 → figpack-0.3.4}/figpack/figpack-figure-dist/assets/neurosift-logo-CLsuwLMO.png +0 -0
  33. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Box.py +0 -0
  34. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/CaptionedView.py +0 -0
  35. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/DataFrame.py +0 -0
  36. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Gallery.py +0 -0
  37. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/GalleryItem.py +0 -0
  38. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Iframe.py +0 -0
  39. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Image.py +0 -0
  40. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/LayoutItem.py +0 -0
  41. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Markdown.py +0 -0
  42. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/MatplotlibFigure.py +0 -0
  43. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/MountainLayout.py +0 -0
  44. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/MountainLayoutItem.py +0 -0
  45. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/MultiChannelTimeseries.py +0 -0
  46. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/PlotlyExtension/PlotlyExtension.py +0 -0
  47. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/PlotlyExtension/__init__.py +0 -0
  48. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/PlotlyExtension/_plotly_extension.py +0 -0
  49. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/PlotlyExtension/plotly_view.js +0 -0
  50. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Spectrogram.py +0 -0
  51. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/Splitter.py +0 -0
  52. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/TabLayout.py +0 -0
  53. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/TabLayoutItem.py +0 -0
  54. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/TimeseriesGraph.py +0 -0
  55. {figpack-0.3.1 → figpack-0.3.4}/figpack/views/__init__.py +0 -0
  56. {figpack-0.3.1 → figpack-0.3.4}/figpack.egg-info/dependency_links.txt +0 -0
  57. {figpack-0.3.1 → figpack-0.3.4}/figpack.egg-info/entry_points.txt +0 -0
  58. {figpack-0.3.1 → figpack-0.3.4}/figpack.egg-info/requires.txt +0 -0
  59. {figpack-0.3.1 → figpack-0.3.4}/setup.cfg +0 -0
  60. {figpack-0.3.1 → figpack-0.3.4}/tests/test_box.py +0 -0
  61. {figpack-0.3.1 → figpack-0.3.4}/tests/test_cli.py +0 -0
  62. {figpack-0.3.1 → figpack-0.3.4}/tests/test_core.py +0 -0
  63. {figpack-0.3.1 → figpack-0.3.4}/tests/test_dataframe.py +0 -0
  64. {figpack-0.3.1 → figpack-0.3.4}/tests/test_extension_system.py +0 -0
  65. {figpack-0.3.1 → figpack-0.3.4}/tests/test_figpack_view.py +0 -0
  66. {figpack-0.3.1 → figpack-0.3.4}/tests/test_file_handler.py +0 -0
  67. {figpack-0.3.1 → figpack-0.3.4}/tests/test_gallery.py +0 -0
  68. {figpack-0.3.1 → figpack-0.3.4}/tests/test_image.py +0 -0
  69. {figpack-0.3.1 → figpack-0.3.4}/tests/test_markdown.py +0 -0
  70. {figpack-0.3.1 → figpack-0.3.4}/tests/test_matplotlib_figure.py +0 -0
  71. {figpack-0.3.1 → figpack-0.3.4}/tests/test_multichannel_timeseries.py +0 -0
  72. {figpack-0.3.1 → figpack-0.3.4}/tests/test_plotly_figure.py +0 -0
  73. {figpack-0.3.1 → figpack-0.3.4}/tests/test_server_manager.py +0 -0
  74. {figpack-0.3.1 → figpack-0.3.4}/tests/test_spectrogram.py +0 -0
  75. {figpack-0.3.1 → figpack-0.3.4}/tests/test_splitter.py +0 -0
  76. {figpack-0.3.1 → figpack-0.3.4}/tests/test_tablayout.py +0 -0
  77. {figpack-0.3.1 → figpack-0.3.4}/tests/test_timeseries_graph.py +0 -0
  78. {figpack-0.3.1 → figpack-0.3.4}/tests/test_upload_bundle.py +0 -0
  79. {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.1
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.1) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.17419621
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.1) [Computer software]. Zenodo. https://doi.org/10.5281/zenodo.17419621
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
 
@@ -2,7 +2,7 @@
2
2
  figpack - A Python package for creating shareable, interactive visualizations in the browser
3
3
  """
4
4
 
5
- __version__ = "0.3.1"
5
+ __version__ = "0.3.4"
6
6
 
7
7
  from .cli import view_figure
8
8
  from .core import FigpackView, FigpackExtension, ExtensionView
@@ -16,9 +16,8 @@ from urllib.parse import urljoin
16
16
  import requests
17
17
 
18
18
  from . import __version__
19
- from .core._server_manager import CORSRequestHandler
20
- from .core._view_figure import serve_files, view_figure
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, tmpdir: str, *, title: str, description: Optional[str] = None
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 is not None:
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, output_path: str, *, title: str, description: str = ""
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(view, tmpdir, title=title, description=description)
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, str(output_path_2), title=title, description=description
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(view, tmpdir, title=title, description=description)
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 figure_pathlib.suffix.lower() in [".gz", ".tgz"] or not str(
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
- ) -> None:
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(self, output_path: str, *, title: str, description: str = "") -> None:
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(self, output_path, title=title, description=description)
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
  """