icplot 0.3.0__py3-none-any.whl → 0.3.3__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.
icplot/converter/image.py CHANGED
@@ -5,6 +5,8 @@ formats
5
5
 
6
6
  import logging
7
7
  import os
8
+ import shutil
9
+ import subprocess
8
10
  from pathlib import Path
9
11
 
10
12
  logger = logging.getLogger(__name__)
@@ -29,6 +31,10 @@ def has_wand() -> bool:
29
31
  return _HAS_WAND
30
32
 
31
33
 
34
+ def has_magick() -> bool:
35
+ return bool(shutil.which("magick"))
36
+
37
+
32
38
  def has_cairo_svg() -> bool:
33
39
  return _HAS_CAIRO_SVG
34
40
 
@@ -39,13 +45,27 @@ def _get_out_filename(source: Path, target: Path | None, extension: str) -> Path
39
45
  return source.parent / f"{source.stem}.{extension}"
40
46
 
41
47
 
48
+ def _pdf_to_png(source: Path, target: Path | None = None, resolution: int = 300):
49
+
50
+ outfile = _get_out_filename(source, target, "png")
51
+ os.makedirs(outfile.parent, exist_ok=True)
52
+ cmd = (
53
+ f"magick -density {resolution} -background white -alpha off {source} {outfile}"
54
+ )
55
+ subprocess.run(cmd, shell=True, check=True)
56
+
57
+
42
58
  def pdf_to_png(source: Path, target: Path | None = None, resolution: int = 300):
43
59
  """
44
60
  Convert a pdf to png with white background
45
61
  """
46
62
 
47
63
  if not has_wand():
48
- raise RuntimeError("Loading Wand failed - no pdf to png support")
64
+ if has_magick():
65
+ _pdf_to_png(source, target, resolution)
66
+ return
67
+ else:
68
+ raise RuntimeError("Loading Wand failed - no pdf to png support")
49
69
 
50
70
  outfile = _get_out_filename(source, target, "png")
51
71
  os.makedirs(outfile.parent, exist_ok=True)
@@ -1 +1,5 @@
1
1
  from . import formats # noqa: F401 — trigger handler registration
