xconv: Make profile system more flexible

Can now select from multiple profiles per file and import from arbitrary modules
master
Taeyeon Mori 7 years ago
parent 010ea8b43f
commit 2b963e7b0f
  1. 5
      lib/python/xconv/profile.py
  2. 76
      lib/python/xconv/profileman.py

@ -25,7 +25,7 @@ xconv ffmpeg wrapper based on AdvancedAV
Decorators for defining xconv profiles Decorators for defining xconv profiles
""" """
from .profileman import index from .profileman import index, make_qname
from functools import wraps from functools import wraps
@ -39,6 +39,7 @@ __all__ = [
"singleaudio" "singleaudio"
] ]
# == Misc. helpers == # == Misc. helpers ==
def __update(f, name, update): def __update(f, name, update):
if hasattr(f, name): if hasattr(f, name):
@ -65,7 +66,7 @@ def profile(f):
ext=None, ext=None,
defines={}, defines={},
features={}) features={})
index[f.__name__] = f index[make_qname(f.__module__, f.__name__)] = f
return f return f

@ -32,33 +32,85 @@ from pathlib import Path
# == Profile Index == # == Profile Index ==
index = {} index = {}
profiles_package = __package__ + ".profiles"
def make_qname(module, name):
"""
Create a qualified name for a profile
"""
# The global profiles package is omitted from the front
if module.startswith("%s." % profiles_package):
module = module[len(profiles_package) + 1:]
# But arbitrary packages can be specified by prepending :
# This, among other things, allows to use profiles defined
# in .py files in the working dir.
else:
module = ":" + module
# If it's not deeply nested and the module name
# and profile name are the same, the latter
# can be omitted.
if module.strip(":") != name:
return "%s.%s" % (module, name)
else:
return module
# Examples:
# Profile xconv.profiles.opus/opus:
# - opus
# - opus.opus
# - :xconv.profiles.opus.opus
# Watch out for xconv.profiles/opus (not valid):
# - :xconv.profiles.opus
# Profile xconv.profiles.opus/stuff:
# - opus.stuff
# - :xconv.profiles.opus.stuff
# Profile test/test:
# - :test
# - :test.test
def load_profile(name): def load_profile(name):
"""
Find and load a XConv profile.
"""
# Check if it's already loaded
if name in index: if name in index:
return index[name] return index[name]
try: # See if it's a qualified name
import_module(".profiles.%s" % name, __package__) module = name.rsplit(".", 1)[0] if "." in name[1:] else name
except ImportError as e:
print(e)
pass
if name in index: # Check if it's in the global profiles package or not
return index[name] if module[0] == ":":
module = module[1:]
else:
module = "." + module
load_all_profiles() # Try to import the module
import_module(module, profiles_package)
if name in index: # Return the profile
try:
return index[name] return index[name]
except KeyError:
raise ImportError("Could not find XConv profile '%s'" % name) # Fully qualifying the global profiles package is technically valid.
if name.startswith(":%s." % profiles_package):
qname = make_qname(*name[1:].rsplit(".", 1))
if qname in index:
return index[qname]
raise ImportError("Module %s doesn't contain XConv profile %s" % (module, name))
def load_all_profiles(): def load_all_profiles():
"""
Load all profile definitions
"""
for location in profilepaths: for location in profilepaths:
for mod in (x for x in Path(location).iterdir() if x.is_file() and x.suffix == ".py"): for mod in (x for x in Path(location).iterdir() if x.is_file() and x.suffix == ".py"):
try: try:
import_module(".profiles.%s" % mod.stem, __package__) import_module(".%s" % mod.stem, profiles_package)
except ImportError: except ImportError:
pass pass

Loading…
Cancel
Save