From 406dadc90cb5d6b454d65a5b33e33b143b5bc796 Mon Sep 17 00:00:00 2001 From: Yannick Augenstein Date: Wed, 22 Oct 2025 09:34:18 +0200 Subject: [PATCH] docs(config): docs for new config system --- docs/_ext/custom-robots.py | 7 +- docs/_templates/module.rst | 3 +- docs/api/configuration.rst | 41 +++++ docs/api/constants.rst | 4 +- docs/api/index.rst | 1 + docs/api/simulation.rst | 5 +- docs/api/sources.rst | 2 +- docs/configuration/index.rst | 156 +++++++++++++++++++ docs/configuration/migration.rst | 31 ++++ docs/configuration/reference.rst | 253 +++++++++++++++++++++++++++++++ docs/extras/index.rst | 12 +- docs/index.rst | 32 ++-- docs/install.rst | 20 +-- tidy3d/config/README.md | 81 ++++++++++ 14 files changed, 594 insertions(+), 54 deletions(-) create mode 100644 docs/api/configuration.rst create mode 100644 docs/configuration/index.rst create mode 100644 docs/configuration/migration.rst create mode 100644 docs/configuration/reference.rst create mode 100644 tidy3d/config/README.md diff --git a/docs/_ext/custom-robots.py b/docs/_ext/custom-robots.py index c0a0002294..72063a7fe0 100644 --- a/docs/_ext/custom-robots.py +++ b/docs/_ext/custom-robots.py @@ -6,18 +6,13 @@ def process_robots_txt(app, exception): # Get the path to the robots.txt file robots_file = os.path.join(app.outdir, "robots.txt") - - # Read the contents of the robots.txt file with open(robots_file) as f: contents = f.read() - # Modify the contents as needed - # site_map = app.config['html_baseurl'] + app.config['version'] + app.config['language'] + 'sitemap.xml' site_map = "/".join( [app.config["html_baseurl"], app.config["language"], app.config["version"], "sitemap.xml"] ).replace("//", "/") - new_content = f"\nSitemap: {site_map}" - contents += new_content + contents += f"\nSitemap: {site_map}" # Update the robots.txt file with the modified contents with open(robots_file, "w") as f: diff --git a/docs/_templates/module.rst b/docs/_templates/module.rst index 32b8bdf00d..cbfd22ee7e 100644 --- a/docs/_templates/module.rst +++ b/docs/_templates/module.rst @@ -39,4 +39,5 @@ .. rubric:: Inherited Common Usage - .. include:: ../_custom_autosummary/{{ fullname }}.rst \ No newline at end of file + .. include:: ../_custom_autosummary/{{ fullname }}.rst + :optional: diff --git a/docs/api/configuration.rst b/docs/api/configuration.rst new file mode 100644 index 0000000000..5bfb84df1c --- /dev/null +++ b/docs/api/configuration.rst @@ -0,0 +1,41 @@ +Configuration API +================= + +.. currentmodule:: tidy3d.config + +The objects and helpers below expose the public configuration interface. + +Manager and Helpers +------------------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.config.ConfigManager + tidy3d.config.get_manager + tidy3d.config.reload_config + +Legacy Compatibility +-------------------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.config.LegacyConfigWrapper + tidy3d.config.Environment + tidy3d.config.EnvironmentConfig + +Registration Utilities +---------------------- + +.. autosummary:: + :toctree: _autosummary/ + :template: module.rst + + tidy3d.config.register_section + tidy3d.config.register_plugin + tidy3d.config.register_handler + tidy3d.config.get_sections + tidy3d.config.get_handlers diff --git a/docs/api/constants.rst b/docs/api/constants.rst index 6a2c0ebca5..f3f8892af6 100644 --- a/docs/api/constants.rst +++ b/docs/api/constants.rst @@ -35,7 +35,7 @@ Tidy3D Configuration :toctree: _autosummary/ :template: module.rst - tidy3d.config.Tidy3dConfig + tidy3d.config.ConfigManager Default Absorber Parameters ---------------------------- @@ -92,4 +92,4 @@ Precision & Comparator Values tidy3d.constants.fp_eps tidy3d.constants.pec_val tidy3d.constants.LARGE_NUMBER - tidy3d.constants.GLANCING_CUTOFF \ No newline at end of file + tidy3d.constants.GLANCING_CUTOFF diff --git a/docs/api/index.rst b/docs/api/index.rst index bb46ae705c..9a77908bd4 100644 --- a/docs/api/index.rst +++ b/docs/api/index.rst @@ -18,6 +18,7 @@ API |:computer:| output_data analytic_beams utilities + configuration mesh/index heat/index charge/index diff --git a/docs/api/simulation.rst b/docs/api/simulation.rst index 412b1a7667..9427064255 100644 --- a/docs/api/simulation.rst +++ b/docs/api/simulation.rst @@ -61,7 +61,8 @@ Logging :toctree: _autosummary/ :template: module.rst - tidy3d.config.logging_level - tidy3d.set_logging_file + tidy3d.log.set_logging_level + tidy3d.log.set_log_suppression + tidy3d.log.set_logging_file ~~~~ diff --git a/docs/api/sources.rst b/docs/api/sources.rst index 4119e93dc6..c9cd9a54c2 100644 --- a/docs/api/sources.rst +++ b/docs/api/sources.rst @@ -6,7 +6,7 @@ Sources Overview -------- -Sources in Tidy3D provide the necessary excitation to investigate the EM behaviour of the structures under simulation. The type of source used in a simulation tends to be very application-specific. For instance, a ``PlaneWave`` source may be used for a unit cell simulation in a metalens; whereas a ``ModeSource`` would be more appropriate for a waveguide crossing problem. +Sources in Tidy3D provide the necessary excitation to investigate the EM behavior of the structures under simulation. The type of source used in a simulation tends to be very application-specific. For instance, a ``PlaneWave`` source may be used for a unit cell simulation in a metalens; whereas a ``ModeSource`` would be more appropriate for a waveguide crossing problem. A generic source can be thought of as composed of two parts: a spatial profile and a temporal profile. The former dictates the field distribution in space, whereas the latter determines the frequency band covered by the source, and by extension, the overall simulation. diff --git a/docs/configuration/index.rst b/docs/configuration/index.rst new file mode 100644 index 0000000000..19596fe11c --- /dev/null +++ b/docs/configuration/index.rst @@ -0,0 +1,156 @@ +Configuration Guide |:gear:| +============================ + +.. highlight:: python + +Working with cloud simulations usually requires a handful of settings such as +your API key, the active environment, and any local tweaks you make while +experimenting. The ``config`` object (available via ``from tidy3d import config``) +keeps all of this in one place through a single interface. This page explains +how it behaves, where values are stored, and how to keep your changes +consistent across sessions. For a catalog of every option, see :doc:`reference`. + +Getting Started +--------------- + +Most users only need the following import:: + + from tidy3d import config + +You can then read or update sections just like attributes:: + + # read values + print(config.web.api_endpoint) + print(config.logging.level) + + # update values + config.logging.level = "DEBUG" + config.web.timeout = 60 + config.save() + +The ``save()`` call writes your edits to disk so the same settings load the +next time you import ``tidy3d``. + +Where Settings Are Stored +------------------------- + +Tidy3D chooses a configuration directory the first time you import the module. +The location depends on your operating system: + +.. list-table:: Default configuration directory + :widths: 30 70 + :header-rows: 1 + + * - Platform + - Path + * - macOS / Linux + - ``~/.config/tidy3d`` + * - Windows + - ``C:\Users\\.config\tidy3d`` + +You can override this by setting the ``TIDY3D_BASE_DIR`` environment variable +*before* importing ``tidy3d``. When it is present, the config files are kept in +``/.tidy3d``. If the chosen location is not writable, Tidy3D falls back to +a temporary directory and warns that the settings will not persist. + +Files Inside the Directory +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- ``config.toml`` – base settings shared by all profiles. +- ``profiles/.toml`` – optional overrides for custom profiles. Each file + only contains the differences from the base settings. + +Priority Order +-------------- + +Whenever you read ``config.
.``, the value comes from the highest +priority source in the list below. Lower entries only apply when the ones above +them do not set a value. + +1. Runtime changes you make in the current Python session. +2. Environment variables (``TIDY3D_
__``). +3. Profile overrides from ``profiles/.toml``. +4. The base ``config.toml`` file. +5. Built-in profiles (for example ``prod`` and ``dev``) bundled with Tidy3D. +6. Default values defined by the software. + +This means environment variables always win over ``config.toml``, and any +attribute you set in code wins over everything else until you discard it or +call ``save()``. + +Making Changes That Last +------------------------ + +Runtime Updates +~~~~~~~~~~~~~~~ + +Assignments like ``config.logging.level = "INFO"`` apply immediately but only +live in memory. They affect new simulations started in the same interpreter but +disappear when the process exits. + +Saving to Disk +~~~~~~~~~~~~~~ + +Call ``config.save()`` to write the current profile to disk. The method removes +environment-variable overrides automatically so you never persist an API key or +other secret that was loaded from the shell. To store the full set of values, +including defaults, pass ``include_defaults=True``:: + + config.save(include_defaults=True) + +Profiles +-------- + +Tidy3D ships with built-in profiles such as ``prod`` and ``dev``. Switch between +them with:: + + config.switch_profile("dev") + +To create your own profile, switch to a new name, edit settings, then call +``save()``:: + + config.switch_profile("my_profile") + config.web.api_endpoint = "https://example.com" + config.save() + +This writes ``profiles/my_profile.toml`` containing only the adjustments you +made. Use ``config.profiles.list()`` to discover available built-in and user +profiles. + +Environment Variables +--------------------- + +Environment variables let you override individual options without touching any +files. The naming pattern is ``TIDY3D_
__``, for example:: + + export TIDY3D_LOGGING__LEVEL=WARNING + +Supported variables take effect the next time you import ``tidy3d``. Remove a +variable or clear the shell environment to restore the lower priority setting. + +Command Line Helpers +-------------------- + +Use ``tidy3d configure`` to store your API key in ``config.toml``. The command +creates the directory if it is missing and updates only the ``web`` section. + +If you have older files in ``~/.tidy3d``, run ``tidy3d config migrate`` to move +them into the new location described above. The command copies the legacy files +into the canonical directory, leaving the originals untouched unless you pass +``--delete-legacy``. Use ``--overwrite`` if you have already started using the +new location and want to replace those files with the legacy versions. + +Legacy Access Points +-------------------- + +Older code paths such as ``tidy3d.config.logging_level`` and ``tidy3d.config.Env`` +still work. They emit a ``DeprecationWarning`` each time you use them to help +you transition to the modern interface. See :doc:`migration` for advice on +updating scripts that depend on these names. + +Next Steps +---------- + +- :doc:`reference` +- :doc:`migration` +- :doc:`../api/configuration` diff --git a/docs/configuration/migration.rst b/docs/configuration/migration.rst new file mode 100644 index 0000000000..d88a7dc3b8 --- /dev/null +++ b/docs/configuration/migration.rst @@ -0,0 +1,31 @@ +Upgrading Existing Setups +========================= + +This short note highlights the differences you may notice when moving from +earlier versions of Tidy3D to the current configuration manager. + +File Locations +-------------- + +- Previous releases stored settings in ``~/.tidy3d`` on all platforms. The new + manager now prefers the platform-specific paths described in + :doc:`index`. +- Your existing ``~/.tidy3d/config`` is still respected. Run + ``tidy3d config migrate`` if you would like to copy it into the new directory. + Append ``--overwrite`` to replace any files that already exist in the new + location, and ``--delete-legacy`` to remove ``~/.tidy3d`` after the copy. + +Environment Switching +--------------------- + +- The ``Env`` helper remains available. Calls such as ``Env.dev.active()`` now + forward to the new manager and produce a ``DeprecationWarning`` to encourage + the modern API, e.g. ``config.switch_profile("dev")``. + +Legacy Attributes +----------------- + +- Shorthand properties ``config.logging_level``, ``config.log_suppression``, + and ``config.use_local_subpixel`` still work and set the equivalent fields in + ``config.logging`` or ``config.simulation``. Each call raises a warning so + you can update scripts at your own pace. diff --git a/docs/configuration/reference.rst b/docs/configuration/reference.rst new file mode 100644 index 0000000000..a68cc327a6 --- /dev/null +++ b/docs/configuration/reference.rst @@ -0,0 +1,253 @@ +Configuration Reference +======================= + +All configuration for ``tidy3d`` lives under a single object: + +.. code-block:: python + + from tidy3d import config + +The tables below list the built-in sections and every option they expose. + +How to read this page +--------------------- + +- Environment variable overrides always take precedence. Follow the pattern + ``TIDY3D_
__`` (nesting continues with additional ``__`` + segments such as ``TIDY3D_PLUGINS__SAMPLE__ENABLED``). +- The *Persisted* column marks fields written to disk when you call + ``config.save()``. Unmarked fields remain in-memory unless you pass + ``include_defaults=True`` or store them in profiles or environment variables. +- Descriptions call out notable allowed values, defaults, and persistence + behavior. Literal values appear in quotes and tuples use the ``(x, y, z)`` + notation seen throughout the API. + + +Logging (``config.logging``) +---------------------------- + +Controls the verbosity and suppression behavior of the global logger. + +.. list-table:: + :header-rows: 1 + :widths: 22 18 10 50 + + * - Option + - Default + - Persisted + - Description + * - ``level`` + - ``"WARNING"`` + - Yes + - Lowest logging level that will be emitted. Accepts ``"DEBUG"``, ``"SUPPORT"``, ``"USER"``, + ``"INFO"``, ``"WARNING"``, ``"ERROR"``, and ``"CRITICAL"``. + * - ``suppression`` + - ``True`` + - No + - Suppress repeated log messages when ``True`` so only the first occurrence of identical + messages is shown. + + +Simulation (``config.simulation``) +---------------------------------- + +Optional overrides that tweak solver behavior at runtime. + +.. list-table:: + :header-rows: 1 + :widths: 22 18 10 50 + + * - Option + - Default + - Persisted + - Description + * - ``use_local_subpixel`` + - ``None`` + - No + - Set to ``True`` to force local subpixel averaging, ``False`` to disable it, or leave ``None`` to keep the solver default. + + +Microwave (``config.microwave``) +-------------------------------- + +Options that apply to the microwave solver add-on. + +.. list-table:: + :header-rows: 1 + :widths: 22 18 10 50 + + * - Option + - Default + - Persisted + - Description + * - ``suppress_rf_license_warning`` + - ``False`` + - No + - Skip the warning about RF license availability when set to ``True``. + + +Adjoint (``config.adjoint``) +---------------------------- + +Parameters for adjoint behavior, including local execution settings and numerical tolerances. +These overrides apply only when ``local_gradient`` is ``True``; otherwise the service uses its +remote defaults and emits a warning reminding you to enable local gradients. + +.. list-table:: + :header-rows: 1 + :widths: 24 18 10 48 + + * - Option + - Default + - Persisted + - Description + * - ``min_wvl_fraction`` + - ``0.05`` + - No + - Minimum fraction of the smallest wavelength used when discretizing cylinders for autograd derivatives. + * - ``points_per_wavelength`` + - ``10`` + - No + - Number of material sample points per wavelength for cylinder discretization (must be positive). + * - ``default_wavelength_fraction`` + - ``0.1`` + - No + - Fallback fraction of the minimum wavelength when adaptive spacing is needed (must be ``>= 0``). + * - ``minimum_spacing_fraction`` + - ``0.01`` + - No + - Smallest normalized spacing allowed when constructing adaptive finite-difference stencils (must be ``>= 0``). + * - ``local_gradient`` + - ``False`` + - Yes + - Enable local gradient evaluation. Remote gradients ignore other adjoint overrides unless this is ``True``. + * - ``local_adjoint_dir`` + - ``"adjoint_data"`` + - Yes + - Directory (relative to the working directory) where intermediate gradient artifacts are stored when ``local_gradient`` is enabled. + * - ``gradient_precision`` + - ``"single"`` + - No + - Floating-point precision used for gradient calculations. Accepts ``"single"`` or ``"double"``. + * - ``monitor_interval_poly`` + - ``(1, 1, 1)`` + - No + - Cell spacing between samples for polynomial autograd monitors. + * - ``monitor_interval_custom`` + - ``(1, 1, 1)`` + - No + - Cell spacing between samples for custom autograd monitors. + * - ``quadrature_sample_fraction`` + - ``0.4`` + - No + - Fraction of uniform samples reused when building Gauss quadrature nodes (between ``0`` and ``1``). + * - ``gauss_quadrature_order`` + - ``7`` + - No + - Maximum Gauss–Legendre order used in composite quadrature rules (must be positive). + * - ``edge_clip_tolerance`` + - ``1e-9`` + - No + - Padding tolerance used when clipping polygon edges during surface integrations (must be ``>= 0``). + * - ``solver_freq_chunk_size`` + - ``None`` + - No + - Upper bound on the number of frequencies processed per chunk during gradient evaluation. Set to a positive integer to enable chunking or leave ``None`` to disable it. + * - ``max_traced_structures`` + - ``500`` + - No + - Maximum number of structures whose fields may be traced in an adjoint run. + * - ``max_adjoint_per_fwd`` + - ``10`` + - No + - Maximum number of adjoint simulations dispatched per forward solve. + + +Web (``config.web``) +-------------------- + +Settings for the cloud API client and related environment overrides. + +.. list-table:: + :header-rows: 1 + :widths: 24 18 10 48 + + * - Option + - Default + - Persisted + - Description + * - ``apikey`` + - ``None`` + - Yes + - API key used for authentication. The value is masked when serialized. Also accepts ``SIMCLOUD_APIKEY`` as a shortcut environment variable. + * - ``ssl_verify`` + - ``True`` + - No + - Verify SSL certificates for API requests. + * - ``enable_caching`` + - ``True`` + - Yes + - Allow the web service to return cached simulation results when available. + * - ``api_endpoint`` + - ``"https://tidy3d-api.simulation.cloud"`` + - No + - Base URL for API calls. Must be an HTTP or HTTPS URL. + * - ``website_endpoint`` + - ``"https://tidy3d.simulation.cloud"`` + - No + - Base URL for the Tidy3D website. Must be an HTTP or HTTPS URL. + * - ``s3_region`` + - ``"us-gov-west-1"`` + - No + - AWS region used by the platform’s S3 storage. + * - ``timeout`` + - ``120`` + - No + - HTTP request timeout in seconds (between ``0`` and ``300``). + * - ``ssl_version`` + - ``None`` + - No + - Explicit TLS version to enforce (for example ``ssl.TLSVersion.TLSv1_2``). Leave ``None`` to let ``requests`` negotiate the version. + * - ``env_vars`` + - ``{}`` + - No + - Additional environment variables exported before API calls. Useful for proxy or credential helpers. + + +Local Cache (``config.local_cache``) +------------------------------------ + +Controls the optional on-disk cache for simulation artifacts. + +.. list-table:: + :header-rows: 1 + :widths: 24 18 10 48 + + * - Option + - Default + - Persisted + - Description + * - ``enabled`` + - ``False`` + - Yes + - Turn the local cache on or off. When enabled, results are reused if the inputs match. + * - ``directory`` + - ``/cache/simulations`` + - Yes + - Directory where cached artifacts are stored. The path is expanded, resolved, and created if missing. ```` comes from ``TIDY3D_BASE_DIR`` when set, otherwise ``XDG_CACHE_HOME`` on Unix or ``~/.cache`` elsewhere (resolving to ``~/.cache/tidy3d/simulations`` by default). + * - ``max_size_gb`` + - ``10.0`` + - Yes + - Maximum cache size in gigabytes. ``0`` disables the size limit. + * - ``max_entries`` + - ``0`` + - Yes + - Maximum number of cached simulations retained. ``0`` means no limit and eviction falls back to size constraints. + + +Plugins (``config.plugins``) +---------------------------- + +Container that holds plugin-defined sections. After a plugin calls +``@register_plugin("name")``, its configuration becomes available under +``config.plugins.`` and follows the same persistence and environment variable rules described above (for example ``TIDY3D_PLUGINS__NAME__FIELD``). diff --git a/docs/extras/index.rst b/docs/extras/index.rst index 8594deb2f7..2d4453e91d 100644 --- a/docs/extras/index.rst +++ b/docs/extras/index.rst @@ -57,15 +57,21 @@ with subpixel averaging is used whenever the mode solver is run locally. Sometimes, you may want to change this behavior, for example to speed up permittivity computation. In this case, you can temporarily disable these -features by setting the config variable:: +features through the configuration manager:: - tidy3d.config.use_local_subpixel = False + from tidy3d import config -This can also be set to ``True`` to ensure that subpixel averaging is used. + config.simulation.use_local_subpixel = False + +Set the value to ``True`` to ensure that subpixel averaging is used, then call +``config.save()`` if you would like the change to persist across sessions. You can check whether local subpixel averaging is turned on:: tidy3d.packaging.tidy3d_extras["use_local_subpixel"] +For a broader overview of configuration options and how they are stored, see +:doc:`../configuration/index`. + Licenses -------- diff --git a/docs/index.rst b/docs/index.rst index ec9f38f384..0d1e3d50a7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -52,9 +52,9 @@ Get Started tidy3d configure --apikey=XXX - And enter your API key when prompted. - - For more detailed installation instructions, see `this page <./install.html>`_. + For more detailed installation instructions, see `this page <./install.html>`_, + and refer to :doc:`configuration/index` if you would like to fine-tune your + settings. .. group-tab:: On Windows |:window:| @@ -75,22 +75,12 @@ Get Started pip install pipx pipx run tidy3d configure --apikey=XXX - If you're running into trouble, you may need to manually set the API key directly in the configuration file where Tidy3D looks for it. - You need to place the ``$HOME/.tidy3d/config`` file in your home directory such as ``C:\Users\username\`` (where ``username`` is your username). - - The API key must be in a file called ``$HOME/.tidy3d/config`` located in your home directory, with the following contents - - .. code-block:: bash - - apikey = "XXX" - - You can manually set up your file like this, or do it through the command line line: - - .. code-block:: bash - - echo 'apikey = "XXX"' > ~/.tidy3d/config - - Note the quotes around `XXX`. + If you're running into trouble, you may need to manually set the API key + directly in the configuration file where Tidy3D looks for it. The ``tidy3d + configure`` command stores the API key for you. If you prefer to manage the + file yourself, place ``config.toml`` in the directory described in + :doc:`configuration/index` (for example ``~/.config/tidy3d`` on macOS/Linux + or ``%APPDATA%\\tidy3d`` on Windows). .. group-tab:: In the Cloud |:cloud:| @@ -261,6 +251,7 @@ Contents :maxdepth: 2 install + configuration/index lectures/index notebooks/docs/index faq/docs/index @@ -271,6 +262,3 @@ Contents development/index changelog About our Solver - - - diff --git a/docs/install.rst b/docs/install.rst index 1a034bed48..afc7c7c2ff 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -78,23 +78,9 @@ Alternatively, the API key can be set up using the environment variable ``SIMCLO export SIMCLOUD_APIKEY="XXX" -Finally, one may manually set the API key directly in the configuration file where Tidy3D looks for it. - -The API key must be in a file called ``.tidy3d/config`` located in your home directory, with the following contents - -.. code-block:: python - - apikey = "XXX" - -You can manually set up your file like this, or do it through the command line line: - -.. code-block:: python - - echo 'apikey = "XXX"' > ~/.tidy3d/config - -Note the quotes around `XXX`. - -Note that Windows users will most likely need to place the ``.tidy3d/config`` file in their ``C:\Users\username\`` directory (where ``username`` is your username). +Finally, one may manually set the API key directly in the configuration file +where Tidy3D looks for it. The path and file format differ slightly between +platforms; see :doc:`configuration/index` for the up-to-date layout. diff --git a/tidy3d/config/README.md b/tidy3d/config/README.md new file mode 100644 index 0000000000..63fa3790ee --- /dev/null +++ b/tidy3d/config/README.md @@ -0,0 +1,81 @@ +# `tidy3d.config` Architecture + +`tidy3d.config` combines defaults, environment overrides, profile files, and plugin sections so `config` always reflects the active settings. This note is aimed at contributors who need to extend or debug the module. + +## Big Picture + +- Section schemas live in `sections.py` and register via `register_section`. +- `ConfigManager` merges builtin defaults, saved files, environment overrides, and runtime edits, then runs section handlers. +- `ConfigLoader` handles disk IO while `serializer.py` preserves comments and key order inside TOML files. +- `registry.py` tracks sections and handlers so late imports (plugins, tests) attach automatically. +- `legacy.py` keeps the historical API working by delegating to the manager. + +## Runtime Flow + +1. Importing `tidy3d.config` registers built-in sections and handlers. +2. `ConfigManager` attaches to the registry, loads builtin and user profiles, applies environment overrides, and composes the effective tree. +3. Handlers push side effects (logging level, env vars, cache dirs). Calls to `update_section` reload the tree and re-run the relevant handlers. + +## Component Map + +```mermaid +flowchart LR + subgraph ImportTime["Import Time"] + sections_py["sections.py
@register_section"] --> registry_py + sections_handlers["sections.py
@register_handler"] --> registry_py + end + + subgraph Registry + registry_py["registry.py
section & handler registries"] + end + + subgraph Manager + manager_py["manager.ConfigManager"] --> loader_py + manager_py --> handlers["Registered handlers"] + manager_py --> legacy_wrapper["legacy.LegacyConfigWrapper"] + manager_py --> plugins_accessor["plugins accessor"] + end + + subgraph Persistence + loader_py["loader.ConfigLoader"] --> serializer_py + serializer_py["serializer.py
annotated TOML builder"] --> filesystem["config.toml
profiles/.toml"] + end + + env_vars["Environment variables"] --> loader_py + builtin_profiles["profiles.py
BUILTIN_PROFILES"] --> manager_py + runtime_overrides["Runtime overrides"] --> manager_py + plugins["register_plugin(...)
(plugin imports)"] --> registry_py + registry_py --> manager_py +``` + +## Module Reference + +- `sections.py` - Pydantic models for built-in sections (logging, simulation, microwave, adjoint, web, local cache, plugin container) registered via `register_section`. The bundled models inherit from the internal `ConfigSection` helper, but external code can use plain `BaseModel` subclasses. Optional handlers perform side effects. Fields mark persistence with `json_schema_extra={"persist": True}`. +- `registry.py` - Stores section and handler registries and notifies the attached manager so new entries appear immediately. +- `manager.py` - `ConfigManager` caches validated models, tracks runtime overrides per profile, filters persisted fields, exposes helpers such as `plugins`, `profiles`, and `format`. `SectionAccessor` routes attribute access to `update_section`. +- `loader.py` - Resolves the config directory, loads `config.toml` and `profiles/.toml`, parses environment overrides, and writes atomically through `serializer.build_document`. +- `serializer.py` - Builds stable TOML documents with descriptive comments derived from section docstrings. +- `profiles.py` - Supplies builtin profiles merged ahead of user overrides. +- `legacy.py` - Implements backward-compatible wrappers and deprecation warnings around the manager. + +## Extending the System + +1. Define a Pydantic model and decorate it with `register_section`. Built-in sections use `ConfigSection`, but the decorator accepts any `BaseModel`. +2. Optionally define a handler with `register_handler` for side effects that must track the section. +3. Ensure the module imports during startup so registration happens automatically. + +## Handler Rules + +- Handlers receive the validated section model. +- They must tolerate repeated calls and only run for sections that changed unless you trigger `config.reload_config()` for a full pass. + +## Persistence Notes + +- Only fields tagged with `persist` write by default. Call `config.save(include_defaults=True)` to emit the full tree. +- `ConfigLoader` writes files atomically and leaves a `.bak` backup while swapping. + +## Debugging + +- `config.format()` prints the composed tree - handy for verifying merges. +- Inspect `_compose_without_env()` in a debugger to view the persisted state only. +- `get_sections()` and `get_handlers()` confirm that new registrations landed.