[//000000001]: # (punk::cap \- punk capabilities plugin system) [//000000002]: # (Generated from file '\_module\_punk\_cap\-0\.1\.0\.tm\.man' by tcllib/doctools with format 'markdown') [//000000003]: # (Copyright © 2023 JMNoble \- BSD licensed) [//000000004]: # (punk::cap\(0\) 0\.1\.0 doc "punk capabilities plugin system")
[ Main Table Of Contents | Table Of Contents | Keyword Index ]
# NAME punk::cap \- capability provider and handler plugin system # Table Of Contents - [Table Of Contents](#toc) - [Synopsis](#synopsis) - [Description](#section1) - [Overview](#section2) - [Concepts](#subsection1) - [API](#section3) - [Namespace punk::cap::class](#subsection2) - [Namespace punk::cap](#subsection3) - [Namespace punk::cap::advanced](#subsection4) - [Internal](#section4) - [Namespace punk::cap::capsystem](#subsection5) - [Copyright](#copyright) # SYNOPSIS package require punk::cap [class::__interface\_caphandler\.registry__ __pkg\_register__ *pkg* *capname* *capdict* *fullcapabilitylist*](#1) [class::__interface\_caphandler\.registry__ __pkg\_unregister__ *pkg*](#2) [class::__interface\_capprovider\.registration__ __get\_declarations__](#3) [class::__interface\_capprovider\.provider__ __constructor__ *providerpkg*](#4) [class::__interface\_capprovider\.provider__ __register__ ?capabilityname\_glob?](#5) [class::__interface\_capprovider\.provider__ __capabilities__](#6) [__capability\_exists__ *capname*](#7) [__capability\_has\_handler__ *capname*](#8) [__capability\_get\_handler__ *capname*](#9) [advanced::__promote\_provider__ *pkg*](#10) [advanced::__demote\_provider__ *pkg*](#11) # DESCRIPTION # Overview punk::cap provides management of named capabilities and the provider packages and handler packages that implement a pluggable capability\. ## Concepts 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 *capability provider* \- a package which registers as providing one or more capablities\. registered using register\_package 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\. # API ## Namespace punk::cap::class class definitions - *handler\_classes* 1. *CLASS interface\_caphandler\.registry* * class::__interface\_caphandler\.registry__ __pkg\_register__ *pkg* *capname* *capdict* *fullcapabilitylist* 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\.registry__ __pkg\_unregister__ *pkg* 1. *CLASS interface\_caphandler\.sysapi* - *provider\_classes* 1. *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' * class::__interface\_capprovider\.registration__ __get\_declarations__ 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\. 1. *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 } * class::__interface\_capprovider\.provider__ __constructor__ *providerpkg* * class::__interface\_capprovider\.provider__ __register__ ?capabilityname\_glob? 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 * class::__interface\_capprovider\.provider__ __capabilities__ return a list of capabilities supported by this provider package ## Namespace punk::cap Main punk::cap API for client programs interested in using capability handler packages and associated \(registered\) provider packages - __capability\_exists__ *capname* Return a boolean indicating if the named capability exists \(0|1\) - __capability\_has\_handler__ *capname* Return a boolean indicating if the named capability has a handler package installed \(0|1\) - __capability\_get\_handler__ *capname* 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 :: ## Namespace punk::cap::advanced 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\. - advanced::__promote\_provider__ *pkg* 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 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\. - advanced::__demote\_provider__ *pkg* 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 ## Namespace punk::cap::capsystem Internal functions used to communicate between punk::cap and capability handlers # COPYRIGHT Copyright © 2023 JMNoble \- BSD licensed