diff --git a/prismedia/configuration.py b/prismedia/configuration.py new file mode 100644 index 0000000..b928e78 --- /dev/null +++ b/prismedia/configuration.py @@ -0,0 +1,58 @@ +from configparser import RawConfigParser +from os.path import splitext, basename, dirname, abspath + + +class Configuration: + """ + Configuration manager that read the configuration from multiples nfo files that are commons for all interfaces + The configuration will be read and overridden in the following order: + NFO.txt -> nfo.txt -> directory_name.txt -> video_file.txt -> video_name.txt + (value in the rightmost file override values in preceding files) + + Your interface may add to this list from either side. Refer to the plugin's description. + A plugin can also override completely this configuration by using other means. For example the cli plugins takes + command line arguments with more importance than any nfo file. + + Attributes: + CONFIG_FILE Filename for the base configuration file that should be used to set global behavior for + prismedia and its plugins + """ + CONFIG_FILE = "prismedia.config" # TODO: replace with "config.txt"? something else? + + def __init__(self): + self.root_path = dirname(abspath(__file__)) + self.config_parser = RawConfigParser() + self.configuration_file_list = [] + self.base_configuration_file = self.root_path + "/config/" + self.CONFIG_FILE + self.config_parser.read(self.base_configuration_file) + + def read_commons_nfo(self, video_path, video_name): + video_directory = dirname(video_path) + directory_name = basename(video_directory) + video_file = splitext(basename(video_path))[0] + + self.configuration_file_list.append(video_directory + "/" + "NFO.txt") + self.configuration_file_list.append(video_directory + "/" + "nfo.txt") + self.configuration_file_list.append(video_directory + "/" + directory_name + ".txt") + self.configuration_file_list.append(video_directory + "/" + video_file + ".txt") + if video_name and video_name != video_file: + self.configuration_file_list.append(video_directory + "/" + video_name + ".txt") + + self.config_parser.read(self.configuration_file_list) + + # Do not use this in actual production ready code. Prismedia should not write any file + # This can be used in local to see how a plugin's variable needs to be written in the global NFO + # I am afraid that trying to save a plugin info will also save the current config for the video + def _write_config(self): + """ + Write the content of the ConfigParser in a file. + """ + # Do not use `assert` since we want to do the opposite and optimize the other way around + if not __debug__: + raise AssertionError("The method `Configuration._write_config` should not be called in production") + + with open(self.base_configuration_file + "_generated", "w") as configFile: + self.config_parser.write(configFile) + + +configuration_instance = Configuration() diff --git a/prismedia/core.py b/prismedia/core.py index 272eac9..a968ba1 100644 --- a/prismedia/core.py +++ b/prismedia/core.py @@ -3,15 +3,16 @@ # NOTE: Since we use config file to set some defaults values, it is not possible to use the standard syntax with brackets, we use parenthesis instead. # If we were to use them we would override configuration file values with default values of cli. -# TODO: change `youtube-at` and `peertube-at` that are not easely expendable as options in my opinion +# TODO: change `youtube-at` and `peertube-at` that are not easily expendable as options in my opinion # TODO: remove `--url-only` and `--batch` """ prismedia - tool to upload videos to different platforms (historically Peertube and Youtube) Usage: - prismedia [options] --file= | [ [...]] + prismedia [cli] [options] --file= + prismedia [...] prismedia --heartbeat - prismedia -h | --help | -V | --version + prismedia --help | -h | --version | -V Options: -f, --file=STRING Path to the video file to upload in mp4. This is the only mandatory option except if you provide the name of a plugin interface (see ). @@ -104,70 +105,87 @@ Languages: Korean, Mandarin, Portuguese, Punjabi, Russian, Spanish """ -import cli +import os +import logging import pluginInterfaces as pi + +import configuration import utils import video as vid from docopt import docopt from yapsy.PluginManager import PluginManagerSingleton -import os -import logging # logging.basicConfig(level=logging.DEBUG) VERSION = "prismedia v1.0.0-plugins-alpha" -def loadPlugins(basePluginsPath): +def loadPlugins(): + from yapsy.ConfigurablePluginManager import ConfigurablePluginManager + + config = configuration.configuration_instance + basePluginsPath = [config.root_path + "/plugins"] + + # TODO: check if AutoInstallPluginManager can help install new plugins or if it is already easy enough to download + # and unzip a file. + PluginManagerSingleton.setBehaviour([ConfigurablePluginManager]) pluginManager = PluginManagerSingleton.get() - pluginManager.setPluginPlaces(basePluginsPath) + pluginManager.setPluginPlaces(directories_list=basePluginsPath) + pluginManager.setPluginInfoExtension("prismedia-plugin") + pluginManager.setConfigParser(config.config_parser, pluginManager.config_has_changed) # Define the various categories corresponding to the different # kinds of plugins you have defined pluginManager.setCategoriesFilter({ - pi.PluginTypes.ALL : pi.IPrismediaBasePlugin, - pi.PluginTypes.INTERFACE : pi.IInterfacePlugin, - pi.PluginTypes.PLATFORM : pi.IPlatformPlugin, - pi.PluginTypes.CONSUMER : pi.IConsumerPlugin, + pi.PluginTypes.ALL: pi.IPrismediaBasePlugin, + pi.PluginTypes.INTERFACE: pi.IInterfacePlugin, + pi.PluginTypes.PLATFORM: pi.IPlatformPlugin, + pi.PluginTypes.CONSUMER: pi.IConsumerPlugin, }) pluginManager.collectPlugins() + return pluginManager # TODO: cut this function into smaller ones def main(): logger = logging.getLogger('Prismedia') - basePluginsPath = [os.path.dirname(os.path.abspath(__file__)) + "/plugins"] - loadPlugins(basePluginsPath) - pluginManager = PluginManagerSingleton.get() + # TODO: Check: Maybe this does not work good when installed via pip. + pluginManager = loadPlugins() # TODO: add the arguments’s verification (copy/adapt the Schema table) options = docopt(__doc__, version=VERSION) # Helper functionalities help the user but do not upload anything - if not cli.helperFunctionality(options): + if not utils.helperFunctionalities(options): exit(os.EX_OK) - video = cli.parseOptions(options) + # Get all arguments needed by core only before calling any plugin + listPlatforms = utils.getOption(options, "--platform") + listConsumers = utils.getOption(options, "--consumer") + if options[""]: - interface = pluginManager.getPluginByName(options[""], pi.PluginTypes.INTERFACE) - try: - if not interface.plugin_object.prepare_options(video, options): - # The plugin asked to stop execution. - exit(os.EX_OK) - except Exception as e: - logger.critical(utils.get_exception_string(e)) - exit(os.EX_CONFIG) + interface_name = utils.getOption("") + else: + interface_name = "cli" + interface = pluginManager.getPluginByName(interface_name, pi.PluginTypes.INTERFACE) + + video = vid.Video() + try: + if not interface.plugin_object.prepare_options(video, options): + # The plugin asked to stop execution. + exit(os.EX_OK) + except Exception as e: + logger.critical(utils.get_exception_string(e)) + exit(os.EX_CONFIG) - listPlatforms = utils.getOption(options, "--platform", []) if listPlatforms: platforms = pluginManager.getPluginsOf(categories=pi.PluginTypes.PLATFORM, name=[listPlatforms.split(",")]) else: platforms = pluginManager.getPluginsOfCategory(pi.PluginTypes.PLATFORM) - listConsumers = utils.getOption(options, "--consumer", None) if listConsumers: consumers = pluginManager.getPluginsOf(categories=pi.PluginTypes.CONSUMER, name=[listConsumers.split(",")]) else: @@ -190,7 +208,7 @@ def main(): print(plugin.name + " found a malformed option.") exit(os.EX_CONFIG) except Exception as e: - logger.critical(utils.get_exception_string(e)) + logger.critical("Error while preparing plugin `" + plugin.name + "`: " + utils.get_exception_string(e)) exit(os.EX_CONFIG) for plugin in consumers: diff --git a/prismedia/pluginInterfaces.py b/prismedia/pluginInterfaces.py index 51189b8..e3af47a 100644 --- a/prismedia/pluginInterfaces.py +++ b/prismedia/pluginInterfaces.py @@ -21,7 +21,7 @@ class IPrismediaBasePlugin(IPlugin): - `video`: video object to be uploaded - `options`: a dictionary of options to be used by Prismedia and other plugins """ - raise NotImplementedError("`getOptions` must be reimplemented by %s" % self) + raise NotImplementedError("`prepare_options` must be reimplemented by %s" % self) ### @@ -69,4 +69,4 @@ class IConsumerPlugin(IPrismediaBasePlugin): What to do once the uploads are done. - `video` is an object containing the video details. The `platforms` key contain a list of the platforms the video has been uploaded to and the status """ - raise NotImplementedError("`getOptions` must be reimplemented by %s" % self) + raise NotImplementedError("`finished` must be reimplemented by %s" % self) diff --git a/prismedia/plugins/interfaces/cli.py b/prismedia/plugins/interfaces/cli.py index 05339fe..979729a 100644 --- a/prismedia/plugins/interfaces/cli.py +++ b/prismedia/plugins/interfaces/cli.py @@ -1,39 +1,68 @@ import pluginInterfaces as pi import utils -import video as vid +import configuration class Cli(pi.IInterfacePlugin): """ This is the default interface plugin. It is used when no interface plugin is specified. + + Its core functionality is available as a function call to `prepare_options(video, options)` if you do not need the + Cli object. + This can be useful to let other plugins to rely on the defaults behaviors proposed by this one and extend it. """ def prepare_options(self, video, options): - video.path = utils.getOption(options, "--file", video.path) - video.thumbnail = utils.getOption(options, "--thumbnail", video.thumbnail) - video.name = utils.getOption(options, "--name", video.name) - video.description = utils.getOption(options, "--description", video.description) - video.playlistName = utils.getOption(options, "--playlist", video.playlistName) - video.privacy = utils.getOption(options, "--privacy", video.privacy).lower() - video.category = utils.getOption(options, "--category", video.category).lower() - tags = utils.getOption(options, "--tag", video.tags) - if isinstance(tags, str): - tags = tags.split(",") - video.tags = tags - video.language = utils.getOption(options, "--language", video.language).lower() - video.originalDate = utils.getOption(options, "--original-date", video.originalDate) - # TODO: set as an object: { "all": date1, "platformX": date2, …}? - # Maybe the publishAt by platform is better placed in `self.platform` - # And so publishAt would only contains the global date. - video.publishAt = utils.getOption(options, "--publish-at", video.publishAt) - # TODO: Add a list of licences - video.licence = utils.getOption(options, "--licence", video.licence) - video.disableComments = utils.getOption(options, "--disable-comments", video.disableComments) - video.nsfw = utils.getOption(options, "--nsfw", video.nsfw) - - autoOriginalDate = utils.getOption(options, "--auto-original-date", False) - if autoOriginalDate: - # TODO: Implement - raise NotImplementedError("--auto-original-date functionality is not yet implemented.") - - return video + prepare_options(video, options) + + +def prepare_options(video, options): + # TODO: Add the configuration file from the `--nfo` cli argument + + _store_docopt_to_configuration(video, options) + _populate_configuration_into_video(video) + + +def _store_docopt_to_configuration(options): + items = {} + for key, value in options: + if key.startswith("--"): + options.pop(key) + items[key.strip("- ")] = value + + configuration.configuration_instance.config_parser.read_dict(items) + + +def _populate_configuration_into_video(self, video): + config = configuration.configuration_instance + + video.path = utils.getOption(config, "file", video.path) + video.thumbnail = utils.getOption(config, "thumbnail", video.thumbnail) + video.name = utils.getOption(config, "name", video.name) + video.description = utils.getOption(config, "description", video.description) + video.playlistName = utils.getOption(config, "playlist", video.playlistName) + video.privacy = utils.getOption(config, "privacy", video.privacy).lower() + video.category = utils.getOption(config, "category", video.category).lower() + tags = utils.getOption(config, "tag", video.tags) + if isinstance(tags, str): + tags = tags.split(",") + video.tags = tags + video.language = utils.getOption(config, "language", video.language).lower() + video.originalDate = utils.getOption(config, "original-date", video.originalDate) + # TODO: set as an object: { "all": date1, "platformX": date2, … }? + # Maybe the publishAt by platform is better placed in `self.platform` + # And so publishAt would only contains the global date. + video.publishAt = utils.getOption(config, "publish-at", video.publishAt) + # TODO: Add a list of licences + video.licence = utils.getOption(config, "licence", video.licence) + video.disableComments = utils.getOption(config, "disable-comments", video.disableComments) + video.nsfw = utils.getOption(config, "nsfw", video.nsfw) + + autoOriginalDate = utils.getOption(config, "auto-original-date", False) + if autoOriginalDate: + # TODO: Implement + raise NotImplementedError("auto-original-date functionality is not yet implemented.") + + return video + + diff --git a/prismedia/plugins/interfaces/help.py b/prismedia/plugins/interfaces/help.py index c10d2c6..d6ef0bc 100644 --- a/prismedia/plugins/interfaces/help.py +++ b/prismedia/plugins/interfaces/help.py @@ -6,11 +6,12 @@ from yapsy.PluginManager import PluginManagerSingleton class Help(pi.IInterfacePlugin): """ The help plugin print the usage information of prismedia’s plugins. - Use it by simply calling `prismedia help `. + Use it by simply calling `prismedia help ...`. For example `prismedia help help` bring this help. """ def prepare_options(self, video, options): + print(__name__) pluginManager = PluginManagerSingleton.get() if options[""]: @@ -28,6 +29,7 @@ class Help(pi.IInterfacePlugin): print(plugin.name + "\t" + plugin.description) print("Usage:", plugin.plugin_object.__doc__) + # Generic help this plugin is able to give for the if p == "help": print("The plugins are stored in the following folders:", pluginManager.getPluginLocator().plugins_places) diff --git a/prismedia/plugins/platforms/peertube.py b/prismedia/plugins/platforms/peertube.py index fa56650..05a2913 100644 --- a/prismedia/plugins/platforms/peertube.py +++ b/prismedia/plugins/platforms/peertube.py @@ -3,16 +3,13 @@ import pluginInterfaces as pi import utils -import video as vid -import os import mimetypes import json import logging -import sys import datetime import pytz -from os.path import splitext, basename, abspath # TODO: remove me, we already import `os` or at least choose one +from os.path import splitext, basename, abspath from tzlocal import get_localzone from configparser import RawConfigParser @@ -20,6 +17,7 @@ from requests_oauthlib import OAuth2Session from requests_toolbelt import MultipartEncoder, MultipartEncoderMonitor from oauthlib.oauth2 import LegacyApplicationClient from clint.textui.progress import Bar as ProgressBar +from yapsy.PluginManager import PluginManagerSingleton logger = logging.getLogger('Prismedia') @@ -30,7 +28,8 @@ class Peertube(pi.IPlatformPlugin): The connections files should be set as # TODO: EXPLAIN HOW TO SETUP THE SECRET FILES - `publish-at-peertube=DATE`: overrides the default `publish-at=DATE` for this platform. # TODO: Maybe we will use a [] section on the config fire, explain that. """ - SECRETS_FILE = 'peertube_secret' + NAME = "peertube" # TODO: find if it is possible to get the plugin’s name from inside the plugin + SECRETS_FILE = "peertube_secret" PRIVACY = { "public": 1, "unlisted": 2, @@ -75,14 +74,17 @@ class Peertube(pi.IPlatformPlugin): def __init__(self): self.channelCreate = False - self.name = "peertube" # TODO: find if it is possible to get the plugin’s name from inside the plugin self.oauth = {} self.secret = {} def prepare_options(self, video, options): + pluginManager = PluginManagerSingleton.get() # TODO: get the `publish-at-peertube=DATE` option # TODO: get the `channel` and `channel-create` options - video.platform[self.name].channel = "" + pluginManager.registerOptionFromPlugin("Platform", self.NAME, "publish-at", "2034-05-07T19:00:00") + pluginManager.registerOptionFromPlugin("Platform", self.NAME, "channel", "toto") + pluginManager.registerOptionFromPlugin("Platform", self.NAME, "channel-create", False) + video.platform[self.NAME].channel = "" self.secret = RawConfigParser() self.secret.read(self.SECRETS_FILE) @@ -117,17 +119,17 @@ class Peertube(pi.IPlatformPlugin): def get_channel_by_name(self, user_info, video): for channel in user_info["videoChannels"]: - if channel['displayName'] == video.platform[self.name].channel: + if channel['displayName'] == video.platform[self.NAME].channel: return channel['id'] def create_channel(self, instance_url, video): template = ('Peertube: Channel %s does not exist, creating it.') - logger.info(template % (video.platform[self.name].channel)) - channel_name = utils.cleanString(video.platform[self.name].channel) + logger.info(template % (video.platform[self.NAME].channel)) + channel_name = utils.cleanString(video.platform[self.NAME].channel) # Peertube allows 20 chars max for channel name channel_name = channel_name[:19] data = '{"name":"' + channel_name + '", \ - "displayName":"' + video.platform[self.name].channel + '", \ + "displayName":"' + video.platform[self.NAME].channel + '", \ "description":null, \ "support":null}' @@ -280,8 +282,8 @@ class Peertube(pi.IPlatformPlugin): fields.append(("tags[]", strtag)) # If peertubeAt exists, use instead of publishAt - if video.platform[self.name].publishAt: - publishAt = video.platform[self.name].publishAt + if video.platform[self.NAME].publishAt: + publishAt = video.platform[self.NAME].publishAt elif video.publishAt: publishAt = video.publishAt @@ -301,13 +303,13 @@ class Peertube(pi.IPlatformPlugin): fields.append(("thumbnailfile", get_file(video.thumbnail))) fields.append(("previewfile", get_file(video.thumbnail))) - if hasattr(video.platform[self.name], "channel"): # TODO: Should always be present + if hasattr(video.platform[self.NAME], "channel"): # TODO: Should always be present channel_id = self.get_channel_by_name(user_info, video) if not channel_id and self.channelCreate: channel_id = self.create_channel(instance_url, video) elif not channel_id: logger.warning("Peertube: Channel `" + video.platform[ - self.name].channel + "` is unknown, using default channel.") # TODO: debate if we should have the same message and behavior than playlist: "does not exist, please set --channelCreate" + self.NAME].channel + "` is unknown, using default channel.") # TODO: debate if we should have the same message and behavior than playlist: "does not exist, please set --channelCreate" channel_id = self.get_default_channel(user_info) else: channel_id = self.get_default_channel(user_info) @@ -347,8 +349,8 @@ class Peertube(pi.IPlatformPlugin): logger.info("Peertube: Video was successfully uploaded.") template_url = "%s/videos/watch/%s" - video.platform[self.name].url = template_url % (instance_url, uuid) - logger.info("Peertube: Watch it at " + video.platform[self.name].url + ".") + video.platform[self.NAME].url = template_url % (instance_url, uuid) + logger.info("Peertube: Watch it at " + video.platform[self.NAME].url + ".") # Upload is successful we may set playlist if 'playlist_id' in locals(): set_playlist(instance_url, video_id, playlist_id) diff --git a/prismedia/utils.py b/prismedia/utils.py index 25970ef..c060310 100644 --- a/prismedia/utils.py +++ b/prismedia/utils.py @@ -2,7 +2,9 @@ # coding: utf-8 from configparser import RawConfigParser, NoOptionError, NoSectionError -from os.path import dirname, splitext, basename, isfile, getmtime +from os.path import dirname, splitext, basename, isfile, getmtime, exists +from yapsy.PluginManager import PluginManagerSingleton +import pluginInterfaces as pi import re import unidecode import logging @@ -24,12 +26,28 @@ VALID_LANGUAGES = ("arabic", "english", "french", "portuguese", "punjabi", "russian", "spanish") VALID_PROGRESS = ("percentage", "bigfile", "accurate") + +def helperFunctionalities(options): + pluginManager = PluginManagerSingleton.get() + + optionName = "--heartbeat" + if options.get(optionName): + for plugin in pluginManager.getPluginsOfCategory(pi.PluginTypes.PLATFORM): + plugin.plugin_object.heartbeat() + return False + else: + options.pop(optionName) + + return True + + def get_exception_string(e): if hasattr(e, "message"): return str(e.message) else: return str(e) + def validateVideo(path): supported_types = ["video/mp4"] detected_type = magic.from_file(path, mime=True) @@ -73,6 +91,7 @@ def validateLanguage(language): else: return False + def validateDate(date): return datetime.datetime.strptime(date, "%Y-%m-%dT%H:%M:%S") @@ -103,7 +122,7 @@ def validateOriginalDate(originalDate): def validateThumbnail(thumbnail): supported_types = ['image/jpg', 'image/jpeg'] - if os.path.exists(thumbnail) and \ + if exists(thumbnail) and \ magic.from_file(thumbnail, mime=True) in supported_types: return thumbnail else: @@ -148,81 +167,81 @@ def searchOriginalDate(options): return datetime.datetime.fromtimestamp(int(fileModificationDate[0])).isoformat() -# return the nfo as a RawConfigParser object -def loadNFO(filename): - try: - logger.info("Loading " + filename + " as NFO") - nfo = RawConfigParser() - nfo.read(filename, encoding='utf-8') - return nfo - except Exception as e: - logger.critical("Problem loading NFO file " + filename + ": " + str(e)) - exit(1) - return False - - -def parseNFO(options): - video_directory = dirname(options.get('--file')) - directory_name = basename(video_directory) - nfo_txt = False - nfo_directory = False - nfo_videoname = False - nfo_file = False - nfo_cli = False - - if isfile(video_directory + "/" + "nfo.txt"): - nfo_txt = loadNFO(video_directory + "/" + "nfo.txt") - elif isfile(video_directory + "/" + "NFO.txt"): - nfo_txt = loadNFO(video_directory + "/" + "NFO.txt") - - if isfile(video_directory + "/" + directory_name + ".txt"): - nfo_directory = loadNFO(video_directory + "/" + directory_name + ".txt") - - if options.get('--name'): - if isfile(video_directory + "/" + options.get('--name')): - nfo_videoname = loadNFO(video_directory + "/" + options.get('--name') + ".txt") - - video_file = splitext(basename(options.get('--file')))[0] - if isfile(video_directory + "/" + video_file + ".txt"): - nfo_file = loadNFO(video_directory + "/" + video_file + ".txt") - - if options.get('--nfo'): - if isfile(options.get('--nfo')): - nfo_cli = loadNFO(options.get('--nfo')) - else: - logger.critical("Given NFO file does not exist, please check your path.") - exit(1) - - # If there is no NFO and strict option is enabled, then stop there - if options.get('--withNFO'): - if not isinstance(nfo_cli, RawConfigParser) and \ - not isinstance(nfo_file, RawConfigParser) and \ - not isinstance(nfo_videoname, RawConfigParser) and \ - not isinstance(nfo_directory, RawConfigParser) and \ - not isinstance(nfo_txt, RawConfigParser): - logger.critical("You have required the strict presence of NFO but none is found, please use a NFO.") - exit(1) - - # We need to load NFO in this exact order to keep the priorities - # options in cli > nfo_cli > nfo_file > nfo_videoname > nfo_directory > nfo_txt - for nfo in [nfo_cli, nfo_file, nfo_videoname, nfo_directory, nfo_txt]: - if nfo: - # We need to check all options and replace it with the nfo value if not defined (None or False) - for key, value in options.items(): - key = key.replace("--", "") - try: - # get string options - if value is None and nfo.get('video', key): - options['--' + key] = nfo.get('video', key) - # get boolean options - elif value is False and nfo.getboolean('video', key): - options['--' + key] = nfo.getboolean('video', key) - except NoOptionError: - continue - except NoSectionError: - logger.critical(nfo + " misses section [video], please check syntax of your NFO.") - exit(1) - return options +# # return the nfo as a RawConfigParser object +# def loadNFO(filename): +# try: +# logger.info("Loading " + filename + " as NFO") +# nfo = RawConfigParser() +# nfo.read(filename, encoding='utf-8') +# return nfo +# except Exception as e: +# logger.critical("Problem loading NFO file " + filename + ": " + str(e)) +# exit(1) +# return False +# +# +# def parseNFO(options): +# video_directory = dirname(options.get('--file')) +# directory_name = basename(video_directory) +# nfo_txt = False +# nfo_directory = False +# nfo_videoname = False +# nfo_file = False +# nfo_cli = False +# +# if isfile(video_directory + "/" + "nfo.txt"): +# nfo_txt = loadNFO(video_directory + "/" + "nfo.txt") +# elif isfile(video_directory + "/" + "NFO.txt"): +# nfo_txt = loadNFO(video_directory + "/" + "NFO.txt") +# +# if isfile(video_directory + "/" + directory_name + ".txt"): +# nfo_directory = loadNFO(video_directory + "/" + directory_name + ".txt") +# +# if options.get('--name'): +# if isfile(video_directory + "/" + options.get('--name')): +# nfo_videoname = loadNFO(video_directory + "/" + options.get('--name') + ".txt") +# +# video_file = splitext(basename(options.get('--file')))[0] +# if isfile(video_directory + "/" + video_file + ".txt"): +# nfo_file = loadNFO(video_directory + "/" + video_file + ".txt") +# +# if options.get('--nfo'): +# if isfile(options.get('--nfo')): +# nfo_cli = loadNFO(options.get('--nfo')) +# else: +# logger.critical("Given NFO file does not exist, please check your path.") +# exit(1) +# +# # If there is no NFO and strict option is enabled, then stop there +# if options.get('--withNFO'): +# if not isinstance(nfo_cli, RawConfigParser) and \ +# not isinstance(nfo_file, RawConfigParser) and \ +# not isinstance(nfo_videoname, RawConfigParser) and \ +# not isinstance(nfo_directory, RawConfigParser) and \ +# not isinstance(nfo_txt, RawConfigParser): +# logger.critical("You have required the strict presence of NFO but none is found, please use a NFO.") +# exit(1) +# +# # We need to load NFO in this exact order to keep the priorities +# # options in cli > nfo_cli > nfo_file > nfo_videoname > nfo_directory > nfo_txt +# for nfo in [nfo_cli, nfo_file, nfo_videoname, nfo_directory, nfo_txt]: +# if nfo: +# # We need to check all options and replace it with the nfo value if not defined (None or False) +# for key, value in options.items(): +# key = key.replace("--", "") +# try: +# # get string options +# if value is None and nfo.get('video', key): +# options['--' + key] = nfo.get('video', key) +# # get boolean options +# elif value is False and nfo.getboolean('video', key): +# options['--' + key] = nfo.getboolean('video', key) +# except NoOptionError: +# continue +# except NoSectionError: +# logger.critical(nfo + " misses section [video], please check syntax of your NFO.") +# exit(1) +# return options def cleanString(toclean): @@ -231,7 +250,8 @@ def cleanString(toclean): return cleaned -def getOption(options, optionName, defaultValue = None): + +def getOption(options, optionName, defaultValue=None): value = options.get(optionName) options.pop(optionName)