add confutil
This commit is contained in:
parent
868e810a95
commit
252dae4b12
54
README.md
54
README.md
|
@ -1,12 +1,14 @@
|
|||
# utils
|
||||
Small tools needed to solve immediate tasks independently or as part of a project
|
||||
|
||||
* [camsutil](https://git.hmp.today/pavel.muhortov/utils#camsutil)
|
||||
* [cronutil](https://git.hmp.today/pavel.muhortov/utils#cronutil)
|
||||
* [ffmpeger.py](https://git.hmp.today/pavel.muhortov/utils#ffmpeger-py)
|
||||
* [procutil.py](https://git.hmp.today/pavel.muhortov/utils#procutil-py)
|
||||
* [sendmail.py](https://git.hmp.today/pavel.muhortov/utils#sendmail-py)
|
||||
* [`camsutil`](https://git.hmp.today/pavel.muhortov/utils#camsutil)
|
||||
* [`cronutil`](https://git.hmp.today/pavel.muhortov/utils#cronutil)
|
||||
* [`confutil`.py](https://git.hmp.today/pavel.muhortov/utils#confutil-py)
|
||||
* [`ffmpeger`.py](https://git.hmp.today/pavel.muhortov/utils#ffmpeger-py)
|
||||
* [`procutil`.py](https://git.hmp.today/pavel.muhortov/utils#procutil-py)
|
||||
* [`sendmail`.py](https://git.hmp.today/pavel.muhortov/utils#sendmail-py)
|
||||
____
|
||||
## camsutil
|
||||
## `camsutil`
|
||||
**Description:** Creation of a request to the camera API based on the prepared template
|
||||
**Dependencies:** Python 3 (tested version 3.9.5)
|
||||
|
||||
|
@ -48,7 +50,7 @@ with open('img.jpg', 'wb') as output:
|
|||
```
|
||||
|
||||
____
|
||||
## cronutil
|
||||
## `cronutil`
|
||||
**Description:** Control wrapper for the [schedule](https://github.com/dbader/schedule) package
|
||||
**Dependencies:** Python 3 (tested version 3.9.5)
|
||||
|
||||
|
@ -87,7 +89,39 @@ cron.start()
|
|||
```
|
||||
|
||||
____
|
||||
## ffmpeger.py
|
||||
## `confutil`.py
|
||||
**Description:** Parser of configs, arguments, parameters
|
||||
**Dependencies:** Python 3 (tested version 3.9.5)
|
||||
|
||||
Example config to parse:
|
||||
```text
|
||||
[main]
|
||||
# This block contains basic parameters
|
||||
|
||||
|
||||
[httpd]
|
||||
# This block contains parameters for the http server
|
||||
|
||||
# Address to which to bind listening
|
||||
#address=0.0.0.0;
|
||||
# Port to which to bind listening. Port below 1024 requires root privileges.
|
||||
port=8800;
|
||||
# Working directory (available to everyone)
|
||||
directory=www;
|
||||
```
|
||||
|
||||
Example usage in Python:
|
||||
```Python
|
||||
from os import path
|
||||
from confutil import Parse
|
||||
|
||||
conf = path.splitext(__file__)[0] + '.conf'
|
||||
if path.exists(conf):
|
||||
print(Parse(parameters=conf, block='httpd'))
|
||||
```
|
||||
|
||||
____
|
||||
## `ffmpeger`.py
|
||||
**Description:** FFmpeg management from Python
|
||||
**Dependencies:** Python 3 (tested version 3.9.5), installed or downloaded ffmpeg, [procutil.py](https://git.hmp.today/pavel.muhortov/utils#procutil-py) in the same directory
|
||||
|
||||
|
@ -120,7 +154,7 @@ FFmpeg.run(src='null, anull', preset='240p', fps=10)
|
|||
```
|
||||
|
||||
____
|
||||
## procutil.py
|
||||
## `procutil`.py
|
||||
**Description:** Find a running process from Python
|
||||
**Dependencies:** Python 3 (tested version 3.9.5)
|
||||
|
||||
|
@ -152,7 +186,7 @@ if processes:
|
|||
for process in processes:
|
||||
print(process)
|
||||
```
|
||||
## sendmail.py
|
||||
## `sendmail`.py
|
||||
**Description:** Sending email from Python
|
||||
**Dependencies:** Python 3 (tested version 3.9.5)
|
||||
|
||||
|
|
135
confutil.py
Normal file
135
confutil.py
Normal file
|
@ -0,0 +1,135 @@
|
|||
from argparse import ArgumentParser
|
||||
from os import path, sep
|
||||
|
||||
|
||||
class Parse:
|
||||
"""
|
||||
Parser of configs, arguments, parameters
|
||||
"""
|
||||
def __init__(self, parameters, block: str = None):
|
||||
"""
|
||||
Object constructor
|
||||
:param parameters: dictionary as "key":"value" or
|
||||
ArgumentParser class object or
|
||||
string path to the file or
|
||||
string as "var1=val1;var2=val2"
|
||||
:param block: string name of target block from text
|
||||
"""
|
||||
self.data = {}
|
||||
if type(parameters) is dict:
|
||||
self._dict2dict(parameters)
|
||||
if type(parameters) is ArgumentParser:
|
||||
self._dict2dict(self.argv2dict(parameters))
|
||||
if type(parameters) is str:
|
||||
if path.exists(parameters):
|
||||
self._dict2dict(self.strs2dict(self.conf2strs(parameters), block))
|
||||
else:
|
||||
self._dict2dict(self.strs2dict(parameters, block))
|
||||
|
||||
def __str__(self):
|
||||
"""
|
||||
Overrides method for print(object)
|
||||
:return: string with contents of the object's dictionary
|
||||
"""
|
||||
string = ''
|
||||
for key, val in self.data.items():
|
||||
string += str(type(val)) + ' ' + str(key) + ' = ' + str(val) + '\n'
|
||||
return string
|
||||
|
||||
def _dict2dict(self, dictionary: dict):
|
||||
"""
|
||||
Updates or adds dictionary data
|
||||
:param dictionary: dictionary as "key":"value"
|
||||
:return: None
|
||||
"""
|
||||
self.data.update(dictionary)
|
||||
|
||||
def expand(self, store: str = None):
|
||||
"""
|
||||
Expand dictionary "key":"name.conf" to dictionary "key":{subkey: subval}
|
||||
:param store: string path to directory with name.conf
|
||||
:return: expanded dictionary as "key":{subkey: subval}
|
||||
"""
|
||||
for key in self.data:
|
||||
if store:
|
||||
config = store + sep + self.data[key]
|
||||
else:
|
||||
config = self.data[key]
|
||||
with open(config) as file:
|
||||
self.data[key] = Parse(file.read()).data
|
||||
return self.data
|
||||
|
||||
@classmethod
|
||||
def argv2dict(cls, parser: ArgumentParser):
|
||||
"""
|
||||
Converts startup arguments to a dictionary
|
||||
:param parser: argparse.ArgumentParser class object
|
||||
:return: dictionary as "key":"value"
|
||||
"""
|
||||
parser = ArgumentParser(add_help=False, parents=[parser])
|
||||
return vars(parser.parse_args())
|
||||
|
||||
@classmethod
|
||||
def conf2strs(cls, config: str):
|
||||
"""
|
||||
Builds a dictionary from a file containing parameters
|
||||
:param config: string path to the file
|
||||
:return: string as "var1=val1;\nvar2=val2;"
|
||||
"""
|
||||
with open(config) as file:
|
||||
raw = file.read()
|
||||
strs = ''
|
||||
for line in raw.splitlines():
|
||||
if not line.lstrip().startswith('#'):
|
||||
strs += line + '\n'
|
||||
return strs
|
||||
|
||||
@classmethod
|
||||
def strs2dict(cls, strings: str, blockname: str):
|
||||
"""
|
||||
Builds a dictionary from a strings containing parameters
|
||||
:param strings: string as "var1=val1;var2=val2;"
|
||||
:param blockname: string name of target block from text
|
||||
:return: dictionary as "key":"value"
|
||||
"""
|
||||
dictionary = {}
|
||||
if blockname:
|
||||
strings = cls.block(blockname, strings)
|
||||
for line in strings.replace('\n', ';').split(';'):
|
||||
if not line.lstrip().startswith('#') and "=" in line:
|
||||
dictionary[line.split('=')[0].strip()] = line.split('=')[1].strip().split(';')[0].strip()
|
||||
return dictionary
|
||||
|
||||
@classmethod
|
||||
def str2bool(cls, value: str):
|
||||
"""
|
||||
Converts a string value to boolean
|
||||
:param value: string containing "true" or "false", "yes" or "no", "1" or "0"
|
||||
:return: bool True or False
|
||||
"""
|
||||
return str(value).lower() in ("true", "yes", "1")
|
||||
|
||||
@classmethod
|
||||
def block(cls, blockname: str, text: str):
|
||||
"""
|
||||
Cuts a block of text between line [blockname] and line [next block] or EOF
|
||||
:param blockname: string in [] after which the block starts
|
||||
:param text: string of text from which the block is needed
|
||||
:return: string of text between line [block name] and line [next block]
|
||||
"""
|
||||
level = 1
|
||||
save = False
|
||||
result = ''
|
||||
for line in text.splitlines():
|
||||
if line.startswith('[') and blockname in line:
|
||||
level = line.count('[')
|
||||
save = True
|
||||
elif line.startswith('[') and '['*level in line:
|
||||
save = False
|
||||
elif save:
|
||||
result += line + '\n'
|
||||
return result
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pass
|
Loading…
Reference in New Issue
Block a user