excel-codegen 0.9.0__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.
Files changed (82) hide show
  1. excel_codegen/__init__.py +160 -0
  2. excel_codegen/__main__.py +8 -0
  3. excel_codegen/cli.py +1250 -0
  4. excel_codegen/derived.py +465 -0
  5. excel_codegen/example_pack.py +107 -0
  6. excel_codegen/examples/README.md +69 -0
  7. excel_codegen/examples/abs_fpi/ABS_FPI_load_cases.xlsx +0 -0
  8. excel_codegen/examples/abs_fpi/ABS_FPI_load_cases_render.bat +22 -0
  9. excel_codegen/examples/abs_fpi/ABS_FPI_load_cases_render.sh +23 -0
  10. excel_codegen/examples/abs_fpi/README.md +121 -0
  11. excel_codegen/examples/abs_fpi/abs_fpi.yaml +310 -0
  12. excel_codegen/examples/abs_fpi/abs_fpi_external.xlsx +0 -0
  13. excel_codegen/examples/abs_fpi/abs_fpi_external.yaml +162 -0
  14. excel_codegen/examples/abs_fpi/abs_fpi_external_render.bat +22 -0
  15. excel_codegen/examples/abs_fpi/abs_fpi_external_render.sh +23 -0
  16. excel_codegen/examples/abs_fpi/abs_fpi_internal.xlsx +0 -0
  17. excel_codegen/examples/abs_fpi/abs_fpi_internal.yaml +266 -0
  18. excel_codegen/examples/abs_fpi/abs_fpi_internal_render.bat +22 -0
  19. excel_codegen/examples/abs_fpi/abs_fpi_internal_render.sh +23 -0
  20. excel_codegen/examples/abs_fpi/compose.yaml +20 -0
  21. excel_codegen/examples/abs_fpi/generated/COT1-d20.559-mu60.js +124 -0
  22. excel_codegen/examples/abs_fpi/generated/COT1-d20.559-mu60_summary.md +30 -0
  23. excel_codegen/examples/abs_fpi/generated/EXT-T15-mu0-kf-1.js +91 -0
  24. excel_codegen/examples/abs_fpi/generated/EXT-T15-mu0-kf-1_summary.md +23 -0
  25. excel_codegen/examples/abs_fpi/generated/EXT-T15-mu90-kf+1.js +91 -0
  26. excel_codegen/examples/abs_fpi/generated/EXT-T15-mu90-kf+1_summary.md +23 -0
  27. excel_codegen/examples/abs_fpi/generated/EXT-T20.559-mu90-kf+1.js +91 -0
  28. excel_codegen/examples/abs_fpi/generated/EXT-T20.559-mu90-kf+1_summary.md +23 -0
  29. excel_codegen/examples/abs_fpi/generated/WBT6-d15.059-mu0.js +124 -0
  30. excel_codegen/examples/abs_fpi/generated/WBT6-d15.059-mu0_summary.md +30 -0
  31. excel_codegen/examples/abs_fpi/generated/WBT6-d8-mu90.js +124 -0
  32. excel_codegen/examples/abs_fpi/generated/WBT6-d8-mu90_summary.md +30 -0
  33. excel_codegen/examples/abs_fpi/generated/WBT7-d20.559-mu90.js +124 -0
  34. excel_codegen/examples/abs_fpi/generated/WBT7-d20.559-mu90_summary.md +30 -0
  35. excel_codegen/examples/abs_fpi/templates/ext_body.js.j2 +91 -0
  36. excel_codegen/examples/abs_fpi/templates/ext_summary.md.j2 +23 -0
  37. excel_codegen/examples/abs_fpi/templates/int_body.js.j2 +124 -0
  38. excel_codegen/examples/abs_fpi/templates/int_summary.md.j2 +30 -0
  39. excel_codegen/examples/basic/example.yaml +97 -0
  40. excel_codegen/examples/basic/example_formula.yaml +86 -0
  41. excel_codegen/examples/basic/generated/uart_init_Case1.c +6 -0
  42. excel_codegen/examples/basic/generated/uart_init_Case2.c +6 -0
  43. excel_codegen/examples/basic/generated/uart_summary_Case1.md +4 -0
  44. excel_codegen/examples/basic/generated/uart_summary_Case2.md +4 -0
  45. excel_codegen/examples/basic/generated_formula/uart_init_Case1.c +5 -0
  46. excel_codegen/examples/basic/generated_formula/uart_init_Case2.c +5 -0
  47. excel_codegen/examples/basic/generated_formula/uart_pins_Case1.csv +1 -0
  48. excel_codegen/examples/basic/generated_formula/uart_pins_Case2.csv +1 -0
  49. excel_codegen/examples/basic/template.xlsx +0 -0
  50. excel_codegen/examples/basic/template_formula.xlsx +0 -0
  51. excel_codegen/examples/basic/template_formula_render.bat +22 -0
  52. excel_codegen/examples/basic/template_formula_render.sh +23 -0
  53. excel_codegen/examples/basic/template_render.bat +22 -0
  54. excel_codegen/examples/basic/template_render.sh +23 -0
  55. excel_codegen/examples/nastran/generated/case_control.deck +18 -0
  56. excel_codegen/examples/nastran/generated/cc_01_LC1.inc +8 -0
  57. excel_codegen/examples/nastran/generated/cc_02_LC2.inc +8 -0
  58. excel_codegen/examples/nastran/generated/cc_03_LC3.inc +8 -0
  59. excel_codegen/examples/nastran/generated/cc_04_COMB4.inc +8 -0
  60. excel_codegen/examples/nastran/generated/cc_05_LC5.inc +8 -0
  61. excel_codegen/examples/nastran/generated/cc_summary_01_LC1.md +1 -0
  62. excel_codegen/examples/nastran/generated/cc_summary_02_LC2.md +1 -0
  63. excel_codegen/examples/nastran/generated/cc_summary_03_LC3.md +1 -0
  64. excel_codegen/examples/nastran/generated/cc_summary_04_COMB4.md +1 -0
  65. excel_codegen/examples/nastran/generated/cc_summary_05_LC5.md +1 -0
  66. excel_codegen/examples/nastran/nastran_case_control.xlsx +0 -0
  67. excel_codegen/examples/nastran/nastran_case_control.yaml +141 -0
  68. excel_codegen/examples/nastran/nastran_case_control_render.bat +22 -0
  69. excel_codegen/examples/nastran/nastran_case_control_render.sh +23 -0
  70. excel_codegen/excel_io.py +1885 -0
  71. excel_codegen/formula.py +674 -0
  72. excel_codegen/formula_eval.py +685 -0
  73. excel_codegen/jinja_env.py +92 -0
  74. excel_codegen/models.py +1008 -0
  75. excel_codegen/renderer.py +558 -0
  76. excel_codegen/utils.py +225 -0
  77. excel_codegen-0.9.0.dist-info/METADATA +179 -0
  78. excel_codegen-0.9.0.dist-info/RECORD +82 -0
  79. excel_codegen-0.9.0.dist-info/WHEEL +5 -0
  80. excel_codegen-0.9.0.dist-info/entry_points.txt +2 -0
  81. excel_codegen-0.9.0.dist-info/licenses/LICENSE +21 -0
  82. excel_codegen-0.9.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,92 @@
