3. Toolcat toepassingen

3.1. Inleiding

Deze handleiding richt zich in de eerste plaats op ontwikkelaars: de handleiding gaat er van uit dat een aantal programmeringsconcepten bekend zijn. De terminologie die wordt gebruikt, past ook bij dit doelpubliek.

Toolcat toepassingen zijn CLI toepassingen die geschreven zijn in de Python programmeertaal. Dezelfde opzet is echter ook implementeerbaar in andere (dynamische) programmeertalen.

Deze toepassingen volgen een rigoureuze structuur:

  • invocatie: dit is de manier waarop ze worden geactiveerd

  • codering: de manier waarop ze worden samengesteld

  • naamgeving

  • documentatie

Toolcat toepassingen zijn al toe aan de vierde generatie. De verbeteringen tegenover de vorige generaties zijn divers:

  • er is een automatische en intuïtieve toegang tot de functies vanuit de programmeertaal zelf (API)

  • het gebruik van types zorgt voor een snellere ontwikkeling terwijl de input toch nauwgezet wordt gecontroleerd

  • minder code door doorgedreven herbruikbaarheid

  • automatische documentatie die zowel de richtlijnen van de Brocade documentatie respecteert als de richtlijnen van de betreffende programmeertaal

  • geïmplementeerd in Python3

Toolcat toepassingen worden opgebouwd in een 3-ledige hiërarchie:

  • Op het meest algemene niveau is er de generieke toolcat infrastructuur. Deze bevat instrumenten om toolcat applicaties efficiënt aan te maken en te installeren. Op dit niveau worden ook de algemene Toolcat types gedefinieerd. Uitbreiding van dit niveau biedt onmiddellijk meer faciliteiten aan andere Toolcat toepassingen.

  • Het tweede niveau speelt zich af op de specifieke Toolcat applicatie zelf: op dit niveau kunnen Toolcat types worden gedefinieerd die uitsluitend worden gebruikt binnen deze Toolcat applicatie zelf.

  • Het derde niveau is het meest specifieke niveau: hier wordt een specifieke functie van een Toolcat applicatie beschreven.

Documentatiestrings zijn erg belangrijk. Niet alleen vervullen ze de rol van documentatie zoals in elke Python software maar ze zijn bovendien gestructureerd met behulp van YAML. Deze structuur wordt gebruikt om 5 doelstellingen te realiseren:

  • documentatie van de software zoals elke Python ontwikkelaar dit verwacht

  • productie van reST zodat de documentatie kan worden toegevoegd aan de Brocade documentatie

  • kwaliteitstesten op de software, tijdens compile time, te kunnen uitvoeren

  • uitvoerbaarheidstesten op de software, op het ogenblik van invocatie, te kunnen uitvoeren

  • de invocatie van de Toolcat applicatie aan te sturen.

Dit specifiek gebruik van de documentatiestrings kan als erg controlerend, zelfs betuttelend overkomen. De structuur van de Toolcat toepassingen onderscheidt 2 gedeelten:

  • een zeer gestructureerde documentatie

  • het code gedeelte

Het code gedeelte wordt ontdaan van heel wat repetitief (en toch best complex) programmeerwerk. De opmerking - dirigerende houding naar het ontwikkelproces - is inderdaad correct voor wat het documentatie gedeelte betreft. Dit gedeelte hoort echter thuis in de communicatie activiteiten in een ontwikkelteam: stroomlijning is hier essentieel. Deze structuur zorgt ook voor een hoge graad van homogeniteit tussen de Toolcat toepassingen onderling.

3.2. Software

Systemen waarop Toolcat toepassingen worden geïnstalleerd moeten beschikken over:

3.3. Definities

Een Toolcat applicatie wordt samengesteld uit diverse onderdelen. We geven een aantal definities:

3.3.1. Een Toolcat module

Een Toolcat applicatie is een naam (uniek onder de verzameling van de toolcat applicaties) en een collectie van functies.

Deze naam voldoet aan de reguliere uitdrukking [a-z][a-z0-9]*.

Gedurende de rest van de documentatie gebruiken we de naam app voor de Toolcat applicatie.

De functies worden verzameld in een Python module die dezelfde naam draagt als de Toolcat applicatie en die natuurlijk de extensie .py heeft.

Deze module kan in een andere Python toepassing steeds worden geïmporteerd op volgende wijze:

from anet.app import app

De toolcat module begint - zoals steeds in Python - met een documentatiestring. Deze string (triple quoted) heeft een YAML structuur (een mapping) die vier sleutels beschrijft: Titel (verplicht), Naam voor de executable (optioneel), Beschrijving (verplicht), Voorwaarden (optioneel).

3.3.1.1. Voorbeeld

In het volgende voorbeeld wordt de mutil Toolcat applicatie beschreven:

Titel: mutil toolkit

Beschrijving: |

    :mod:`mutil` is een toolbox met basis M operaties.

3.3.1.2. Documentatie velden

3.3.1.2.1. Titel

Dit verplichte veld beschrijft kort (minder dan 80 karakters) het onderwerp van deze specifieke Toolcat applicatie. De markup van de titel is deze van een reST titel. In het bijzonder betekent dit dat er geen linebreaks mogen voorkomen.

De sleutel in de YAML structuur is Titel.

Caution

Let op de hoofdletter in Titel

3.3.1.2.2. Naam voor de executable

Dit is een optionele identifier (korter dan 32). Indien deze werd gespecificeerd, dan levert deze een alternatieve naam voor de CLI toepassing. De executable van de CLI wordt steeds aangemaakt op basis van de naam van de module (app):

  • app

  • indien de registry waarde toolcat-prefix is gespecificeerd, dan is ook de geconcateneerde vorm van deze prefix en app een naam voor de toepassing.

Is de Naam voor de executable gegeven, dan kan komen er extra namen: vervang in het voorgaande app door de Naam voor de executable.

Er zijn nog andere manieren om een Toolcat applicatie op te starten.

3.3.1.2.3. Beschrijving

Dit verplichte veld vertelt wat het doel is van deze Toolcat applicatie. De markup is deze van een reST paragraaf. Vertel niet hoe de software in elkaar zit, maar wel wat we aan algemene functionaliteit kunnen verwachten van deze module. Ga niet in detail: laat dit aspect over aan de individuele functies. Bespreek ook de randvoorwaarden waarbinnen deze toepassing moet kunnen werken.

De sleutel in de YAML structuur is Beschrijving.

Caution

Let op de hoofdletter in Beschrijving

3.3.1.2.4. Voorwaarden

Dit optionele veld somt een aantal voorwaarden op die moeten voldaan zijn bij invocatie van de Toolcat applicatie. Dit veld is opnieuw een mapping waarbij een aantal mogelijke vaste termen worden verbonden met een string. Deze string somt steeds de mogelijk toegelaten waarden (in één of andere vorm) op. Wordt een dergelijke waarde voorafgegaan door een EXCLAMATION MARK, dan wordt hiermee alle andere waarden bedoeld. Dit betekent nog dat als er 2 verschillende waarden voorkomen die beginnen met een EXCLAMATION MARK, alle waarden toegelaten zijn. Toch betekent dit niet dat daardoor de voorwaarde overbodig wordt: op het ogenblik van invocatie wordt immers de current waarde berekend. Zo is bij de test op m, de current waarde, de versie van MUMPS die actief is. Die waarde wordt uit de registry gehaald. Is deze waarde dan niet gedefinieerd, dan faalt ook de test, ongeacht de mogelijke waarden.

De Voorwaarden slaagt indien er aan ALLE termen uit de mapping wordt voldaan.

Er zijn de volgende termen:

os

Geef op 1 lijn, gescheiden door COMMA, de mogelijke waarden: unix, mac, win

qtech

Geef op 1 lijn, in hoofdletters, gescheiden door COMMA, de letters die mogen voorkomen in registry(qtechng-type): B, P, D, W

uid

Geef op 1 lijn, gescheiden door COMMA, de UIDs die deze Toolcat applicatie mogen uitvoeren

gid

Geef op 1 lijn, gescheiden door COMMA, de GIDs waarvan de gebruikers deze Toolcat applicatie mogen uitvoeren

m

Geef op 1 lijn, gescheiden door COMMA, de M versies die moeten geïnstalleerd zijn: cache, gtm, none

registry

Geef een mapping van registry sleutels. Elke waarde is een Python reguliere uitdrukking (full match). De registry waarde wordt afgemeten tegen deze reguliere uitdrukking. Elke sleutel moet matchen.

sysname

Geef op 1 lijn, gescheiden door COMMA, de mogelijk waarden voor de system name (met Python glob pattern wildcards)

sysgroup

Geef op 1 lijn, gescheiden door COMMA, de mogelijke waarden voor de system group (met Python glob pattern wildcards)

time

Geef op 1 lijn, tijdstippen ranges in hh:mm-hh:mm notatie. De Toolcat applicatie kan slechts worden geactiveerd in dit interval.

workdir

Geef op 1 lijn, gescheiden door SEMICOLON, directory's (met Python glob pattern wildcards). De current working directory wordt hiertegen gematcht.

Indien de toegelaten waarden beginnen met een EXCLAMATION MARK, dan wordt deze EXCLAMATION MARK verwijderd maar wordt ook de test omgekeerd.

