Refactor Package For Flexibility
Restructure the class hierarchy of ActiveConfigEnvironment to support a more generic structure.
The goal is to strip out the envvar specific code into a subclass while retaining the generic operations into a baseclass with the goal that we can create a new derived class that will live in parallel with the envvar handlers but for modules.
Let's call these new subclasses ActiveConfigEnvironmentEnvvar
and ActiveConfigEnvironmentModule
.
The ultimate goal is to create a structure where custom use-cases can be handled by including the base classes desired into a new subclass... for example:
from ActiveConfigEnvironment import *
class MyEnvironmentConfigClass(ActiveConfigEnvironmentEnvvar, ActiveConfigEnvironmentModule):
def __init__(self, filename=None):
if filename is not None:
self.inifilepath = filename
My idea of the new structure is something like this:
classDiagram
ActiveConfigEnvironmentBase<|--ActiveConfigEnvironmentEnvvar
ActiveConfigEnvironmentBase<|--ActiveConfigEnvironmentModule
ActiveConfigEnvironmentEnvvar<|--MyEnvironmentConfigClass
ActiveConfigEnvironmentModule<|--MyEnvironmentConfigClass
ActiveConfigEnvironmentBase: +actions
ActiveConfigEnvironmentBase: +apply()
ActiveConfigEnvironmentBase: +pretty_print_actions()
ActiveConfigEnvironmentBase: +generate_actions_script()
ActiveConfigEnvironmentBase: +write_actions_to_file()
ActiveConfigEnvironmentBase: +handler_initialize()
ActiveConfigEnvironmentBase: +handler_finalize()
ActiveConfigEnvironmentBase: #_new_action_list_entry()
ActiveConfigEnvironmentBase: #_initialize_handler_parameters()
ActiveConfigEnvironmentBase: #_remove_prefix()
ActiveConfigEnvironmentBase: #_gen_actions_script_bash()
ActiveConfigEnvironmentBase: #_gen_actions_script_bash_shebang()
ActiveConfigEnvironmentBase: #_gen_actions_script_bash_header()
ActiveConfigEnvironmentBase: #_gen_actions_script_python()
ActiveConfigEnvironmentBase: #_gen_actions_script_python_shebang()
ActiveConfigEnvironmentBase: #_gen_actions_Script_python_header()
ActiveConfigEnvironmentEnvvar: +pretty_print_envvars()
ActiveConfigEnvironmentEnvvar: #_handler_envvar_assert_not_empty()
ActiveConfigEnvironmentEnvvar: #_handler_envvar_find_in_path()
ActiveConfigEnvironmentEnvvar: #_handler_envvar_prepend()
ActiveConfigEnvironmentEnvvar: #_handler_envvar_remove()
ActiveConfigEnvironmentEnvvar: #_handler_envvar_remove_path_entry()
ActiveConfigEnvironmentEnvvar: #_handler_envvar_remove_substr()
ActiveConfigEnvironmentEnvvar: #_handler_envvar_set()
ActiveConfigEnvironmentEnvvar: #_handler_envvar_set_if_empty()
ActiveConfigEnvironmentEnvvar: #_handler_envvar_unset()
ActiveConfigEnvironmentEnvvar: #_apply_envvar()
ActiveConfigEnvironmentEnvvar: #_helper_handler_common_envvar()
ActiveConfigEnvironmentEnvvar: #_gen_actions_command_envvar()
ActiveConfigEnvironmentEnvvar: #_gen_actions_script_bash_header_envvar()
ActiveConfigEnvironmentEnvvar: #_gen_actions_script_bash_body_envvar()
ActiveConfigEnvironmentEnvvar: #_gen_actions_script_python_header_envvar()
ActiveConfigEnvironmentEnvvar: #_gen_actions_script_python_body_envvar()
ActiveConfigEnvironmentModule: +pretty_print_modules()
ActiveConfigEnvironmentModule: #_handler_module_load()
ActiveConfigEnvironmentModule: #_handler_module_purge()
ActiveConfigEnvironmentModule: #_handler_module_remove()
ActiveConfigEnvironmentModule: #_handler_module_swap()
ActiveConfigEnvironmentModule: #_handler_module_unload()
ActiveConfigEnvironmentModule: #_handler_module_use()
ActiveConfigEnvironmentModule: #_apply_module()
ActiveConfigEnvironmentModule: #_helper_handler_common_module()
ActiveConfigEnvironmentModule: #_gen_actions_command_module()
ActiveConfigEnvironmentModule: #_gen_actions_script_bash_header_module()
ActiveConfigEnvironmentModule: #_gen_actions_script_bash_body_module()
ActiveConfigEnvironmentModule: #_gen_actions_script_python_body_module()
ActiveConfigEnvironmentModule: #_gen_actions_script_python_body_module()
MyEnvironmentConfigClass: +generate_actions_script()
MyEnvironmentConfigClass: +write_actions_to_file()
There is still work to be done but the general idea is that operations defined in our .ini
files would have some form like:
<class>-<operation> [arg0..argN] : [value]
Which is a bit of a further refinement of what is defined in ActiveConfigParser
since we are adding an additional class concept to an operation. For example, envvar operations may look like:
envvar-set ENVVAR_NAME : ENVVAR_VALUE
envvar-append ENVVAR_NAME : ENVVAR_VALUE
and environment module (or LMOD) operations might be:
module-load MODULE_NAME : VERSION_NUMBER
module-unload MODULE_NAME
Actions
The general idea in this class stack is to consider these operations to define some sort of action that would be executed via some means. Currently I have bash
and python
generators in mind but we could expand this to add powershell
and other environments as well at some point.
An action defines an individual thing that is to be done, such as setting an environment variable or prepending something to the PATH or loading an environment module, etc.
When processing these ini files we want to be able to do one of three things with our list of actions:
- apply it in the current executing python script.
-
generate a runner script that will execute the actions defined.
- We can write this script out to a file.
- We consider the script to consist of three blocks:
- Shebang line (i.e.,
#!/usr/bin/bash
) - Header Block - This is where we should put any helper functions, etc. that are needed to execute the actions.
- Body Block - This is where we would put the actual action commands.
- Shebang line (i.e.,
Modularity
A further goal of this project is to create a class based structure that is designed to be extended in a manner similar to how ActiveConfigParser
is structured:
- Prefer lazy evaluated properties
- Structured method naming that can be searched for via pattern matching in base-class methods.