1
+ """Jinja2 环境与自定义过滤器(模板渲染与派生参数求值共用一套语义)。
2
+
3
+ 单独成模块的原因:``renderer`` 依赖 ``excel_io``,而 ``excel_io`` 又要能求值派生参数
4
+ (``derived:``);把环境构造放在最底层,两边都 import 它,避免循环依赖。
5
+
6
+ **模板渲染与派生参数必须用同一个环境** —— 否则 ``{{ x }}`` 与 ``derived: x`` 的
7
+ 数值形态(整数浮点、bool、None)会不一致。
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from collections.abc import Sequence
13
+ from pathlib import Path
14
+ from typing import Any
15
+
16
+ from jinja2 import Environment, FileSystemLoader, StrictUndefined, Undefined
17
+
18
+ from .utils import to_text
19
+
20
+ __all__ = ["build_environment", "pvs", "wrap"]
21
+
22
+
23
+ # --------------------------------------------------------------------------- #
24
+ # 过滤器
25
+ # --------------------------------------------------------------------------- #
26
+ def pvs(value: Any, prefix: Any = "", suffix: Any = "") -> str:
27
+ """Prefix + Value + Suffix 过滤器:``{{ "A" | pvs("GPIO", "_PORT") }}`` -> ``GPIOA_PORT``。"""
28
+ return f"{to_text(prefix)}{to_text(value)}{to_text(suffix)}"
29
+
30
+
31
+ def wrap(value: Any, prefix: Any = "", suffix: Any = "") -> str:
32
+ """``pvs`` 的别名:``{{ "A" | wrap("GPIO", "_PORT") }}`` -> ``GPIOA_PORT``。"""
33
+ return pvs(value, prefix, suffix)
34
+
35
+
36
+ # --------------------------------------------------------------------------- #
37
+ # 环境
38
+ # --------------------------------------------------------------------------- #
39
+ def finalize_value(value: Any) -> Any:
40
+ """Jinja2 输出收尾:让 ``{{ x }}`` 与 ``{{ x.value }}`` 的文本形态一致。
41
+
42
+ 只在 ``bool`` / ``float`` / ``None`` 上做规范化,其余类型原样交给 Jinja2:
43
+
44
+ * ``{{ x.value }}``(float ``340.0``)-> ``340``,与 ``{{ x }}`` 相同
45
+ * ``{{ flag.value }}``(bool)-> ``true`` / ``false``,与 :func:`utils.to_text` 相同
46
+ * ``{{ none_value }}`` -> ``""``(而不是 ``None``)
47
+ """
48
+ if value is None or isinstance(value, (bool, float)):
49
+ return to_text(value)
50
+ return value
51
+
52
+
53
+ def build_environment(
54
+ *,
55
+ strict: bool = True,
56
+ trim_blocks: bool = False,
57
+ lstrip_blocks: bool = False,
58
+ keep_trailing_newline: bool = True,
59
+ search_path: Sequence[str | Path] | None = None,
60
+ **options: Any,
61
+ ) -> Environment:
62
+ """构建带 ``pvs`` / ``wrap`` 过滤器的 Jinja2 环境。
63
+
64
+ 默认使用 ``StrictUndefined``:模板引用了不存在的变量会立刻报错,而不是静默渲染成空串。
65
+ ``finalize`` 负责把数值统一成文本形态(见 :func:`finalize_value`)。
66
+
67
+ :param search_path: 给了就装一个 ``FileSystemLoader``,模板里的 ``{% include "片段.j2" %}``
68
+ 会按这些目录去找(相对**声明模板的那个文件**解析,见指南 §17)。
69
+ """
70
+ finalize = options.pop("finalize", finalize_value)
71
+ loader = FileSystemLoader([str(item) for item in search_path]) if search_path else None
72
+ environment = Environment(
73
+ loader=loader,
74
+ undefined=StrictUndefined if strict else Undefined,
75
+ trim_blocks=trim_blocks,
76
+ lstrip_blocks=lstrip_blocks,
77
+ keep_trailing_newline=keep_trailing_newline,
78
+ autoescape=False,
79
+ finalize=finalize,
80
+ **options,
81
+ )
82
+ environment.filters["pvs"] = pvs
83
+ environment.filters["wrap"] = wrap
84
+ # 常用数学函数:Jinja 只把 min/max 做成过滤器,表达式里 `max(a, b)` 会报 undefined。
85
+ # 派生参数(derived:)与模板都用同一套全局函数,语义是 Python 的。
86
+ environment.globals.setdefault("min", min)
87
+ environment.globals.setdefault("max", max)
88
+ environment.globals.setdefault("abs", abs)
89
+ environment.globals.setdefault("int", int)
90
+ environment.globals.setdefault("float", float)
91
+ environment.globals.setdefault("round", round)
92
+ return environment