diff --git a/pyproject.toml b/pyproject.toml index 536d113..26064fd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -99,20 +99,45 @@ select = [ "F", # flake8 "E", # pycodestyle Errors "W", # pycodestyle Warnings - # "I", # isort + "I", # isort + "NPY", # Numpy + "N", # pep8-naming + "D", # pydocstyle ] ignore = [ "E203", # Whitespace before ':' + "D100", # Missing docstring in public module + "D101", # Missing docstring in public class + "D102", # Missing docstring in public method + "D103", # Missing docstring in public function + "D104", # Missing docstring in public package + "D105", # Missing docstring in magic method + "D106", # Missing docstring in public nested class + "D107", # Missing docstring in __init__ + "D401", # First line should be in imperative mood + "D403", # First word of the first line should be capitalized + "D404", # First word of the docstring should not be "This" + #"N802", # Function name should be lowercase + #"N803", # Argument name should be lowercase + "N813", # Camelcase imported as lowercase + #"N815", # Variable in class scope should not be mixedCase + "N818", # Exception name should be named with an Error suffix ] fixable = ["ALL"] # Allow fix for all enabled rules (when `--fix`) is provided. unfixable = [] [tool.ruff.lint.per-file-ignores] "*__init__.py" = ["F401"] +"rbxml.py" = ["N803"] +"tables.py" = ["N802", "N815"] + + +[tool.ruff.lint.pydocstyle] +convention = "numpy" [tool.ruff.lint.isort] combine-as-imports = true -# length-sort = true +length-sort = false [tool.ruff.format] quote-style = "double" diff --git a/pyrekordbox/__init__.py b/pyrekordbox/__init__.py index ae4fe80..254da77 100644 --- a/pyrekordbox/__init__.py +++ b/pyrekordbox/__init__.py @@ -2,19 +2,19 @@ # Author: Dylan Jones # Date: 2022-04-10 +from .anlz import AnlzFile, get_anlz_paths, read_anlz_files, walk_anlz_paths +from .config import get_config, show_config, update_config +from .db6 import Rekordbox6Database, open_rekordbox_database from .logger import logger -from .config import show_config, get_config, update_config -from .rbxml import RekordboxXml, XmlDuplicateError, XmlAttributeKeyError -from .anlz import get_anlz_paths, walk_anlz_paths, read_anlz_files, AnlzFile from .mysettings import ( + DevSettingFile, + DjmMySettingFile, + MySetting2File, + MySettingFile, get_mysetting_paths, read_mysetting_file, - MySettingFile, - MySetting2File, - DjmMySettingFile, - DevSettingFile, ) -from .db6 import Rekordbox6Database, open_rekordbox_database +from .rbxml import RekordboxXml, XmlAttributeKeyError, XmlDuplicateError try: from ._version import version as __version__ diff --git a/pyrekordbox/__main__.py b/pyrekordbox/__main__.py index e255c29..8d1a257 100644 --- a/pyrekordbox/__main__.py +++ b/pyrekordbox/__main__.py @@ -4,11 +4,12 @@ import os import re -import sys import shutil +import sys import urllib.request from pathlib import Path -from pyrekordbox.config import write_db6_key_cache, _cache_file + +from pyrekordbox.config import _cache_file, write_db6_key_cache KEY_SOURCES = [ { diff --git a/pyrekordbox/anlz/__init__.py b/pyrekordbox/anlz/__init__.py index 7da56f2..0cca9b5 100644 --- a/pyrekordbox/anlz/__init__.py +++ b/pyrekordbox/anlz/__init__.py @@ -5,6 +5,7 @@ import re from pathlib import Path from typing import Union + from . import structs from .file import AnlzFile @@ -77,7 +78,7 @@ def walk_anlz_dirs(root_dir: Union[str, Path]): The path of the root directory. Yields - ------- + ------ anlz_dir : str The path of a directory containing ANLZ files """ @@ -96,7 +97,7 @@ def walk_anlz_paths(root_dir: Union[str, Path]): The path of the root directory. Yields - ------- + ------ anlz_dir : str The path of a directory containing ANLZ files. anlz_files : Sequence of str diff --git a/pyrekordbox/anlz/file.py b/pyrekordbox/anlz/file.py index 45bdcbb..010e9c6 100644 --- a/pyrekordbox/anlz/file.py +++ b/pyrekordbox/anlz/file.py @@ -6,10 +6,12 @@ from collections import abc from pathlib import Path from typing import Union -from .tags import TAGS -from . import structs + from construct import Int16ub +from . import structs +from .tags import TAGS + logger = logging.getLogger(__name__) XOR_MASK = bytearray.fromhex("CB E1 EE FA E5 EE AD EE E9 D2 E9 EB E1 E9 F3 E8 E9 F4 E1") diff --git a/pyrekordbox/anlz/tags.py b/pyrekordbox/anlz/tags.py index 5989918..2795f9f 100644 --- a/pyrekordbox/anlz/tags.py +++ b/pyrekordbox/anlz/tags.py @@ -4,7 +4,9 @@ import logging from abc import ABC + import numpy as np + from . import structs logger = logging.getLogger(__name__) @@ -439,7 +441,7 @@ class PWV5AnlzTag(AbstractAnlzTag): LEN_HEADER = 24 def get(self): - """Parse the Waveform Color Detail Tag (PWV5) + """Parse the Waveform Color Detail Tag (PWV5). The format of the entries is: diff --git a/pyrekordbox/config.py b/pyrekordbox/config.py index fed452b..3cbf7eb 100644 --- a/pyrekordbox/config.py +++ b/pyrekordbox/config.py @@ -363,7 +363,6 @@ def _get_rb5_config( def _extract_pw(pioneer_install_dir: Path) -> str: # pragma: no cover """Extract the password for decrypting the Rekordbox 6 database key.""" - asar_data = read_rekordbox6_asar(pioneer_install_dir) match_result = re.search('pass: ".(.*?)"', asar_data) if match_result is None: diff --git a/pyrekordbox/db6/__init__.py b/pyrekordbox/db6/__init__.py index 0b09ebb..6419a94 100644 --- a/pyrekordbox/db6/__init__.py +++ b/pyrekordbox/db6/__init__.py @@ -2,6 +2,8 @@ # Author: Dylan Jones # Date: 2022-05-07 +from .database import Rekordbox6Database, open_rekordbox_database +from .smartlist import SmartList from .tables import ( AgentRegistry, CloudAgentRegistry, @@ -41,5 +43,3 @@ SettingFile, UuidIDMap, ) -from .smartlist import SmartList -from .database import Rekordbox6Database, open_rekordbox_database diff --git a/pyrekordbox/db6/aux_files.py b/pyrekordbox/db6/aux_files.py index 791a574..234e27c 100644 --- a/pyrekordbox/db6/aux_files.py +++ b/pyrekordbox/db6/aux_files.py @@ -2,9 +2,10 @@ # Author: Dylan Jones # Date: 2023-09-10 -from pathlib import Path -from datetime import datetime import xml.etree.cElementTree as xml +from datetime import datetime +from pathlib import Path + from ..config import get_config from ..utils import pretty_xml diff --git a/pyrekordbox/db6/database.py b/pyrekordbox/db6/database.py index f54d496..adbf7fa 100644 --- a/pyrekordbox/db6/database.py +++ b/pyrekordbox/db6/database.py @@ -5,21 +5,23 @@ import datetime import logging import secrets -from uuid import uuid4 from pathlib import Path from typing import Optional -from sqlalchemy import create_engine, or_, event, MetaData, select -from sqlalchemy.orm import Session, Query +from uuid import uuid4 + +from sqlalchemy import MetaData, create_engine, event, or_, select from sqlalchemy.exc import NoResultFound +from sqlalchemy.orm import Query, Session from sqlalchemy.sql.sqltypes import DateTime, String -from ..utils import get_rekordbox_pid, warn_deprecated + +from ..anlz import AnlzFile, get_anlz_paths, read_anlz_files from ..config import get_config -from ..anlz import get_anlz_paths, read_anlz_files, AnlzFile -from .registry import RekordboxAgentRegistry +from ..utils import get_rekordbox_pid, warn_deprecated +from . import tables from .aux_files import MasterPlaylistXml -from .tables import DjmdContent, FileType, PlaylistType +from .registry import RekordboxAgentRegistry from .smartlist import SmartList -from . import tables +from .tables import DjmdContent, FileType, PlaylistType try: from sqlcipher3 import dbapi2 as sqlite3 # noqa diff --git a/pyrekordbox/db6/registry.py b/pyrekordbox/db6/registry.py index edd9922..795f346 100644 --- a/pyrekordbox/db6/registry.py +++ b/pyrekordbox/db6/registry.py @@ -4,6 +4,7 @@ import logging from contextlib import contextmanager + from sqlalchemy.orm.exc import ObjectDeletedError logger = logging.getLogger(__name__) diff --git a/pyrekordbox/db6/smartlist.py b/pyrekordbox/db6/smartlist.py index 5e1c87f..fbdfb3e 100644 --- a/pyrekordbox/db6/smartlist.py +++ b/pyrekordbox/db6/smartlist.py @@ -4,14 +4,14 @@ import logging import xml.etree.cElementTree as xml +from dataclasses import dataclass +from datetime import datetime from enum import Enum, IntEnum from typing import List, Union -from datetime import datetime -from dataclasses import dataclass -from sqlalchemy import or_, and_, not_ -from sqlalchemy.sql.elements import BooleanClauseList from dateutil.relativedelta import relativedelta # noqa +from sqlalchemy import and_, not_, or_ +from sqlalchemy.sql.elements import BooleanClauseList from .tables import DjmdContent diff --git a/pyrekordbox/db6/tables.py b/pyrekordbox/db6/tables.py index 892d735..7884a24 100644 --- a/pyrekordbox/db6/tables.py +++ b/pyrekordbox/db6/tables.py @@ -6,15 +6,26 @@ import math import struct -import numpy as np -from enum import IntEnum from datetime import datetime +from enum import IntEnum from typing import List -from sqlalchemy import Column, Integer, VARCHAR, BigInteger, SmallInteger, Text, Float -from sqlalchemy import ForeignKey, TypeDecorator -from sqlalchemy.orm import DeclarativeBase, relationship, backref, mapped_column, Mapped + +import numpy as np +from sqlalchemy import ( + VARCHAR, + BigInteger, + Column, + Float, + ForeignKey, + Integer, + SmallInteger, + Text, + TypeDecorator, +) from sqlalchemy.ext.associationproxy import association_proxy from sqlalchemy.inspection import inspect +from sqlalchemy.orm import DeclarativeBase, Mapped, backref, mapped_column, relationship + from .registry import RekordboxAgentRegistry __all__ = [ diff --git a/pyrekordbox/mysettings/__init__.py b/pyrekordbox/mysettings/__init__.py index 38f2ae2..95f811c 100644 --- a/pyrekordbox/mysettings/__init__.py +++ b/pyrekordbox/mysettings/__init__.py @@ -4,14 +4,15 @@ import re from pathlib import Path + from . import structs from .file import ( FILES, - SettingsFile, - MySettingFile, - MySetting2File, - DjmMySettingFile, DevSettingFile, + DjmMySettingFile, + MySetting2File, + MySettingFile, + SettingsFile, ) RE_MYSETTING = re.compile(".*SETTING[0-9]?.DAT$") diff --git a/pyrekordbox/mysettings/file.py b/pyrekordbox/mysettings/file.py index d770120..30a97d2 100644 --- a/pyrekordbox/mysettings/file.py +++ b/pyrekordbox/mysettings/file.py @@ -5,8 +5,10 @@ """Rekordbox My-Setting file handlers.""" import re -from construct import Struct from collections.abc import MutableMapping + +from construct import Struct + from . import structs # fmt: off diff --git a/pyrekordbox/rbxml.py b/pyrekordbox/rbxml.py index d1c29ed..dda72dc 100644 --- a/pyrekordbox/rbxml.py +++ b/pyrekordbox/rbxml.py @@ -7,10 +7,12 @@ import logging import os.path import urllib.parse +import xml.etree.cElementTree as xml from abc import abstractmethod from collections import abc -import xml.etree.cElementTree as xml + import bidict + from .utils import pretty_xml logger = logging.getLogger(__name__) @@ -658,7 +660,7 @@ def entries(self): @property def key_type(self): - """str: The type of key used by the playlist node""" + """str: The type of key used by the playlist node.""" return NODE_KEYTYPE_MAPPING.get(self._element.attrib.get("KeyType")) @property diff --git a/pyrekordbox/utils.py b/pyrekordbox/utils.py index 5f4fef7..6e8fa1f 100644 --- a/pyrekordbox/utils.py +++ b/pyrekordbox/utils.py @@ -6,9 +6,10 @@ import os import warnings -import psutil -from xml.dom import minidom import xml.etree.cElementTree as xml +from xml.dom import minidom + +import psutil warnings.simplefilter("always", DeprecationWarning) @@ -122,7 +123,7 @@ def get_rekordbox_agent_pid(raise_exec=False): def pretty_xml(element, indent=None, encoding="utf-8"): - """Generates a formatted string of an XML element. + r"""Generates a formatted string of an XML element. Parameters ---------- diff --git a/pyrekordbox/xml.py b/pyrekordbox/xml.py index 9aa417c..557e8a6 100644 --- a/pyrekordbox/xml.py +++ b/pyrekordbox/xml.py @@ -2,7 +2,7 @@ # Author: Dylan Jones # Date: 2022-04-10 -from .utils import warn_deprecated as _warn_deprecated from .rbxml import * # noqa: F401, F403 +from .utils import warn_deprecated as _warn_deprecated _warn_deprecated("pyrekordbox.xml", "pyrekordbox.rbxml", remove_in="0.4.0") diff --git a/tests/test_anlz.py b/tests/test_anlz.py index 3781d55..735d4c3 100644 --- a/tests/test_anlz.py +++ b/tests/test_anlz.py @@ -3,9 +3,11 @@ # Date: 2023-02-01 import os -import pytest + import numpy as np +import pytest from numpy.testing import assert_equal + from pyrekordbox import anlz TEST_ROOT = os.path.join(os.path.dirname(os.path.dirname(__file__)), ".testdata") diff --git a/tests/test_config.py b/tests/test_config.py index f44e96f..53606a3 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -2,10 +2,12 @@ # Author: Dylan Jones # Date: 2023-10-02 -import pytest import json from pathlib import Path -from pyrekordbox.config import update_config, get_config + +import pytest + +from pyrekordbox.config import get_config, update_config RB_SETTING = """ diff --git a/tests/test_db6.py b/tests/test_db6.py index 85b8a9c..5ce5d06 100644 --- a/tests/test_db6.py +++ b/tests/test_db6.py @@ -3,15 +3,17 @@ # Date: 2023-02-01 import os -import pytest -from pytest import mark -from pathlib import Path import shutil import tempfile +from pathlib import Path + +import pytest +from pytest import mark from sqlalchemy.orm.query import Query + from pyrekordbox import Rekordbox6Database, open_rekordbox_database from pyrekordbox.db6 import tables -from pyrekordbox.db6.smartlist import SmartList, LogicalOperator, Operator, Property +from pyrekordbox.db6.smartlist import LogicalOperator, Operator, Property, SmartList TEST_ROOT = Path(__file__).parent.parent / ".testdata" LOCKED = TEST_ROOT / "rekordbox 6" / "master_locked.db" diff --git a/tests/test_mysetting.py b/tests/test_mysetting.py index d1fc67d..219d992 100644 --- a/tests/test_mysetting.py +++ b/tests/test_mysetting.py @@ -3,12 +3,14 @@ # Date: 2022-10-25 import os + import pytest + from pyrekordbox.mysettings import ( - read_mysetting_file, - MySettingFile, - MySetting2File, DjmMySettingFile, + MySetting2File, + MySettingFile, + read_mysetting_file, ) from pyrekordbox.mysettings.file import compute_checksum diff --git a/tests/test_xml.py b/tests/test_xml.py index af4be8a..8f9ebf1 100644 --- a/tests/test_xml.py +++ b/tests/test_xml.py @@ -3,9 +3,11 @@ # Date: 2022-05-07 import os + import pytest + from pyrekordbox import RekordboxXml -from pyrekordbox.rbxml import Tempo, PositionMark, XmlDuplicateError +from pyrekordbox.rbxml import PositionMark, Tempo, XmlDuplicateError TEST_ROOT = os.path.join(os.path.dirname(os.path.dirname(__file__)), ".testdata") XML5 = os.path.join(TEST_ROOT, "rekordbox 5", "database.xml")