2
+ from .config import MermaidConfig, RenderConfig, TexConfig
3
+ from .render import render
4
+
5
+ __all__ = ["RenderConfig", "MermaidConfig", "TexConfig", "render"]
@@ -5,8 +5,10 @@ Mermaid must already be set up on the system, eg. via the npm ecosystem.
5
5
  """
6
6
 
7
7
  import logging
8
+ import os
8
9
  import shutil
9
10
  import subprocess
11
+ from pathlib import Path
10
12
 
11
13
  from ..config import RenderContext
12
14
 
@@ -26,16 +28,20 @@ def render(ctx: RenderContext):
26
28
  raise RuntimeError("Mermaid CLI 'mmdc' not found in path.")
27
29
 
28
30
  if ctx.output_dir:
29
- ctx.output_dir.mkdir(exist_ok=True)
31
+ ctx.output_dir.mkdir(exist_ok=True, parents=True)
30
32
  output_path = ctx.output_dir / f"{ctx.source.stem}.{ctx.output_type}"
31
33
  else:
32
34
  output_path = ctx.source.parent / f"{ctx.source.stem}.{ctx.output_type}"
33
35
 
34
36
  logger.info("Rendering: %s -> %s", ctx.source, output_path)
35
37
 
36
- cmd = f"mmdc -i {ctx.source} -o {output_path}"
37
- if ctx.config.mermaid.browser_config:
38
- cmd += f" -p {ctx.config.mermaid.browser_config}"
38
+ browser_config = ctx.config.mermaid.browser_config
39
+ if not browser_config and (env_path := os.environ.get("MMDC_PUPPETEER_CONFIG")):
40
+ browser_config = Path(env_path)
41
+
42
+ cmd = f"mmdc -i '{ctx.source}' -o '{output_path}'"
43
+ if browser_config:
44
+ cmd += f" -p '{browser_config}'"
39
45
  logger.debug("Command: %s", cmd)
40
46
  subprocess.run(cmd, shell=True, check=True)
41
47
  logger.info("Done: %s", output_path.name)
@@ -24,6 +24,9 @@ def render(ctx: RenderContext):
24
24
  logger.info("Rendering: %s -> %s", ctx.source, ctx.output_type)
25
25
 
26
26
  cmd = ["plantuml", f"-t{ctx.output_type}"]
27
+ if ctx.output_dir:
28
+ ctx.output_dir.mkdir(exist_ok=True, parents=True)
29
+ cmd.extend(["-o", str(ctx.output_dir)])
27
30
  if ctx.config.plantuml.config_path:
28
31
  cmd.extend(["-config", str(ctx.config.plantuml.config_path.resolve())])
29
32
  cmd.append(str(ctx.source))
@@ -37,7 +37,7 @@ def _run_commands(ctx: RenderContext, work_dir: Path):
37
37
  logger.debug("Engine: %s | work_dir: %s", ctx.config.tex.build_engine, work_dir)
38
38
 
39
39
  if ctx.config.tex.build_engine == "pdflatex":
40
- cmd = f"{ctx.config.tex.build_engine} {' '.join(extra_flags)} {ctx.source}"
40
+ cmd = f"{ctx.config.tex.build_engine} {' '.join(extra_flags)} '{ctx.source}'"
41
41
  logger.info("Command: %s", cmd.strip())
42
42
  with open(work_dir / "stdout.txt", "w", encoding="utf-8") as f:
43
43
  subprocess.run(
@@ -45,6 +45,7 @@ def _run_commands(ctx: RenderContext, work_dir: Path):
45
45
  shell=True,
46
46
  check=True,
47
47
  cwd=work_dir,
48
+ env=tex_env,
48
49
  stdout=f,
49
50
  stderr=f,
50
51
  stdin=subprocess.DEVNULL,
@@ -92,7 +93,9 @@ def render(ctx: RenderContext):
92
93
  work_dir = ctx.build_dir / ctx.source.stem
93
94
  work_dir.mkdir(exist_ok=True, parents=True)
94
95
 
95
- _run_commands(ctx, work_dir)
96
+ err = _run_commands(ctx, work_dir)
97
+ if err:
98
+ raise RuntimeError(f"Render failed for {ctx.source.name}: {err}")
96
99
 
97
100
  tex_path = work_dir / ctx.source.name
98
101
  if ctx.config.tex.build_engine == "pdflatex":
icplot/renderer/render.py CHANGED
@@ -61,10 +61,13 @@ def _get_extension(path: Path) -> str:
61
61
 
62
62
 
63
63
  def _collect_sources(root: Path, formats: list[str], excludes: list[str]) -> list[Path]:
64
- files = []
64
+ files: list[Path] = []
65
65
  if root.is_file():
66
66
  logger.info("Using source: %s", root)
67
67
  suffix = _get_extension(root)
68
+ if suffix not in _ENVIRONMENT_CHECKS:
69
+ logger.warning("Unknown extension .%s — no renderer registered", suffix)
70
+ return files
68
71
  if _ENVIRONMENT_CHECKS[suffix]():
69
72
  files.append(root)
70
73
  else:
@@ -76,6 +79,9 @@ def _collect_sources(root: Path, formats: list[str], excludes: list[str]) -> lis
76
79
  if not formats:
77
80
  formats = _FORMATS
78
81
  for f in formats:
82
+ if f not in _ENVIRONMENT_CHECKS:
83
+ logger.warning("Unknown format requested: %s — skipping", f)
84
+ continue
79
85
  if _ENVIRONMENT_CHECKS[f]():
80
86
  files.extend(find_files(root, f, excludes))
81
87
  else:
@@ -97,6 +103,9 @@ def _setup_tasks(
97
103
  output_formats = _DEFAULT_OUTPUT_FORMATS[ext]
98
104
 
99
105
  for fmt in output_formats:
106
+ if ext not in _RENDERERS:
107
+ logger.warning("No renderer for extension .%s — skipping %s", ext, f)
108
+ continue
100
109
  tasks.append(
101
110
  partial(
102
111
  _RENDERERS[ext],
@@ -135,6 +144,6 @@ def render(
135
144
  if errors:
136
145
  logger.error("%d/%d task(s) failed:", len(errors), len(tasks))
137
146
  for task_error in errors:
138
- logger.error(" %s", task_error[1].relative_to(root))
147
+ logger.error(" %s", task_error.args[0].source.relative_to(root))
139
148
  else:
140
149
  logger.info("Done — %d/%d task(s) succeeded", succeeded, len(tasks))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: icplot
3
- Version: 0.3.0
3
+ Version: 0.3.3
4
4
  Summary: Utilities for generating plots and graphics for technical reports.
5
5
  Author-email: "James Grogan, Irish Centre for High End Computing" <james.grogan@ichec.ie>
6
6
  Project-URL: Repository, https://git.ichec.ie/performance/toolshed/icplot
@@ -8,7 +8,7 @@ icplot/charts/tree.py,sha256=a7v092_RZkj1Q_SBdMvDRwPll3mnZBQQpHf8ZL7LzkA,3303
8
8
  icplot/converter/__init__.py,sha256=GfcJduTKQpUgiqxLnF-6lZN_CCuQMDeGbddHA61DmOU,108
9
9
  icplot/converter/cli.py,sha256=Eq8POhpmoBZQBiMSC1ksBwHCzyiZFYX5C8UT_TnoCb4,621
10
10
  icplot/converter/convert.py,sha256=KQdmtNx3JsoGRelWY9ajBex079SuLgyhRrKuUAPr678,781
11
- icplot/converter/image.py,sha256=oEMcB15T3cpto6EFdukgQLfUvjZCnQR9VLdC4kuxYyI,2075
11
+ icplot/converter/image.py,sha256=6iNqRspxhSrsFHXBexNAzPdjwAGb3GCG0_LbX6e09bM,2630
12
12
  icplot/geometry/__init__.py,sha256=rKIBe0dGG2toJM5BXWX8yJoWVKPVhOyik5P_ksn5l3k,125
13
13
  icplot/geometry/base.py,sha256=9HcgcglPMRtnszvS_sFf--FjCgx-swqqqRb5pT_8U10,1434
14
14
  icplot/geometry/operations.py,sha256=qZYHbBJ-pKG_T2BChKSLR4__fszbdVS-jQjUoLvpeQA,1476
@@ -31,17 +31,17 @@ icplot/graph/axis.py,sha256=3nyXoqdD-ui2C9CEr7-tZYaYeZI2AHyOU_kPK_qJGfc,965
31
31
  icplot/graph/plot.py,sha256=pGwrPoo646tsIMNc8UapsGgOF69gz-qceyDrvhKhzo4,1895
32
32
  icplot/graph/plot_group.py,sha256=EGaKWo86vSIPDCfolBQrUocalhZlZGLRqN9UhDvaj3Q,1697
33
33
  icplot/graph/series.py,sha256=V4CbozIopX3DFC8Bx82WXSXKNT__85kWaHfovtwmIpY,3169
34
- icplot/renderer/__init__.py,sha256=j32WdVwl_mkR98_JxHnlcc5BhcUNLqqF8ob2T0GMikg,69
34
+ icplot/renderer/__init__.py,sha256=qFbCv5_5AGNUhi4XC0CTZPpxRvsmnL4xtJKCr5AW7Mk,223
35
35
  icplot/renderer/cli.py,sha256=GIhDmmaqnrvCZ8EtKxG6AyGcYfq1aibho-Qn4Li1Ylw,1385
36
36
  icplot/renderer/config.py,sha256=2yHNMOk-J0cg4eIQc69zo62bEMdKF4-rXwXxk2vozHU,959
37
- icplot/renderer/render.py,sha256=5YypuoE7H6faX7j7UnnVHJ5r_39ntBG1Q7UwzayMyRk,4323
37
+ icplot/renderer/render.py,sha256=mQAy4pkpm71gZmxvcg05t1FWS3D7jkazZsMrbGU16ws,4805
38
38
  icplot/renderer/video.py,sha256=pgqFx8t-jA672dPaHTJDQntDfd8OjbJLaeU2n0ioy2w,747
39
39
  icplot/renderer/charts/pgfgantt.py,sha256=c59uBa-qpki8EiL-dqsv0J7yOnSZ87A9Y1GjMZU4yYE,2079
40
40
  icplot/renderer/charts/svggantt.py,sha256=8jQBXA7ZrCPDNDXN0GjvRDSId7n6yBGv8QNvK-B8AYc,1724
41
41
  icplot/renderer/formats/__init__.py,sha256=-J5zT5tAmaM8WPLaPvuWcrs9NVhS0GEAZTTpHpt437g,81
42
- icplot/renderer/formats/mermaid.py,sha256=OdTWotOtvIHMRJ5xxD2ul82XK4NSEx1uo7vu00EbgEo,1099
43
- icplot/renderer/formats/plantuml.py,sha256=YlYld0xGUcQjF45HINpxVlbdzHgkk6LvwghGAQiFxG0,1022
44
- icplot/renderer/formats/tex.py,sha256=DxgZMo2ZYLHVsBm3D_NdDcbMNZjbY0wndH9nCc254LQ,3815
42
+ icplot/renderer/formats/mermaid.py,sha256=Fe-3UKcDCJ0G4PCvPZ4UX69-6xQLa56Yw_QI87s4qTk,1297
43
+ icplot/renderer/formats/plantuml.py,sha256=W1jNVwXBrcsKrAY8iByeYWbVodARGl-xmgg35ZgQQ_c,1151
44
+ icplot/renderer/formats/tex.py,sha256=FnM84CqwZAKs13EKNDoQCmO7ESI4gMsKdsU8fnM_rGk,3938
45
45
  icplot/renderer/graph/__init__.py,sha256=gP9iFHKgIMzXs9i5dJJ5VKtMvSWnBLQ8lRWdS4xItKw,57
46
46
  icplot/renderer/graph/color.py,sha256=MxhzXMxvwCXNBkrlcpH49T2pZTd5fabw7QQEmk4Vy40,480
47
47
  icplot/renderer/graph/matplotlib.py,sha256=2UsIFJgX39tF7GFzPNkOR3OzTt7UHCeVCrbU0Ef8HJM,5516
@@ -57,9 +57,9 @@ icplot/theme/theme.py,sha256=-dbg9dueQR-Z7vkItaXAZw7RWzgLgx9MbkMRg06IxjI,3643
57
57
  icplot/theme/theme_generator.py,sha256=HDZ9Q_-yrDB2hlULQ2T4sAzrW013_ffkeJ7r-zEW_hc,4380
58
58
  icplot/theme/templates/puml.j2,sha256=YUW-awHGGhFtgat7CWUyu1q4ZiUamGrG15eq4ZGa9O4,3498
59
59
  icplot/theme/templates/tikz.j2,sha256=vJGbokhsPSoXiy2xK23r1imouHsdGGpwsRMF7rfraEA,6010
60
- icplot-0.3.0.dist-info/licenses/LICENSE,sha256=JedcPd23DfREo3CH5_Sc8He0jmmbOWIm1_sQaisXZ9E,34592
61
- icplot-0.3.0.dist-info/METADATA,sha256=3CLZaiR7nhLbMRiT8g_lSm1RTjJX8drkV8a03QmZAiI,3584
62
- icplot-0.3.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
63
- icplot-0.3.0.dist-info/entry_points.txt,sha256=6CdEGO5Z4NTQoOeRITTKGtzT3xNX47CGHZuWNWxZuZs,52
64
- icplot-0.3.0.dist-info/top_level.txt,sha256=T_ecIGmXlOO4_xP86S-OFL8nnoxmDQFXjcDoIwpiHQk,7
65
- icplot-0.3.0.dist-info/RECORD,,
60
+ icplot-0.3.3.dist-info/licenses/LICENSE,sha256=JedcPd23DfREo3CH5_Sc8He0jmmbOWIm1_sQaisXZ9E,34592
61
+ icplot-0.3.3.dist-info/METADATA,sha256=F2X0dajppDIDUAw9lbAYvYWTnU6JNgBDhgWAhiAgKGM,3584
62
+ icplot-0.3.3.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
63
+ icplot-0.3.3.dist-info/entry_points.txt,sha256=6CdEGO5Z4NTQoOeRITTKGtzT3xNX47CGHZuWNWxZuZs,52
64
+ icplot-0.3.3.dist-info/top_level.txt,sha256=T_ecIGmXlOO4_xP86S-OFL8nnoxmDQFXjcDoIwpiHQk,7
65
+ icplot-0.3.3.dist-info/RECORD,,
File without changes