diff --git a/pyproject.toml b/pyproject.toml index 7194929..3de99da 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,6 @@ virtual = true dev-dependencies = [ "ruff>=0.4.3", "fake-bpy-module-4-0>=20231118", - ## TODO: Blender 4.1 (when available) "pre-commit>=3.7.0", "commitizen>=3.25.0", ## Requires charset-normalizer>=2.1.0 @@ -167,6 +166,7 @@ version_provider = "pep621" tag_format = "v$version" # Version Bumping +retry_after_failure = true major_version_zero = true update_changelog_on_bump = true diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/flow_kinds/array.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/flow_kinds/array.py index 67458a4..c9428ab 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/flow_kinds/array.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/contracts/flow_kinds/array.py @@ -101,9 +101,8 @@ class ArrayFlow: return ArrayFlow( values=float(spux.scaling_factor(self.unit, unit)) * self.values, unit=unit, - is_sorted=self.is_sorted, ## TODO: Can we really say that? + is_sorted=self.is_sorted, ) - ## TODO: Is this scaling numerically stable? msg = f'Tried to rescale unitless LazyDataValueRange to unit {unit}' raise ValueError(msg) diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/managed_objs/managed_bl_mesh.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/managed_objs/managed_bl_mesh.py index 06a2122..66649d7 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/managed_objs/managed_bl_mesh.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/managed_objs/managed_bl_mesh.py @@ -227,8 +227,6 @@ class ManagedBLMesh(base.ManagedObj): @property def mesh_as_arrays(self) -> dict: - ## TODO: Cached - # Ensure Updated Geometry log.debug('Updating View Layer') bpy.context.view_layer.update() diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/web_importers/__init__.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/web_importers/__init__.py index 80ff89f..9c87ccc 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/web_importers/__init__.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/web_importers/__init__.py @@ -14,11 +14,11 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -# from . import tidy_3d_web_importer +from . import tidy_3d_web_runner BL_REGISTER = [ - # *tidy_3d_web_importer.BL_REGISTER, + *tidy_3d_web_runner.BL_REGISTER, ] BL_NODES = { - # **tidy_3d_web_importer.BL_NODES, + **tidy_3d_web_runner.BL_NODES, } diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/web_importers/tidy3d_web_runner.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/web_importers/tidy3d_web_runner.py index 41279a7..2f63596 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/web_importers/tidy3d_web_runner.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/inputs/web_importers/tidy3d_web_runner.py @@ -56,8 +56,6 @@ class RunSimulation(bpy.types.Operator): node = context.node node.cloud_task.submit() - ## TODO: Start modal timer that checks progress in a subprocess. - return {'FINISHED'} @@ -174,7 +172,6 @@ class Tidy3DWebRunnerNode(base.MaxwellSimNode): """Checks whether all conditions are satisfied to be able to actually run a simulation.""" if self.task_info is not None: return self.task_info.status == 'draft' - ## TODO: Rely on Visible Cost Estimate return False #################### @@ -282,5 +279,5 @@ BL_REGISTER = [ Tidy3DWebRunnerNode, ] BL_NODES = { - ct.NodeType.Tidy3DWebRunner: (ct.NodeCategory.MAXWELLSIM_OUTPUTS_WEBEXPORTERS) + ct.NodeType.Tidy3DWebRunner: (ct.NodeCategory.MAXWELLSIM_INPUTS_WEBIMPORTERS) } diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/outputs/web_exporters/__init__.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/outputs/web_exporters/__init__.py index 1b419e5..ff3d1ad 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/outputs/web_exporters/__init__.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/outputs/web_exporters/__init__.py @@ -14,13 +14,11 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -from . import tidy3d_web_exporter, tidy3d_web_runner +from . import tidy3d_web_exporter BL_REGISTER = [ *tidy3d_web_exporter.BL_REGISTER, - *tidy3d_web_runner.BL_REGISTER, ] BL_NODES = { **tidy3d_web_exporter.BL_NODES, - **tidy3d_web_runner.BL_NODES, } diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/temporal_shapes/wave_temporal_shape.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/temporal_shapes/wave_temporal_shape.py index 65d9bab..10eb77f 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/temporal_shapes/wave_temporal_shape.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/nodes/sources/temporal_shapes/wave_temporal_shape.py @@ -125,9 +125,6 @@ class WaveTemporalShapeNode(base.MaxwellSimNode): temporal_shape = output_sockets['Temporal Shape'] jax_amp_time = functools.partial(ct.manual_amp_time, temporal_shape) - ## TODO: Don't just partial() it up, do it property in the ParamsFlow! - ## -> Right now it's recompiled every time. - return ct.LazyValueFuncFlow( func=jax_amp_time, func_args=[spux.PhysicalType.Time], diff --git a/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/expr.py b/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/expr.py index 4778c1c..996f63b 100644 --- a/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/expr.py +++ b/src/blender_maxwell/node_trees/maxwell_sim_nodes/sockets/expr.py @@ -27,11 +27,6 @@ from blender_maxwell.utils import extra_sympy_units as spux from .. import contracts as ct from . import base -## TODO: This is a big node, and there's a lot to get right. -## - Dynamically adjust socket color in response to, especially, the unit dimension. -## - Generally pay attention to validity checking; it's make or break. -## - For array generation, it may pay to have both a symbolic expression (producing output according to `shape` as usual) denoting how to actually make values, and how many. Enables ex. easy symbolic plots. - log = logger.get(__name__) Int2: typ.TypeAlias = tuple[int, int] @@ -77,6 +72,15 @@ class InfoDisplayCol(enum.StrEnum): class ExprBLSocket(base.MaxwellSimSocket): + """The `Expr` ("Expression") socket is an accessible approach to specifying any expression. + + - **Shape**: There is an intuitive UI for scalar, 2D, and 3D, but the `Expr` socket also supports parsing mathematical expressions of any shape (including matrices). + - **Math Type**: Support integer, rational, real, and complex mathematical types, for which there is an intuitive UI for scalar, 2D, and 3D cases. + - **Physical Type**: Supports the declaration of a physical unit dimension, for which a UI exists for the user to switch between long lists of valid units for that dimension, with automatic conversion of the value. This causes the expression to become unit-aware, which will be respected when using it for math. + - **Symbols**: Supports the use of variables (each w/predefined `MathType`) to define arbitrary mathematical expressions, which can be used as part of a function composition chain and/or as a parameter realized at `Viz` / when generating batched simulations / when performing gradient-based optimization. + - **Information UX**: All information encoded by the expression is presented using an intuitive UI, including filterable access to the shape of any data passing through a linked socket. + """ + socket_type = ct.SocketType.Expr bl_label = 'Expr' use_info_draw = True @@ -556,12 +560,11 @@ class ExprBLSocket(base.MaxwellSimSocket): @property def info(self) -> ct.ArrayFlow: return ct.InfoFlow( - output_name='_', ## TODO: Something else + output_name='_', output_shape=self.shape, output_mathtype=self.mathtype, output_unit=self.unit, ) - ## TODO: When expression can be used w/arrays, then allow directly outputting a LazyArrayRange pumped through the given expression. Or something like that. #################### # - FlowKind: Capabilities @@ -572,8 +575,6 @@ class ExprBLSocket(base.MaxwellSimSocket): socket_type=self.socket_type, active_kind=self.active_kind, ) - ## TODO: Prevent all invalid linkage between sockets used as expressions, but don't be too brutal :) - ## - This really is a killer feature. But we want to get it right. So we leave it as todo until we know exactly how to tailor CapabilitiesFlow to these needs. #################### # - UI @@ -774,7 +775,6 @@ class ExprSocketDef(base.SocketDef): ] = ct.FlowKind.Value # Socket Interface - ## TODO: __hash__ like socket method based on these? shape: tuple[int, ...] | None = None mathtype: spux.MathType = spux.MathType.Real physical_type: spux.PhysicalType | None = None @@ -785,16 +785,13 @@ class ExprSocketDef(base.SocketDef): # FlowKind: Value default_value: spux.SympyExpr = sp.S(0) - abs_min: spux.SympyExpr | None = None ## TODO: Not used (yet) - abs_max: spux.SympyExpr | None = None ## TODO: Not used (yet) - ## TODO: Idea is to use this scalar uniformly for all shape elements - ## TODO: -> But we may want to **allow** using same-shape for diff. bounds. + abs_min: spux.SympyExpr | None = None + abs_max: spux.SympyExpr | None = None # FlowKind: LazyArrayRange default_min: spux.SympyExpr = sp.S(0) default_max: spux.SympyExpr = sp.S(1) default_steps: int = 2 - ## TODO: Configure lin/log/... scaling (w/enumprop in UI) # UI show_info_columns: bool = False diff --git a/src/blender_maxwell/nodeps/operators/uninstall_deps.py b/src/blender_maxwell/nodeps/operators/uninstall_deps.py index 32c33a1..eff5fe6 100644 --- a/src/blender_maxwell/nodeps/operators/uninstall_deps.py +++ b/src/blender_maxwell/nodeps/operators/uninstall_deps.py @@ -108,8 +108,6 @@ class UninstallPyDeps(bpy.types.Operator): # Brutally Delete / Remake PyDeps Folder ## The point isn't to protect against dedicated stupididy. ## Just to nudge away a few of the obvious "bad ideas" users might have. - ## TODO: Handle rmtree.avoids_symlink_attacks - ## TODO: Handle audit events log.warning( 'Deleting and Creating Folder at "%s": %s', 'pydeps_path', diff --git a/src/blender_maxwell/nodeps/utils/blender_type_enum.py b/src/blender_maxwell/nodeps/utils/blender_type_enum.py index 07032f1..5d4f202 100644 --- a/src/blender_maxwell/nodeps/utils/blender_type_enum.py +++ b/src/blender_maxwell/nodeps/utils/blender_type_enum.py @@ -29,7 +29,7 @@ def prefix_values_with(prefix: str) -> type[enum.Enum]: Returns: A new StrEnum class with altered member values. """ - ## TODO: DO NOT USE FOR ENUMS WITH METHODS + ## DO NOT USE FOR ENUMS WITH METHODS def _decorator(cls: enum.StrEnum): new_members = { @@ -49,7 +49,6 @@ def prefix_values_with(prefix: str) -> type[enum.Enum]: #################### # - BlenderTypeEnum #################### -## TODO: Migrate everyone to simple StrEnums class BlenderTypeEnum(str, enum.Enum): """Homegrown `str` enum for Blender types.""" @@ -84,7 +83,7 @@ def wrap_values_in_MT(cls) -> type[enum.Enum]: new_cls = enum.Enum(cls.__name__, new_members, type=BlenderTypeEnum) new_cls.__doc__ = cls.__doc__ new_cls.__module__ = cls.__module__ - new_cls.get_tree = cls.get_tree ## TODO: This is wildly specific... + new_cls.get_tree = cls.get_tree # Return New (Replacing) Enum Class return new_cls diff --git a/src/blender_maxwell/utils/logger.py b/src/blender_maxwell/utils/logger.py index 31d96c8..bab0ffe 100644 --- a/src/blender_maxwell/utils/logger.py +++ b/src/blender_maxwell/utils/logger.py @@ -35,12 +35,10 @@ from ..nodeps.utils.simple_logger import ( OUTPUT_CONSOLE = rich.console.Console( color_system='truecolor', - ## TODO: color_system should be 'auto'; bl_run.py hijinks are interfering ) ERROR_CONSOLE = rich.console.Console( color_system='truecolor', stderr=True, - ## TODO: color_system should be 'auto'; bl_run.py hijinks are interfering ) rich.traceback.install(show_locals=True, console=ERROR_CONSOLE) diff --git a/src/scripts/bl_install_addon.py b/src/scripts/bl_install_addon.py index 336ac41..4682161 100644 --- a/src/scripts/bl_install_addon.py +++ b/src/scripts/bl_install_addon.py @@ -40,7 +40,6 @@ def install_and_enable_addon(addon_name: str, addon_zip: Path) -> None: ), ] ): - ## TODO: Check if addon file path exists? in_pref_addons = addon_name in bpy.context.preferences.addons existing_files_found = { addon_path: (Path(addon_path) / addon_name).exists() diff --git a/src/scripts/pack.py b/src/scripts/pack.py index ee0e72f..16f1986 100644 --- a/src/scripts/pack.py +++ b/src/scripts/pack.py @@ -14,8 +14,6 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -# noqa: INP001 - import contextlib import logging import tempfile @@ -131,7 +129,6 @@ def main(): replace_if_exists=True, remove_after_close=False, ): - # TODO: GPG signature for distribution pass