Caution

Let op de hoofdletter in Voorwaarden

3.3.1.3. Structuur

Na de documentatiestring komen de Python imports. De volgorde is:

  • de modules uit de Python standard library

  • de modules uit anet.core

  • de toolcat infrastructuur

  • de specifieke modules

Meer in het bijzonder wordt de toolcat infrastructuur geïmporteerd.

from anet.toolcatng.toolcat import toolcat

Na het import gedeelte worden - indien gewenst - de Toolcat applicatie specifieke types gedefinieerd. Deze specifieke types zijn belangrijk: ze zorgen ervoor dat de gebruikte concepten in de Toolcat applicatie uniform worden benoemd en dat ze terdege worden ondersteund (getest en getransformeerd), zowel in de documentatie als in het gebruik.

Vervolgens worden de Toolcat functies gedefinieerd. De volgorde is belangrijk:

  • de eerste functie is meteen ook de default toolcat functie

  • de volgorde in de module is ook de volgorde in de documentatie

Caution

Enkel de Toolcat functies zijn zichtbaar buiten de module

3.3.2. Toolcat functies

Toolcat functies worden gekenmerkt door:

  • hun naam (in het vervolg van deze documentatie gebruiken we steeds de naam verb)

  • hun signatuur

  • de toolcat decorator

  • hun documentatie string

from anet.toolcatng.toolcat import toolcat

@toolcat
def verb(args, modifiers=None, verbose=False, debug=False):
    """
    ...
    """
    pass

Alle functies - behalve help() - worden gedefinieerd in de module van de Toolcat applicatie.

De functie help() is speciaal: deze functie worden opgezet door de toolcat infrastructuur zelf en hoeft niet afzonderlijk te worden gedefinieerd. De Toolcat applicatie kan wel een eigen implementatie hebben en dan wordt hier voorrang aan gegeven.

In het vervolg van dit hoofdstuk gaan we de verschillende onderdelen bespreken. Merk alvast op dat - in tegenstelling tot de Toolcat toepassingen van vroegere generaties - de afspraken die worden gemaakt ook bindend zijn: bij het opstarten van de applicatie gaat het systeem nagaan of deze afspraken worden gehonoreerd.

3.3.2.1. Naam

De naam (bijvoorbeeld: verb) van een functie voldoet aan de reguliere uitdrukking [a-z][a-z0-9]*

Er is dus geen beperking op de lengte van de naam. Toch is het aan te raden - en volgens de Python traditie - eerder een korte namen te kiezen. In Toolcat toepassingen van vroegere generaties werd de naam steevast voorafgegaan door de naam van de applicatie en een underscore. Dit kan nu niet meer.

In de rest van de documentatie gaan we geregeld verb gebruiken als naam voor de Toolcat functie.

3.3.2.2. Decorator

De Toolcat decorator heeft slechts een beperkte maar toch een belangrijke taak: hij karakteriseert de functie als een Toolcat functie.

3.3.2.3. Signatuur

Er zijn een beperkt aantal afspraken die gelden voor de signatuur van een functie. Sommige van deze afspraken zijn afdwingbaar, andere zijn dan weer stijlrichtlijnen.

De parameters die we meegeven aan een functie invocatie, kunnen we opsplitsen in 4 groepen:

  • de argumenten-lijst

  • de modifiers

  • verbose

  • debug

  • de API-only argumenten

Er gelden de volgende regels:

  • als er modifiers kunnen zijn, dan moet die steeds de eerste of de tweede parameter zijn. Deze parameter heeft None als defaultwaarde: de Toolcat decorator transformeert modifiers naar een functie van 1 argument. Toepassen van deze functie levert ofwel de modifier waarde op, ofwel None. Als er - volgens de documentatie - geen modifiers kunnen zijn, dan mag deze parameter ook niet voorkomen.

  • de volgende parameter is de pseudo-parameter verbose. Enkel indien verbose voorkomt in de signatuur van de functie mag deze pseudo-parameter ook worden gebruikt bij invocatie.

  • de volgende parameter is de pseudo-parameter debug. Enkel indien debug voorkomt in de signatuur van de functie mag deze pseudo-parameter ook worden gebruikt bij invocatie.

  • API-only parameters komen achteraan en mogen - zoals reeds gezegd - enkel worden gespecificeerd bij naam. Ze hebben een passende default waarde en ze kunnen niet worden ingevuld vanuit de commando-lijn.

3.3.2.3.1. args

Indien de documentatiestring aanduidt dat er geen argumenten kunnen zijn, dan mag args ook niet voorkomen in de signatuur van de functie.

Als er een argumenten-lijst is, dan is dit steeds de eerste parameter. De naam van deze parameter is args.

De argumenten-lijst wordt niet gespecificeerd door middel van een naam, maar steeds door positie: met andere woorden, de argumenten-lijst staat steeds vooraan in de functie call.

De argumenten-lijst is de enige parameter die wordt gespecificeerd door positie: al de andere parameters worden opgegeven door hun naam

De argumenten-lijst heeft geen default waarde in de signatuur.

3.3.2.3.2. modifiers

Indien de documentatiestring aanduidt dat er geen modifiers kunnen zijn, dan mag modifiers ook niet voorkomen in de signatuur van de functie.

Als er modifiers kunnen zijn, dan moet die steeds de eerste of de tweede (net na args) parameter zijn. Deze parameter heeft None als defaultwaarde.

Een modifier moet steeds een functie zijn met 1 argument: de modifierstring.

De Toolcat infrastructuur zorgt ervoor dat de modifiers uit de CLI omgezet worden naar een passende functie. Deze functie transformeert de modifierstring naar 1 van 3 mogelijke structuren:

  • None: indien de modifier niet gedefinieerd werd voor deze modifierstring

  • Een lijst met waarden indien de modifier meer dan 1 waarde KAN bevatten

  • Een enkele waarde indien de modifier hoogstens 1 waarde kan bevatten.

Als de Toolcat functie in een API context wordt gebruikt, dan moet de ontwikkelaar er zelf voor zorgen dat de modifier een passende functies is.

debug


Dit is een booleaanse waarde die de caller kan gebruiken om aan te sturen dat hij in debug mode werkt. De ontwikkelaar kan op de juiste plaatsen in de code, extra informatie tonen.

Ontbreekt deze parameter in de functie signatuur en gebruikt de caller deze pseudo-modifier, dan wordt er een foutboodschap gegenereerd.

Als de parameter voorkomt in de signatuur, dan moet hij ook een default waarde True of False hebben.

3.3.2.3.3. verbose

Dit is een booleaanse waarde: deze kan in functie code worden gebruikt om extra zaken op stdout te schrijven. De caller van de functie kan op deze wijze aansturen of hij al dan niet een minimale output wilt.

Ontbreekt deze parameter in de functie signatuur en gebruikt de caller deze pseudo-modifier, dan wordt er een foutboodschap gegenereerd.

Als de parameter voorkomt in de signatuur, dan moet hij ook een default waarde True of False hebben.

3.3.2.3.4. API

De API argumenten staan aan het einde van de signatuur. Elk argument moet van een passende default-waarde worden voorzien. Deze default-waarde moet steeds None zijn.

De volgorde waarin deze argumenten worden gedefinieerd is dezelfde als de volgorde in de documentatiestring. args, modifiers, verbose, debug mogen niet als naam worden gebruikt.

3.3.2.4. Documentatiestring

De documentatiestring van een toolcat functie volgt dezelfde principes als een Python documentatiestring. Binnenin de Toolcat infrastructuur speelt hij echter een belangrijke rol die de mogelijkheden van vrije tekst verre overtreffen. De documentatiestring is daarom gestructureerd met 2 instrumenten:

  • YAML

  • reST

Deze instrumenten bieden heel wat voordelen:

  • leesbare documentatie

  • documentatie die kan worden ingebed in het Brocade documentatiesysteem

  • documentatie die kan worden omgezet in code die heel wat standaard werk uit de handen van de ontwikkelaar neemt

Om dit mogelijk te maken, moeten er - vanzelfsprekend - afspraken worden gemaakt.

De documentatiestring bestaat uit diverse onderdelen die in volgorde moeten worden gespecificeerd.

  • de titel

  • beschrijving van de functionaliteit

  • voorwaarde

  • de triggers

  • voorbeelden

  • de argumenten

  • de modifiers

  • de API argumenten

