punkshell_module_punk::cap - capability provider and handler plugin system
punk::cap provides management of named capabilities and the provider packages and handler packages that implement a pluggable capability.
see also tcllib pluginmgr for an alternative which uses safe interpreters
A capability may be something like providing a folder of files, or just a data dictionary, and/or an API
capability handler - a package/namespace which may provide validation and standardised ways of looking up provider data registered (or not) using register_capabilityname <capname> <capnamespace>
capability provider - a package which registers as providing one or more capablities.
registered using register_package <pkg> <capabilitylist> the capabilitylist is a list of 2-element lists where the first element is the capabilityname and the second element is a (possibly empty) dict of data relevant to that capability A capabilityname may appear multiple times. ie a package may register that it provides the capability with multiple datasets.
class definitions
handler_classes
CLASS interface_caphandler.registry
METHODS
handler may override and return 0 (indicating don't register)e.g if pkg capdict data wasn't valid overridden handler must be able to handle multiple calls for same pkg - but it may return 1 or 0 as it wishes.
CLASS interface_caphandler.sysapi
METHODS
provider_classes
CLASS interface_cappprovider.registration
Your provider package will need to instantiate this object under a sub-namespace called capsystem within your package namespace.
If your package namespace is mypackages::providerpkg then the object command would be at mypackages::providerpkg::capsystem::capprovider.registration
Example code for your provider package to evaluate within its namespace:
namespace eval capsystem { if {[info commands capprovider.registration] eq ""} { punk::cap::class::interface_capprovider.registration create capprovider.registration oo::objdefine capprovider.registration { method get_declarations {} { set decls [list] lappend decls [list punk.templates {relpath ../templates}] lappend decls [list another_capability_name {somekey blah key2 etc}] return $decls } } } }
The above example declares that your package can be registered as a provider for the capabilities named 'punk.templates' and 'another_capability_name'
METHODS
This method must be overridden by your provider using oo::objdefine cappprovider.registration as in the example above. There must be at least one 2-element list in the result for the provider to be registerable.
The first element of the list is the capabilityname - which can be custom to your provider/handler packages - or a well-known name that other authors may use/implement.
The second element is a dictionary of keys specific to the capability being implemented. It may be empty if the any potential capability handlers for the named capability don't require registration data.
CLASS interface_capprovider.provider
Your provider package will need to instantiate this directly under it's own namespace with the command name of provider
namespace eval mypackages::providerpkg { punk::cap::class::interface_capprovider.provider create provider mypackages::providerpkg }
METHODS
This is the mechanism by which a user of your provider package will register your package as a provider of the capability named.
A user of your provider may elect to register all your declared capabilities:
package require mypackages::providerpkg mypackages::providerpkg::provider register *
Or a specific capability may be registered:
package require mypackages::providerpkg mypackages::providerpkg::provider register another_capability_name
return a list of capabilities supported by this provider package
Main punk::cap API for client programs interested in using capability handler packages and associated (registered) provider packages
Return a boolean indicating if the named capability exists (0|1)
Return a boolean indicating if the named capability has a handler package installed (0|1)
Return the base namespace of the active handler package for the named capability.
The base namespace for a handler will always be the package name, but prefixed with ::
punk::cap::advanced API. Functions here are generally not the preferred way to interact with punk::cap.
In some cases they may allow interaction in less safe ways or may allow use of features that are unavailable in the base namespace.
Some functions are here because they are only marginally or rarely useful, and they are here to keep the base API simple.
Move the named provider package to the preferred end of the list (tail).
The active handler may or may not utilise this for preferencing. See documentation for the specific handler package to confirm.
promote/demote doesn't always make a lot of sense .. should preferably be configurable per capapbility for multicap provider pkgs
The idea is to provide a crude way to preference/depreference packages independently of order the packages were loaded e.g a caller or cap-handler can ascribe some meaning to the order of the 'providers' key returned from punk::cap::capabilities <capname>
The order of providers will be the order the packages were loaded & registered
the naming: "promote vs demote" operates on a latest-package-in-list has higher preference assumption (matching last pkg loaded)
Each capability handler could and should implement specific preferencing methods within its own API if finer control needed. In some cases the preference/loading order may be inapplicable/irrelevant to a particular capability anyway.
As this is just a basic mechanism, which can't support independent per-cap preferencing for multi-cap packages - it only allows putting the pkgs to the head or tail of the lists.
Whether particular caps or users of caps do anything with this ordering is dependent on the cap-handler and/or calling code.
Move the named provider package to the preferred end of the list (tail).
The active handler may or may not utilise this for preferencing. See documentation for the specific handler package to confirm.
Internal functions used to communicate between punk::cap and capability handlers
Copyright © 2023 JMNoble - BSD licensed