|
1 | 1 | # Template Registry |
2 | 2 |
|
3 | | -A thread-safe singleton registry for managing dataset templates in MDIO applications. |
| 3 | +A simple, thread-safe place to discover and fetch dataset templates for MDIO. |
4 | 4 |
|
5 | | -## Overview |
| 5 | +## Why use it |
6 | 6 |
|
7 | | -The `TemplateRegistry` implements the singleton pattern to ensure there's only one instance managing |
8 | | -all dataset templates throughout the application lifecycle. This provides a centralized registry for |
9 | | -template management with thread-safe operations. |
| 7 | +- One place to find all available templates |
| 8 | +- Safe to use across threads and the whole app (singleton) |
| 9 | +- Every fetch gives you your own editable copy (no side effects) |
| 10 | +- Comes preloaded with common seismic templates |
10 | 11 |
|
11 | | -**Important:** When you retrieve a template from the registry using `get()`, you receive a |
12 | | -**deep copy** of the template. This means each retrieved template is an independent, |
13 | | -modifiable instance that can be customized for your specific use case without affecting the |
14 | | -original template or other retrieved copies. |
| 12 | +```{note} |
| 13 | +Fetching a template with `get_template()` returns a deep copy. Editing it will not change the |
| 14 | +registry or anyone else’s copy. |
| 15 | +``` |
| 16 | + |
| 17 | +## Quick start |
| 18 | + |
| 19 | +```python |
| 20 | +from mdio.builder.template_registry import get_template, list_templates |
15 | 21 |
|
16 | | -## Features |
| 22 | +# See what's available |
| 23 | +print(list_templates()) |
| 24 | +# e.g. ["Seismic2DPostStackTime", "Seismic3DPostStackDepth", ...] |
17 | 25 |
|
18 | | -- **Singleton Pattern**: Ensures only one registry instance exists |
19 | | -- **Thread Safety**: All operations are thread-safe using locks |
20 | | -- **Global Access**: Convenient global functions for common operations |
21 | | -- **Deep Copy on Retrieval**: Each `get()` call returns an independent copy that can be modified without side effects |
22 | | -- **Default Templates**: The registry is instantiated with the default set of templates |
| 26 | +# Grab a template by name |
| 27 | +tpl = get_template("Seismic3DPostStackTime") |
23 | 28 |
|
24 | | -## Usage |
| 29 | +# Customize your copy (safe) |
| 30 | +tpl.add_units({"amplitude": "unitless"}) |
| 31 | +``` |
25 | 32 |
|
26 | | -### Basic Usage |
| 33 | +## Common tasks |
27 | 34 |
|
28 | | -To consume a template from the registry, use the global convenience functions: |
| 35 | +### Fetch a template you can edit |
29 | 36 |
|
30 | 37 | ```python |
31 | 38 | from mdio.builder.template_registry import get_template |
| 39 | + |
| 40 | +tpl = get_template("Seismic2DPostStackDepth") |
| 41 | +# Use/modify tpl freely — it’s your copy |
| 42 | +``` |
| 43 | + |
| 44 | +### List available templates |
| 45 | + |
| 46 | +```python |
32 | 47 | from mdio.builder.template_registry import list_templates |
33 | 48 |
|
34 | | -# Get a template |
35 | | -template = get_template("PostStack3DTime") |
| 49 | +names = list_templates() |
| 50 | +for name in names: |
| 51 | + print(name) |
| 52 | +``` |
| 53 | + |
| 54 | +### Check if a template exists |
36 | 55 |
|
37 | | -# List all registered templates |
38 | | -templates = list_templates() |
| 56 | +```python |
| 57 | +from mdio.builder.template_registry import is_template_registered |
| 58 | + |
| 59 | +if is_template_registered("Seismic3DPostStackTime"): |
| 60 | + ... # safe to fetch |
39 | 61 | ``` |
40 | 62 |
|
41 | | -If you need to register a custom template, you can use the `TemplateRegistry` class directly: |
| 63 | +### Register your own template (optional) |
| 64 | + |
| 65 | +If you have a custom template class, register an instance so others can fetch it by name: |
42 | 66 |
|
43 | 67 | ```python |
44 | 68 | from typing import Any |
45 | | -from mdio.builder.template_registry import TemplateRegistry |
| 69 | +from mdio.builder.template_registry import register_template |
46 | 70 | from mdio.builder.templates.abstract_dataset_template import AbstractDatasetTemplate |
47 | 71 | from mdio.builder.templates.types import SeismicDataDomain |
48 | 72 |
|
49 | | -# Get the registry |
50 | | -registry = TemplateRegistry() |
51 | | - |
52 | | -# Define template |
53 | | -class MyDatasetTemplate(AbstractDatasetTemplate): |
54 | | - """A mock template for demonstration purposes.""" |
55 | | - |
| 73 | +class MyTemplate(AbstractDatasetTemplate): |
56 | 74 | def __init__(self, domain: SeismicDataDomain = "time"): |
57 | | - """Your implementation goes here.""" |
58 | 75 | super().__init__(domain) |
59 | 76 |
|
60 | 77 | @property |
61 | 78 | def _name(self) -> str: |
62 | | - return f"MyDatasetTemplate{self._data_domain.capitalize()}" |
| 79 | + # The public name becomes something like "MyTemplateTime" |
| 80 | + return f"MyTemplate{self._data_domain.capitalize()}" |
63 | 81 |
|
64 | 82 | def _load_dataset_attributes(self) -> dict[str, Any]: |
65 | | - return {"surveyType": "2D", "gatherType": "custom_type"} |
66 | | - |
67 | | - |
68 | | -template = MyDatasetTemplate(domain="time") |
69 | | -template_name = registry.register(template) |
| 83 | + return {"surveyType": "2D", "gatherType": "custom"} |
70 | 84 |
|
71 | | -# Retrieve a template using a its name |
72 | | -template = registry.get("MyDatasetTemplateTime") |
73 | | - |
74 | | -# Check if template exists |
75 | | -if registry.is_registered("MyDatasetTemplateTime"): |
76 | | - print("Template is registered") |
77 | | - |
78 | | -# List all templates |
79 | | -template_names = registry.list_all_templates() |
| 85 | +# Make it available globally |
| 86 | +registered_name = register_template(MyTemplate("time")) |
| 87 | +print(registered_name) # "MyTemplateTime" |
80 | 88 | ``` |
81 | 89 |
|
82 | | -### Template Independence and Modification |
83 | | - |
84 | | -Each call to `get()` returns an independent copy of the template, allowing you to customize templates |
85 | | -without affecting other instances: |
86 | | - |
87 | | -```python |
88 | | -from mdio.builder.template_registry import get_template |
89 | | - |
90 | | -# Get two instances of the same template |
91 | | -template1 = get_template("PostStack3DTime") |
92 | | -template2 = get_template("PostStack3DTime") |
93 | | - |
94 | | -# They are different objects |
95 | | -assert template1 is not template2 |
96 | | - |
97 | | -# Modify the first template |
98 | | -template1.add_units({"amplitude": "meters"}) |
| 90 | +```{tip} |
| 91 | +Use `list_templates()` to discover the exact names to pass to `get_template()`. |
| 92 | +``` |
99 | 93 |
|
100 | | -# The second template is unaffected |
101 | | -# template2 does not have the custom units from template1 |
| 94 | +## Troubleshooting |
102 | 95 |
|
103 | | -# Get a fresh copy - also unaffected by previous modifications |
104 | | -template3 = get_template("PostStack3DTime") |
105 | | -``` |
| 96 | +- KeyError: “Template 'XYZ' is not registered.” |
| 97 | + - The name is wrong or not registered yet. |
| 98 | + - Call `list_templates()` to see valid names, or `is_template_registered(name)` to check first. |
106 | 99 |
|
107 | | -## Best Practices |
| 100 | +## FAQ |
108 | 101 |
|
109 | | -1. **Use Global Functions**: For simple operations, prefer the global convenience functions |
110 | | -2. **Register Early**: Register all templates during application startup |
111 | | -3. **Testing Isolation**: Always reset the registry in test setup/teardown |
| 102 | +- Do I need to create a TemplateRegistry instance? |
| 103 | + No. Use the global helpers: `get_template`, `list_templates`, `register_template`, and `is_template_registered`. |
| 104 | +- Are templates shared between callers or threads? |
| 105 | + No. Each `get_template()` call returns a deep-copied instance that is safe to modify independently. |
112 | 106 |
|
113 | | -## API Reference |
| 107 | +## API reference |
114 | 108 |
|
115 | 109 | ```{eval-rst} |
116 | 110 | .. automodule:: mdio.builder.template_registry |
|
0 commit comments