94 lines
2.6 KiB
Python
94 lines
2.6 KiB
Python
import re
|
|
import os
|
|
from pathlib import Path
|
|
from fnmatch import fnmatch
|
|
from glob import glob
|
|
|
|
|
|
class Template:
|
|
field_pattern = re.compile(r'{(\w+)\*{0,2}}')
|
|
field_pattern_recursive = re.compile(r'{(\w+)\*{2}}')
|
|
|
|
def __init__(self, template):
|
|
#asset_data_path = Path(lib_path) / ASSETLIB_FILENAME
|
|
|
|
self.raw = template
|
|
|
|
@property
|
|
def glob_pattern(self):
|
|
pattern = self.field_pattern_recursive.sub('**', self.raw)
|
|
pattern = self.field_pattern.sub('*', pattern)
|
|
return pattern
|
|
|
|
@property
|
|
def re_pattern(self):
|
|
pattern = self.field_pattern_recursive.sub('([\\\w -_.\/]+)', self.raw)
|
|
pattern = self.field_pattern.sub('([\\\w -_.]+)', pattern)
|
|
pattern = pattern.replace('?', '.')
|
|
pattern = pattern.replace('*', '.*')
|
|
|
|
return re.compile(pattern)
|
|
|
|
@property
|
|
def fields(self):
|
|
return self.field_pattern.findall(self.raw)
|
|
#return [f or '0' for f in fields]
|
|
|
|
def parse(self, path):
|
|
|
|
path = Path(path).as_posix()
|
|
|
|
res = self.re_pattern.findall(path)
|
|
if not res:
|
|
print('Could not parse {path} with {self.re_pattern}')
|
|
return {}
|
|
|
|
fields = self.fields
|
|
|
|
if len(fields) == 1:
|
|
field_values = res
|
|
else:
|
|
field_values = res[0]
|
|
|
|
return {k:v for k,v in zip(fields, field_values)}
|
|
|
|
def format(self, data=None, **kargs):
|
|
|
|
data = {**(data or {}), **kargs}
|
|
|
|
try:
|
|
path = self.raw.format(**data)
|
|
except KeyError as e:
|
|
print(f'Cannot format {self.raw} with {data}, field {e} is missing')
|
|
return
|
|
|
|
path = os.path.expandvars(path)
|
|
return Path(path)
|
|
|
|
def glob(self, directory, pattern=None):
|
|
'''If pattern is given it need to be absolute'''
|
|
if pattern is None:
|
|
pattern = Path(directory, self.glob_pattern).as_posix()
|
|
|
|
for entry in os.scandir(directory):
|
|
entry_path = Path(entry.path)
|
|
if entry.is_file() and fnmatch(entry_path.as_posix(), pattern):
|
|
yield entry_path
|
|
elif entry.is_dir():
|
|
yield from self.glob(entry.path, pattern)
|
|
|
|
def find(self, data, **kargs):
|
|
pattern = self.format(data, **kargs)
|
|
|
|
pattern_str = str(pattern)
|
|
if '*' not in pattern_str and '?' not in pattern_str:
|
|
return pattern
|
|
|
|
paths = glob(pattern.as_posix())
|
|
if paths:
|
|
return Path(paths[0])
|
|
|
|
return pattern
|
|
|
|
def __repr__(self):
|
|
return f'Template({self.raw})' |