[ Main Table Of Contents | Table Of Contents | Keyword Index ]

punkshell_module_punk::cap(0) 0.1.0 doc "punk capabilities plugin system"

Name

punkshell_module_punk::cap - capability provider and handler plugin system

Table Of Contents

Synopsis

Description

Overview

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

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 <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.

API

Namespace punk::cap::class

class definitions

  • handler_classes

    1. CLASS interface_caphandler.registry

      METHODS

      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
    2. CLASS interface_caphandler.sysapi

      METHODS

  • 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'

      METHODS

      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.

    2. 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

      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 <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.

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

Keywords

capability, module, plugin