diff --git a/plugin_cmds/cmd_decrypt.py b/plugin_cmds/cmd_decrypt.py index dc428c64..f17132db 100644 --- a/plugin_cmds/cmd_decrypt.py +++ b/plugin_cmds/cmd_decrypt.py @@ -38,7 +38,7 @@ class SupportedFiles(Enum): @classmethod def get_supported_list(cls): - return list(set(item.value for item in cls)) + return list({item.value for item in cls}) @classmethod def is_supported_suffix(cls, value): @@ -66,9 +66,9 @@ def _get_input_files( raise click.BadParameter("{filename}: file not found or supported.") expanded_filter = filter( - lambda x: SupportedFiles.is_supported_file(x), expanded + SupportedFiles.is_supported_file, expanded ) - expanded = list(map(lambda x: pathlib.Path(x).resolve(), expanded_filter)) + expanded = [pathlib.Path(x).resolve() for x in expanded_filter] filenames.extend(expanded) return filenames @@ -135,7 +135,7 @@ def extract_chapters(initial, current): if "chapters" in current: return initial + [current] + current["chapters"] else: - return initial + [current] + return [*initial, current] chapters = list( reduce( @@ -630,7 +630,7 @@ def cli( FILES are the names of the file to decrypt. Wildcards `*` and recursive lookup with `**` are supported. - Only FILES with `aax` or `aaxc` suffix are processed. + Only FILES with `aax` or `aaxc` suffix are processed. Other files are skipped silently. """ if not which("ffmpeg"): diff --git a/plugin_cmds/cmd_goodreads-transform.py b/plugin_cmds/cmd_goodreads-transform.py index aaf9aaed..703506fa 100644 --- a/plugin_cmds/cmd_goodreads-transform.py +++ b/plugin_cmds/cmd_goodreads-transform.py @@ -30,7 +30,7 @@ @pass_session @pass_client async def cli(session, client, output): - """YOUR COMMAND DESCRIPTION""" + """YOUR COMMAND DESCRIPTION.""" logger.debug("fetching library") bunch_size = session.params.get("bunch_size") library = await Library.from_api_full_sync( diff --git a/plugin_cmds/cmd_image-urls.py b/plugin_cmds/cmd_image-urls.py index 099fa0a3..a8778921 100644 --- a/plugin_cmds/cmd_image-urls.py +++ b/plugin_cmds/cmd_image-urls.py @@ -8,7 +8,7 @@ @timeout_option() @pass_client() async def cli(client, asin): - """Print out the image urls for different resolutions for a book""" + """Print out the image urls for different resolutions for a book.""" r = await client.get( f"catalog/products/{asin}", response_groups="media", diff --git a/plugin_cmds/cmd_listening-stats.py b/plugin_cmds/cmd_listening-stats.py index fe4d0117..089d48a7 100644 --- a/plugin_cmds/cmd_listening-stats.py +++ b/plugin_cmds/cmd_listening-stats.py @@ -52,8 +52,8 @@ async def _get_stats_year(client, year): ) @pass_client async def cli(client, output, signup_year): - """Get and analyse listening statistics""" - year_range = [y for y in range(signup_year, current_year+1)] + """Get and analyse listening statistics.""" + year_range = list(range(signup_year, current_year+1)) r = await asyncio.gather( *[_get_stats_year(client, y) for y in year_range] diff --git a/plugin_cmds/convert_oa_cred.py b/plugin_cmds/convert_oa_cred.py index edda9121..eeb0511c 100644 --- a/plugin_cmds/convert_oa_cred.py +++ b/plugin_cmds/convert_oa_cred.py @@ -1,6 +1,6 @@ """Converts the credentials.json file from OpenAudible >= v2.4 beta to an -audible-cli auth file. The credentials.json file from OpenAudible leaves -unchanged, so you can use one device registration for OpenAudible and +audible-cli auth file. The credentials.json file from OpenAudible leaves +unchanged, so you can use one device registration for OpenAudible and audible-cli. """ @@ -41,7 +41,7 @@ def make_auth_file(fn, origin): device_info = extensions["device_info"] customer_info = extensions["customer_info"] - website_cookies = dict() + website_cookies = {} for cookie in tokens["website_cookies"]: website_cookies[cookie["Name"]] = cookie["Value"].replace(r'"', r"") @@ -70,8 +70,8 @@ def make_auth_file(fn, origin): help="OpenAudible credentials.json file") @pass_session def cli(session, input): - """Converts a OpenAudible credential file to a audible-cli auth file - + """Converts a OpenAudible credential file to a audible-cli auth file. + Stores the auth files in app dir """ fdata = pathlib.Path(input).read_text("utf-8") diff --git a/pyproject.toml b/pyproject.toml index c1ce49ec..8ebdff09 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -195,28 +195,22 @@ lines-after-imports = 2 # individual findings. Shrink the list by fixing a rule in a file and # dropping its code here. "docs/source/conf.py" = ["A001"] -"plugin_cmds/cmd_decrypt.py" = ["C401", "C417", "PLR0917", "PLW0108", "RUF005", "W291"] -"plugin_cmds/cmd_goodreads-transform.py" = ["D415", "G004"] -"plugin_cmds/cmd_image-urls.py" = ["D415"] -"plugin_cmds/cmd_listening-stats.py" = ["C416", "D415"] -"plugin_cmds/convert_oa_cred.py" = ["A002", "C408", "D205", "D415", "W291", "W293"] -"src/audible_cli/_logging.py" = ["B028", "C408", "D205", "G004"] -"src/audible_cli/cli.py" = ["C408", "D415"] +"plugin_cmds/cmd_decrypt.py" = ["PLR0917"] +"plugin_cmds/cmd_goodreads-transform.py" = ["G004"] +"plugin_cmds/convert_oa_cred.py" = ["A002", "D205"] +"src/audible_cli/_logging.py" = ["D205", "G004"] "src/audible_cli/cmds/__init__.py" = ["D205"] -"src/audible_cli/cmds/cmd_api.py" = ["D415", "G004", "W291"] -"src/audible_cli/cmds/cmd_download.py" = ["ASYNC240", "C901", "D415", "G004", "PLR0917", "PLW0603", "PLW2901", "S101"] -"src/audible_cli/cmds/cmd_library.py" = ["D415"] -"src/audible_cli/cmds/cmd_manage.py" = ["D415", "PLR0917"] -"src/audible_cli/cmds/cmd_quickstart.py" = ["D415", "W291"] -"src/audible_cli/cmds/cmd_wishlist.py" = ["D415", "G004"] -"src/audible_cli/config.py" = ["B904", "D415", "D417", "G004", "W291", "W293"] -"src/audible_cli/decorators.py" = ["B904", "D205", "D415", "RUF001", "W293"] +"src/audible_cli/cmds/cmd_api.py" = ["G004"] +"src/audible_cli/cmds/cmd_download.py" = ["ASYNC240", "C901", "G004", "PLR0917", "PLW0603", "PLW2901", "S101"] +"src/audible_cli/cmds/cmd_manage.py" = ["PLR0917"] +"src/audible_cli/cmds/cmd_wishlist.py" = ["G004"] +"src/audible_cli/config.py" = ["B904", "D417", "G004"] +"src/audible_cli/decorators.py" = ["B904", "D205", "RUF001"] "src/audible_cli/downloader.py" = ["G004", "PLR0917"] -"src/audible_cli/exceptions.py" = ["D415"] -"src/audible_cli/models.py" = ["B904", "D205", "D415", "G004", "S101", "W293"] -"src/audible_cli/plugins.py" = ["D200", "D205", "D415", "UP031"] +"src/audible_cli/models.py" = ["B904", "D205", "G004", "S101"] +"src/audible_cli/plugins.py" = ["D205"] "src/audible_cli/utils.py" = ["G004", "PGH004", "PLR0917"] -"utils/update_chapter_titles.py" = ["C408", "D205", "D415", "S101", "W293"] +"utils/update_chapter_titles.py" = ["D205", "S101"] [tool.pytest.ini_options] diff --git a/src/audible_cli/_logging.py b/src/audible_cli/_logging.py index 371292fb..96d2888a 100644 --- a/src/audible_cli/_logging.py +++ b/src/audible_cli/_logging.py @@ -33,7 +33,7 @@ def _set_level(obj, level: str | int | None) -> None: if 0 < obj.level < audible_cli_logger.level: warn( f"{obj.name} level is lower than " - f"{audible_cli_logger.name} logger level" + f"{audible_cli_logger.name} logger level", stacklevel=2 ) def _set_handler(self, handler, name, level): @@ -119,11 +119,11 @@ def _normalize_logger(logger): def _normalize_style_kwargs(styles): normalized_styles = { - "error": dict(fg="red"), - "exception": dict(fg="red"), - "critical": dict(fg="red"), - "debug": dict(fg="blue"), - "warning": dict(fg="yellow") + "error": {"fg": "red"}, + "exception": {"fg": "red"}, + "critical": {"fg": "red"}, + "debug": {"fg": "blue"}, + "warning": {"fg": "yellow"} } if styles: normalized_styles.update(styles) @@ -131,7 +131,7 @@ def _normalize_style_kwargs(styles): def _normalize_echo_kwargs(echo_kwargs): - normamized_echo_kwargs = dict() + normamized_echo_kwargs = {} if echo_kwargs: normamized_echo_kwargs.update(echo_kwargs) return normamized_echo_kwargs diff --git a/src/audible_cli/cli.py b/src/audible_cli/cli.py index 9f1535eb..97dbf6c3 100644 --- a/src/audible_cli/cli.py +++ b/src/audible_cli/cli.py @@ -22,7 +22,7 @@ logger = logging.getLogger("audible_cli") click_basic_config(logger) -CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"]) +CONTEXT_SETTINGS = {"help_option_names": ["-h", "--help"]} @plugins.from_folder(get_plugin_dir()) @@ -42,7 +42,7 @@ def cli(): @version_option @verbosity_option(cli_logger=logger) def quickstart(ctx): - """Entrypoint for the quickstart command""" + """Entrypoint for the quickstart command.""" try: sys.exit(ctx.forward(cmd_quickstart.cli)) except click.Abort: diff --git a/src/audible_cli/cmds/cmd_api.py b/src/audible_cli/cmds/cmd_api.py index cd0ff2c7..9e6ba8ea 100644 --- a/src/audible_cli/cmds/cmd_api.py +++ b/src/audible_cli/cmds/cmd_api.py @@ -61,10 +61,10 @@ ) @pass_session def cli(session, **options): - """Send requests to an Audible API endpoint + """Send requests to an Audible API endpoint. - Take a look at - https://audible.readthedocs.io/en/latest/misc/external_api.html for known + Take a look at + https://audible.readthedocs.io/en/latest/misc/external_api.html for known endpoints and parameters. """ auth = session.auth diff --git a/src/audible_cli/cmds/cmd_download.py b/src/audible_cli/cmds/cmd_download.py index 3f1ef159..73c6ddc2 100644 --- a/src/audible_cli/cmds/cmd_download.py +++ b/src/audible_cli/cmds/cmd_download.py @@ -836,7 +836,7 @@ def display_counter(): @pass_session @pass_client(headers=CLIENT_HEADERS) async def cli(session, api_client, **params): - """Download audiobook(s) from library""" + """Download audiobook(s) from library.""" client = api_client.session output_dir = pathlib.Path(params.get("output_dir")).resolve() diff --git a/src/audible_cli/cmds/cmd_library.py b/src/audible_cli/cmds/cmd_library.py index 18ba1685..4e5042bc 100644 --- a/src/audible_cli/cmds/cmd_library.py +++ b/src/audible_cli/cmds/cmd_library.py @@ -20,7 +20,7 @@ @click.group("library") def cli(): - """Interact with library""" + """Interact with library.""" async def _get_library(session, client, resolve_podcasts): @@ -77,7 +77,7 @@ async def _get_library(session, client, resolve_podcasts): @pass_session @pass_client async def export_library(session, client, **params): - """Export library""" + """Export library.""" @wrap_async def _prepare_item(item): @@ -165,7 +165,7 @@ def _prepare_item(item): @pass_session @pass_client async def list_library(session, client, resolve_podcasts): - """List titles in library""" + """List titles in library.""" @wrap_async def _prepare_item(item): diff --git a/src/audible_cli/cmds/cmd_manage.py b/src/audible_cli/cmds/cmd_manage.py index 70421403..63e70d97 100644 --- a/src/audible_cli/cmds/cmd_manage.py +++ b/src/audible_cli/cmds/cmd_manage.py @@ -17,35 +17,35 @@ @click.group("manage") def cli(): - """Manage audible-cli""" + """Manage audible-cli.""" @cli.group("config") def manage_config(): - """Manage config""" + """Manage config.""" @cli.group("profile") def manage_profiles(): - """Manage profiles""" + """Manage profiles.""" @cli.group("auth-file") def manage_auth_files(): - """Manage auth files""" + """Manage auth files.""" @manage_config.command("edit") @pass_session def config_editor(session): - """Open the config file with default editor""" + """Open the config file with default editor.""" click.edit(filename=os.fspath(session.config.filename)) @manage_profiles.command("list") @pass_session def list_profiles(session): - """List all profiles in the config file""" + """List all profiles in the config file.""" head = ["P", "Profile", "auth file", "cc"] config = session.config profiles = config.data.get("profile") @@ -91,7 +91,7 @@ def list_profiles(session): @pass_session @click.pass_context def add_profile(ctx, session, profile, country_code, auth_file, is_primary): - """Adds a profile to config file""" + """Adds a profile to config file.""" if not (session.config.dirname / auth_file).exists(): logger.error("Auth file doesn't exists") raise click.Abort() @@ -112,7 +112,7 @@ def add_profile(ctx, session, profile, country_code, auth_file, is_primary): ) @pass_session def remove_profile(session, profile): - """Remove one or multiple profile(s) from config file""" + """Remove one or multiple profile(s) from config file.""" profiles = session.config.data.get("profile") for p in profile: if p not in profiles: @@ -180,7 +180,7 @@ def add_auth_file( session, auth_file, password, audible_username, audible_password, country_code, external_login, with_username ): - """Register a new device and add an auth file to config dir""" + """Register a new device and add an auth file to config dir.""" build_auth_file( filename=session.config.dirname / auth_file, username=audible_username, @@ -214,7 +214,7 @@ def check_if_auth_file_exists(session, ctx, param, value): help="The optional password for the auth file." ) def remove_auth_file(auth_file, password): - """Deregister a device and remove auth file from config dir""" + """Deregister a device and remove auth file from config dir.""" auth = Authenticator.from_file(auth_file, password) device_name = auth.device_info["device_name"] auth.refresh_access_token() diff --git a/src/audible_cli/cmds/cmd_quickstart.py b/src/audible_cli/cmds/cmd_quickstart.py index ddb2bc34..06a35995 100644 --- a/src/audible_cli/cmds/cmd_quickstart.py +++ b/src/audible_cli/cmds/cmd_quickstart.py @@ -40,15 +40,15 @@ def ask_user(config: ConfigFile): secho(welcome_message, bold=True) secho(len(welcome_message) * "=", bold=True) - intro = """Quickstart will guide you through the process of build a basic + intro = """Quickstart will guide you through the process of build a basic config, create a first profile and assign an auth file to the profile now. -The profile created by quickstart will set as primary. It will be used, if no +The profile created by quickstart will set as primary. It will be used, if no other profile is chosen. -An auth file can be shared between multiple profiles. Simply enter the name of -an existing auth file when asked about it. Auth files have to be stored in the -config dir. If the auth file doesn't exists, it will be created. In this case, +An auth file can be shared between multiple profiles. Simply enter the name of +an existing auth file when asked about it. Auth files have to be stored in the +config dir. If the auth file doesn't exists, it will be created. In this case, an authentication to the audible server is necessary to register a new device. """ echo() @@ -139,7 +139,7 @@ def ask_user(config: ConfigFile): @click.command("quickstart") @pass_session def cli(session): - """Quick setup audible""" + """Quick setup audible.""" config_file: pathlib.Path = session.app_dir / CONFIG_FILE config = ConfigFile(config_file, file_exists=False) if config_file.is_file(): diff --git a/src/audible_cli/cmds/cmd_wishlist.py b/src/audible_cli/cmds/cmd_wishlist.py index babe177c..b89daa47 100644 --- a/src/audible_cli/cmds/cmd_wishlist.py +++ b/src/audible_cli/cmds/cmd_wishlist.py @@ -35,7 +35,7 @@ async def _get_wishlist(client): @click.group("wishlist") def cli(): - """Interact with wishlist""" + """Interact with wishlist.""" @cli.command("export") @@ -56,7 +56,7 @@ def cli(): ) @pass_client async def export_wishlist(client, **params): - """Export wishlist""" + """Export wishlist.""" @wrap_async def _prepare_item(item): @@ -134,7 +134,7 @@ def _prepare_item(item): @timeout_option @pass_client async def list_wishlist(client): - """List titles in wishlist""" + """List titles in wishlist.""" @wrap_async def _prepare_item(item): @@ -179,7 +179,7 @@ def _prepare_item(item): @timeout_option @pass_client(limits=limits) async def add_wishlist(client, asin, title): - """Add asin(s) to wishlist + """Add asin(s) to wishlist. Run the command without any option for interactive mode. """ @@ -262,7 +262,7 @@ async def add_asin(asin): @timeout_option @pass_client(limits=limits) async def remove_wishlist(client, asin, title): - """Remove asin(s) from wishlist + """Remove asin(s) from wishlist. Run the command without any option for interactive mode. """ diff --git a/src/audible_cli/config.py b/src/audible_cli/config.py index f25d7c33..8482bcfe 100644 --- a/src/audible_cli/config.py +++ b/src/audible_cli/config.py @@ -24,15 +24,15 @@ class ConfigFile: - """Presents an audible-cli configuration file + """Presents an audible-cli configuration file. - Instantiate a :class:`~audible_cli.config.ConfigFile` will load the file - content by default. To create a new config file, the ``file_exists`` + Instantiate a :class:`~audible_cli.config.ConfigFile` will load the file + content by default. To create a new config file, the ``file_exists`` argument must be set to ``False``. - Audible-cli configuration files are written in the toml markup language. - It has a main section named `APP` and sections for each profile named - `profile.`. + Audible-cli configuration files are written in the toml markup language. + It has a main section named `APP` and sections for each profile named + `profile.`. Args: filename: The file path to the config file @@ -68,26 +68,26 @@ def __init__( @property def filename(self) -> pathlib.Path: - """Returns the path to the config file""" + """Returns the path to the config file.""" return self._config_file @property def dirname(self) -> pathlib.Path: - """Returns the path to the config file directory""" + """Returns the path to the config file directory.""" return self.filename.parent @property def data(self) -> dict[str, str | dict]: - """Returns the configuration data""" + """Returns the configuration data.""" return self._config_data @property def app_config(self) -> dict[str, str]: - """Returns the configuration data for the APP section""" + """Returns the configuration data for the APP section.""" return self.data["APP"] def has_profile(self, name: str) -> bool: - """Check if a profile with this name are in the configuration data + """Check if a profile with this name are in the configuration data. Args: name: The name of the profile @@ -95,7 +95,7 @@ def has_profile(self, name: str) -> bool: return name in self.data["profile"] def get_profile(self, name: str) -> dict[str, str]: - """Returns the configuration data for these profile name + """Returns the configuration data for these profile name. Args: name: The name of the profile @@ -118,7 +118,7 @@ def get_profile_option( ) -> str: """Returns the value for an option for the given profile. - Looks first, if an option is in the ``profile`` section. If not, it + Looks first, if an option is in the ``profile`` section. If not, it searches for the option in the ``APP`` section. If not found, it returns the ``default``. @@ -143,14 +143,14 @@ def add_profile( write_config: bool = True, **additional_options ) -> None: - """Adds a new profile to the config + """Adds a new profile to the config. Args: name: The name of the profile auth_file: The name of the auth_file - country_code: The country code of the marketplace to use with + country_code: The country code of the marketplace to use with this profile - is_primary: If ``True``, this profile is set as primary in the + is_primary: If ``True``, this profile is set as primary in the ``APP`` section write_config: If ``True``, save the config to file """ @@ -173,7 +173,7 @@ def add_profile( self.write_config() def delete_profile(self, name: str, write_config: bool = True) -> None: - """Deletes a profile from config + """Deletes a profile from config. Args: name: The name of the profile @@ -196,10 +196,10 @@ def write_config( self, filename: str | pathlib.Path | None = None ) -> None: - """Write the config data to file + """Write the config data to file. Args: - filename: If not ``None`` the config is written to these file path + filename: If not ``None`` the config is written to these file path instead of ``self.filename`` """ f = pathlib.Path(filename or self.filename).resolve() @@ -214,7 +214,7 @@ def write_config( class Session: - """Holds the settings for the current session""" + """Holds the settings for the current session.""" def __init__(self) -> None: self._auths: dict[str, Authenticator] = {} self._config: CONFIG_FILE | None = None @@ -228,27 +228,27 @@ def __init__(self) -> None: @property def params(self): - """Returns the parameter of the session - - Parameter are usually added using the ``add_param_to_session`` - callback on a click option. This way an option from a parent command + """Returns the parameter of the session. + + Parameter are usually added using the ``add_param_to_session`` + callback on a click option. This way an option from a parent command can be accessed from his subcommands. """ return self._params @property def app_dir(self): - """Returns the path of the app dir""" + """Returns the path of the app dir.""" return self._app_dir @property def plugin_dir(self): - """Returns the path of the plugin dir""" + """Returns the path of the plugin dir.""" return self._plugin_dir @property def config(self): - """Returns the ConfigFile for this session""" + """Returns the ConfigFile for this session.""" if self._config is None: conf_file = self.app_dir / CONFIG_FILE self._config = ConfigFile(conf_file) @@ -257,9 +257,9 @@ def config(self): @property def selected_profile(self): - """Returns the selected config profile name for this session - - The `profile` to use must be set using the ``add_param_to_session`` + """Returns the selected config profile name for this session. + + The `profile` to use must be set using the ``add_param_to_session`` callback of a click option. Otherwise, the primary profile from the config is used. """ @@ -277,11 +277,11 @@ def get_auth_for_profile( profile: str, password: str | None = None ) -> audible.Authenticator: - """Returns an Authenticator for a profile + """Returns an Authenticator for a profile. - If an Authenticator for this profile is already loaded, it will + If an Authenticator for this profile is already loaded, it will return the Authenticator without reloading it. This way a session can - hold multiple Authenticators for different profiles. Commands can use + hold multiple Authenticators for different profiles. Commands can use this to make API requests for more than one profile. Args: @@ -324,7 +324,7 @@ def get_auth_for_profile( @property def auth(self): - """Returns the Authenticator for the selected profile""" + """Returns the Authenticator for the selected profile.""" profile = self.selected_profile password = self.params.get("password") return self.get_auth_for_profile(profile, password) diff --git a/src/audible_cli/decorators.py b/src/audible_cli/decorators.py index 394e9874..50732dd4 100644 --- a/src/audible_cli/decorators.py +++ b/src/audible_cli/decorators.py @@ -29,7 +29,7 @@ def wrapper(*args, **kwargs): def wrap_async(f): - """Wrap a synchronous function and runs them in an executor""" + """Wrap a synchronous function and runs them in an executor.""" @wraps(f) async def wrapper(*args, loop=None, executor=None, **kwargs): @@ -60,8 +60,8 @@ async def wrapper(session, *args, **kwargs): def add_param_to_session(ctx: click.Context, param, value): - """Add a parameter to :class:`Session` `param` attribute - + """Add a parameter to :class:`Session` `param` attribute. + This is usually used as a callback for a click option """ session = ctx.ensure_object(Session) diff --git a/src/audible_cli/exceptions.py b/src/audible_cli/exceptions.py index ec91c3d8..cfbee82b 100644 --- a/src/audible_cli/exceptions.py +++ b/src/audible_cli/exceptions.py @@ -5,19 +5,19 @@ class AudibleCliException(Exception): - """Base class for all errors""" + """Base class for all errors.""" class NotFoundError(AudibleCliException): - """Raised if an item is not found""" + """Raised if an item is not found.""" class NotDownloadableAsAAX(AudibleCliException): - """Raised if an item is not downloadable in aax format""" + """Raised if an item is not downloadable in aax format.""" class FileDoesNotExists(AudibleCliException): - """Raised if a file does not exist""" + """Raised if a file does not exist.""" def __init__(self, file): if isinstance(file, Path): @@ -28,7 +28,7 @@ def __init__(self, file): class DirectoryDoesNotExists(AudibleCliException): - """Raised if a directory does not exist""" + """Raised if a directory does not exist.""" def __init__(self, path): if isinstance(path, Path): @@ -39,7 +39,7 @@ def __init__(self, path): class ProfileAlreadyExists(AudibleCliException): - """Raised if an item is not found""" + """Raised if an item is not found.""" def __init__(self, name): message = f"Profile {name} already exist" @@ -47,11 +47,11 @@ def __init__(self, name): class LicenseDenied(AudibleCliException): - """Raised if a license request is not granted""" + """Raised if a license request is not granted.""" class NoDownloadUrl(AudibleCliException): - """Raised if a license response does not contain a download url""" + """Raised if a license response does not contain a download url.""" def __init__(self, asin): message = f"License response for {asin} does not contain a download url" @@ -59,7 +59,7 @@ def __init__(self, asin): class DownloadUrlExpired(AudibleCliException): - """Raised if a download url is expired""" + """Raised if a download url is expired.""" def __init__(self, lr_file): message = f"Download url in {lr_file} is expired." @@ -67,7 +67,7 @@ def __init__(self, lr_file): class VoucherNeedRefresh(AudibleCliException): - """Raised if a voucher reached his refresh date""" + """Raised if a voucher reached his refresh date.""" def __init__(self, lr_file): message = f"Refresh date for voucher {lr_file} reached." @@ -75,7 +75,7 @@ def __init__(self, lr_file): class ItemNotPublished(AudibleCliException): - """Raised if a voucher reached his refresh date""" + """Raised if a voucher reached his refresh date.""" def __init__(self, asin: str, pub_date): # Never fail while building an error message. Without a usable diff --git a/src/audible_cli/models.py b/src/audible_cli/models.py index 0c3fba16..56e6446f 100644 --- a/src/audible_cli/models.py +++ b/src/audible_cli/models.py @@ -173,7 +173,7 @@ def _prepare_data(self, data: dict) -> dict: def _get_codec(self, quality: str): """If quality is not ``best``, ensures the given quality is present in - them codecs list. Otherwise, will find the best aax quality available + them codecs list. Otherwise, will find the best aax quality available. """ assert quality in ("best", "high", "normal",) @@ -215,8 +215,8 @@ def _get_codec(self, quality: str): return best[0], best[3] async def get_child_items(self, **request_params) -> Optional["Library"]: - """Get child elements of MultiPartBooks and Podcasts - + """Get child elements of MultiPartBooks and Podcasts. + With these all parts of a MultiPartBook or all episodes of a Podcasts can be shown. """ diff --git a/src/audible_cli/plugins.py b/src/audible_cli/plugins.py index adcf1b7f..1f5b710c 100644 --- a/src/audible_cli/plugins.py +++ b/src/audible_cli/plugins.py @@ -1,5 +1,5 @@ """Core components for click_plugins -https://github.com/click-contrib/click-plugins +https://github.com/click-contrib/click-plugins. """ import os import pathlib @@ -111,8 +111,7 @@ class provides a modified help message informing the user that the plugin """ def __init__(self, name): - """Define the special help messages after instantiating a `click.Command()`. - """ + """Define the special help messages after instantiating a `click.Command()`.""" click.Command.__init__(self, name) util_name = os.path.basename((sys.argv and sys.argv[0]) or __file__) @@ -127,12 +126,10 @@ def __init__(self, name): "its author for help.\n\n\b\n" + traceback.format_exc()) self.short_help = ( - icon + " Warning: could not load plugin. See `%s %s --help`." - % (util_name, self.name)) + icon + f" Warning: could not load plugin. See `{util_name} {self.name} --help`.") def invoke(self, ctx): - """Print the traceback instead of doing nothing. - """ + """Print the traceback instead of doing nothing.""" click.echo(self.help, color=ctx.color) ctx.exit(1) diff --git a/utils/update_chapter_titles.py b/utils/update_chapter_titles.py index d02582dc..c1bf986b 100644 --- a/utils/update_chapter_titles.py +++ b/utils/update_chapter_titles.py @@ -1,5 +1,5 @@ """This script replaces the chapter titles from a ffmetadata file with the one -extracted from an API metadata/voucher file +extracted from an API metadata/voucher file. Example: @@ -151,7 +151,7 @@ def update_title_from_api_meta(self, api_meta): def update_chapters_from_api_meta(self, api_meta, separate_branding=True): """Replace all chapter data from api meta file. - + This replaces TIMEBASE, START, END and title. If api meta files contains more chapters than ffmetadata file, the additionell chapters are added. If separate_branding is True Audible Branding Intro and Outro will become @@ -212,7 +212,7 @@ def update_chapters_from_api_meta(self, api_meta, separate_branding=True): self._ffmeta_parsed["CHAPTER"] = new_chapters -CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"]) +CONTEXT_SETTINGS = {"help_option_names": ["-h", "--help"]} @click.command(context_settings=CONTEXT_SETTINGS)