pyrekordbox 0.2.1__py3-none-any.whl → 0.2.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- docs/source/formats/anlz.md +178 -7
- docs/source/formats/db6.md +1 -1
- docs/source/index.md +2 -6
- docs/source/quickstart.md +68 -45
- docs/source/tutorial/index.md +1 -1
- pyrekordbox/__init__.py +1 -1
- pyrekordbox/_version.py +2 -2
- pyrekordbox/anlz/file.py +39 -0
- pyrekordbox/anlz/structs.py +3 -5
- pyrekordbox/config.py +71 -27
- pyrekordbox/db6/database.py +260 -33
- pyrekordbox/db6/registry.py +22 -0
- pyrekordbox/db6/tables.py +3 -4
- {pyrekordbox-0.2.1.dist-info → pyrekordbox-0.2.2.dist-info}/METADATA +12 -11
- pyrekordbox-0.2.2.dist-info/RECORD +80 -0
- {pyrekordbox-0.2.1.dist-info → pyrekordbox-0.2.2.dist-info}/top_level.txt +0 -2
- tests/test_config.py +175 -0
- tests/test_db6.py +78 -0
- build/lib/build/lib/docs/source/conf.py +0 -178
- build/lib/build/lib/pyrekordbox/__init__.py +0 -22
- build/lib/build/lib/pyrekordbox/__main__.py +0 -204
- build/lib/build/lib/pyrekordbox/_version.py +0 -16
- build/lib/build/lib/pyrekordbox/anlz/__init__.py +0 -127
- build/lib/build/lib/pyrekordbox/anlz/file.py +0 -186
- build/lib/build/lib/pyrekordbox/anlz/structs.py +0 -299
- build/lib/build/lib/pyrekordbox/anlz/tags.py +0 -508
- build/lib/build/lib/pyrekordbox/config.py +0 -596
- build/lib/build/lib/pyrekordbox/db6/__init__.py +0 -45
- build/lib/build/lib/pyrekordbox/db6/aux_files.py +0 -213
- build/lib/build/lib/pyrekordbox/db6/database.py +0 -1808
- build/lib/build/lib/pyrekordbox/db6/registry.py +0 -304
- build/lib/build/lib/pyrekordbox/db6/tables.py +0 -1618
- build/lib/build/lib/pyrekordbox/logger.py +0 -23
- build/lib/build/lib/pyrekordbox/mysettings/__init__.py +0 -32
- build/lib/build/lib/pyrekordbox/mysettings/file.py +0 -369
- build/lib/build/lib/pyrekordbox/mysettings/structs.py +0 -282
- build/lib/build/lib/pyrekordbox/utils.py +0 -162
- build/lib/build/lib/pyrekordbox/xml.py +0 -1294
- build/lib/build/lib/tests/__init__.py +0 -3
- build/lib/build/lib/tests/test_anlz.py +0 -206
- build/lib/build/lib/tests/test_db6.py +0 -1039
- build/lib/build/lib/tests/test_mysetting.py +0 -203
- build/lib/build/lib/tests/test_xml.py +0 -629
- build/lib/docs/source/conf.py +0 -178
- build/lib/pyrekordbox/__init__.py +0 -22
- build/lib/pyrekordbox/__main__.py +0 -204
- build/lib/pyrekordbox/_version.py +0 -16
- build/lib/pyrekordbox/anlz/__init__.py +0 -127
- build/lib/pyrekordbox/anlz/file.py +0 -186
- build/lib/pyrekordbox/anlz/structs.py +0 -299
- build/lib/pyrekordbox/anlz/tags.py +0 -508
- build/lib/pyrekordbox/config.py +0 -596
- build/lib/pyrekordbox/db6/__init__.py +0 -45
- build/lib/pyrekordbox/db6/aux_files.py +0 -213
- build/lib/pyrekordbox/db6/database.py +0 -1808
- build/lib/pyrekordbox/db6/registry.py +0 -304
- build/lib/pyrekordbox/db6/tables.py +0 -1618
- build/lib/pyrekordbox/logger.py +0 -23
- build/lib/pyrekordbox/mysettings/__init__.py +0 -32
- build/lib/pyrekordbox/mysettings/file.py +0 -369
- build/lib/pyrekordbox/mysettings/structs.py +0 -282
- build/lib/pyrekordbox/utils.py +0 -162
- build/lib/pyrekordbox/xml.py +0 -1294
- build/lib/tests/__init__.py +0 -3
- build/lib/tests/test_anlz.py +0 -206
- build/lib/tests/test_db6.py +0 -1039
- build/lib/tests/test_mysetting.py +0 -203
- build/lib/tests/test_xml.py +0 -629
- pyrekordbox-0.2.1.dist-info/RECORD +0 -129
- {pyrekordbox-0.2.1.dist-info → pyrekordbox-0.2.2.dist-info}/LICENSE +0 -0
- {pyrekordbox-0.2.1.dist-info → pyrekordbox-0.2.2.dist-info}/WHEEL +0 -0
build/lib/docs/source/conf.py
DELETED
@@ -1,178 +0,0 @@
|
|
1
|
-
# Configuration file for the Sphinx documentation builder.
|
2
|
-
#
|
3
|
-
# This file only contains a selection of the most common options. For a full
|
4
|
-
# list see the documentation:
|
5
|
-
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
6
|
-
|
7
|
-
# -- Path setup --------------------------------------------------------------
|
8
|
-
|
9
|
-
# If extensions (or modules to document with autodoc) are in another directory,
|
10
|
-
# add these directories to sys.path here. If the directory is relative to the
|
11
|
-
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
12
|
-
#
|
13
|
-
import os
|
14
|
-
import sys
|
15
|
-
|
16
|
-
sys.path.insert(0, os.path.abspath("../.."))
|
17
|
-
|
18
|
-
import pyrekordbox
|
19
|
-
|
20
|
-
|
21
|
-
# -- Project information -----------------------------------------------------
|
22
|
-
|
23
|
-
project = "pyrekordbox"
|
24
|
-
copyright = "2022-2023, Dylan Jones"
|
25
|
-
author = "Dylan L. Jones"
|
26
|
-
release = pyrekordbox.__version__
|
27
|
-
version = release
|
28
|
-
for sp in "abcfr":
|
29
|
-
version = version.split(sp)[0]
|
30
|
-
|
31
|
-
# -- General configuration ---------------------------------------------------
|
32
|
-
|
33
|
-
# If your documentation needs a minimal Sphinx version, state it here.
|
34
|
-
needs_sphinx = "4.4"
|
35
|
-
|
36
|
-
# Add any Sphinx extension module names here, as strings. They can be
|
37
|
-
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
38
|
-
# ones.
|
39
|
-
extensions = [
|
40
|
-
"sphinx.ext.autodoc",
|
41
|
-
"numpydoc",
|
42
|
-
"myst_parser",
|
43
|
-
"numpydoc",
|
44
|
-
"sphinx_copybutton",
|
45
|
-
"sphinx.ext.napoleon",
|
46
|
-
"sphinx.ext.autosummary",
|
47
|
-
"sphinx.ext.autosectionlabel",
|
48
|
-
"matplotlib.sphinxext.plot_directive",
|
49
|
-
"sphinx.ext.intersphinx", # links to numpy, scipy ... docs
|
50
|
-
"sphinx.ext.coverage",
|
51
|
-
"sphinx.ext.extlinks", # define roles for links
|
52
|
-
"sphinx.ext.viewcode",
|
53
|
-
]
|
54
|
-
|
55
|
-
# If you need extensions of a certain version or higher, list them here.
|
56
|
-
needs_extensions = {"myst_parser": "0.13.7"}
|
57
|
-
|
58
|
-
# Add any paths that contain templates here, relative to this directory.
|
59
|
-
templates_path = ["_templates"]
|
60
|
-
|
61
|
-
# List of patterns, relative to source directory, that match files and
|
62
|
-
# directories to ignore when looking for source files.
|
63
|
-
# This pattern also affects html_static_path and html_extra_path.
|
64
|
-
|
65
|
-
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "tests"]
|
66
|
-
|
67
|
-
# The suffix(es) of source filenames.
|
68
|
-
# You can specify multiple suffix as a list of string:
|
69
|
-
source_suffix = [".rst", ".md"]
|
70
|
-
|
71
|
-
# Add any paths that contain custom static files (such as style sheets) here,
|
72
|
-
# relative to this directory. They are copied after the builtin static files,
|
73
|
-
# so a file named "default.css" will overwrite the builtin "default.css".
|
74
|
-
html_static_path = ["_static"]
|
75
|
-
|
76
|
-
html_theme_options = {
|
77
|
-
"light_logo": "logos/dark/logo_primary.svg",
|
78
|
-
"dark_logo": "logos/light/logo_primary.svg",
|
79
|
-
"sidebar_hide_name": True,
|
80
|
-
"footer_icons": [
|
81
|
-
{
|
82
|
-
"name": "GitHub",
|
83
|
-
"url": "https://github.com/dylanljones/pyrekordbox",
|
84
|
-
"html": """
|
85
|
-
<svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 16 16">
|
86
|
-
<path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"></path>
|
87
|
-
</svg>
|
88
|
-
""",
|
89
|
-
"class": "",
|
90
|
-
},
|
91
|
-
],
|
92
|
-
}
|
93
|
-
|
94
|
-
# html_title = f"{release} documentation"
|
95
|
-
|
96
|
-
# -- Options for HTML output -------------------------------------------------
|
97
|
-
|
98
|
-
# The theme to use for HTML and HTML Help pages. See the documentation for
|
99
|
-
# a list of builtin themes.
|
100
|
-
html_theme = "furo"
|
101
|
-
|
102
|
-
# The name of the Pygments (syntax highlighting) style to use.
|
103
|
-
# pygments_style = "sphinx"
|
104
|
-
# pygments_dark_style = "monokai"
|
105
|
-
|
106
|
-
# We need headers to be linkable to so ask MyST-Parser to autogenerate anchor IDs for
|
107
|
-
# headers up to and including level 3.
|
108
|
-
myst_heading_anchors = 3
|
109
|
-
|
110
|
-
# Prettier support formatting some MyST syntax but not all, so let's disable the
|
111
|
-
# unsupported yet still enabled by default ones.
|
112
|
-
myst_disable_syntax = [
|
113
|
-
"colon_fence",
|
114
|
-
"myst_block_break",
|
115
|
-
"myst_line_comment",
|
116
|
-
"math_block",
|
117
|
-
]
|
118
|
-
|
119
|
-
|
120
|
-
# Don't show type hints
|
121
|
-
autodoc_typehints = "none"
|
122
|
-
|
123
|
-
# Preserve order
|
124
|
-
autodoc_member_order = "bysource"
|
125
|
-
|
126
|
-
|
127
|
-
# -- Apidoc ------------------------------------------------------------------
|
128
|
-
|
129
|
-
add_module_names = True
|
130
|
-
|
131
|
-
|
132
|
-
# -- Autosummary -------------------------------------------------------------
|
133
|
-
|
134
|
-
autosummary_generate = True
|
135
|
-
# autosummary_imported_members = True
|
136
|
-
|
137
|
-
|
138
|
-
# -- Numpy extension ---------------------------------------------------------
|
139
|
-
|
140
|
-
numpydoc_use_plots = True
|
141
|
-
# numpydoc_xref_param_type = True
|
142
|
-
# numpydoc_xref_ignore = "all" # not working...
|
143
|
-
numpydoc_show_class_members = False
|
144
|
-
|
145
|
-
|
146
|
-
# -- Intersphinx -------------------------------------------------------------
|
147
|
-
|
148
|
-
# taken from https://gist.github.com/bskinn/0e164963428d4b51017cebdb6cda5209
|
149
|
-
intersphinx_mapping = {
|
150
|
-
"python": (r"https://docs.python.org", None),
|
151
|
-
"numpy": (r"https://docs.scipy.org/doc/numpy/", None),
|
152
|
-
"np": (r"https://docs.scipy.org/doc/numpy/", None),
|
153
|
-
"matplotlib": (r"https://matplotlib.org/", None),
|
154
|
-
"<name>": ("https://docs.python.org/3/", None),
|
155
|
-
}
|
156
|
-
|
157
|
-
|
158
|
-
# -- Auto-run sphinx-apidoc --------------------------------------------------
|
159
|
-
|
160
|
-
|
161
|
-
def run_apidoc(_):
|
162
|
-
from sphinx.ext.apidoc import main
|
163
|
-
import os
|
164
|
-
import sys
|
165
|
-
|
166
|
-
sys.path.append(os.path.join(os.path.dirname(__file__), ".."))
|
167
|
-
cur_dir = os.path.abspath(os.path.dirname(__file__))
|
168
|
-
proj_dir = os.path.dirname(os.path.dirname(cur_dir))
|
169
|
-
doc_dir = os.path.join(proj_dir, "docs")
|
170
|
-
output_path = os.path.join(doc_dir, "source", "generated")
|
171
|
-
module = os.path.join(proj_dir, "pyrekordbox")
|
172
|
-
exclude = os.path.join(module, "tests")
|
173
|
-
template_dir = os.path.join(doc_dir, "source", "_templates", "apidoc")
|
174
|
-
main(["-fMeT", "-o", output_path, module, exclude, "--templatedir", template_dir])
|
175
|
-
|
176
|
-
|
177
|
-
def setup(app):
|
178
|
-
app.connect("builder-inited", run_apidoc)
|
@@ -1,22 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
# Author: Dylan Jones
|
3
|
-
# Date: 2022-04-10
|
4
|
-
|
5
|
-
from .logger import logger
|
6
|
-
from .config import show_config, get_config
|
7
|
-
from .xml import RekordboxXml, XmlDuplicateError, XmlAttributeKeyError
|
8
|
-
from .anlz import get_anlz_paths, walk_anlz_paths, read_anlz_files, AnlzFile
|
9
|
-
from .mysettings import (
|
10
|
-
get_mysetting_paths,
|
11
|
-
read_mysetting_file,
|
12
|
-
MySettingFile,
|
13
|
-
MySetting2File,
|
14
|
-
DjmMySettingFile,
|
15
|
-
DevSettingFile,
|
16
|
-
)
|
17
|
-
from .db6 import Rekordbox6Database, open_rekordbox_database
|
18
|
-
|
19
|
-
try:
|
20
|
-
from ._version import version as __version__
|
21
|
-
except ImportError: # pragma: no cover
|
22
|
-
__version__ = "unknown"
|
@@ -1,204 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
# Author: Dylan Jones
|
3
|
-
# Date: 2023-08-15
|
4
|
-
|
5
|
-
import os
|
6
|
-
import re
|
7
|
-
import sys
|
8
|
-
import shutil
|
9
|
-
import urllib.request
|
10
|
-
from pathlib import Path
|
11
|
-
from pyrekordbox.config import write_db6_key_cache, _cache_file
|
12
|
-
|
13
|
-
KEY_SOURCES = [
|
14
|
-
{
|
15
|
-
"url": r"https://raw.githubusercontent.com/mganss/CueGen/19878e6eb3f586dee0eb3eb4f2ce3ef18309de9d/CueGen/Generator.cs", # noqa: E501
|
16
|
-
"regex": re.compile(
|
17
|
-
r'((.|\n)*)Config\.UseSqlCipher.*\?.*"(?P<dp>.*)".*:.*null',
|
18
|
-
flags=re.IGNORECASE | re.MULTILINE,
|
19
|
-
),
|
20
|
-
},
|
21
|
-
{
|
22
|
-
"url": r"https://raw.githubusercontent.com/dvcrn/go-rekordbox/8be6191ba198ed7abd4ad6406d177ed7b4f749b5/cmd/getencryptionkey/main.go", # noqa: E501
|
23
|
-
"regex": re.compile(
|
24
|
-
r'((.|\n)*)fmt\.Print\("(?P<dp>.*)"\)', flags=re.IGNORECASE | re.MULTILINE
|
25
|
-
),
|
26
|
-
},
|
27
|
-
]
|
28
|
-
|
29
|
-
|
30
|
-
class WorkingDir:
|
31
|
-
def __init__(self, path):
|
32
|
-
self._prev = Path.cwd()
|
33
|
-
self.path = Path(path)
|
34
|
-
|
35
|
-
def __enter__(self):
|
36
|
-
if self.path != self._prev:
|
37
|
-
self.path.mkdir(parents=True, exist_ok=True)
|
38
|
-
os.chdir(self.path)
|
39
|
-
|
40
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
41
|
-
if self.path != self._prev:
|
42
|
-
os.chdir(self._prev)
|
43
|
-
|
44
|
-
|
45
|
-
def clone_repo(https_url: str) -> Path:
|
46
|
-
path = Path.cwd() / https_url.split("/")[-1]
|
47
|
-
if not path.exists():
|
48
|
-
os.system(f"git clone {https_url}")
|
49
|
-
assert path.exists()
|
50
|
-
else:
|
51
|
-
print(f"Repository {https_url} already cloned")
|
52
|
-
return path
|
53
|
-
|
54
|
-
|
55
|
-
def clone_pysqlcipher3() -> Path:
|
56
|
-
return clone_repo(r"https://github.com/coleifer/sqlcipher3")
|
57
|
-
|
58
|
-
|
59
|
-
def clone_sqlcipher_amalgamation() -> Path:
|
60
|
-
return clone_repo(r"https://github.com/geekbrother/sqlcipher-amalgamation")
|
61
|
-
|
62
|
-
|
63
|
-
def patch_pysqlcipher_setup(pysqlcipher_dir, cryptolib="libcrypto.lib"):
|
64
|
-
path = Path(pysqlcipher_dir, "setup.py")
|
65
|
-
|
66
|
-
with open(path, "r") as fh:
|
67
|
-
text = fh.read()
|
68
|
-
|
69
|
-
if cryptolib:
|
70
|
-
lib_old = "os.environ.get('OPENSSL_LIBNAME') or 'libeay32.lib'"
|
71
|
-
lib_new = f"os.environ.get('OPENSSL_LIBNAME') or '{cryptolib}'"
|
72
|
-
text = text.replace(lib_old, lib_new)
|
73
|
-
|
74
|
-
with open(path, "w") as fh:
|
75
|
-
fh.write(text)
|
76
|
-
|
77
|
-
|
78
|
-
def prepare_pysqlcipher(pysqlcipher_dir: Path, amalgamation_src: Path):
|
79
|
-
# Copy amalgamation files to pysqlcipher directory
|
80
|
-
root = pysqlcipher_dir
|
81
|
-
root.mkdir(parents=True, exist_ok=True)
|
82
|
-
shutil.copy2(amalgamation_src / "sqlite3.c", root / "sqlite3.c")
|
83
|
-
shutil.copy2(amalgamation_src / "sqlite3.h", root / "sqlite3.h")
|
84
|
-
|
85
|
-
|
86
|
-
def install_pysqlcipher(
|
87
|
-
tmpdir="pysqlcipher3",
|
88
|
-
crypto_lib="libcrypto.lib",
|
89
|
-
pyexecutable="",
|
90
|
-
build=True,
|
91
|
-
install=True,
|
92
|
-
cleanup=True,
|
93
|
-
):
|
94
|
-
if sys.platform != "win32":
|
95
|
-
print("Not on Windows, aborting...")
|
96
|
-
return
|
97
|
-
|
98
|
-
tmpdir = Path(tmpdir)
|
99
|
-
# Download pysqlcipher3 and prepare amalgamation build
|
100
|
-
with WorkingDir(tmpdir):
|
101
|
-
pysqlcipher_dir = clone_pysqlcipher3()
|
102
|
-
amalgamation_dir = clone_sqlcipher_amalgamation()
|
103
|
-
amalgamation_src = amalgamation_dir / "src"
|
104
|
-
|
105
|
-
prepare_pysqlcipher(pysqlcipher_dir, amalgamation_src)
|
106
|
-
if os.getenv("OPENSSL_LIBNAME") is None:
|
107
|
-
print("No OPENSSL_LIBNAME environment variable found, updating `setup.py`!")
|
108
|
-
patch_pysqlcipher_setup(pysqlcipher_dir, crypto_lib)
|
109
|
-
|
110
|
-
# Build amalgamation and install pysqlcipher
|
111
|
-
if not pyexecutable:
|
112
|
-
pyexecutable = sys.executable
|
113
|
-
|
114
|
-
with WorkingDir(pysqlcipher_dir):
|
115
|
-
if build:
|
116
|
-
# Build amalgamation
|
117
|
-
print()
|
118
|
-
os.system(f"{pyexecutable} setup.py build_static build")
|
119
|
-
if install:
|
120
|
-
# Install pysqlcipher package
|
121
|
-
print()
|
122
|
-
os.system(f"{pyexecutable} setup.py install")
|
123
|
-
|
124
|
-
# Remove temporary files
|
125
|
-
if cleanup:
|
126
|
-
try:
|
127
|
-
print()
|
128
|
-
print("Cleaning up")
|
129
|
-
tmpdir.unlink(missing_ok=True)
|
130
|
-
except PermissionError as e:
|
131
|
-
print()
|
132
|
-
print(e)
|
133
|
-
print(f"Could not remove temporary directory '{tmpdir}'!")
|
134
|
-
|
135
|
-
|
136
|
-
def download_db6_key():
|
137
|
-
dp = ""
|
138
|
-
for source in KEY_SOURCES:
|
139
|
-
url = source["url"]
|
140
|
-
regex = source["regex"]
|
141
|
-
print(f"Looking for key: {url}")
|
142
|
-
|
143
|
-
res = urllib.request.urlopen(url)
|
144
|
-
data = res.read().decode("utf-8")
|
145
|
-
match = regex.match(data)
|
146
|
-
if match:
|
147
|
-
dp = match.group("dp")
|
148
|
-
break
|
149
|
-
if dp:
|
150
|
-
print(f"Found key, updating cache file {_cache_file}")
|
151
|
-
write_db6_key_cache(dp)
|
152
|
-
else:
|
153
|
-
print("No key found in the online sources.")
|
154
|
-
|
155
|
-
|
156
|
-
def main():
|
157
|
-
from argparse import ArgumentParser
|
158
|
-
|
159
|
-
parser = ArgumentParser("pyrekordbox")
|
160
|
-
subparsers = parser.add_subparsers(dest="command")
|
161
|
-
|
162
|
-
# Download Rekordbx 6 database key command
|
163
|
-
subparsers.add_parser(
|
164
|
-
"download-key",
|
165
|
-
help="Download the Rekordbox 6 database key from the internet "
|
166
|
-
"and write it to the cache file.",
|
167
|
-
)
|
168
|
-
|
169
|
-
# Install pysqlcipher3 command (Windows only)
|
170
|
-
install_parser = subparsers.add_parser(
|
171
|
-
"install-sqlcipher",
|
172
|
-
help="Build sqlcipher against amalgamation and install pysqlcipher3",
|
173
|
-
)
|
174
|
-
install_parser.add_argument(
|
175
|
-
"-t",
|
176
|
-
"--tmpdir",
|
177
|
-
type=str,
|
178
|
-
default=".tmp",
|
179
|
-
help="Path for storing temporary data (default: '.tmp')",
|
180
|
-
)
|
181
|
-
install_parser.add_argument(
|
182
|
-
"-l",
|
183
|
-
"--cryptolib",
|
184
|
-
type=str,
|
185
|
-
default="libcrypto.lib",
|
186
|
-
help="The name of the OpenSSl crypto libary (default: 'libcrypto.lib')",
|
187
|
-
)
|
188
|
-
install_parser.add_argument(
|
189
|
-
"-b",
|
190
|
-
"--buildonly",
|
191
|
-
action="store_true",
|
192
|
-
help="Don't install sqlcipher3, only build the amalgamation",
|
193
|
-
)
|
194
|
-
|
195
|
-
# Parse args and handle command
|
196
|
-
args = parser.parse_args(sys.argv[1:])
|
197
|
-
if args.command == "download-key":
|
198
|
-
download_db6_key()
|
199
|
-
elif args.command == "install-sqlcipher":
|
200
|
-
install_pysqlcipher(args.tmpdir, args.cryptolib, install=not args.buildonly)
|
201
|
-
|
202
|
-
|
203
|
-
if __name__ == "__main__":
|
204
|
-
main()
|
@@ -1,16 +0,0 @@
|
|
1
|
-
# file generated by setuptools_scm
|
2
|
-
# don't change, don't track in version control
|
3
|
-
TYPE_CHECKING = False
|
4
|
-
if TYPE_CHECKING:
|
5
|
-
from typing import Tuple, Union
|
6
|
-
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
7
|
-
else:
|
8
|
-
VERSION_TUPLE = object
|
9
|
-
|
10
|
-
version: str
|
11
|
-
__version__: str
|
12
|
-
__version_tuple__: VERSION_TUPLE
|
13
|
-
version_tuple: VERSION_TUPLE
|
14
|
-
|
15
|
-
__version__ = version = '0.2.1'
|
16
|
-
__version_tuple__ = version_tuple = (0, 2, 1)
|
@@ -1,127 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
# Author: Dylan Jones
|
3
|
-
# Date: 2023-02-01
|
4
|
-
|
5
|
-
import re
|
6
|
-
from pathlib import Path
|
7
|
-
from typing import Union
|
8
|
-
from . import structs
|
9
|
-
from .file import AnlzFile
|
10
|
-
|
11
|
-
RE_ANLZ = re.compile("ANLZ[0-9]{4}.(DAT|EXT|2EX)")
|
12
|
-
|
13
|
-
|
14
|
-
def is_anlz_file(path: Union[str, Path]) -> bool:
|
15
|
-
"""Checks if the name of a file matches the ANLZ file name pattern.
|
16
|
-
|
17
|
-
Parameters
|
18
|
-
----------
|
19
|
-
path : str or Path
|
20
|
-
The file path to check
|
21
|
-
|
22
|
-
Returns
|
23
|
-
-------
|
24
|
-
is_anlz : bool
|
25
|
-
True if the file is an ANLZ file.
|
26
|
-
|
27
|
-
Examples
|
28
|
-
--------
|
29
|
-
>>> is_anlz_file("ANLZ0000.DAT")
|
30
|
-
True
|
31
|
-
|
32
|
-
>>> is_anlz_file("/path/to/ANLZ0000.DAT")
|
33
|
-
False
|
34
|
-
|
35
|
-
>>> is_anlz_file("ANLZ.DAT")
|
36
|
-
False
|
37
|
-
"""
|
38
|
-
path = Path(path)
|
39
|
-
if not path.exists() or not path.is_file():
|
40
|
-
return False
|
41
|
-
return bool(RE_ANLZ.match(path.name))
|
42
|
-
|
43
|
-
|
44
|
-
def get_anlz_paths(root: Union[str, Path]) -> dict:
|
45
|
-
"""Returns the paths of all existing ANLZ files in a directory.
|
46
|
-
|
47
|
-
Parameters
|
48
|
-
----------
|
49
|
-
root : str or Path
|
50
|
-
The path of the directory containing ANLZ files.
|
51
|
-
|
52
|
-
Returns
|
53
|
-
-------
|
54
|
-
anlz_paths : dict[str, Path]
|
55
|
-
The file paths stored as dictionary with the type of ANLZ file as keys
|
56
|
-
("DAT", "EXT", "EX2")
|
57
|
-
|
58
|
-
Examples
|
59
|
-
--------
|
60
|
-
>>> p = get_anlz_paths("directory/")
|
61
|
-
>>> p["DAT"]
|
62
|
-
directory/ANLZ0000.DAT
|
63
|
-
"""
|
64
|
-
paths = {"DAT": None, "EXT": None, "2EX": None}
|
65
|
-
for path in Path(root).iterdir():
|
66
|
-
if RE_ANLZ.match(path.name):
|
67
|
-
paths[path.suffix[1:].upper()] = path
|
68
|
-
return paths
|
69
|
-
|
70
|
-
|
71
|
-
def walk_anlz_dirs(root_dir: Union[str, Path]):
|
72
|
-
"""Finds all ANLZ directory paths recursively.
|
73
|
-
|
74
|
-
Parameters
|
75
|
-
----------
|
76
|
-
root_dir : str or Path
|
77
|
-
The path of the root directory.
|
78
|
-
|
79
|
-
Yields
|
80
|
-
-------
|
81
|
-
anlz_dir : str
|
82
|
-
The path of a directory containing ANLZ files
|
83
|
-
"""
|
84
|
-
for path in Path(root_dir).rglob("*"):
|
85
|
-
if path.is_dir():
|
86
|
-
if any(is_anlz_file(f) for f in path.iterdir()):
|
87
|
-
yield path
|
88
|
-
|
89
|
-
|
90
|
-
def walk_anlz_paths(root_dir: Union[str, Path]):
|
91
|
-
"""Finds all ANLZ directory paths and the containing file paths recursively.
|
92
|
-
|
93
|
-
Parameters
|
94
|
-
----------
|
95
|
-
root_dir : str or Path
|
96
|
-
The path of the root directory.
|
97
|
-
|
98
|
-
Yields
|
99
|
-
-------
|
100
|
-
anlz_dir : str
|
101
|
-
The path of a directory containing ANLZ files.
|
102
|
-
anlz_files : Sequence of str
|
103
|
-
The file paths of the ANLZ files in `anlz_dir`.
|
104
|
-
"""
|
105
|
-
root_dir = Path(root_dir)
|
106
|
-
assert root_dir.exists()
|
107
|
-
for anlz_dir in walk_anlz_dirs(root_dir):
|
108
|
-
files = {k: path for k, path in get_anlz_paths(anlz_dir).items() if path}
|
109
|
-
yield anlz_dir, files
|
110
|
-
|
111
|
-
|
112
|
-
def read_anlz_files(root: Union[str, Path] = "") -> dict:
|
113
|
-
"""Open all ANLZ files in the given root directory.
|
114
|
-
|
115
|
-
Parameters
|
116
|
-
----------
|
117
|
-
root : str or Path, optional
|
118
|
-
The root directory of the ANLZ files to open.
|
119
|
-
|
120
|
-
Returns
|
121
|
-
-------
|
122
|
-
anlz_files : dict
|
123
|
-
The opened ANLZ files stored in a dict with the corresponding file paths
|
124
|
-
as keys.
|
125
|
-
"""
|
126
|
-
paths = get_anlz_paths(root)
|
127
|
-
return {path: AnlzFile.parse_file(path) for path in paths.values() if path}
|