Er zijn een aantal tips en stijlkenmerken die het aanmaken van de documentatiestring helpen:

  • laat de documentatiestring beginnen en eindigen met """

  • gebruik steeds insprongen van 4 spaties

  • laat in een documentatiestring je cursor nooit de 80ste kolom overschrijden.

  • het YAML sleutelwoord op het eerste niveau begint steeds met een hoofdletter

  • de YAML sleutelwoorden op de andere niveau's beginnen steeds met een kleine letter

  • indien er voor een documentatie enkel het betekenis veld dient te worden ingevuld, dan mag deze tekst onmiddellijk bij het vorige niveau staan.

  • indien type niet werd gespecificeerd, dan is het any

  • indien een veld begint met vrije tekst waarvan het eerste karakter een letter is, laat het dan een hoofdletter zijn.

  • documenteer niet overtollig, laat zoveel mogelijk over aan het type

  • streef naar maximale leesbaarheid van de documentatiestring in je Python code: maak je geen zorgen om de reST productie.

  • je documentatiestring is functionele documentatie: hou je niet bezig met het uit te leggen hoe de software precies in elkaar zit: doe dit in de code zelf.

  • aarzel niet om een lege lijn te plaatsen tussen diverse velden

  • genummerde argumenten moeten precies 1 waarde opleveren.

Note

Escape regels voor YAML

  • Speciale karakters kan je escapen met APOSTROPHE en QUOTATION MARK

  • APOSTROPHE en QUOTATION MARK kan je escapen door deze te verdubbelen.

  • Bevat je string een karakter uit LEFT CURLY BRACKET, RIGHT CURLY BRACKET, LEFT SQUARE BRACKET, RIGHT SQUARE BRACKET, LESS-THAN SIGN, GREATER-THAN SIGN, EQUALS SIGN, PERCENT SIGN, COMMERCIAL AT, COMMA, AMPERSAND, ASTERIX, QUESTION MARK, NUMBER SIGN, VERTICAL LINE, HYPHEN-MINUS, EXCLAMATION MARK, dan kan je de string het beste tussen APOSTROPHE plaatsen

  • '\n' toont \n

  • "\n" voegt een nieuwe lijn in.

3.3.2.4.1. Voorbeeld

Het volgende voorbeeld beschrijft de documentatiestring van mutil info. De verschillende onderdelen worden later beschreven.

from anet.toolcatng.toolcat import toolcat

@toolcat
 def info(args, *, modifiers=None, debug=False):
     """\
     Titel: Toont informatie omtrent de M installatie

     Beschrijving: |
         Toont allerhande informatie over het aanwezig M systeem.

     Triggers: info

     Voorbeelden:
         - mutil info
         - mutil info license
         - mutil info glo 'XBLK*'
         - mutil info glo @cat
         - mutil info glo BCAT
         - mutil info file myfiles*.zwr
         - mutil info obj bcawstrt
         - mutil info obj staff
         - mutil info obj catchall
         - mutil info var UDwks
         - mutil info upgrade

     Argumenten:
         arg1:
             betekenis: bepaalt het informatie onderwerp
             default: system
             type: symbol
             waarden:
                 system: M systeem
                 config: M configuratie
                 license: M licentie
                 glo: informatie over een global (statistieken, mapping,..)
                 file: informatie over een file, relevant voor M
                 obj: |
                     informatie over een geinstalleerd M object.
                     Dit kan zijn:
                     - menu item
                     - menu folder
                     - search object
                     - lookup
                     - M routine
                     - loi type
                     - identificatie van een gebruikersproces
                     - identificatie van een meta type
                     - python module
                     - ...
                 var: informatie over het gebruik van een variabele
                 upgrade: informatie over het upgraden van mutil commando's naar de huidige versie

         arg*:
             betekenis: |
                 Patroon, waaraan de objecten moeten voldoen.
                 Enkel zinvol in combinatie met global
             aantal: 1..
             type: string

     Modifiers:
         uci:
             betekenis: bepaal de M namespace waar je de operatie wil uitvoeren.
             default: DB
             type: string

     """
3.3.2.4.2. Titel

Dit verplichte veld beschrijft kort (minder dan 80 karakters) het onderwerp van deze specifieke toolcat functie. De markup van de titel is deze van een reST titel. In het bijzonder betekent dit dat er geen linebreaks mogen voorkomen.

De sleutel in de YAML mapping is Titel. (Let op de hoofdletter).

3.3.2.4.3. Beschrijving

Dit verplichte veld vertelt wat het doel is van deze functie. De markup is deze van een reST paragraaf. Vertel niet hoe de software in elkaar zit, maar wel wat we kunnen verwachten van deze functie. Bespreek ook de randvoorwaarden waarbinnen deze functie moet kunnen werken.

Er zijn 2 componenten aan deze beschrijving:

  • Beschrijving van het side-effect (de intentie van de functie invocatie)

  • Beschrijving van de return waarde van de Python functie

De sleutel in de YAML mapping is Beschrijving.

3.3.2.4.4. Voorwaarden

Dit optionele veld somt een aantal voorwaarden op die moeten voldaan zijn bij invocatie van de Toolcat functie. Deze voorwaarden komen bovenop de voorwaarden van de Toolcat applicatie.

Dit veld is opnieuw een mapping waarbij een aantal mogelijke vaste termen worden verbonden met een string. Deze string somt steeds de mogelijk toegelaten waarden (in één of andere vorm) op. Wordt een dergelijke waarde voorafgegaan door een EXCLAMATION MARK, dan wordt hiermee alle andere waarden bedoeld. Dit betekent nog dat als er 2 waarden voorkomen die beginnen met een EXCLAMATION MARK, alle waarden toegelaten zijn. Toch betekent dit niet dat daardoor de voorwaarde overbodig wordt: op het ogenblik van invocatie wordt immers de current waarde berekend. Zo is bij de test op m, de current waarde, de versie van MUMPS die actief is. Die waarde wordt uit de registry gehaald. Is deze waarde dan niet gedefinieerd, dan faalt ook de test, ongeacht de mogelijke waarden.

De Voorwaarden slaagt indien er aan ALLE termen uit de mapping wordt voldaan.

Er zijn de volgende termen:

os

Geef op 1 lijn, gescheiden door COMMA, de mogelijke waarden: unix, mac, win

qtech

Geef op 1 lijn, in hoofdletters, gescheiden door COMMA, de letters die mogen voorkomen in registry(qtechng-type): B, P, D, W

uid

Geef op 1 lijn, gescheiden door COMMA, de uids die deze Toolcat applicatie mogen uitvoeren

gid

Geef op 1 lijn, gescheiden door COMMA, de gids waarvan de gebruikers deze Toolcat applicatie mogen uitvoeren

m

Geef op 1 lijn, gescheiden door COMMA, de M versies die moeten geïnstalleerd zijn: cache, gtm, none

registry

Geef een mapping van registry sleutels. Elke waarde is een Python reguliere uitdrukking (full match). De registry waarde wordt afgemeten tegen deze reguliere uitdrukking. Elke sleutel moet matchen.

sysname

Geef op 1 lijn, gescheiden door COMMA, de mogelijk waarden voor de system name (met Python glob pattern wildcards)

sysgroup

Geef op 1 lijn, gescheiden door COMMA, de mogelijke waarden voor de system group (met Python glob pattern wildcards)

time

Geef op 1 lijn, tijdstippen ranges in hh:mm-hh:mm notatie. De Toolcat applicatie kan slechts worden geactiveerd in dit interval.

workdir

Geef op 1 lijn, gescheiden door SEMICOLON, directories (met Python glob pattern wildcards). De current working directory wordt hiertegen gematcht.

Indien de toegelaten waarden beginnen met een EXCLAMATION MARK, dan wordt deze EXCLAMATION MARK verwijderd maar wordt ook de test omgekeerd.

Caution

Let op de hoofdletter in Voorwaarden

3.3.2.4.5. Triggers

De triggers is een optioneel documentatie veld. Ze worden ook steeds aangevuld met de naam van de functie. Triggers worden gebruikt bij het identificeren van deze functie bij het gebruik in de CLI interface. Dit identificatieproces verloopt als volgt: als de caller een zoekstring intikt, dan worden alle triggers van alle functies doorzocht. Enkel de triggers die een prefix zijn van de zoekstring worden weerhouden. Dit moet precies 1 trigger opleveren en de corresponderende functie wordt geselecteerd.

Dit houdt in dat een trigger nooit een prefix mag zijn van een andere trigger.

Een trigger beantwoordt aan [a-z][a-z0-9]*. De triggers staan op 1 lijn bij de sleutel Triggers en zijn gescheiden door een COMMA. WHITESPACE is niet belangrijk.

Triggers zijn heel handig bij het interactief gebruik. Bij het gebruik in meta-informatie (zoals automatische processen) zijn ze echter af te raden: triggers zijn immers vaak vrij persoonlijk. In dergelijke omgevingen is het beter de naam te gebruiken.

3.3.2.4.6. Voorbeelden

Dit verplichte veld is een YAML lijst met als sleutelwoord Voorbeelden. Elk voorbeeld neemt precies 1 lijn in beslag en begint met de naam van de Toolcat applicatie, gevolgd door de naam van de functie (zonder - prefix). Geef steeds de geprefereerde invocatie en neem voorbeelden uit de praktijk.

Elk voorbeeld moet uitvoerbaar zijn in de betekenis dat dit - op een passend Brocade platform - tot een geldige invocatie moet leiden.

3.3.2.4.7. Argumenten

Dit veld is verplicht.

Argumenten zijn per definitie naamloos. In YAML worden ze ingeleid door het sleutelwoord Argumenten. Indien er geen argumenten kunnen zijn, dan moet de documentatie hier de string Geen argumenten zijn.

De rest van deze paragraaf behandelt de situatie dat er wel argumenten kunnen zijn.

Argumenten vallen uiteen in 2 groepen.

  • genummerde argumenten

  • niet-genummerde argumenten

Genummerde argumenten staan vooraan in de argumentenlijst: elk genummerd argument komt juist 1 maal voor. Elk van deze argumenten heeft zijn eigen natuur (type).

De niet-genummerde argumenten staan achteraan. Het reële aantal kan onbepaald zijn. Ze zijn homogeen van aard en hebben dus ook dezelfde natuur (type).

De genummerde argumenten worden aangeduid door de identificatie arg en een volgnummer. De niet-genummerde argumenten worden aangeduid met arg*.

Er zijn de volgende subvelden:

  • betekenis: korte omschrijving van de rol van dit argument in minder dan 80 karakters

  • expandeer: ja/nee (default: 'nee'). Geeft aan of de expandeer optie wordt toegepast. Dit is een algoritme (eigen aan het type) dat de waarde van het argument kan omzetten naar een andere waarde. Bij genummerde argumenten moet dit leiden tot precies 1 waarde.

  • aantal: komt enkel voor bij niet-genummerde argumenten (bij genummerde argumenten is deze waarde immers steeds 1). Gebruik de range notatie (verplicht veld)

    • n..m: komt minstens n keer en maximaal m keer voor

    • n..: komt minstens n maal voor

    • ..m: komt maximaal m maal voor

    • ..: komt onbepaald aantal keer voor (hetzelfde als 0..)

  • default: kan worden gebruikt om een default waarde op te geven. Kan enkel worden gebruikt bij genummerde argumenten of bij *niet-genummerde argumenten * die minstens 1 maal voorkomen.

  • type: het type van een argument kan onmiddellijk een aantal specifieke subvelden inleiden. Indien type ontbreekt, dan is het steeds any.

3.3.2.4.8. Modifiers

Modifiers kunnen ontbreken en ze hoeven in dat geval ook niet te worden gedocumenteerd. Indien er wel modifiers kunnen voorkomen, dan komt de documentatie in de sleutel Modifiers.

Beschrijf elke - mogelijk - voorkomende modifier met behulp van de volgende velden:

  • betekenis: korte omschrijving van de rol van dit argument

  • expandeer: ja/nee (default: 'nee'). Geeft aan of de expandeer optie wordt toegepast.

  • aantal: default is 1. Gebruik de range notatie:

    • n..m: komt minstens n keer en maximaal m keer voor

    • n..: komt minstens n maal voor

    • ..m: komt maximaal m maal voor

    • ..: komt onbepaald aantal keer voor

    Modifiers kunnen dus multiple zijn. In het geval dat ze multiple kunnen zijn, is de waarde van de modifier steeds een Python list. Indien ze maximaal 1 keer kunnen voorkomen, dan is de waarde ook enkelvoudig.

  • default: default waarde (mag ontbreken)

  • type: het type van de modifier werkt eveneens met een aantal subvelden. Indien type ontbreekt, dan is het steeds any.

3.3.2.4.9. API argumenten

Extra API argumenten zijn zeldzaam. Ze hebben steeds een naam binnen de Python functie. Ze worden dan ook aan de hand van die naam gedocumenteerd. De API argumenten zelf komen onder de sleutel API argumenten. Elke argument krijgt zijn documentatie bij de sleutel van dezelfde naam. Deze documentatie heeft een reST structuur.

Zorg ervoor dat in de signatuur de API argumenten in dezelfde volgorde als in de documentatie worden gespecificeerd.

Note

De YAML structuur is zo gekozen dat de documentatie:

  • conform is aan de Python documentatieregels voor functies

  • heel goed leesbaar is in de code

  • rigoureus transformeerbaar is naar reST documentatie

  • tekstfragmenten zoals 'minimum', 'maximum', 'waarden' ... zijn niet vrijblijvend: ze hebben een strikte betekenis binnen de Toolcat infrastructuur.

  • de volgorde lijkt wat ongewoon: men zou verwachten dat type prominenter vooraan zou staan. Echter, type kan komen met zijn eigen attributen die er dan onmiddellijk op volgen. Een goed voorbeeld is te zien bij type: symbol.

  • default volgt dan weer op aantal. De reden hiervan is dat het aantal bepaalt of er een default kan zijn: een default is immers pas zinvol indien het aantal gelijk is aan 1 of begint met 1..

Note

Het kan soms handig zijn om teksten uit de documentatie te verwijderen ZONDER ze te schrappen. Dit kan met het NUMBER SIGN: dit karakter luidt immers een YAML commentaar in.

3.4. API

De API van een Toolcat applicatie is eenvoudig: deze functies kunnen individueel worden geactiveerd volgens de gebruikelijke Python methodes.

De argumenten moeten als list aangeboden worden, de modifiers als dict.

Is de naam van de Toolcat applicatie app, dan kan dit bijvoorbeeld als volgt:

from anet.app import app

app.verb(args)

3.5. Argumenten en modifier types

Het gebruik van types zorgt voor een hoge graad van homogeniteit binnenin een gegeven Toolcat applicatie maar ook tussen Toolcat toepassingen onderling.

De specificatie van een type heeft 4 gevolgen:

  • types kunnen met eigen attributen komen. Die moeten passend worden toegevoegd aan de documentatiestring.

  • expansie mogelijkheden: het type kan de gegeven argumentwaarde omvormen naar 0, 1 of meerdere argumenten. Dit is bijvoorbeeld het geval met wildcards bij path argumenten.

  • het gebruik van argumenten en modifiers kan bij invocatie worden getest

  • argumenten en modifier waarden kunnen bij invocatie worden omgezet naar native waarden: een string kan bijvoorbeeld worden omgevormd naar een datetime.date() object.

Er zijn twee soorten types:

  • de types die worden gedefinieerd in de toolcatinfrastructuur: de standaardtypes

  • de types die specifiek zijn voor een gegeven Toolcat applicatie

3.5.1. Standaardtypes

De standaardtypes zijn:

  • any

  • boole

  • date

  • daterange

  • datetime

  • datetimerange

  • dir

  • docmandb

  • docmanpath

  • encoding

  • file

  • glob

  • global

  • integer

  • json

  • loi

  • path

  • regex

  • string

  • symbol

Elk van deze types komen met diverse attributen. Een type wordt dan ook voorgesteld door een YAML map waarvan de attributen sleutels zijn.

3.5.1.1. any

Input

elk Python object

Extra documentatievelden

Er zijn geen extra documentatievelden

Expansie

Er zijn geen expansie mogelijkheden

Test

Er is geen test

Transformatie

Er is geen transformatie

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: any
    arg2: Beschrijving ...
    arg*:
        betekenis: |
            Beschrijving ...
        aantal: 1..
        default: E17

Modifiers:
    firstname: Beschrijving ...
    lastname:
        betekenis: Beschrijving ...
        aantal: 0..

3.5.1.2. boole

Input
  • een string beginnend met een karakter uit 1yYJjOo wordt omgezet in True

  • een string beginnend met een karakter uit 0Nn wordt omgezet in False

  • elk ander object wordt omgezet in bool(object)

Extra documentatievelden

Er zijn geen extra documentatievelden

Expansie

Er zijn geen expansie mogelijkheden

Test

Er is geen test

Transformatie

De waarde wordt onderworpen aan base.yes(). Het resultaat is dus steeds True of False

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: boole
    arg*:
        betekenis: |
            Beschrijving ...
        aantal: 1..
        default: true
        type: boole

Modifiers:
    delete:
        betekenis: Na verwerking worden de bestanden geschrapt
        default: false
        type: boole

3.5.1.3. date

Input
  • een datetime.date() object

  • een datetime.datetime() object

  • een datetime.timedelta() object

  • een integer: offset in dagen tegenover vandaag

  • een string in $H formaat

  • een string in $H formaat met SEMICOLON notatie

  • een string in +$H_"," notatie

  • een string in +$H_";" notatie

  • een string in YYYY-MM-DD notatie

  • een string in 0000-MM-DD (0000 wordt vervangen door het actuele jaar)

  • een string in 0000-00-DD (00 wordt vervangen door de actuele maand)

  • 0000-00-00 staat voor vandaag

  • T staat voor vandaag

  • date+n staat voor date + n dagen (date staat voor een date object in een string formaat)

  • date-n staat voor date - n dagen (date staat voor een date object in een string formaat)

Extra documentatievelden
  • minimum: Optioneel. Oudste mogelijke datum (beschreven op dezelfde wijze als een date waarde). Mag enkel worden gespecificeerd als de waarde verschillend is van leeg.

  • maximum: Optioneel. Jongste mogelijke datum (beschreven op dezelfde wijze als een date waarde). Mag enkel worden gespecificeerd als de waarde verschillend is van leeg.

Expansie

Er zijn geen expansie mogelijkheden

Test

Geldig indien de input van het juiste formaat is en minimum en maximum worden gerespecteerd.

Transformatie

Wordt omgezet in een datetime.date() object

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: date
        minimum: 2000-01-01
        maximum: T-1
    arg*:
        betekenis: |
            Beschrijving ...
        aantal: 1..
        default: 2000-02-28
        type: date

Modifiers:
    startdate:
        betekenis: Zoek in records aangemaakt na ...
        type: date
        default: T-100

3.5.1.4. daterange

Input
  • de string ..

  • een date object in een string notatie, gevolgd door ..

  • een date object in een string notatie, voorafgegaan door ..

  • een date object in een string notatie, gevolgd door .., gevolgd door een date object in een string notatie

  • een tuple of list van 2 elementen:
    • heeft het eerste element een logische False waarde, dan wordt dit het begin der tijden

    • heeft het tweede element een logische False waarde, dan wordt dit het einde der tijden

    • in alle ander gevallen zijn deze elementen date objecten.

Extra documentatievelden

Er zijn geen extra documentatievelden

Expansie

Er zijn geen expansie mogelijkheden

Test

Geldig indien de input van het juiste formaat is en minimum en maximum worden gerespecteerd.

Transformatie

Wordt omgezet in een tuple waarvan het de elementen ofwel None ofwel datetime.date() objecten zijn. Zijn het beiden datetime.date(), dan staat de vroegere datum steeds vooraan.

Note

Zijn de eindpunten van het interval bepaald, dan zijn ze ook steeds inbegrepen in het interval.

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: daterange
    arg*:
        betekenis: |
            Beschrijving ...
        aantal: 1..
        default: T-100..T


Modifiers:
    startdate:
        betekenis: Zoek in records aangemaakt na ...
        type: daterange
        default: T-1..T+1

3.5.1.5. datetime

Input
  • een datetime.datetime() object

  • een datetime.delta() object (de tijd wordt berekend tegenover nu)

  • een integer: offset in seconden

  • een string in $H formaat

  • een string in $H formaat met SEMICOLON notatie

  • een string in YYYY-MM-DD hh:mm:ss notatie. 0000 en 00 worden door passend vervangen.

  • een string in hh:mm:ss formaat (basis: datum van vandaag)

  • een string in hh:mm formaat (basis: datum van vandaag)

  • een string in hh:mm:ssT+n formaat (basis: datum van vandaag + n dagen)

  • een string in hh:mm:ssT-n formaat (basis: datum van vandaag - n dagen)

  • een string in hh:mmT+n formaat (basis: datum van vandaag + n dagen)

  • een string in hh:mmT-n formaat (basis: datum van vandaag - n dagen)

Extra documentatievelden
  • minimum: Optioneel. Oudste mogelijke tijd (beschreven op dezelfde wijze als een date waarde)

  • maximum: Optioneel. Jongste mogelijke tijd (beschreven op dezelfde wijze als een date waarde)

Expansie

Er zijn geen expansie mogelijkheden

Test

Geldig indien de input van het juiste formaat is en minimum en maximum worden gerespecteerd.

Transformatie

Wordt omgezet in een datetime.datetime() object

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: datetime
        minimum: 09:00
        maximum: 17:00
    arg*:
        betekenis: |
            Beschrijving ...
        type: datetime
        aantal: 1 ..

Modifiers:
    starttime:
        betekenis: Zoek in records aangemaakt na ...
        type: datetime
        default: 09:00

3.5.1.6. dir

Input
  • een pathlib.Path object

  • een string

Extra documentatievelden
  • mode: een string met een aantal termen (COMMA gescheiden) uit
    • bestaand

    • maakbaar

    • schrijfbaar

    • leesbaar

    • wisbaar

  • expandeer: ja/nee (Python rglob betekenis)

Expansie

De expansie mogelijkheden volgen de (uitgebreide) glob specificatie.

Test

Wordt gecontroleerd tegen de mode en of dit een directory kan zijn en of de mode van toepassing is of kan zijn.

Transformatie

Wordt omgezet in een pathlib.Path object

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: dir
        mode: leesbaar
    arg*:
        betekenis: |
            Beschrijving ...
        type: dir
        mode: schrijfbaar
        expandeer: ja
        aantal: 1 ..

Modifiers:
    startdir:
        betekenis: Zoek in subdirectories van ...
        type: dir
        default: /library/process

3.5.1.7. docmandb

Input
  • een docbase.Db object

  • een string

  • een docbase.Path object

  • een docbase.File object

Extra documentatievelden

  • mode: een string met een aantal termen (COMMA gescheiden) uit
    • bestaand

    • maakbaar

  • expandeer: ja/nee (Python :code:Python glob pattern betekenis)

Expansie

De expansie mogelijkheden volgen de glob specificatie tegenover de bestaande docman databanken

Test

Wordt gecontroleerd tegen de mode

Transformatie

Wordt omgezet in het corresponderende docbase.Db object

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: docmandb
        mode: bestaand
    arg*:
        betekenis: |
            Beschrijving ...
        type: docmandb
        expandeer: ja
        aantal: 1 ..

Modifiers:
    imagedb:
        betekenis: Zoek bestanden in ...
        type: docmandb
        default: exchange

3.5.1.8. docmanpath

Input
  • een docbase.Path object

  • een string

  • een docbase.File object

Extra documentatievelden
  • mode: een string met een aantal termen (COMMA gescheiden) uit
    • bestaand

    • maakbaar

Expansie

Geen

Test

Wordt gecontroleerd tegen de mode

Transformatie

Wordt omgezet in het corresponderende docbase.Path object

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: docmanpath
        mode: bestaand
    arg*:
        betekenis: |
            Beschrijving ...
        type: docmanpath
        aantal: 1 ..

Modifiers:
    imagefile:
        betekenis: JPEG te gebruiken als achtergrond van de desktop ...
        type: docmanpath
        default: bestaand

3.5.1.9. encoding

Input: een string die een gekende python karakter encodering representeert

Extra documentatievelden

Er zijn geen extra documentatievelden

Expansie

Er zijn geen expansie mogelijkheden

Test

Geldig indien de invoer gevonden wordt als encoding

Transformatie

De invoer wordt omgezet naar zijn basis encoding naam, dus bijvoorbeeld 'utf8' wordt 'utf-8'.

Argumenten:
    arg1:
        betekenis: |
           Beschrijving ...
        type: encoding
    arg*:
        betekenis: |
            Beschrijving ...
        aantal: 1..
        default: utf-8
        type: boole

Modifiers:
    encoding:
        betekenis: In welke karakter encoding is de invoer
        type: encoding

3.5.1.10. file

Input
  • een pathlib.Path object

  • een string

Extra documentatievelden
  • mode: een string met een aantal termen (COMMA gescheiden) uit
    • bestaand

    • maakbaar

    • schrijfbaar

    • leesbaar

    • wisbaar

    • uitvoerbaar

  • expandeer: ja/nee (Python rglob betekenis)

Expansie

De expansie mogelijkheden volgen de (uitgebreide) glob specificatie.

Test

Wordt gecontroleerd tegen de mode en of dit een regulier bestand kan zijn.

Transformatie

Wordt omgezet in een pathlib.Path object

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: file
        mode: schrijfbaar
    arg*:
        betekenis: |
            Beschrijving ...
        type: file
        mode: schrijfbaar
        expandeer: ja
        aantal: 1 ..

Modifiers:
    imagefile:
        betekenis: Bestand met ...
        type: file
        default: /library/process/doc/ua.jpg

3.5.1.11. integer

Input
  • een int

  • een string (beginnend met 'o': octaal, 'x': hexadecimaal, 'b': binair)

Extra documentatievelden
  • minimum: Optionele minimum waarde

  • maximum: Optionele maximum waarde

Expansie

Geen expansie

Test

Wordt gecontroleerd tegen het formaat en de minimum en maximum waarde

Transformatie

Wordt omgezet in een int

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: integer
        minimum: 0
        maximum: 100
    arg*:
        betekenis: |
            Beschrijving ...
        type: integer
        minimum: 0
        maximum: 1000
        aantal: 1 ..

Modifiers:
    divisor:
        betekenis: Deler ...
        type: integer
        default: 11
        minimum: 1
        maximum: 100

3.5.1.12. path

Input
  • een pathlib.Path object

  • een string

Extra documentatievelden
  • mode: een string met een aantal termen (COMMA gescheiden) uit
    • bestaand

    • maakbaar

    • schrijfbaar

    • leesbaar

    • wisbaar

    • uitvoerbaar

  • expandeer: ja/nee (Python rglob betekenis)

Expansie

De expansie mogelijkheden volgen de (uitgebreide) glob specificatie.

Test

Wordt gecontroleerd tegen de mode en of dit een reguliere file of een directory kan zijn.

Transformatie

Wordt omgezet in een pathlib.Path object

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: path
        mode: schrijfbaar
    arg*:
        betekenis: |
            Beschrijving ...
        type: path
        mode: schrijfbaar
        expandeer: ja
        aantal: 1..

Modifiers:
    imagefile:
        betekenis: Bestand met ...
        type: path
        default: /library/process/doc/ua.jpg

3.5.1.13. string

Input
  • een string

  • een bytestring

  • een integer

Extra documentatievelden
  • codec: zet de bytestring om in een string

  • regexp: reguliere uitdrukking

  • rstrip, lstrip, strip: weghalen van WHITESPACE

  • lower, upper: hoofdletters, kleine letters

Expansie

Geen

Test

Test tegen de reguliere uitdrukking

Transformatie

Wordt omgezet in het corresponderende str object

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: string
        codec: UTF-8
    arg*:
        betekenis: |
            Beschrijving ...
        type: string
        codec: brocade
        upper: ja
        aantal: 1 ..

Modifiers:
    subject:
        betekenis: Onderwerp van ...
        type: string
        default: wiskunde

3.5.1.14. symbol

Input
  • een string

Extra documentatievelden
  • waarden: een YAML map die de naam verbindt met een betekenis

  • lower, upper: hoofdletters, kleine letters

  • expandeer: ja/nee (Python :code:Python glob pattern betekenis)

Expansie

Expansie gebeurt in de verzameling van de symbolen

Test

Test tegen de verzameling

Transformatie

De input wordt omgezet tegen het eerste symbool waarvan de input een prefix is.

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: symbol
        waarden:
            r: rood
            g: groen
            b: blauw
    arg*:
        betekenis: |
            Beschrijving ...
        type: symbol
        waarden:
            mercurius: Mercurius
            venus: Venus
            aarde: Aarde
            mars: Mars
        aantal: 1 ..

Modifiers:
    server:
        betekenis: Productieserver met ...
        type: symbol
        waarden:
            legato: dev.anet.be
            moto: anet.be
            dolce: doc.anet.be
        default: moto

3.5.1.15. loi

Input
  • een string

Extra documentatievelden

vorm: verzameling van toegelaten waarden van lois (gescheiden door COMMA). Er mogen wildcards worden gebruikt.

Expansie

Geen

Test

Test tegen de verzameling. Er worden ook, per type, een aantal rudimentaire testen uitgevoerd. Bijvoorbeeld bij het type c, wordt er gekeken of de waarde begint met c:, dat er exact 2 : in staan en dat de derde component numeriek is en niet begint met 0. Deze testen worden stelselmatig opgebouwd.

Transformatie

De input wordt behouden.

Voorbeelden:

Argumenten:
    arg1:
        betekenis: |
            Beschrijving van de rol van dit argument.
            Deze beschrijving kan over meerdere lijnen gaan.
        type: loi
        vorm: c:*
    arg*:
        betekenis: |
            Beschrijving ...
        type: loi
        vorm: c:*
        aantal: 1 ..

Modifiers:
    reeks:
        betekenis: Reeksbeschrijving met ...
        type: loi
        vorm: c:*

3.5.2. Specifieke types

De ontwikkelaar kan specifieke types gaan ontwikkelen. Deze worden gedefinieerd binnen de specifieke Toolcat module zelf.

Elk type heeft een naam die voldoet aan [a-z][a-z0-9]*. Het type zelf wordt ontwikkeld door een subclass te definiëren van toolcat.Type. Deze subclass heeft als naam, de naam van het type waarvan de eerste letter in uppercase wordt gezet.

Er zijn 6 elementen te specificeren. 4 ervan - methods - zijn optioneel.

Deze methodes werken met 3 argumenten: behalve self is er ook de actuele waarde. Het derde argument is een :code`dict` met de documentatievelden.

3.5.2.1. De documentatiestring

De documentatiestring van de corresponderende klasse is belangrijk. Zoals gebruikelijk in Python, bestaat deze uit 2 delen:

  • een korte, samenvattende titel: deze wordt gebruikt in de reST documentatie daar waar een argument of modifier van dit type wordt verklaard.

  • een uitgebreide documentatie - gescheiden van de titel door een lege lijn - die meer informatie verschaft over de betekenis en het gebruik van dit Toolcat types. Ook deze komt in het reST verhaal maar is minder nadrukkelijk aanwezig.

De documentatiestring is in reST en is verplicht.

3.5.2.2. fields

Deze statische eigenschap van de klasse somt in een lijst alle toegelaten documentatievelden op (die horen bij het type). De volgorde in de lijst is belangrijk: de software gaat controleren of deze volgorde wordt gebruikt in de documentatiestring. De namen van de velden kunnen ook worden aangevuld met een EXCLAMATION MARK (zonder whitespace). Dit teken geeft aan dat het veld een verplicht veld is.

3.5.2.3. De __init__ methode

Deze methode is optioneel. __init__ werkt, behalve met self, nog met 1 extra argument: docfields, de attributen die worden meegegeven uit de documentatie. Dit is een dict die kan worden verwerkt om in de andere methodes te worden gebruikt. De verwerkte waarde moet een dict opleveren die wordt toegewezen aan self.docfields.

3.5.2.4. De expand methode

Deze is optioneel en wordt enkel geactiveerd indien expansie aan de orde is. Deze methode werkt steeds met door test_run() goedgekeurde waarden. Deze methode kan vanzelfsprekend gebruik maken van self.docfields.

Note

De expand begint steeds met 1 waarde en geeft steeds een lijst terug.

3.5.2.5. De test_run methode

Deze is optioneel. Het resultaat geeft aan of de specifieke waarde toegelaten is. De waarde is toegelaten indien het teruggeven resultaat de lege string is. Indien de waarde niet is toegelaten, dan is de return waarde een string die verklaart waarom de waarde faalt!

Note

De return string moet steeds in ASCII zijn.

3.5.2.6. De test_doc methode

Deze is optioneel. Deze methode controleert bij het installeren van de Toolcat applicatie, of de velden wel goed gespecificeerd zijn.

Note

De return string moet steeds in ASCII zijn.

3.5.2.7. De transform methode

Deze is optioneel. Deze methode transformeert de waarde naar een passend Python object. Van deze methode wordt verwacht dat hij idempotent is: het voeden met de berekende waarde transformeert de waarde naar zichzelf. Deze methode geeft steeds 1 waarde terug.

3.5.2.8. Voorbeelden

De standaard types worden op dezelfde manier gedefinieerd als de specifieke types:

class Boole(Type):
    """Een object van type `boole` wordt steeds herleid tot :code:`True` of :code:`False`

