Description
Currently, users who need custom drivers must either subclass a built-in driver and manage their own constructor function, or dynamically mutate driver.rules after instantiation. There is no way to register a custom driver so that it works seamlessly with Platform enum lookup, get_hconfig(), and other constructor functions.
Additionally, users cannot override built-in drivers — if the Cisco IOS driver does not match their environment, they must bypass the standard API entirely.
Proposed Change
1. Expose HConfigDriverBase and HConfigDriverRules as public API
Ensure these are exported from hier_config (or hier_config.platforms) so users can subclass HConfigDriverBase without reaching into internal modules:
from hier_config import HConfigDriverBase, HConfigDriverRules
2. Add a driver registration function that extends Platform
from hier_config import register_driver, Platform, HConfigDriverBase, HConfigDriverRules
class MyNOSDriver(HConfigDriverBase):
@staticmethod
def _instantiate_rules() -> HConfigDriverRules:
return HConfigDriverRules(...)
register_driver("MY_NOS", MyNOSDriver)
# Platform enum is now extended with the new value
config = get_hconfig(Platform.MY_NOS, config_text)
register_driver() adds a new member to the Platform enum and maps it to the given driver class. All constructors (get_hconfig(), get_hconfig_fast_load(), etc.) use the registered driver automatically.
3. Override built-in drivers
Passing an existing Platform value overrides the built-in driver:
register_driver("CISCO_IOS", MyCustomIOSDriver)
# Now uses MyCustomIOSDriver instead of the built-in
config = get_hconfig(Platform.CISCO_IOS, config_text)
4. Optional: unregister_driver() and get_registered_drivers()
unregister_driver(Platform.MY_NOS) # removes custom platform
get_registered_drivers() # returns dict of all registered drivers
Implementation Notes
The current driver lookup lives in constructors.py:get_hconfig_driver() with a hardcoded dict mapping Platform -> driver class. This would become a module-level registry dict that register_driver() writes to and get_hconfig_driver() reads from. Built-in drivers are registered at import time as defaults.
Extending a Python Enum at runtime requires care. Options include:
- Use
enum.extend_enum (aenum library) or a custom metaclass
- Rebuild
Platform with the new member via Platform = Enum("Platform", {**existing, name: auto()})
- Use a registry that accepts both
Platform members and registered string keys, with Platform extended via __getattr__ on the module
Benefits
- Users can bring their own drivers without forking the library
- Built-in drivers can be overridden for environments with non-standard behavior
- Custom platforms are first-class
Platform enum members — no separate enum needed
- Eliminates the need for the custom
get_custom_hconfig_driver() pattern documented in docs/drivers.md
Breaking Change
Yes — Platform enum becomes dynamically extensible. The get_hconfig_driver() internal lookup changes. Users who imported the hardcoded platform-to-driver mapping would need to update.
Description
Currently, users who need custom drivers must either subclass a built-in driver and manage their own constructor function, or dynamically mutate
driver.rulesafter instantiation. There is no way to register a custom driver so that it works seamlessly withPlatformenum lookup,get_hconfig(), and other constructor functions.Additionally, users cannot override built-in drivers — if the Cisco IOS driver does not match their environment, they must bypass the standard API entirely.
Proposed Change
1. Expose
HConfigDriverBaseandHConfigDriverRulesas public APIEnsure these are exported from
hier_config(orhier_config.platforms) so users can subclassHConfigDriverBasewithout reaching into internal modules:2. Add a driver registration function that extends
Platformregister_driver()adds a new member to thePlatformenum and maps it to the given driver class. All constructors (get_hconfig(),get_hconfig_fast_load(), etc.) use the registered driver automatically.3. Override built-in drivers
Passing an existing
Platformvalue overrides the built-in driver:4. Optional:
unregister_driver()andget_registered_drivers()Implementation Notes
The current driver lookup lives in
constructors.py:get_hconfig_driver()with a hardcoded dict mappingPlatform-> driver class. This would become a module-level registry dict thatregister_driver()writes to andget_hconfig_driver()reads from. Built-in drivers are registered at import time as defaults.Extending a Python
Enumat runtime requires care. Options include:enum.extend_enum(aenum library) or a custom metaclassPlatformwith the new member viaPlatform = Enum("Platform", {**existing, name: auto()})Platformmembers and registered string keys, withPlatformextended via__getattr__on the moduleBenefits
Platformenum members — no separate enum neededget_custom_hconfig_driver()pattern documented indocs/drivers.mdBreaking Change
Yes —
Platformenum becomes dynamically extensible. Theget_hconfig_driver()internal lookup changes. Users who imported the hardcoded platform-to-driver mapping would need to update.