fix Command, refactor Operator

This commit is contained in:
Johann Dreo 2025-08-09 10:47:10 +02:00
commit 5e93595624

View file

@ -27,17 +27,6 @@ class Flick:
def __repr__(self): def __repr__(self):
return f"Flick({self.date},{self.target},{self.ext})" return f"Flick({self.date},{self.target},{self.ext})"
def as_file(self):
# Assemble the flick properties as if it was a file.
# Current date with second precision (i.e. without micro-seconds).
tag = self.date.isoformat().split(".")[0]
name,ext = os.path.splitext(self.target)
if self.ext:
ext = self.ext
flickname = name + self.date_sep + tag + ext
return os.path.join(save_dir, flickname)
class Flicker: class Flicker:
"""Build a new timestamped file name.""" """Build a new timestamped file name."""
def __init__(self, target, delay=10): def __init__(self, target, delay=10):
@ -65,6 +54,7 @@ class Flicker:
class Operator: class Operator:
"""Interface example for an Operator (but can actually be any callable with the same signature).""" """Interface example for an Operator (but can actually be any callable with the same signature)."""
def __call__(self, target, flick, alt_ext = None): def __call__(self, target, flick, alt_ext = None):
raise NotImplemented raise NotImplemented
@ -77,14 +67,25 @@ class Save(Operator):
def __init__(self, save_dir, date_sep, date_template): def __init__(self, save_dir, date_sep, date_template):
self.date_template = date_template self.date_template = date_template
self.date_sep = date_sep
self.save_dir = save_dir self.save_dir = save_dir
self.date_sep = date_sep
# Make a glob search expression with the date template. # Make a glob search expression with the date template.
self.fields = {'Y':4,'m':2,'d':2,'H':2,'M':2,'S':2} self.fields = {'Y':4,'m':2,'d':2,'H':2,'M':2,'S':2}
self.glob_template = self.date_template self.glob_template = self.date_template
for k in self.fields: for k in self.fields:
self.glob_template = self.glob_template.replace("%"+k,'?'*self.fields[k]) self.glob_template = self.glob_template.replace("%"+k,'?'*self.fields[k])
def as_file(self, flick):
# Assemble the flick properties as if it was a file.
# Current date with second precision (i.e. without micro-seconds).
tag = flick.date.isoformat().split(".")[0]
name,ext = os.path.splitext(flick.target)
if flick.ext:
ext = flick.ext
flickname = name + self.date_sep + tag + ext
return os.path.join(self.save_dir, flickname)
def find_last_save(self, target): def find_last_save(self, target):
full = os.path.expanduser(target) full = os.path.expanduser(target)
head = os.path.basename(full) head = os.path.basename(full)
@ -110,7 +111,7 @@ class Save(Operator):
return None return None
def save(self, flick): def save(self, flick):
flickfile = flick.as_file() flickfile = self.as_file(flick)
logging.info("Copy %s as %s", target, flickfile) logging.info("Copy %s as %s", target, flickfile)
try: try:
shutil.copy(target, flickfile) shutil.copy(target, flickfile)
@ -139,7 +140,7 @@ class Save(Operator):
save(flick) save(flick)
class Command(Operator): class Command(Save):
"""Run a user-defined command. """Run a user-defined command.
Takes the target and the flick as argument. Takes the target and the flick as argument.
The command should be a python 3 format string. The command should be a python 3 format string.
@ -147,21 +148,23 @@ class Command(Operator):
You can omit one of the named arguments. You can omit one of the named arguments.
For example: 'touch {flick}'""" For example: 'touch {flick}'"""
def __init__(self, command, alt_ext = None): def __init__(self, command, save_dir = ".", date_sep = "_", date_template = '%Y-%m-%dT%H:%M:%S', alt_ext = None):
super(type(self),self).__init__(save_dir, date_sep, date_template)
self.cmd = command self.cmd = command
self.alt_ext = alt_ext self.alt_ext = alt_ext
def __repr__(self): def __repr__(self):
return "Command(\"{}\",\"{}\")".format(self.cmd,self.alt_ext) return f"Command(\"{self.cmd}\",{self.save_dir}, {self.date_sep},{self.date_template},{self.alt_ext})"
def __call__(self, target, flick): def __call__(self, target, flick):
# Change the extension, if asked. # Change the extension, if asked.
flickname,flickext = os.path.splitext(flick) flickname,flickext = os.path.splitext(flick.target)
if self.alt_ext: if self.alt_ext:
flick.ext = self.alt_ext flick.ext = self.alt_ext
cmd = self.cmd.format(target=target,flick=flick) cmd = self.cmd.format(target=flick.target,flick=self.as_file(flick))
logging.info("Run command: %s", cmd ) logging.info("Run command: %s", cmd)
try: try:
# We want the shell because we may call shell command or need environment variables. # We want the shell because we may call shell command or need environment variables.
proc = subprocess.run(cmd, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) proc = subprocess.run(cmd, shell=True, check=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@ -315,9 +318,8 @@ if __name__=="__main__":
logging.basicConfig(level=log_as[asked.verbose], format='%(asctime)s -- %(message)s', datefmt=asked.template) logging.basicConfig(level=log_as[asked.verbose], format='%(asctime)s -- %(message)s', datefmt=asked.template)
available = existing; available = existing;
available["save"][1] = Save(asked.directory, asked.separator, asked.template) available["save"][1] = Save(asked.directory, asked.separator, asked.template)
available["inkscape"][1] = Command("inkscape {target} --without-gui --export-png={flick} --export-area-page", "png") available["inkscape"][1] = Command("inkscape {target} --without-gui --export-png={flick} --export-area-page", asked.directory, asked.separator, asked.template, "png")
available["git"][1] = Command("git add {target} ; git commit -m 'Automatic flicksave commit: {flick}'") available["git"][1] = Command("git add {target} ; git commit -m 'Automatic flicksave commit: {flick}'")
available["log"][1] = Log() available["log"][1] = Log()