Het object wordt onderworpen aan :code:`system.yes(object)`"""

    def transform(self, value):
        return yes(value)
class Symbol(Type):
    """Een object van type `symbol` moet een waarde aannemen uit een *vooraf* opgegeven verzameling van strings

- de mogelijke symbolen moet voldoen aan :regexp:`[a-zA-Z][a-zA-Z0-9]*`
- het type laat expansie toe tegenover de gegeven verzameling van strings.
- om een symbool te specificeren, is het voldoende een prefix - die leidt tot precies 1 symbool - op te geven.

Extra attributen:

- `lower`: zet de input om naar kleine letters
- `upper`: zet de input om naar hoofdletters
- `expandeer`: expansie van de input (enkel voor modifiers en naamloze argumenten)
- `waarden`: de verzameling van de symbolen gescheiden door een |COMMA|

"""

    fields = ['waarden', 'expandeer', 'lower', 'upper']


    def __init__(self, docfields):
        self.docfields = docfields
        for x in 'lower', 'upper', 'expandeer':
            self.docfields[x] = yes(self.docfields.get(x)])
        self.docfields['waarden'] = re.findall('[a-zA-Z][a-zA-Z0-9]*', self.docfields.get('waarden', ''))

    def test_run(self, value):
        if not isinstance(value, str):
            return "[{value!a}] is geen string".format(value=value)
        value = self.transform(value)
        expand = self.docfields['expandeer']
        waarden = self.docfields['waarden']
        if expand and value.translate(None,'[?*') != value:
            return ""
        found = set()
        for v in waarden:
            if v.startswith(value):
                found.add(v)
        if not found:
            return "[{value!a}] leidt niet tot een symbool".format(value=value)

        if len(found) > 1:
            return "[{value!a}] leidt tot meerdere symbolen".format(value=value)

        return ""

    def expand(self, value):
        value = self.transform(value)
        waarden = self.docfields['waarden']
        values = []
        for v in waarden:
            if fnmatch.fnmatch(v, value):
                values.append(v)
        result = []
        for v in values:
            for w in waarden:
                if w.startswith(v):
                    result.append(w)
        return result

    def transform(self, value):
        value = value.strip()
        if self.docfields['lower']:
            value = value.lower()
        if self.docfields['upper']:
            value = value.upper()
        return value

3.6. De CLI interface

3.6.1. Naam

De naam van een Toolcat applicatie is een identifier van de vorm [a-z][a-z0-9]*.

Op basis van deze naam wordt ook de Toolcat applicatie geactiveerd. Dit kan (meestal) op 3 manieren:

  • brocade_name ...: deze naam wordt het best gebruikt bij automatische processen en in code

  • name ...: deze naam wordt slechts gebruikt indien er al geen programma bestaat onder deze naam.

  • toolcat name ...: toolcat is dus een applicatie die als bootstrap kan dienen voor de Toolcat toepassingen

Vervang name door de naam van de Toolcat applicatie.

3.6.2. Argumentenlijst

De argumentenlijst is een JSON lijst die de argumenten van de invocatie structureert. Elk element in de lijst is een string.

Deze lijst wordt door de toolcat infrstructuur opgesplitst in een Python tuple (het invocatietuple) met 2 elementen:

  • het eerste element zijn de gewone argumenten. Dit is opnieuw een lijst van strings die ook mag ook leeg zijn.

  • de tweede lijst bevat een dict. De sleutels zijn de modifiers en de waarden zijn opnieuw lijsten van strings. De dict mag ook leeg zijn.

De toolcat infrastructuur maakt dit tuple aan zonder kennis van types en zonder informatie omtrent de specifieke Toolcat applicatie zelf.

In deze fase zijn er 4 speciale strings:

  • de strings die beginnen met unhex=

  • de strings die volledig bestaan uit =

  • de strings die beginnen met paramsfile=

  • de strings die beginnen met paramsstring=

De toolcat parser houdt 2 vlaggen bij:

  • argument-hex-encoded. Bij aanvang van het parsing proces staat deze vlag op False

  • no-modifiers. Bij aanvang van het parsing proces staat deze vlag eveneens op False: er kunnen zowel gewone argumenten als modifiers zijn.

De toolcat parser verwerkt de elementen uit de argumentenlijst sequentieel:

  • de parser inspecteert het element:

    • Staat argument-hex-encoded op True

    • Is het element van de vorm [1234567890abcdefABCDEF]+

    • is het aantal karakters in het element even

    dan wordt het element vervangen door binascii.unhexlify(element).

  • de parser inspecteert het resultaat:

    • Bevat het element enkel = en staat no-modifiers op False, dan skipt de parser dit element en de vlag no-modifiers wordt op True gezet.

    • Staat no-modifiers op True, dan wordt het element toegevoegd aan de gewone argumenten

    • Bevat het element geen =, dan wordt het element toegevoegd aan de gewone argumenten

    • Begint het element met unhex=, dan wordt het gedeelte geëvalueerd door system.yes() en krijgt de argument-hex-encoded deze waarde. Het element wordt verder geskipt.

    • Begint het element met paramsfile=, dan wordt het gedeelte na = geïnterpreteerd als een JSON bestand dat een nieuwe argumentenlijst bevat. Deze lijst wordt volledig autonoom geparset. Dit levert een tuple op: elk gewoon argument uit het eerste element wordt toegvoegd aan de reeds bestaande lijst met gewone argumenten. De modifiers uit het tweede element worden eveneens opgenomen in de reeds bestaande dict: nieuw modifiers worden gewoon toegevoegd, bestaande modifiers worden aangevuld. paramsfile=... zelf wordt geskipped door de parser.

    • Begint het element met paramsstring=, dan wordt de string op dezelfde wijze behandeld als de inhoud van de JSON file bij ipt.

    • Andere waarde zijn modifiers. Noteren we ze als key=value, dan worden ze als volgt behandeld in de dict: dict[key] = dict.get(key,[]) + [value]

3.6.3. Aanduiding van de functie

De specifieke functie van de Toolcat applicatie die wordt geactiveerd, is afhankelijk van de lijst met de gewone argumenten:

  • is deze lijst niet leeg, dan wordt de functie bepaald door het eerste argument. Van deze string worden de - tekens die aan het begin staan, verwijderd. Is het overblijvende gedeelte leeg, dan werd de functie niet goed gespecificeerd en komt er een foutmelding. De niet-lege string wordt dan afgemeten tegen de triggers: bestaat er een trigger waarvan deze string een prefix is, dan wordt de corresponderende functie geactiveerd. Bestaan er geen dergelijke triggers, dan komt er opnieuw een fout melding.

  • is deze lijst leeg, dan wordt de eerst gedefinieerde functie in de toolcat module geactiveerd (de default functie)

Note

In tegenstelling tot de vroegere generatie Toolcat toepassingen, hoeft de functieaanduiding niet met een - te beginnen. Dit is meer in overeenstemming met bijvoorbeeld toepassingen zoals hg.

3.6.4. Best practice

De beste manier om de functie verb met argumenten arg1, arg2, arg3 en modifiers m1=v1, m2=v2 van een Toolcat applicatie app op te roepen is:

app m1=v1 m2=v2 = verb arg1 arg2 arg3

Door eerst de modifiers te specificeren en deze te splitsen van de functienaam en argumenten, voorkomt men problemen met = in gewone argumenten. Dit kan zeker belangrijk zijn bij het gebruik van wildcards.

De prefix brocade_ is zelden nodig maar is aangewezen bij niet-interactief werk.

Deze vorm noemen we ook de canonieke vorm.

3.6.5. Voorbeelden

Voorbeeld 1:

Argumentenlijst van

lapith search Lipsius 1547 1606 search=person db=viaf

heeft de volgende structuur:

(
  ["search", "Lipsius", "1547", "1606"],   # args
  {"search": ["person"],
  "db": ["viaf"]}                  # modifiers
)

Voorbeeld 2:

Argumentenlijst van

docman -path cmd /exchange/root.ext murder=2017-01-31

heeft de volgende structuur:

(
  ["-path", "cmd", "/exchange/root.ext"],  # args
  {"murder": ["2017-01-31"]}               # modifiers
)

Voorbeeld 3:

Argumentenlijst van

docman path cmd unhex=yes 2f65786368616e67652f726f6f742e657874 murder=2017-01-31

heeft de volgende structuur:

(
  ["path", "cmd", "/exchange/root.ext"],   # args
  {"murder": ["2017-01-31"]}               # modifiers
)

Voorbeeld 4:

Argumentenlijst van

brocade_docman murder=2017-01-31 = path cmd /exchange/root.ext

heeft de volgende structuur:

(
  ["path", "cmd", "/exchange/root.ext"],   # args
  {"murder": ["2017-01-31"]}               # modifiers
)

3.6.6. Verwerking van het invocatietuple

Het invocatietuple is samengesteld uit de argumentenlijst.

Op dat ogenblik gebeuren er een aantal operaties op de argumenten en de modifiers. Het eindpunt van deze bewerkingen kan tweeërlei zijn:

  • een foutboodschap

  • een invocatie van de passende Toolcat functie

Note

De verwerking van het invocatietuple kan pas gebeuren met een goed geïnstalleerde en goed werkende Toolcat applicatie. Het installeren en definiëren van de Toolcat applicatie is een compile-time activiteit, de verwerking van het invocatietuple is een runtime activiteit.

3.6.6.1. Fase 1: Bepalen van de Toolcat functie

Dit gebeurt op basis van de argumenten. Indien er argumenten bestaan, dan wordt het eerste argument beschouwd als een trigger voor de Toolcat functie. In dit geval wordt dit argument links ontdaan van het MINUS karakter. In de lijst met Toolcat functies wordt er gezocht naar een trigger die een prefix is van dit argument. Wordt er geen corresponderende Toolcat functie gevonden, dan faalt de invocatie.

Bestaan er geen argumenten, dan is de eerst gedefinieerde Toolcat functie in de Toolcat applicatie module ook de geselecteerde Toolcat functie (zijn er geen Toolcat functies, dan faalt de invocatie).

Het eerste argument - indien het bestaat - wordt ook geschrapt uit de argumenten.

3.6.6.2. Fase 2: Analyse van de speciale modifiers

De speciale modifiers (debug, verbose, stdin, stderr, stdout, daemon, log) worden uit de modifiers van het invocatietuple genomen (zijn er meervoudige waarden, dan wordt de laatste uit de lijst genomen).

Er wordt dan geverifieerd of deze modifiers toegelaten zijn in de signatuur van de Toolcat functie. Indien ze niet voorkomen, dan wordt er een waarschuwing op sys.stderr geprint en de modifier heeft verder geen effect.

De voorkomende waarden van deze speciale modifiers worden verder nog in de decorator gebruikt maar ze worden hoe dan ook uit de modifier dict geschrapt.

3.6.6.3. Fase 3: Analyse van de documentatiestring van de Toolcat functie

De YAML documentatiestring - waarvan we reeds weten dat hij de juiste structuur heeft - wordt geanalyseerd en in een intern Python object opgeslagen.

Deze operatie mag de invocatie niet doen falen!

3.6.6.4. Fase 4: Bepalen van de default modifiers

Uit de documentatiestring weten we welke modifiers er kunnen voorkomen. Modifiers die ontbreken bij de actuele invocatie worden verder geïnspecteerd: sommige van deze modifiers - hopelijk allemaal - hebben een defaultwaarde. De modifiers uit het invocatietuple worden passend aangevuld.

3.6.6.5. Fase 5: Overtollige modifiers

Modifiers uit het invocatietuple die niet voorkomen in de modifiers uit de documentatiestring doen eveneens de invocatie falen: ze scheppen immers verwachtingen die niet kunnen worden ingevuld.

3.6.6.6. Fase 6: Controle en expansie van de modifiers

De modifiers uit het invocatietuple worden dan gecontroleerd tegenover hun type. Dit kan ook leiden tot expansie. Modifiers die de test niet overleven doen de invocatie falen.

3.6.6.7. Fase 7: Onderzoeken van de multipliciteit van de modifiers

Alle modifiers uit de documentatiestring worden nu onderzocht op hun multipliciteit. Modifiers die niet voldoen aan deze multipliciteit doen de invocatie falen. Meer in het bijzonder: niet gedefinieerde modifiers uit het invocatietuple die toch aanwezig moeten zijn, doen de invocatie mislukken.

3.6.6.8. Fase 8: Transformatie van de modifiers

De modifiers voldoen nu aan de testen. Ze worden nu omgezet naar Python native objecten.

3.6.6.9. Fase 9: Enkelvoudige modifiers

Modifiers die van nature enkelvoudig zijn - waarschijnlijk de meerderheid - worden nu uit hun lijst genomen!

3.6.6.10. Fase 10: Bestaan van argumenten

Uit de signatuur van de Toolcat functie kunnen we afleiden of er argumenten worden verwacht. Indien dit strijdig is met het aantal argumenten uit het invocatietuple dan faalt de invocatie.

3.6.6.11. Fase 10: Verwerking van de genummerde argumenten

Uit de documentatiestring kunnen we de genummerde argumenten afleiden. Rekening houden met hun eventuele defaultwaarden kunnen we de argumenten controleren tegenover hun types. Genummerde argumenten worden immers niet geëxpandeerd. Faalt de controle dan faalt ook de invocatie. De argumenten worden ook getransformeerd naar een native Python object. Het getransformeerde argument wordt dan ook - in volgorde - toegevoegd aan de uiteindelijke lijst.

3.6.6.12. Fase 11: Controle en expansie van de anonieme argumenten

De anonieme argumenten zijn homogeen van type. Dit type bepaalt - samen met de invocatie - o.f.v. en hoe deze waarden moeten worden geëxpandeerd. De lijst met argumenten wordt aangepast.

3.6.6.13. Fase 12: Multipliciteit van de anonieme argumenten

De documentatiestring levert een bovengrens en een ondergrens van het aantal anonieme argumenten. Hou er ook rekening mee dat expansie kan betekenen dat er uiteindelijk minder argumenten overblijven! Het werkelijk aantal argumenten wordt gecontroleerd tegen deze bovengrens en ondergrens. Indien deze test faalt, dan faalt ook de invocatie.

3.6.6.14. Fase 13: Transformatie van de anonieme argumenten

De anonieme argumenten worden getransformeerd naar een native Python object en toegevoegd aan de lijst van de genummerde argumenten.

3.6.6.15. Fase 14: Toepassing van de decorator

3.6.6.15.1. Logging

Indien log=True, dan wordt log omgevormd naar een functie met dezelfde functionaliteit als print(). Alleen schrijft deze functie naar een vaste plaats in de Brocade omgeving. De decorator zorgt er ook steeds voor dat bij de start van de uitvoering van de functie reeds informatie wordt weggeschreven. Hetzelfde gebeurt bij het beëindigen van de functie. Verder is het aan de ontwikkelaar om de nieuwe log functie passend te gebruiken.

3.6.6.15.2. Daemon

Indien daemon=True, dan wordt de Toolcat applicatie verder uitgevoerd als een daemon.

3.6.6.15.3. Standard Streams

De standard streams (stderr, stdout, stdin) worden passend omgeleid. Net zoals log worden ze functies die verder kunnen worden gebruikt net zoals print()

3.6.6.15.4. Debug

Indien debug=True, dan ondergaat debug dezelfde behandeling als log. Het schrijven gebeurt wel naar sys.stderr.

Indien debug=False, dan wordt debug een functie zonder effecten.

3.6.6.16. Uitvoering

De parameters worden ingevuld in de Toolcat functie en de invocatie wordt uitgevoerd.

3.7. Het gebruik van toolcat

3.7.1. Toolcat voor ontwikkelaars

3.7.1.1. Nieuwe Toolcat applicatie

De eenvoudigste manier om een nieuwe Toolcat applicatie aan te maken is met de instructie:

qtechng file new app.py --create --hint=toolcat --qdir={qdir}

3.7.1.2. Installatie

Een Toolcat applicatie wordt zoals steeds geïnstalleerd met behulp van een install.py file in een Brocade project. Plaats in de install.py file de lijnen:

from anet.core import installer

# Indien niet alle python files tot de toolcatapplicatie behoren,
# dan moet 'pyfiles' een lijst bevatten met de juiste python files

# indien de bestanden in de module eerst dienen te worden
# geschrapt, zet dan 'init=True'

installer.toolcat(project="app", pyfiles=None, init=False)

3.7.2. Toolcat voor gebruikers

3.7.2.1. Interactief

Er zijn heel wat faciliteiten om een Toolcat applicatie aantrekkelijk te maken voor interactief gebruik:

  • het gebruik van triggers

  • de helpfuncties

  • de 'canonieke' vorm

lapith update dbnl

3.7.2.2. Procman

De beste manier om een Toolcat applicatie te gebruiken in procman is via toolcat

toolcat = run lapith update dbnl

Dit heeft heel wat voordelen:

  • rigoureuse opsplisting van argumenten en modifiers

  • goede terugvindbaarheid

  • gebruik van 'cwd', 'r4args' en 'r4mods' modifiers

3.7.2.3. M

Een Toolcat applicatie app wordt gebruikt via de macro m4_toolcat.

macro toolcat($error, $ta, $verb, $args=MDargs, $modifiers=MDmod, $stdout="", $glo=""):
    '''
    $synopsis: Voer een toolcat commando uit vanuit M
    $error: return code
    $ta: Toolcat applicatie. Gebruik de naam ZONDER de prefix aangegeven in
         de registry waarde toolcat-prefix
    $verb: Naam van de Toolcat functie (gebruik de naam in plaats van een trigger)
    $args: (Sequentiele) Lijst met argumenten
    $modifiers: Mumps structuur van de gedaante:
                modifier: waarde (voor enkelvoudige modifiers)
                    of
                modifier,1..: waarde (voor multiple modifiers)
    $stdout: indien niet leeg, dan wordt de output afgeleid naar deze file
    $glo: indien niet leeg, dan wordt dit als een globale reference (eventueel in path-notatie).
          De output wordt gesplitst op '\n' en, beginnend vanaf 1, toegevoegd aan de global (in de vorm @glo@(1..))
    $example: m4_toolcat(error, "procman", "run", args=ZAargs)
    '''
    «k MDargs,MDmod s $error=$$%Toolcat^uossh($ta,$verb,.$args,.$modifiers,$stdout)»

3.7.2.4. Python

Een Toolcat applicatie kan eenvoudig worden gebruikt als een API binnenin Python:

from anet.mutil import mutil

mutil.info(['var', 'UDrou'])

3.7.3. Toolcat services

Een Toolcat applicatie biedt een aantal standaard services.

3.7.3.1. Help

De help faciliteit komt in drie vormen:

  • een ingebouwde help functie

  • een pseudo-modifier

  • integratie met de Brocade documentatie

3.7.3.1.1. Help functie

Elke Toolcat applicatie app heeft een help functie: het is de toolcat infrastructuur zelf die dit voor zijn rekening neemt. Net zoals een Toolcat applicatie zelf, werkt deze met de CLI.

Zonder verdere argumenten toont: (voorbeeld met mutil)

mutil help

een overzicht van de mogelijke functies

Met 1 argument wordt de help getoond van deze specifieke functie. Het argument wordt gezien als een trigger (of beter: iets dat een trigger als prefix heeft).

mutil help info
3.7.3.1.2. Help modifier

Een invocatie van een Toolcat applicatie kan worden aangevuld met een modifier help. Deze modifier is een booleaanse modifier. Indien deze True is, dan wordt informatie ommtrent de invocatie getoond.

  • Indien er een functie wordt geidentificeerd, dan wordt de help omtrent deze functie getoond

  • Er wordt een canonieke invocatie getoond met minimale unhex

3.7.3.1.3. Integratie met Brocade documentatie

De help gegevens kunnen worden omgezet naar reST en met behulp van de .. toolcat:: app modifier worden geïntegreerd in een bestaand reST document.

Deze documentatie kan ook via de CLI worden geactiveerd. Dit gebeurt op dezelfde wijze als de help functie.

3.7.3.1.4. Redirectie van stdin

Door middel van de stdin= pseudo-modifier kan stdin worden omgeleid naar een bestand. Dit bestand moet bestaan op het moment van invocatie.

De redirectie gaat op voor alle Python code, C plugins, kind processen.

3.7.3.1.5. Redirectie van stdout

Door middel van de stdout= pseudo-modifier kan stdout worden omgeleid naar een bestand. Komt er na het = teken geen bestandsnaam, dan wordt stdout omgeleid naar /dev/null/ (op alle platformen).

De redirectie gaat op voor alle Python code, C plugins, kind processen.

3.7.3.1.6. Redirectie van stderr

Door middel van de stderr= pseudo-modifier kan stderr worden omgeleid naar een bestand. Komt er na het = teken geen bestandsnaam, dan wordt stderr omgeleid naar /dev/null/ (op alle platformen). Komt er na het = teken het woord stdout, dan wordt stderr omgeleid naar stdout.

De redirectie gaat op voor alle Python code, C plugins, kind processen.

3.7.3.1.7. Current working directory

Door middel van de cwd= pseudo-modifier kan de current working directory worden vastgelegd.

3.7.3.1.8. Uitvoering in de background

Door middel van de daemon= pseudo-modifier kan de Toolcat applicatie in de background worden uitgevoerd. Dit proces wordt ook zijn eigen session leader .

3.7.3.1.9. Logging

Het opstarten en beëindigen van een invocatie wordt gelogd (tenminste indien de registry waarde toolcat-log-dir bestaat en verwijst naar een directory).

Bij het starten van een Toolcat functie vanuit de CLI worden de argumenten genoteerd en ook een unieke identifier van de invocatie samengesteld. Deze gegevens worden in een JSON-file weggeschreven. Bij het beëindigen van de invocatie wordt opnieuw een JSON-file weggeschreven in deze directory.

De Toolcat infrastructuur onderhoudt deze bestanden.

3.7.3.1.10. Watch

Elke Toolcat applicatie heeft een Toolcat functie watch(). Dit is een functie die luistert naar resources. Als op deze resources opdrachten verschijnen, dan worden deze door de Toolcat applicatie verwerkt.

Op dit ogenblik is één resource geïmplementeerd: het monitoren van een directory.