vse_toolbox/file_utils.py

187 lines
5.3 KiB
Python
Raw Permalink Normal View History

2023-03-14 13:38:04 +01:00
import importlib
import re
import subprocess
2023-04-22 15:42:38 +02:00
import platform
2023-03-14 13:38:04 +01:00
import sys
import unicodedata
from pathlib import Path
2024-04-10 16:15:57 +02:00
from os.path import expandvars
import json
import glob
2023-03-14 13:38:04 +01:00
2023-04-22 15:42:38 +02:00
2023-03-14 13:38:04 +01:00
def install_module(module_name, package_name=None):
'''Install a python module with pip or return it if already installed'''
try:
module = importlib.import_module(module_name)
except ModuleNotFoundError:
print(f'Installing Module {module_name} ....')
2023-07-11 16:27:43 +02:00
subprocess.call([sys.executable, '-m', 'ensurepip', '--upgrade'])
2023-03-14 13:38:04 +01:00
subprocess.call([sys.executable, '-m', 'pip', 'install', package_name or module_name])
module = importlib.import_module(module_name)
return module
def import_module_from_path(path):
from importlib import util
try:
path = Path(path)
spec = util.spec_from_file_location(path.stem, str(path))
mod = util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod
except Exception as e:
print(f'Cannot import file {path}')
print(e)
2023-05-05 09:46:50 +02:00
def fuzzy_match(s1, s2, case_sensitive=False):
'''Tell how much two passed strings are similar 1.0 being exactly similar'''
from difflib import SequenceMatcher
if case_sensitive:
similarity = SequenceMatcher(None, s1, s2)
else:
similarity = SequenceMatcher(None, s1.lower(), s2.lower())
return similarity.ratio()
2023-03-14 13:38:04 +01:00
def norm_str(string, separator='_', format=str.lower, padding=0):
string = str(string)
string = string.replace('_', ' ')
string = string.replace('-', ' ')
string = re.sub('[ ]+', ' ', string)
string = re.sub('[ ]+\/[ ]+', '/', string)
string = string.strip()
if format:
string = format(string)
# Padd rightest number
string = re.sub(r'(\d+)(?!.*\d)', lambda x : x.group(1).zfill(padding), string)
string = string.replace(' ', separator)
string = unicodedata.normalize('NFKD', string).encode('ASCII', 'ignore').decode("utf-8")
2023-03-17 22:55:06 +01:00
return string
def norm_name(string, separator='_', format=str.lower, padding=0):
string = str(string)
string = string.split('/')[-1] #used to remove first slash -> albert / albert_casque -> albert_casque
string = string.replace('_', ' ')
string = string.replace('-', ' ')
string = re.sub('[ ]+', ' ', string)
string = re.sub('[ ]+\/[ ]+', '/', string)
string = string.strip()
if format:
string = format(string)
# Padd rightest number
string = re.sub(r'(\d+)(?!.*\d)', lambda x : x.group(1).zfill(padding), string)
string = string.replace(' ', separator)
string = unicodedata.normalize('NFKD', string).encode('ASCII', 'ignore').decode("utf-8")
2023-03-14 13:38:04 +01:00
return string
def read_file(path):
2024-05-24 09:44:19 +02:00
'''Read a file with an extension in (json, yaml, yml, txt, log)'''
2023-03-14 13:38:04 +01:00
2024-05-24 09:44:19 +02:00
exts = ('.json', '.yaml', '.yml', '.txt', '.log')
2023-03-14 13:38:04 +01:00
if not path:
print('Try to read empty file')
path = Path(path)
if not path.exists():
print('File not exist', path)
return
if path.suffix not in exts:
print(f'Cannot read file {path}, extension must be in {exts}')
return
txt = path.read_text()
data = None
if path.suffix.lower() in ('.yaml', '.yml'):
yaml = install_module('yaml')
try:
data = yaml.safe_load(txt)
2024-04-10 16:15:57 +02:00
except Exception as e:
print(e)
2023-03-14 13:38:04 +01:00
print(f'Could not load yaml file {path}')
return
elif path.suffix.lower() == '.json':
try:
data = json.loads(txt)
2024-04-10 16:15:57 +02:00
except Exception as e:
print(e)
2023-03-14 13:38:04 +01:00
print(f'Could not load json file {path}')
return
else:
data = txt
2023-04-22 15:42:38 +02:00
return data
def open_file(filepath, env=None, select=False):
if platform.system() == 'Darwin': # macOS
cmd = ['open']
if select:
cmd += ['-R']
elif platform.system() == 'Windows': # Windows
cmd = ['explorer']
if select:
cmd += ['/select,']
else: # linux variants
cmd = ['xdg-open']
if select:
cmd = ['nemo']
cmd += [str(filepath)]
2023-05-08 18:25:04 +02:00
subprocess.Popen(cmd, env=env)
2024-04-10 16:15:57 +02:00
# def parse(string, template):
# template = re.sub(r'{index:(.+?)}', r'(?P<index>.+)', template)
# reg = re.sub(r'{(.+?)}', r'(?P<_\1>.+)', template)
2023-05-08 18:25:04 +02:00
2024-04-10 16:15:57 +02:00
# values = list(re.search(reg, string).groups())
# keys = re.findall(r'{(.+?)}', template) + ['index']
2023-05-08 18:25:04 +02:00
2024-04-10 16:15:57 +02:00
# return dict(zip(keys, values))
def parse(template, string):
reg = re.sub(r'{[^}]*}|\.', lambda m: m.group() if m.group().startswith('{') else r'\.', template)
reg = re.sub(r'{(.+?)}', r'(?P<\1>.*)', reg)
#print(string, template, reg)
if result := re.match(reg, string):
return result.groupdict()
2024-04-16 14:28:02 +02:00
def expand(template, **kargs):
template = Path(template).as_posix()
template = expandvars(template)
2024-04-10 16:15:57 +02:00
for key, value in kargs.items():
2024-04-16 14:28:02 +02:00
template = re.sub(r'\{%s\}'%key, value, template)
return template
def find_last(template, **kargs):
pattern = expand(template, **kargs)
2024-04-10 16:15:57 +02:00
pattern = re.sub(r'{\w+:(\d{2})d}', lambda x : '?' * int(x.groups()[0]), pattern)
pattern = re.sub(r'{.*?}', '*', pattern)
filepaths = glob.glob(pattern)
if filepaths:
2024-04-16 14:28:02 +02:00
return Path(max(filepaths))
else:
print(f'No preview found for template {pattern}')