You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: Add functional metadata API for plugin inter-communication
Add BasePlugin.metadata() method for cleaner plugin metadata access
and inter-plugin communication. This API provides namespaced storage
on decorated functions with auto-creation for own namespace.
Changes:
- Add metadata() method to BasePlugin (plugin.py:205-265)
- Auto-creates empty dict for own namespace access
- Returns empty dict (not stored) for non-existent other namespaces
- Update all development.md examples to use metadata() API
- Fix plugin naming example ('logger' → 'logging')
- Fix standard plugins list (remove typerule/valrule)
- Rewrite Global Plugin Registry section (user-focused)
- Strengthen plugin registration guidance (should vs can)
- Emphasize same semantics for built-in and external plugins
- Add 7 comprehensive tests for metadata API
- Test cross-plugin dependencies and lifecycle patterns
Test results: 204/204 passing, 82% coverage
Copy file name to clipboardExpand all lines: docs/plugins/development.md
+78-40Lines changed: 78 additions & 40 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,13 +4,14 @@
4
4
5
5
SmartSwitch supports a flexible plugin system that allows you to extend handler functionality. Plugins can add logging, monitoring, type checking, async support, or any other cross-cutting concern.
6
6
7
-
> **📖 Deep Dive**: For a comprehensive understanding of the middleware pattern behind plugins, including detailed execution flow diagrams and the reference LoggingPlugin implementation, see the [Middleware Pattern Guide](middleware-pattern.md).
7
+
> **📖 Deep Dive**: For a comprehensive understanding of the middleware pattern behind plugins, including detailed execution flow diagrams and the reference LoggingPlugin implementation, see the [Middleware Pattern Guide](middleware.md).
8
8
9
9
## Quick Links
10
10
11
-
-**[Middleware Pattern](middleware-pattern.md)** - Understand the bidirectional execution flow (onCalling/onCalled)
11
+
-**[Middleware Pattern](middleware.md)** - Understand the bidirectional execution flow (onCalling/onCalled)
12
12
-**[Plugin Naming Guidelines](#plugin-naming)** - How to name your plugins correctly
13
-
-**[LoggingPlugin as Reference](middleware-pattern.md#reference-implementation-loggingplugin)** - Use this as your template
13
+
-**[Global Registration](#global-plugin-registry)** - Register plugins for string-based loading (RECOMMENDED)
14
+
-**[LoggingPlugin as Reference](middleware.md#reference-implementation-loggingplugin)** - Use this as your template
14
15
15
16
## The Plugin Protocol
16
17
@@ -20,7 +21,20 @@ All plugins must implement the `SwitcherPlugin` protocol:
#sw = Switcher().plug(SmartAsyncPlugin()) # Different semantics
243
277
```
244
278
245
-
Built-in plugins are pre-registered:
279
+
**Built-in plugins** are pre-registered:
246
280
-`"logging"` - Call history and monitoring
247
281
-`"pydantic"` - Type validation via Pydantic models
248
282
283
+
**Recommended practice**: Register external plugins once at application startup to maintain consistent plugin loading semantics throughout your codebase.
284
+
249
285
## Plugin Naming
250
286
251
287
### Core Principle: Name by Function, Not Framework
@@ -266,7 +302,7 @@ class SwitcherMetricsPlugin:
266
302
267
303
```python
268
304
classLoggingPlugin:
269
-
plugin_name ="logger"# ✅ Clear: logs things
305
+
plugin_name ="logging"# ✅ Clear: logs things
270
306
271
307
classMetricsPlugin:
272
308
plugin_name ="metrics"# ✅ Clear: tracks metrics
@@ -551,7 +587,9 @@ print(sw.counter.get_count('my_handler')) # From counter plugin
551
587
**Standard plugins** (shipped with SmartSwitch):
552
588
- Can be loaded by string name: `sw.plug('logging')`
553
589
- Registered in `Switcher._get_standard_plugin()`
554
-
- Examples: `logging`, `typerule`, `valrule`
590
+
- Examples: `logging`, `pydantic`
591
+
592
+
**Note**: `typerule` and `valrule` are **decorators**, not plugins. They work differently.
555
593
556
594
**External plugins** (third-party packages):
557
595
- Must be imported and instantiated: `sw.plug(MyPlugin())`
@@ -822,7 +860,7 @@ Creating a SmartSwitch plugin (v0.6.0+):
822
860
1. ✅ Inherit from `BasePlugin` for common functionality
823
861
2. ✅ Override `on_decorate(func, switcher)` for setup phase (optional)
824
862
3. ✅ Implement `_wrap_handler(func, switcher)` for wrapping logic (required)
825
-
4. ✅ Use `func._plugin_meta[plugin_name]` to store/share metadata
863
+
4. ✅ Use `self.metadata(func)` to store/share metadata
826
864
5. ✅ Use `@wraps` to preserve function metadata
827
865
6. ✅ Provide public methods for user interaction
828
866
7. ✅ Test with multiple handlers and in combination with other plugins
0 commit comments