[//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