Module t2py.T2Plugin
Classes
class T2Plugin (name: str, config: str = None)
-
Class representing a Tranalyzer plugin.
Parameters
name
:str
- The name of the plugin.
config
:str
, default: None
- The name of the config file to load.
Raises
NameError
- If the plugin could not be found.
Expand source code
class T2Plugin: """Class representing a Tranalyzer plugin. Parameters ---------- name : str The name of the plugin. config : str, default: None The name of the config file to load. Raises ------ NameError If the plugin could not be found. """ def __init__( self, name: str, config: str = None ): if name not in T2Utils.valid_plugin_names(): raise NameError(f'Plugin {name} could not be found') self._name = name self._description = None self._number = None flags = T2Utils.list_config(name) self._default = None self._flags = dict.fromkeys(flags) self._modified_flags = {} for flag in self._flags: self._flags[flag] = T2Utils.get_config_from_source(name, flag) self._add_dict_entry(flag, self._flags[flag]) self.config_file = config if config: self.load_config(config) @property def config_file(self) -> str: """The configuration file where changes will be persisted in this session. `None` means the changes are persisted directly into the source files, e.g., `src/pluginName.h`. """ return self._config_file @config_file.setter def config_file(self, config: str) -> str: self._config_file = config @property def name(self) -> str: """The name of the plugin.""" return self._name @property def description(self) -> str: """The description of the plugin.""" if not self._description: self._description = T2Utils.plugin_description(self.name) return self._description @property def number(self) -> str: """The number of the plugin.""" if not self._number: self._number = T2Utils.plugin_number(self.name) return self._number @property def flags(self) -> List[str]: """The list of configuration flags available for the plugin.""" return list(self._flags.keys()) @property def default(self) -> Dict[str, Any]: """The list of configuration flags and their default values.""" if not self._default: self._default = dict.fromkeys(self.flags) for flag in self.flags: self._default[flag] = T2Utils.get_default(self.name, flag) return self._default @property def changes(self) -> Dict[str, Any]: """The list of configuration flags modified but not yet persisted.""" return self._modified_flags def discard_changes(self): """Discard all non-committed changes made in this session. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.changes {'MAX_IP': 5} >>> arpDecode.discard_changes() >>> arpDecode.changes {} """ for flag in list(self._modified_flags): self._set_config(flag, T2Utils.get_config_from_source(self.name, flag)) self._modified_flags.clear() def status(self): """Print the current configuration status of the plugin. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.status() 1 change pending: MAX_IP = 5 """ pending_changes = len(self.changes) if pending_changes == 0: print('No changes pending') else: blue_text = '\033[0;34m{} change{} pending:\033[0m' print(blue_text.format(pending_changes, "s" if pending_changes > 1 else "")) for name, value in sorted(self.changes.items()): print(f' {name} = {value}') def diff( self, base: str = None ) -> Dict[str, Any]: """Compare the current configuration with the default configuration. Parameters ---------- base : str, default: None The base configuration to use for comparison. Currently, only `'default'` is supported. Returns ------- dict The flags differing from `base` as keys, the current value as values. Raises ------ NotImplementedError When trying to compare the current configuration with base other than `'default'`. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.apply_changes() >>> arpDecode.diff() {'MAX_IP': 5} """ if base and base != 'default': raise NotImplementedError( "Comparing configuration with other than 'default' currently not implemented") changes = {} for flag, value in self._flags.items(): if not self._values_equal(value, self.default[flag]): changes[flag] = value return changes def load_config( self, config: str ): """Load a config file. Parameters ---------- config : str The name of the config file to load. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.load_config('/tmp/arpDecode.config') """ with open(config, encoding='utf-8') as f: for line in f: line = line.strip() if line.startswith('#') or len(line) == 0: continue key_val = line.split('=') self._set_config(key_val[0].strip(), key_val[1].strip()) def generate_config( self, outfile: str = None, verbose: bool = False ): """Generate a config file with the default values. Parameters ---------- outfile : str, default: None The name of the config file to generate. If `None`, use `'pluginName.config'` in the plugin home folder. verbose : bool, default: False - If `True`, print the output (`stdout` and `stderr`) of the command. - If `False`, do not print anything. Raises ------ subprocess.CalledProcessError If the process exited with a non-zero exit code. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.generate_config('/tmp/arpDecode.config') """ T2Utils.generate_config(self.name, outfile, verbose=verbose) def save_config( self, outfile: str = None, verbose: bool = False ): """Generate a config file with the current modified values. Parameters ---------- outfile : str, default: None The name of the config file to save. If `None`, use `'pluginName.config'` in the plugin home folder. verbose : bool, default: False - If `True`, print the output (`stdout` and `stderr`) of the command. - If `False`, do not print anything. Raises ------ subprocess.CalledProcessError If one of the processes exited with a non-zero exit code. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.save_config('/tmp/arpDecode.config') """ if not outfile and self.config_file: outfile = self.config_file self.generate_config(outfile, verbose=verbose) for flag, value in self.changes.items(): T2Utils.set_config(self.name, flag, value, outfile=outfile, verbose=verbose) def reset( self, name: Union[str, List[str]] = None ): """Reset flags to their default value. Parameters ---------- name : str or list of str, default: None `name` can be: - a single flag, e.g., `'MY_FLAG'`. - a list of flags, e.g., `['MY_FLAG1', 'MY_FLAG2']`. - `None` to reset all flags. Raises ------ NameError If a flag does not exist for this plugin. See Also -------- T2Plugin.apply_changes : Apply the current modifications to the plugin. T2Plugin.set_default : Alias for `T2Plugin.reset()` Notes ----- `T2Plugin.apply_changes()` must be called later to apply the changes. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.reset('MAX_IP') >>> arpDecode.apply_changes() """ if not name: self.reset(self.flags) elif isinstance(name, list): for n in name: if n not in self.flags: raise NameError(f"Flag '{n}' does not exist for {self.name} plugin") if n in self._modified_flags: del self._modified_flags[n] self._set_config(n, self.default[n]) elif name not in self.flags: raise NameError(f"Flag '{name}' does not exist for {self.name} plugin") else: if name in self._modified_flags: del self._modified_flags[name] self._set_config(name, self.default[name]) def get_default( self, name: str ) -> Any: """Get the default value for the configuration flag `name`. Parameters ---------- name : str The name of the flag to get the default value from. Raises ------ NameError If the flag `name` does not exist for this plugin. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.get_default('MAX_IP') 10 """ if name not in self.flags: raise NameError(f"Flag '{name}' does not exist for {self.name} plugin") return self.default[name] def set_default( self, name: Union[str, List[str]] = None ): """Reset flags to their default value. Parameters ---------- name : str or list of str, default: None `name` can be: - a single flag, e.g., `'MY_FLAG'`. - a list of flags, e.g., `['MY_FLAG1', 'MY_FLAG2']`. - `None` to reset all flags. Raises ------ NameError If a flag does not exist for this plugin. See Also -------- T2Plugin.apply_changes : Apply the current modifications to the plugin. T2Plugin.reset : Alias for `T2Plugin.set_default()` Notes ----- `T2Plugin.apply_changes()` must be called later to apply the changes. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.set_default('MAX_IP') >>> arpDecode.apply_changes() """ self.reset(name) def list_config(self) -> List[str]: """List the configuration flags available for the plugin. Returns ------- list of str The list of configuration flags available for the plugin. See Also -------- T2Plugin.flags : The list of configuration flags available for the plugin. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.list_config() ['MAX_IP'] """ return self.flags def apply_changes( self, outfile: str = None, verbose: bool = False ): """Apply the current modifications to the plugin. Parameters ---------- outfile : str, default: None - If `None`, edit the sources directly. - Else apply the config to `outfile`, e.g., `'myPlugin.config'`. verbose : bool, default: False - If `True`, print the output (`stdout` and `stderr`) of the command. - If `False`, do not print anything. Raises ------ subprocess.CalledProcessError If one of the processes exited with a non-zero exit code. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.apply_changes() """ if self._modified_flags: for flag_name, flag_value in self._modified_flags.items(): T2Utils.set_config(self.name, flag_name, flag_value, outfile=outfile, verbose=verbose) self._flags[flag_name] = flag_value self._modified_flags.clear() def build( self, plugin_folder: str = None, force_rebuild: bool = False, debug: bool = False, verbose: bool = False ): """Build the plugin. Parameters ---------- plugin_folder : str, default: None Path to the plugin folder. If `None`, default to `'$HOME/.tranalyzer/plugins'`. force_rebuild : bool, default: False Force the rebuild of the configuration files (`$ t2build -r ...`). debug : bool, default: False Build the plugin in debug mode. verbose : bool, default: False - If `True`, print the output (`stdout` and `stderr`) of the command. - If `False`, do not print anything. Raises ------ subprocess.CalledProcessError If the process exited with a non-zero exit code. See Also -------- T2Plugin.clean : Remove files generated by `T2Plugin.build()`. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.build() """ T2Utils.build(self.name, plugin_folder, force_rebuild, debug, verbose) def clean( self, verbose: bool = False ): """Remove files generated by `T2Plugin.build()`. Parameters ---------- verbose : bool, default: False - If `True`, print the output (`stdout` and `stderr`) of the command. - If `False`, do not print anything. Raises ------ subprocess.CalledProcessError If the process exited with a non-zero exit code. See Also -------- T2Plugin.build : Build the plugin. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.build() >>> arpDecode.clean() """ T2Utils.clean(self.name, verbose=verbose) def unload( self, plugin_folder: str = None, verbose: bool = False ): """Remove (unload) the plugin from the plugin folder. Parameters ---------- plugin_folder : str, default: None The plugin folder from where the plugin must be unloaded. If `None`, use the default plugin folder (`'$HOME/.tranalyzer/plugins'`). verbose : bool, default: False - If `True`, print the output (`stdout` and `stderr`) of the command. - If `False`, do not print anything. Raises ------ subprocess.CalledProcessError If the process exited with a non-zero exit code. Examples -------- >>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.unload() """ T2Utils.unload(self.name, plugin_folder, verbose=verbose) # ========================================================================= # Private functions # ========================================================================= def _values_equal(self, val1: Any, val2: Any): """Compare two values for equality, handling synonym values, such as `'yes'`/1 and `'no'`/0. Parameters ---------- val1, val2 : Any The values to compare. Returns ------- bool `True` if `val1` and `val2` are equal, `False` otherwise. """ return ( (val1 in ['yes', 1] and val2 in ['yes', 1]) or (val1 in ['no', 0] and val2 in ['no', 0]) or (val1 == val2) ) def _set_config(self, name: str, value: Any): """Set the value for the configuration flag `name`. Parameters ---------- name : str The name of the flag to set. value : Any The new value for the flag `name`. Raises ------ NameError If the flag `name` does not exist for this plugin. See Also -------- T2Plugin.apply_changes : Apply the current modifications to the plugin. Notes ----- `T2Plugin.apply_changes()` must be called later to apply the changes. """ if name not in self.flags: raise NameError(f"Flag '{name}' does not exist for {self.name} plugin") source = str(T2Utils.get_config(self.name, name, infile=self.config_file)) if value == 'no': if source != '0': self._modified_flags[name] = 0 self._add_dict_entry(name, 0) elif name in self._modified_flags: del self._modified_flags[name] elif value == 'yes': if source != '1': self._modified_flags[name] = 1 self._add_dict_entry(name, 1) elif name in self._modified_flags: del self._modified_flags[name] elif str(value) != source: self._modified_flags[name] = value self._add_dict_entry(name, value) else: if name in self._modified_flags: del self._modified_flags[name] self._add_dict_entry(name, self._flags[name]) def __setattr__(self, name: str, value: Any): super().__setattr__(name, value) try: if name in self.flags: self._set_config(name, value) except (KeyError, AttributeError): if not name.startswith('_'): _printerr(f"Flag '{name}' does not exist for {self.name} plugin") def _add_dict_entry(self, flag: str, value): self.__dict__[flag] = value
Instance variables
prop changes : Dict[str, Any]
-
The list of configuration flags modified but not yet persisted.
Expand source code
@property def changes(self) -> Dict[str, Any]: """The list of configuration flags modified but not yet persisted.""" return self._modified_flags
prop config_file : str
-
The configuration file where changes will be persisted in this session.
None
means the changes are persisted directly into the source files, e.g.,src/pluginName.h
.Expand source code
@property def config_file(self) -> str: """The configuration file where changes will be persisted in this session. `None` means the changes are persisted directly into the source files, e.g., `src/pluginName.h`. """ return self._config_file
prop default : Dict[str, Any]
-
The list of configuration flags and their default values.
Expand source code
@property def default(self) -> Dict[str, Any]: """The list of configuration flags and their default values.""" if not self._default: self._default = dict.fromkeys(self.flags) for flag in self.flags: self._default[flag] = T2Utils.get_default(self.name, flag) return self._default
prop description : str
-
The description of the plugin.
Expand source code
@property def description(self) -> str: """The description of the plugin.""" if not self._description: self._description = T2Utils.plugin_description(self.name) return self._description
prop flags : List[str]
-
The list of configuration flags available for the plugin.
Expand source code
@property def flags(self) -> List[str]: """The list of configuration flags available for the plugin.""" return list(self._flags.keys())
prop name : str
-
The name of the plugin.
Expand source code
@property def name(self) -> str: """The name of the plugin.""" return self._name
prop number : str
-
The number of the plugin.
Expand source code
@property def number(self) -> str: """The number of the plugin.""" if not self._number: self._number = T2Utils.plugin_number(self.name) return self._number
Methods
def apply_changes(self, outfile: str = None, verbose: bool = False)
-
Apply the current modifications to the plugin.
Parameters
outfile
:str
, default: None
-
- If
None
, edit the sources directly. - Else apply the config to
outfile
, e.g.,'myPlugin.config'
.
- If
verbose
:bool
, default: False
-
- If
True
, print the output (stdout
andstderr
) of the command. - If
False
, do not print anything.
- If
Raises
subprocess.CalledProcessError
- If one of the processes exited with a non-zero exit code.
Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.apply_changes()
def build(self, plugin_folder: str = None, force_rebuild: bool = False, debug: bool = False, verbose: bool = False)
-
Build the plugin.
Parameters
plugin_folder
:str
, default: None
-
Path to the plugin folder.
If
None
, default to'$HOME/.tranalyzer/plugins'
. force_rebuild
:bool
, default: False
- Force the rebuild of the configuration files (
$ t2build -r ...
). debug
:bool
, default: False
- Build the plugin in debug mode.
verbose
:bool
, default: False
-
- If
True
, print the output (stdout
andstderr
) of the command. - If
False
, do not print anything.
- If
Raises
subprocess.CalledProcessError
- If the process exited with a non-zero exit code.
See Also
T2Plugin.clean()
- Remove files generated by
T2Plugin.build()
.
Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.build()
def clean(self, verbose: bool = False)
-
Remove files generated by
T2Plugin.build()
.Parameters
verbose
:bool
, default: False
-
- If
True
, print the output (stdout
andstderr
) of the command. - If
False
, do not print anything.
- If
Raises
subprocess.CalledProcessError
- If the process exited with a non-zero exit code.
See Also
T2Plugin.build()
- Build the plugin.
Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.build() >>> arpDecode.clean()
def diff(self, base: str = None) ‑> Dict[str, Any]
-
Compare the current configuration with the default configuration.
Parameters
base
:str
, default: None
-
The base configuration to use for comparison.
Currently, only
'default'
is supported.
Returns
dict
- The flags differing from
base
as keys, the current value as values.
Raises
NotImplementedError
- When trying to compare the current configuration with base other than
'default'
.
Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.apply_changes() >>> arpDecode.diff() {'MAX_IP': 5}
def discard_changes(self)
-
Discard all non-committed changes made in this session.
Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.changes {'MAX_IP': 5} >>> arpDecode.discard_changes() >>> arpDecode.changes {}
def generate_config(self, outfile: str = None, verbose: bool = False)
-
Generate a config file with the default values.
Parameters
outfile
:str
, default: None
-
The name of the config file to generate.
If
None
, use'pluginName.config'
in the plugin home folder. verbose
:bool
, default: False
-
- If
True
, print the output (stdout
andstderr
) of the command. - If
False
, do not print anything.
- If
Raises
subprocess.CalledProcessError
- If the process exited with a non-zero exit code.
Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.generate_config('/tmp/arpDecode.config')
def get_default(self, name: str) ‑> Any
-
Get the default value for the configuration flag
name
.Parameters
name
:str
- The name of the flag to get the default value from.
Raises
NameError
- If the flag
name
does not exist for this plugin.
Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.get_default('MAX_IP') 10
def list_config(self) ‑> List[str]
-
List the configuration flags available for the plugin.
Returns
list
ofstr
- The list of configuration flags available for the plugin.
See Also
T2Plugin.flags
- The list of configuration flags available for the plugin.
Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.list_config() ['MAX_IP']
def load_config(self, config: str)
-
Load a config file.
Parameters
config
:str
- The name of the config file to load.
Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.load_config('/tmp/arpDecode.config')
def reset(self, name: Union[str, List[str]] = None)
-
Reset flags to their default value.
Parameters
name
:str
orlist
ofstr
, default: None
-
name
can be:- a single flag, e.g.,
'MY_FLAG'
. - a list of flags, e.g.,
['MY_FLAG1', 'MY_FLAG2']
. None
to reset all flags.
- a single flag, e.g.,
Raises
NameError
- If a flag does not exist for this plugin.
See Also
T2Plugin.apply_changes()
- Apply the current modifications to the plugin.
T2Plugin.set_default()
- Alias for
T2Plugin.reset()
Notes
T2Plugin.apply_changes()
must be called later to apply the changes.Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.reset('MAX_IP') >>> arpDecode.apply_changes()
def save_config(self, outfile: str = None, verbose: bool = False)
-
Generate a config file with the current modified values.
Parameters
outfile
:str
, default: None
-
The name of the config file to save.
If
None
, use'pluginName.config'
in the plugin home folder. verbose
:bool
, default: False
-
- If
True
, print the output (stdout
andstderr
) of the command. - If
False
, do not print anything.
- If
Raises
subprocess.CalledProcessError
- If one of the processes exited with a non-zero exit code.
Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.save_config('/tmp/arpDecode.config')
def set_default(self, name: Union[str, List[str]] = None)
-
Reset flags to their default value.
Parameters
name
:str
orlist
ofstr
, default: None
-
name
can be:- a single flag, e.g.,
'MY_FLAG'
. - a list of flags, e.g.,
['MY_FLAG1', 'MY_FLAG2']
. None
to reset all flags.
- a single flag, e.g.,
Raises
NameError
- If a flag does not exist for this plugin.
See Also
T2Plugin.apply_changes()
- Apply the current modifications to the plugin.
T2Plugin.reset()
- Alias for
T2Plugin.set_default()
Notes
T2Plugin.apply_changes()
must be called later to apply the changes.Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.set_default('MAX_IP') >>> arpDecode.apply_changes()
def status(self)
-
Print the current configuration status of the plugin.
Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.MAX_IP = 5 >>> arpDecode.status() 1 change pending: MAX_IP = 5
def unload(self, plugin_folder: str = None, verbose: bool = False)
-
Remove (unload) the plugin from the plugin folder.
Parameters
plugin_folder
:str
, default: None
-
The plugin folder from where the plugin must be unloaded.
If
None
, use the default plugin folder ('$HOME/.tranalyzer/plugins'
). verbose
:bool
, default: False
-
- If
True
, print the output (stdout
andstderr
) of the command. - If
False
, do not print anything.
- If
Raises
subprocess.CalledProcessError
- If the process exited with a non-zero exit code.
Examples
>>> arpDecode = T2Plugin('arpDecode') >>> arpDecode.unload()