Read values out of a config file instead of hardcoding them. Further streamline common tasks in a new base config class.
This commit is contained in:
parent
606f27185c
commit
057ac98843
11 changed files with 83 additions and 69 deletions
|
@ -2,17 +2,9 @@ import io
|
||||||
import pathlib
|
import pathlib
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import tomlkit
|
||||||
|
|
||||||
DOOM=pathlib.Path.home().joinpath("doom")
|
from cliff.command import Command
|
||||||
DSDA_DIR=DOOM.joinpath("dsda-doom")
|
|
||||||
DSDA_VER='0.28.3'
|
|
||||||
DSDA=DSDA_DIR.joinpath('dsda-doom-{}-Linux.appimage'.format(DSDA_VER))
|
|
||||||
IWADS=DOOM.joinpath("iwads")
|
|
||||||
PWADS=DOOM.joinpath("pwads")
|
|
||||||
DEMOS=DOOM.joinpath("demos")
|
|
||||||
OUTPUT=DOOM.joinpath("fabricate")
|
|
||||||
|
|
||||||
DEFAULT_IWAD=IWADS.joinpath("DOOM2.WAD")
|
|
||||||
|
|
||||||
THUMB_WIDTH=1280
|
THUMB_WIDTH=1280
|
||||||
THUMB_HEIGHT=720
|
THUMB_HEIGHT=720
|
||||||
|
@ -22,21 +14,47 @@ TEXT_STROKE_COLOR="srgb(176,0,0)"
|
||||||
|
|
||||||
MIRROR="https://youfailit.net/pub/idgames" # NYC
|
MIRROR="https://youfailit.net/pub/idgames" # NYC
|
||||||
|
|
||||||
def Complevel(wad):
|
|
||||||
complevel = PwadPath(wad).joinpath("complevel")
|
|
||||||
if not complevel.exists():
|
|
||||||
raise Exception("No complevel set in PWAD dir {}.".format(pwadpath))
|
|
||||||
|
|
||||||
with io.open(complevel) as f:
|
class Base(Command):
|
||||||
return f.read().strip()
|
def get_parser(self, prog_name):
|
||||||
|
parser = super().get_parser(prog_name)
|
||||||
|
parser.add_argument('--doom', default=pathlib.Path.home().joinpath("doom"))
|
||||||
|
parser.add_argument('--config-name', default='config.toml')
|
||||||
|
return parser
|
||||||
|
|
||||||
def IwadPath(wad):
|
def run(self, parsed_args):
|
||||||
iwad = DEFAULT_IWAD
|
self._doom = pathlib.Path(parsed_args.doom)
|
||||||
iwadpath = PwadPath(wad).joinpath("iwad")
|
self._config_name = parsed_args.config_name
|
||||||
if iwadpath.exists():
|
self._config = tomlkit.toml_file.TOMLFile(self.doom.joinpath(self.config_name)).read()
|
||||||
with io.open(iwadpath) as f:
|
self._dsda = self._config.get("dsda")
|
||||||
iwad = IWADS.joinpath(f.read().strip() + ".WAD")
|
if self.dsda is None:
|
||||||
return iwad
|
raise Exception(f"required key 'dsda' not set in config {self.doom.joinpath(self.config_name)}.")
|
||||||
|
for d in ("iwads", "pwads", "demos", "fabricate"):
|
||||||
|
self._init_path(d)
|
||||||
|
|
||||||
|
self.take_action(parsed_args)
|
||||||
|
|
||||||
|
def _init_path(self, what):
|
||||||
|
setattr(self, f"_{what}", self.doom.joinpath(self._config.get(what, what)))
|
||||||
|
setattr(type(self), what, property(lambda self: getattr(self, f"_{what}")))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def doom(self):
|
||||||
|
return self._doom
|
||||||
|
|
||||||
|
@property
|
||||||
|
def config_name(self):
|
||||||
|
return self._config_name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dsda(self):
|
||||||
|
return self._doom.joinpath(self._dsda)
|
||||||
|
|
||||||
|
def iwad_path(self, wad):
|
||||||
|
iwad = self.iwads.joinpath(self._config.get("default_iwad"))
|
||||||
|
iwadpath = self.pwads.joinpath("iwad")
|
||||||
|
if iwadpath.exists():
|
||||||
|
with io.open(iwadpath) as f:
|
||||||
|
iwad = self.iwads.joinpath(f.read().strip() + ".WAD")
|
||||||
|
return iwad
|
||||||
|
|
||||||
def PwadPath(wad):
|
|
||||||
return PWADS.joinpath(wad)
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ from abc import abstractmethod
|
||||||
from cliff.command import Command
|
from cliff.command import Command
|
||||||
import dcc.config
|
import dcc.config
|
||||||
import io
|
import io
|
||||||
|
import os
|
||||||
|
|
||||||
class WadMap(dcc.config.Base):
|
class WadMap(dcc.config.Base):
|
||||||
def get_parser(self, prog_name):
|
def get_parser(self, prog_name):
|
||||||
|
@ -15,11 +16,7 @@ class WadMap(dcc.config.Base):
|
||||||
self._wad = parsed_args.wad
|
self._wad = parsed_args.wad
|
||||||
self._map = parsed_args.map
|
self._map = parsed_args.map
|
||||||
self._name = parsed_args.name
|
self._name = parsed_args.name
|
||||||
self.take_action(parsed_args)
|
super().run(parsed_args)
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def take_action(self, parsed_args):
|
|
||||||
pass
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def wad(self):
|
def wad(self):
|
||||||
|
@ -34,9 +31,9 @@ class WadMap(dcc.config.Base):
|
||||||
return "" if self._name is None else "_" + self._name
|
return "" if self._name is None else "_" + self._name
|
||||||
|
|
||||||
def dsda_preamble(self):
|
def dsda_preamble(self):
|
||||||
args = ["-iwad", dcc.config.IwadPath(self.wad)]
|
args = ["-iwad", self.iwad_path(self.wad)]
|
||||||
|
|
||||||
pwadpath = dcc.config.PWADS.joinpath(self.wad)
|
pwadpath = self.pwads.joinpath(self.wad)
|
||||||
wads = sorted(pwadpath.glob('*.wad', case_sensitive=False))
|
wads = sorted(pwadpath.glob('*.wad', case_sensitive=False))
|
||||||
if len(wads) > 0:
|
if len(wads) > 0:
|
||||||
args = args + ["-file"] + wads
|
args = args + ["-file"] + wads
|
||||||
|
@ -45,19 +42,21 @@ class WadMap(dcc.config.Base):
|
||||||
if len(dehs) > 0:
|
if len(dehs) > 0:
|
||||||
args = args + ["-deh"] + dehs
|
args = args + ["-deh"] + dehs
|
||||||
|
|
||||||
complevel = pwadpath.joinpath("complevel")
|
args = args + ["-complevel", self.complevel()]
|
||||||
if not complevel.exists():
|
|
||||||
raise Exception("No complevel set in PWAD dir {}.".format(pwadpath))
|
|
||||||
|
|
||||||
with io.open(complevel) as f:
|
|
||||||
args = args + ["-complevel", dcc.config.Complevel(self.wad)]
|
|
||||||
|
|
||||||
args = args + ["-skill", "4"]
|
args = args + ["-skill", "4"]
|
||||||
args = args + ["-warp", self.map]
|
args = args + ["-warp", self.map]
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
def complevel(self):
|
||||||
|
complevel = self.pwads.joinpath(self.wad).joinpath("complevel")
|
||||||
|
if not complevel.exists():
|
||||||
|
raise Exception("No complevel set in PWAD dir {}.".format(pwadpath))
|
||||||
|
|
||||||
|
with io.open(complevel) as f:
|
||||||
|
return f.read().strip()
|
||||||
|
|
||||||
def demo_in_path(self):
|
def demo_in_path(self):
|
||||||
candidates = [x for x in dcc.config.DEMOS.joinpath(self.wad).glob(self._file_base("*.lmp"))]
|
candidates = [x for x in self.demos.joinpath(self.wad).glob(self._file_base("*.lmp"))]
|
||||||
if len(candidates) == 0:
|
if len(candidates) == 0:
|
||||||
raise Exception("no suitable demo candidates for WAD {} MAP {} name {}.".format(self.wad, self.map, self.name_string))
|
raise Exception("no suitable demo candidates for WAD {} MAP {} name {}.".format(self.wad, self.map, self.name_string))
|
||||||
if len(candidates) == 1:
|
if len(candidates) == 1:
|
||||||
|
@ -65,28 +64,28 @@ class WadMap(dcc.config.Base):
|
||||||
return sorted(filter(lambda s : re.search("-", str(s)), candidates))[-1]
|
return sorted(filter(lambda s : re.search("-", str(s)), candidates))[-1]
|
||||||
|
|
||||||
def dsda_text_path(self):
|
def dsda_text_path(self):
|
||||||
return self._ensure(dcc.config.DEMOS.joinpath(self.wad)).joinpath(self._file_base(".txt"))
|
return self._ensure(self.demos.joinpath(self.wad)).joinpath(self._file_base(".txt"))
|
||||||
|
|
||||||
def video_path(self):
|
def video_path(self):
|
||||||
return self._ensure(dcc.config.OUTPUT.joinpath(self.wad)).joinpath(self._file_base(".mp4"))
|
return self._ensure(self.fabricate.joinpath(self.wad)).joinpath(self._file_base(".mp4"))
|
||||||
|
|
||||||
def demo_out_path(self):
|
def demo_out_path(self):
|
||||||
return self._ensure(dcc.config.DEMOS.joinpath(self.wad)).joinpath(self._file_base(".lmp"))
|
return self._ensure(self.demos.joinpath(self.wad)).joinpath(self._file_base(".lmp"))
|
||||||
|
|
||||||
def target_bucket(self):
|
def target_bucket(self):
|
||||||
return "doom/" + self._file_base(".lmp")
|
return "doom/" + self._file_base(".lmp")
|
||||||
|
|
||||||
def base_thumb_path(self):
|
def base_thumb_path(self):
|
||||||
return self._ensure(dcc.config.OUTPUT.joinpath(self.wad)).joinpath(_file_base("_base.png"))
|
return self._ensure(self.fabricate.joinpath(self.wad)).joinpath(self._file_base("_base.png"))
|
||||||
|
|
||||||
def m_doom_path(self):
|
def m_doom_path(self):
|
||||||
return self._ensure(OUTPUT.joinpath(self.wad)).joinpath("M_DOOM_scaled.png")
|
return self._ensure(self.fabricate.joinpath(self.wad)).joinpath("M_DOOM_scaled.png")
|
||||||
|
|
||||||
def text_thumb_path(self):
|
def text_thumb_path(self):
|
||||||
return self._ensure(dcc.config.OUTPUT.joinpath(self.wad)).joinpath(_file_base("_text.png"))
|
return self._ensure(self.fabricate.joinpath(self.wad)).joinpath(self._file_base("_text.png"))
|
||||||
|
|
||||||
def thumb_path(self):
|
def thumb_path(self):
|
||||||
return self._ensure(dcc.config.OUTPUT.joinpath(self.wad)).joinpath(_file_base("_thumb.png"))
|
return self._ensure(self.fabricate.joinpath(self.wad)).joinpath(self._file_base("_thumb.png"))
|
||||||
|
|
||||||
def _file_base(self, ext):
|
def _file_base(self, ext):
|
||||||
return "{}_map{}{}{}".format(self.wad, self.map, self.name_string, ext)
|
return "{}_map{}{}{}".format(self.wad, self.map, self.name_string, ext)
|
||||||
|
|
|
@ -17,7 +17,7 @@ class DSDA(dcc.doom_base.WadMap):
|
||||||
dip = self.demo_in_path()
|
dip = self.demo_in_path()
|
||||||
dtp = self.dsda_text_path()
|
dtp = self.dsda_text_path()
|
||||||
if not dtp.exists():
|
if not dtp.exists():
|
||||||
command = [dcc.config.DSDA]
|
command = [self.dsda]
|
||||||
if shutil.which("xvfb-run") is not None:
|
if shutil.which("xvfb-run") is not None:
|
||||||
command = ["xvfb-run"] + command
|
command = ["xvfb-run"] + command
|
||||||
# TODO: negative tics should seek from the end, but this doesn't seem to work.
|
# TODO: negative tics should seek from the end, but this doesn't seem to work.
|
||||||
|
@ -51,6 +51,6 @@ class DSDA(dcc.doom_base.WadMap):
|
||||||
|
|
||||||
# TODO: demo names other than uv-max.
|
# TODO: demo names other than uv-max.
|
||||||
fnf = fh1 + "-" + fh2 + ".zip"
|
fnf = fh1 + "-" + fh2 + ".zip"
|
||||||
with zipfile.ZipFile(dcc.config.DEMOS.joinpath(self.wad).joinpath(fnf), mode="w") as zf:
|
with zipfile.ZipFile(self.demos.joinpath(self.wad).joinpath(fnf), mode="w") as zf:
|
||||||
zf.write(dip, arcname=dip.name)
|
zf.write(dip, arcname=dip.name)
|
||||||
zf.write(dtp, arcname=dtp.name)
|
zf.write(dtp, arcname=dtp.name)
|
||||||
|
|
|
@ -4,12 +4,12 @@ import subprocess
|
||||||
|
|
||||||
class Eureka(dcc.doom_base.WadMap):
|
class Eureka(dcc.doom_base.WadMap):
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
iwad = dcc.config.IwadPath(parsed_args.wad)
|
iwad = self.iwad_path(parsed_args.wad)
|
||||||
pwadpath = dcc.config.PwadPath(parsed_args.wad)
|
pwadpath = self.pwads.joinpath(parsed_args.wad)
|
||||||
mw = list(pwadpath.glob('*{}*.wad'.format(parsed_args.wad), case_sensitive=False))
|
mw = list(pwadpath.glob('*{}*.wad'.format(parsed_args.wad), case_sensitive=False))
|
||||||
if len(mw) != 1:
|
if len(mw) != 1:
|
||||||
raise Exception("Unable to guess at main pwad for wad {}.".format(parsed_args.wad))
|
raise Exception("Unable to guess at main pwad for wad {}.".format(parsed_args.wad))
|
||||||
complevel = dcc.config.Complevel(parsed_args.wad)
|
complevel = self.complevel()
|
||||||
port = "vanilla"
|
port = "vanilla"
|
||||||
if complevel == "9":
|
if complevel == "9":
|
||||||
port = "boom"
|
port = "boom"
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
from cliff.command import Command
|
|
||||||
import dcc.config
|
import dcc.config
|
||||||
import omg
|
import omg
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import wand.color
|
import wand.color
|
||||||
import wand.image
|
import wand.image
|
||||||
|
|
||||||
class Extract(Command):
|
class Extract(dcc.config.base):
|
||||||
def get_parser(self, prog_name):
|
def get_parser(self, prog_name):
|
||||||
parser = super().get_parser(prog_name)
|
parser = super().get_parser(prog_name)
|
||||||
parser.add_argument('wad')
|
parser.add_argument('wad')
|
||||||
|
@ -13,7 +12,7 @@ class Extract(Command):
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
wads = sorted(dcc.config.PWADS.joinpath(parsed_args.wad).glob('*.wad', case_sensitive=False), reverse=True)
|
wads = sorted(self.pwads.joinpath(self.wad).glob('*.wad', case_sensitive=False), reverse=True)
|
||||||
|
|
||||||
for w in wads:
|
for w in wads:
|
||||||
try:
|
try:
|
||||||
|
@ -23,7 +22,7 @@ class Extract(Command):
|
||||||
# With no arguments, convert() changes a paletted image to an RGB one.
|
# With no arguments, convert() changes a paletted image to an RGB one.
|
||||||
with wand.image.Image.from_array(np.array(gl.to_Image().convert())) as img:
|
with wand.image.Image.from_array(np.array(gl.to_Image().convert())) as img:
|
||||||
img.transparent_color(wand.color.Color("#ff00ff"), 0.0)
|
img.transparent_color(wand.color.Color("#ff00ff"), 0.0)
|
||||||
img.save(filename=dcc.config.OUTPUT.joinpath(parsed_args.wad).joinpath(parsed_args.lump + ".png"))
|
img.save(filename=self.output.joinpath(parsed_args.wad).joinpath(parsed_args.lump + ".png"))
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Wad {} likely has no lump {} (exception {}).".format(w, parsed_args.lump, e))
|
print("Wad {} likely has no lump {} (exception {}).".format(w, parsed_args.lump, e))
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Fabricate(dcc.doom_base.WadMap):
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
with tempfile.TemporaryDirectory() as td:
|
with tempfile.TemporaryDirectory() as td:
|
||||||
with contextlib.chdir(td):
|
with contextlib.chdir(td):
|
||||||
command = [dcc.config.DSDA]
|
command = [self.dsda]
|
||||||
if not parsed_args.fg and shutil.which("xvfb-run") is not None:
|
if not parsed_args.fg and shutil.which("xvfb-run") is not None:
|
||||||
command = ["xvfb-run"] + command
|
command = ["xvfb-run"] + command
|
||||||
subprocess.run(command + self.dsda_preamble() +
|
subprocess.run(command + self.dsda_preamble() +
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
from cliff.command import Command
|
|
||||||
import dcc.config
|
import dcc.config
|
||||||
import io
|
import io
|
||||||
import json
|
import json
|
||||||
|
@ -6,7 +5,7 @@ import pathlib
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import zipfile
|
import zipfile
|
||||||
|
|
||||||
class Fetch(Command):
|
class Fetch(dcc.config.Base):
|
||||||
def get_parser(self, prog_name):
|
def get_parser(self, prog_name):
|
||||||
parser = super().get_parser(prog_name)
|
parser = super().get_parser(prog_name)
|
||||||
parser.add_argument("id_or_name")
|
parser.add_argument("id_or_name")
|
||||||
|
@ -24,7 +23,7 @@ class Fetch(Command):
|
||||||
|
|
||||||
with urllib.request.urlopen(rpath) as response:
|
with urllib.request.urlopen(rpath) as response:
|
||||||
z = zipfile.ZipFile(io.BytesIO(response.read()))
|
z = zipfile.ZipFile(io.BytesIO(response.read()))
|
||||||
z.extractall(path=dcc.config.PwadPath(wad))
|
z.extractall(path=self.pwads.joinpath(wad))
|
||||||
|
|
||||||
# TODO: explicit error handling. Let users choose when >1 result.
|
# TODO: explicit error handling. Let users choose when >1 result.
|
||||||
def search_idgames(self, wad):
|
def search_idgames(self, wad):
|
||||||
|
|
11
dcc/ls.py
11
dcc/ls.py
|
@ -1,8 +1,7 @@
|
||||||
import cliff.command
|
|
||||||
import dcc.config
|
import dcc.config
|
||||||
import os
|
import os
|
||||||
|
|
||||||
class List(cliff.command.Command):
|
class List(dcc.config.Base):
|
||||||
def get_parser(self, prog_name):
|
def get_parser(self, prog_name):
|
||||||
parser = super().get_parser(prog_name)
|
parser = super().get_parser(prog_name)
|
||||||
parser.add_argument("target")
|
parser.add_argument("target")
|
||||||
|
@ -12,13 +11,13 @@ class List(cliff.command.Command):
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
match parsed_args.target:
|
match parsed_args.target:
|
||||||
case "pwads":
|
case "pwads":
|
||||||
self.list(x.name for x in os.scandir(dcc.config.PWADS) if x.is_dir())
|
self.list(x.name for x in os.scandir(self.pwads) if x.is_dir())
|
||||||
case "iwads":
|
case "iwads":
|
||||||
self.list(x.name for x in os.scandir(dcc.config.IWADS) if x.is_file())
|
self.list(x.name for x in os.scandir(self.iwads) if x.is_file())
|
||||||
case "demos":
|
case "demos":
|
||||||
self.list(x.name for x in os.scandir(dcc.config.DEMOS.joinpath(parsed_args.wad)) if x.name.endswith(".lmp"))
|
self.list(x.name for x in os.scandir(self.demos.joinpath(parsed_args.wad)) if x.name.endswith(".lmp"))
|
||||||
case "videos":
|
case "videos":
|
||||||
self.list(x.name for x in os.scandir(dcc.config.OUTPUT.joinpath(parsed_args.wad)) if x.name.endswith(".mp4"))
|
self.list(x.name for x in os.scandir(self.output.joinpath(parsed_args.wad)) if x.name.endswith(".mp4"))
|
||||||
|
|
||||||
def list(self, gen):
|
def list(self, gen):
|
||||||
# TODO: fancy text?
|
# TODO: fancy text?
|
||||||
|
|
|
@ -4,4 +4,4 @@ import subprocess
|
||||||
|
|
||||||
class Play(dcc.doom_base.WadMap):
|
class Play(dcc.doom_base.WadMap):
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
subprocess.run([dcc.config.DSDA] + self.dsda_preamble())
|
subprocess.run([self.dsda] + self.dsda_preamble())
|
||||||
|
|
|
@ -4,5 +4,5 @@ import subprocess
|
||||||
|
|
||||||
class Record(dcc.doom_base.WadMap):
|
class Record(dcc.doom_base.WadMap):
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
subprocess.run([dcc.config.DSDA] + self.dsda_preamble() +
|
subprocess.run([self.dsda] + self.dsda_preamble() +
|
||||||
["-record", self.demo_out_path()])
|
["-record", self.demo_out_path()])
|
||||||
|
|
|
@ -23,7 +23,7 @@ class Thumb(dcc.doom_base.WadMap):
|
||||||
bi.composite(mdi, gravity="north_west")
|
bi.composite(mdi, gravity="north_west")
|
||||||
|
|
||||||
if parsed_args.index:
|
if parsed_args.index:
|
||||||
with wand.image.Image(filename=dcc.config.OUTPUT.joinpath("doomed_index.png")) as di:
|
with wand.image.Image(filename=self.output.joinpath("doomed_index.png")) as di:
|
||||||
di.border(tc, 1, 1)
|
di.border(tc, 1, 1)
|
||||||
bi.composite(di, gravity="north_east")
|
bi.composite(di, gravity="north_east")
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue