Add a mechanism for building a cache of "system parameters"
- Add a system_parameters module to eryntools that implements some basic types and can write a cache to a file. - Add a system-parameters Python script that builds the cache. - Add init_system_parameters to zsh that exports an environment variable that points to the parameters file - Add an eryn.system-parameters.plist LaunchAgent file for running the script at regular intervals
This commit is contained in:
parent
05b5fef583
commit
661e5516e7
5 changed files with 253 additions and 0 deletions
27
LaunchAgents/eryn.system-parameters.plist
Normal file
27
LaunchAgents/eryn.system-parameters.plist
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>eryn.system-parameters</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>/Users/eryn/bin/system-parameters</string>
|
||||
<string>--output</string>
|
||||
<string>/Users/eryn/.config/eryn/system_parameters.json</string>
|
||||
</array>
|
||||
<key>WorkingDirectory</key>
|
||||
<string>/Users/eryn</string>
|
||||
<key>StandardOutPath</key>
|
||||
<string>/Users/eryn/.config/eryn/system_parameters.output.log</string>
|
||||
<key>StandardErrorPath</key>
|
||||
<string>/Users/eryn/.config/eryn/system_parameters.error.log</string>
|
||||
<key>EnvironmentVariables</key>
|
||||
<dict>
|
||||
<key>PATH</key>
|
||||
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>
|
||||
</dict>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
169
Python/eryntools/src/eryntools/dotfiles/system_parameters.py
Normal file
169
Python/eryntools/src/eryntools/dotfiles/system_parameters.py
Normal file
|
@ -0,0 +1,169 @@
|
|||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
import json
|
||||
import os.path
|
||||
import subprocess
|
||||
import sys
|
||||
from typing import Any, Optional, TextIO, Union
|
||||
|
||||
|
||||
ParameterValue = Union[str, int, float]
|
||||
ParametersObject = dict[str, Any]
|
||||
|
||||
|
||||
_PARAMETERS_FILE = "~/.config/eryn/system_parameters.json"
|
||||
|
||||
|
||||
class SystemParameters:
|
||||
class _Keys:
|
||||
DATA = 'data'
|
||||
PARAMETERS = 'parameters'
|
||||
VALUE = 'value'
|
||||
|
||||
def __init__(self):
|
||||
self._object: ParametersObject = {}
|
||||
|
||||
@property
|
||||
def parameters(self) -> dict:
|
||||
if not self._object:
|
||||
return {}
|
||||
|
||||
return self._object[SystemParameters._Keys.PARAMETERS]
|
||||
|
||||
def load_from_file(self, input_file: TextIO):
|
||||
self._object = json.load(input_file)
|
||||
|
||||
def write_to_file(self, file):
|
||||
json.dump(self._object, file, indent=4, cls=_JSONEncoder)
|
||||
|
||||
def __dir__(self):
|
||||
return dir(self._object)
|
||||
|
||||
def __getattr__(self, name: str) -> Optional[ParameterValue]:
|
||||
if not self._object:
|
||||
return None
|
||||
|
||||
return self._object[SystemParameters._Keys.PARAMETERS][name][SystemParameters._Keys.VALUE]
|
||||
|
||||
def __setattr__(self, name: str, value: 'Parameter'):
|
||||
if not isinstance(value, Parameter):
|
||||
super().__setattr__(name, value)
|
||||
return
|
||||
|
||||
parameter_value: ParametersObject = {
|
||||
SystemParameters._Keys.VALUE: value.value,
|
||||
}
|
||||
|
||||
additional_data = value.additional_data
|
||||
if additional_data:
|
||||
parameter_value[SystemParameters._Keys.DATA] = additional_data
|
||||
|
||||
self._object[name] = parameter_value
|
||||
|
||||
|
||||
class Parameter:
|
||||
@property
|
||||
def value(self) -> str:
|
||||
'''The value of this parameter.'''
|
||||
raise NotImplementedError()
|
||||
|
||||
@property
|
||||
def additional_data(self) -> Optional[dict[str, ParametersObject]]:
|
||||
'''Optional additional data to include in the parameter structure.'''
|
||||
return None
|
||||
|
||||
|
||||
class CommandParameter(Parameter):
|
||||
class _Keys:
|
||||
CODE = 'code'
|
||||
COMMAND = 'command'
|
||||
RESULT = 'result'
|
||||
STDOUT = 'stdout'
|
||||
STDERR = 'stderr'
|
||||
|
||||
def __init__(self, command_arguments: list):
|
||||
self.command = command_arguments
|
||||
self.result: Optional[subprocess.CompletedProcess] = None
|
||||
|
||||
@property
|
||||
def value(self) -> str:
|
||||
self()
|
||||
return self.standard_output.strip()
|
||||
|
||||
@property
|
||||
def standard_output(self) -> str:
|
||||
if not self.result or not self.result.stdout:
|
||||
return ''
|
||||
|
||||
return self.result.stdout.decode('utf-8')
|
||||
|
||||
@property
|
||||
def standard_error(self) -> str:
|
||||
if not self.result or not self.result.stderr:
|
||||
return ''
|
||||
|
||||
return self.result.stderr.decode('utf-8')
|
||||
|
||||
@property
|
||||
def additional_data(self) -> Optional[dict]:
|
||||
self()
|
||||
assert self.result is not None
|
||||
|
||||
obj = {
|
||||
CommandParameter._Keys.COMMAND: self.result.args,
|
||||
CommandParameter._Keys.RESULT: {
|
||||
CommandParameter._Keys.CODE: self.result.returncode,
|
||||
}
|
||||
}
|
||||
|
||||
stdout = self.standard_output
|
||||
if stdout:
|
||||
obj[CommandParameter._Keys.RESULT][CommandParameter._Keys.STDOUT] = stdout.strip()
|
||||
|
||||
stderr = self.standard_error
|
||||
if stderr:
|
||||
obj[CommandParameter._Keys.RESULT][CommandParameter._Keys.STDERR] = stderr.strip()
|
||||
|
||||
return obj
|
||||
|
||||
def __call__(self) -> 'CommandParameter':
|
||||
if not self.result:
|
||||
self.result = subprocess.run(
|
||||
self.command,
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT
|
||||
)
|
||||
|
||||
return self
|
||||
|
||||
|
||||
class _JSONEncoder(json.JSONEncoder):
|
||||
def default(self, o: Any) -> Any:
|
||||
if isinstance(o, SystemParameters):
|
||||
return super().default(o._object)
|
||||
|
||||
return super().default(o)
|
||||
|
||||
|
||||
def main(argv) -> Optional[int]:
|
||||
import argparse
|
||||
|
||||
parser = argparse.ArgumentParser(prog=argv[0])
|
||||
parser.add_argument(
|
||||
'parameters_file',
|
||||
default=os.path.abspath(os.path.expanduser(_PARAMETERS_FILE)),
|
||||
nargs='?',
|
||||
)
|
||||
parser.add_argument('name')
|
||||
arguments = parser.parse_args(argv[1:])
|
||||
|
||||
parameters = SystemParameters()
|
||||
with open(arguments.parameters_file) as f:
|
||||
parameters.load_from_file(f)
|
||||
|
||||
print(getattr(parameters, arguments.name))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
sys.exit(main(sys.argv) or 0)
|
41
bin/system-parameters
Executable file
41
bin/system-parameters
Executable file
|
@ -0,0 +1,41 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
from eryntools.dotfiles.system_parameters import CommandParameter, SystemParameters
|
||||
|
||||
|
||||
class HomebrewPrefix(CommandParameter):
|
||||
def __init__(self):
|
||||
super().__init__(['brew', '--prefix'])
|
||||
|
||||
|
||||
class XcodeSelectPrintPath(CommandParameter):
|
||||
def __init__(self):
|
||||
super().__init__(['xcode-select', '-p'])
|
||||
|
||||
|
||||
def main(argv):
|
||||
parser = argparse.ArgumentParser(prog=argv[0])
|
||||
parser.add_argument('-f', '--file', type=argparse.FileType('r'))
|
||||
parser.add_argument('-o', '--output', type=argparse.FileType('w'), default=sys.stdout)
|
||||
arguments = parser.parse_args(argv[1:])
|
||||
|
||||
output_parameters = SystemParameters()
|
||||
|
||||
if arguments.file:
|
||||
output_parameters.load_from_file(arguments.file)
|
||||
|
||||
parameters = {
|
||||
'homebrew_prefix': HomebrewPrefix(),
|
||||
'xcode_path': XcodeSelectPrintPath(),
|
||||
}
|
||||
|
||||
for name, parameter in parameters.items():
|
||||
setattr(output_parameters, name, parameter)
|
||||
|
||||
output_parameters.write_to_file(arguments.output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import sys
|
||||
sys.exit(main(sys.argv) or 0)
|
15
zsh/func/init_system_parameters
Normal file
15
zsh/func/init_system_parameters
Normal file
|
@ -0,0 +1,15 @@
|
|||
#!/usr/bin/env zsh
|
||||
# Eryn Wells <eryn@erynwells.me>
|
||||
|
||||
function init_system_parameters
|
||||
{
|
||||
local PARAMETERS_FILE="$HOME/.config/eryn/system_parameters"
|
||||
|
||||
if [[ ! -e "$PARAMETERS_FILE" ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
export SYSTEM_PARAMETERS_FILE="$PARAMETERS_FILE"
|
||||
}
|
||||
|
||||
init_system_parameters "$@"
|
1
zshenv
1
zshenv
|
@ -22,6 +22,7 @@ autoload -Uz do_init_functions
|
|||
|
||||
typeset -a zsh_init_env_functions=( \
|
||||
init_path \
|
||||
init_system_parameters \
|
||||
init_env \
|
||||
init_env_aliases \
|
||||
init_env_python \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue