Modules
Modules can be used to apply global updates, or other configuration which needs to be done more frequently than just at package installation. This commonly takes the form of updating configuration files.
Modules can also provide interfaces for the user to manually configure their system.
Modules are python files, similar to pybuilds, and contain functions of
the form do_{name}
or describe_{name}
, where name is the name of
the operation. Do variants should execute the function, while describe
should return a string which describes the operation.
They use the .pmodule
extension.
Installation
Modules must be installed into the MODULEPATH
for them to be activated.
Special Functions
The update
operation is invoked by default (if present) after
installation or removal of mods. It is recommended that update not
produce any output unless changes are necessary. Other helper functions
can be included, but will not have any special meaning.
The prerm
operation is invoked before the module is removed from the
system. Any changes made should be reverted if possible.
Functions of the form describe_{name}
, describe_{name}_options
and
describe_{name}_parameters
can also be used to describe functions and their
parameters. describe_{name}
should return a single string describing the
function (prior to portmod 2.5 this was specified in the doc string), and the
others should each return a list of strings, one for each
parameter, with describe_{name}_options
listing argument names,
and describe_{name}_parameters
listing the corresponding argument
descriptions. Unlike update
and the do_*
functions, describe_*
functions have the same restrictions as global scope code (i.e. no using
imported objects, file i/o, etc. See Sandbox).
Module Description
Module files which contain operations other than update must also
contain a docstring, which is used to describe the module when invoking
portmod <prefix> select
.
Function arguments
Module functions take up to two arguments: state
, which is an object
with a number of constants that describe the module’s environment, and
args
, which contains the arguments passed by the user (if any), in
the form of an object.
do_update
only gets passed thestate
and is not provided with args.All other
do_
functions are provided bothstate
andargs
.
Note that functions expecting too many or too few arguments will case runtime exceptions.
Module state
New constants may be introduced, however they will not be removed between major versions of Portmod.
Valid variables include:
Name |
Value |
---|---|
ROOT |
The root of the module’s installed tree. This location can be used to store custom files which are designed to be used at runtime (e.g. patches) |
CACHE |
A directory that can be used to cache temporary files between runs. It is not guaranteed to persist, however its contents are not automatically deleted |
TEMP |
A directory which can be used to store temporary files during module execution. This directory and all files will be removed after the module has finished executing |
VERSION |
The currently installed version number of the module. Useful for determining if information needs to be regenerated due to an update to the module itself |
Sandbox
Module files execute within the Sandbox.
File access is only permitted within the ROOT
, CACHE
and TEMP
directories passed in the state objects (see above).
The python module portmod.module_util
provides access to two helper
functions:
execute(command)
: Permits execution of binaries. The interface is the same as the pybuild.Pybuild2.execute function.create_file(path)
: Permits access to arbitrary files on the filesystem via redirection. This returns a path to a file within a temporary directory, and the user will be shown the difference between the existing file and the contents of this new file and prompted to allow the changes to proceed after the module is done executing.
Example module
"""Shopping list module"""
import os
def do_update(state):
"""This function isn't actually necessary here. We're not updating anything"""
def describe_list():
return "Displays shopping list"
def do_list(state, args):
"""Displays shopping list"""
path = os.path.join(state.ROOT, "shopping.txt")
if os.path.exists(path):
with open(path, "r") as file:
for line in file.readlines():
print(line)
# Essentials!
print("Eggs")
print("Milk")
print("Carrots")
print("Marmite")
print("Hackle-lo leaves")
def describe_add():
return "Add to list"
def do_add(state, args):
"""Add to list"""
with open(os.path.join(state.ROOT, "shopping.txt"), "a") as file:
print(args.item, file)
def describe_add_options():
return ["item"]
def describe_add_parameters():
return ["item to add to the list"]
Note: while it may be possible to use Portmod for shopping lists, this is outside the scope of the project and is not something which is officially supported. The above is provided as an example of the format only.
Notes
Like Pybuilds, global scope code is not permitted!
Modules must be sourced to get information such as descriptions when running
portmod <prefix> select
, and global code running at this point would
be undesirable.