forgt what i was doing
This commit is contained in:
parent
9af03eea9b
commit
cdff1c7565
5 changed files with 119 additions and 112 deletions
|
|
@ -1,90 +1,80 @@
|
|||
==================
|
||||
|
||||
Configuration File
|
||||
==================
|
||||
-----------
|
||||
config.yaml
|
||||
-----------
|
||||
Something
|
||||
|
||||
ytdl-sub is configured using a ``config.yaml`` file.
|
||||
dl_aliases
|
||||
----------
|
||||
.. _dl_aliases:
|
||||
|
||||
The ``config.yaml`` is made up of two sections:
|
||||
Alias definitions to shorten ``ytdl-sub dl`` arguments. For example,
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
configuration:
|
||||
presets:
|
||||
configuration:
|
||||
dl_aliases:
|
||||
mv: "--preset music_video"
|
||||
u: "--download.url"
|
||||
|
||||
You can jump to any section and subsection of the config using the navigation
|
||||
section to the left.
|
||||
Simplifies
|
||||
|
||||
Note for Windows users, paths can be represented with ``C:/forward/slashes/like/linux``.
|
||||
If you wish to represent paths like Windows, you will need to ``C:\\double\\bashslash\\paths``
|
||||
in order to escape the backslash character.
|
||||
.. code-block:: bash
|
||||
|
||||
configuration
|
||||
~~~~~~~~~~~~~
|
||||
The ``configuration`` section contains app-wide configs applied to all presets
|
||||
and subscriptions.
|
||||
ytdl-sub dl --preset "Jellyfin Music Videos" --download.url "youtube.com/watch?v=a1b2c3"
|
||||
|
||||
.. autoclass:: ytdl_sub.config.config_validator.ConfigOptions()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
:exclude-members: subscription_value, persist_logs, experimental
|
||||
to
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
ytdl-sub dl --mv --u "youtube.com/watch?v=a1b2c3"
|
||||
|
||||
experimental
|
||||
------------
|
||||
TODO(jessebannon) fill out
|
||||
|
||||
``enable_update_with_info_json``
|
||||
|
||||
Enables modifying subscription files using info.json files using the argument
|
||||
``--update-with-info-json``. This feature is still being tested and has the ability to
|
||||
destroy files. Ensure you have a full backup before usage. You have been warned!
|
||||
|
||||
ffmpeg_path
|
||||
-----------
|
||||
Path to ffmpeg executable. Defaults to ``/usr/bin/ffmpeg`` for Linux, and
|
||||
``ffmpeg.exe`` for Windows (in the same directory as ytdl-sub).
|
||||
|
||||
ffprobe_path
|
||||
------------
|
||||
Path to ffprobe executable. Defaults to ``/usr/bin/ffprobe`` for Linux, and
|
||||
``ffprobe.exe`` for Windows (in the same directory as ytdl-sub).
|
||||
|
||||
file_name_max_bytes
|
||||
-------------------
|
||||
Max file name size in bytes. Most OS's typically default to 255 bytes.
|
||||
|
||||
lock_directory
|
||||
--------------
|
||||
The directory to temporarily store file locks, which prevents multiple instances
|
||||
of ``ytdl-sub`` from running. Note that file locks do not work on network-mounted
|
||||
directories. Ensure that this directory resides on the host machine. Defaults to ``/tmp``.
|
||||
|
||||
persist_logs
|
||||
""""""""""""
|
||||
Within ``configuration``, define whether logs from subscription downloads
|
||||
should be persisted.
|
||||
------------
|
||||
TODO(jessebannon) fill out
|
||||
|
||||
.. code-block:: yaml
|
||||
``keep_successful_logs``
|
||||
|
||||
configuration:
|
||||
persist_logs:
|
||||
logs_directory: "/path/to/log/directory"
|
||||
Optional. Whether to store logs when downloading is successful. Defaults to True.
|
||||
|
||||
Log files are stored as
|
||||
``YYYY-mm-dd-HHMMSS.subscription_name.(success|error).log``.
|
||||
``logs_directory``
|
||||
|
||||
.. autoclass:: ytdl_sub.config.config_validator.PersistLogsValidator()
|
||||
:members:
|
||||
:member-order: bysource
|
||||
Required. The directory to store the logs in.
|
||||
|
||||
presets
|
||||
~~~~~~~
|
||||
``presets`` define a `formula` for how to format downloaded media and metadata.
|
||||
umask
|
||||
-----
|
||||
Umask (octal format) to apply to every created file. Defaults to "022".
|
||||
|
||||
This section is work-in-progress!
|
||||
|
||||
preset
|
||||
""""""
|
||||
Presets support inheritance by defining a parent preset:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
presets:
|
||||
custom_preset:
|
||||
...
|
||||
parent_preset:
|
||||
...
|
||||
child_preset:
|
||||
preset: "parent_preset"
|
||||
|
||||
In the example above, ``child_preset`` inherits all fields defined in ``parent_preset``.
|
||||
It is advantageous to use parent presets where possible to reduce duplicate yaml
|
||||
definitions.
|
||||
|
||||
Presets also support inheritance from multiple presets:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
child_preset:
|
||||
preset:
|
||||
- "custom_preset"
|
||||
- "parent_preset"
|
||||
|
||||
In this example, ``child_preset`` will inherit all fields from ``custom_preset``
|
||||
and ``parent_preset`` in that order. The bottom-most preset has the highest
|
||||
priority.
|
||||
|
||||
If you are only inheriting from one preset, the syntax ``preset: "parent_preset"`` is
|
||||
valid YAML. Inheriting from multiple presets require use of a list.
|
||||
working_directory
|
||||
-----------------
|
||||
The directory to temporarily store downloaded files before moving them into their final
|
||||
directory. Defaults to .ytdl-sub-working-directory
|
||||
|
|
|
|||
|
|
@ -22,6 +22,10 @@ from ytdl_sub.validators.validators import StringValidator
|
|||
|
||||
|
||||
class ExperimentalValidator(StrictDictValidator):
|
||||
"""
|
||||
TODO(jessebannon) fill out
|
||||
"""
|
||||
|
||||
_optional_keys = {"enable_update_with_info_json"}
|
||||
_allow_extra_keys = True
|
||||
|
||||
|
|
@ -43,6 +47,10 @@ class ExperimentalValidator(StrictDictValidator):
|
|||
|
||||
|
||||
class PersistLogsValidator(StrictDictValidator):
|
||||
"""
|
||||
TODO(jessebannon) fill out
|
||||
"""
|
||||
|
||||
_required_keys = {"logs_directory"}
|
||||
_optional_keys = {"keep_logs_after", "keep_successful_logs"}
|
||||
|
||||
|
|
@ -98,6 +106,10 @@ class PersistLogsValidator(StrictDictValidator):
|
|||
|
||||
|
||||
class ConfigOptions(StrictDictValidator):
|
||||
"""
|
||||
Something
|
||||
"""
|
||||
|
||||
_optional_keys = {
|
||||
"working_directory",
|
||||
"umask",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
from typing import Type
|
||||
|
||||
from tools.docgen.configuration import ConfigurationDocGen
|
||||
from tools.docgen.docgen import DocGen
|
||||
from tools.docgen.entry_variables import EntryVariablesDocGen
|
||||
from tools.docgen.plugins import PluginsDocGen
|
||||
|
|
@ -28,3 +29,6 @@ class TestDocGen:
|
|||
|
||||
def test_plugins_generated(self):
|
||||
_test_doc_gen(PluginsDocGen)
|
||||
|
||||
def test_configuration_generated(self):
|
||||
_test_doc_gen(ConfigurationDocGen)
|
||||
|
|
|
|||
|
|
@ -1,26 +1,8 @@
|
|||
from pathlib import Path
|
||||
from typing import Any
|
||||
from typing import Dict
|
||||
from typing import Type
|
||||
|
||||
from tools.docgen.docgen import DocGen
|
||||
from tools.docgen.utils import cached_properties
|
||||
from tools.docgen.utils import camel_case_to_human
|
||||
from tools.docgen.utils import get_function_docs
|
||||
from tools.docgen.utils import line_section
|
||||
from tools.docgen.utils import section
|
||||
from tools.docgen.utils import generate_options_validator_docs
|
||||
from ytdl_sub.config.config_validator import ConfigOptions
|
||||
from ytdl_sub.entries.script.variable_definitions import VARIABLES
|
||||
from ytdl_sub.entries.script.variable_definitions import VariableDefinitions
|
||||
|
||||
|
||||
def _variable_class_to_name(obj: Type[Any]) -> str:
|
||||
assert "VariableDefinitions" in obj.__name__, f"{obj.__name__} doesnt have VariableDefinitions"
|
||||
return (
|
||||
camel_case_to_human(obj.__name__)
|
||||
.replace("Variable Definitions", "Variables")
|
||||
.replace("Ytdl Sub", "Ytdl-Sub")
|
||||
)
|
||||
|
||||
|
||||
class ConfigurationDocGen(DocGen):
|
||||
|
|
@ -28,23 +10,14 @@ class ConfigurationDocGen(DocGen):
|
|||
LOCATION = Path("docs/source/config_reference/config_yaml.rst")
|
||||
|
||||
@classmethod
|
||||
def generate(cls) -> str:
|
||||
docs = section("Configuration File", level=0)
|
||||
|
||||
parent_objs: Dict[str, Type[Any]] = {
|
||||
_variable_class_to_name(obj): obj for obj in ConfigOptions.__bases__
|
||||
}
|
||||
|
||||
for idx, name in enumerate(sorted(parent_objs.keys())):
|
||||
docs += line_section(section_idx=idx)
|
||||
docs += section(name, level=1)
|
||||
|
||||
for variable_function_name in cached_properties(parent_objs[name]):
|
||||
docs += get_function_docs(
|
||||
function_name=variable_function_name,
|
||||
obj=parent_objs[name],
|
||||
pre_docstring=f":type: ``{getattr(VARIABLES, variable_function_name).human_readable_type()}``\n",
|
||||
level=2,
|
||||
)
|
||||
def generate(cls):
|
||||
docs = generate_options_validator_docs(
|
||||
name="Configuration File",
|
||||
options=ConfigOptions,
|
||||
offset=0,
|
||||
skip_properties=False,
|
||||
recurse_property_options=True,
|
||||
property_sections=True
|
||||
)
|
||||
|
||||
return docs
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ from typing import Any
|
|||
from typing import Dict
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
from typing import Set
|
||||
from typing import Type
|
||||
|
||||
from ytdl_sub.config.validators.options import OptionsValidator
|
||||
from ytdl_sub.script.utils.type_checking import is_optional, get_optional_type
|
||||
from ytdl_sub.validators.validators import Validator
|
||||
|
||||
LEVEL_CHARS: Dict[int, str] = {0: "=", 1: "-", 2: "~", 3: "^"}
|
||||
|
||||
|
|
@ -25,6 +25,19 @@ def _should_filter_property(property_name: str) -> bool:
|
|||
"unresolvable",
|
||||
)
|
||||
|
||||
def _is_validator_property(options: Type[Validator], property_name: str) -> Optional[Type[Validator]]:
|
||||
property_return_type = inspect.getfullargspec(getattr(options, property_name).fget).annotations['return']
|
||||
if is_optional(property_return_type):
|
||||
property_return_type = get_optional_type(property_return_type)
|
||||
|
||||
try:
|
||||
if issubclass(property_return_type, Validator):
|
||||
return property_return_type
|
||||
except TypeError:
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def section(name: str, level: Optional[int]) -> str:
|
||||
if level is None:
|
||||
|
|
@ -85,7 +98,7 @@ def get_function_docs(
|
|||
|
||||
|
||||
def generate_options_validator_docs(
|
||||
name: str, options: Type[OptionsValidator], offset: int, skip_properties: bool
|
||||
name: str, options: Type[Validator], offset: int, skip_properties: bool, recurse_property_options: bool = False, property_sections: bool = False
|
||||
) -> str:
|
||||
docs = ""
|
||||
docs += section(name, level=offset + 0)
|
||||
|
|
@ -98,6 +111,21 @@ def generate_options_validator_docs(
|
|||
|
||||
property_names = [prop for prop in properties(options) if not _should_filter_property(prop)]
|
||||
for property_name in sorted(property_names):
|
||||
docs += get_function_docs(function_name=property_name, obj=options, level=None, display_function_name=f"``{property_name}``")
|
||||
maybe_validator_property = _is_validator_property(options, property_name) if recurse_property_options else None
|
||||
if maybe_validator_property:
|
||||
docs += generate_options_validator_docs(
|
||||
name=property_name,
|
||||
options=maybe_validator_property,
|
||||
offset=offset + 1,
|
||||
skip_properties=False,
|
||||
recurse_property_options=False
|
||||
)
|
||||
else:
|
||||
docs += get_function_docs(
|
||||
function_name=property_name,
|
||||
obj=options,
|
||||
level=(offset + 1) if property_sections else None,
|
||||
display_function_name=f"``{property_name}``" if not property_sections else None,
|
||||
)
|
||||
|
||||
return docs
|
||||
|
|
|
|||
Loading…
Reference in a new issue