Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,19 @@

# Cache
/DeDRM_plugin/__pycache__
/DeDRM_plugin/standalone/__pycache__
/DeDRM_plugin/standalone/__pycache__
**/__pycache__

# Generated build artifacts — never committed, rebuilt on demand by dedrm.py
DeDRM_plugin.zip
DeDRM_tools.zip
DeDRM_plugin_build_tmp/

# User key config written by standalone CLI on first successful decryption
dedrm.json

# AI agent working files
.claude/

# Generated HTML from markdown plan docs
*.html
53 changes: 53 additions & 0 deletions DeDRM_plugin/__calibre_compat_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,58 @@
if "calibre" in sys.modules:
# Explicitly set the package identifier so we are allowed to import stuff ...
__package__ = "calibre_plugins.dedrm"
else:
# Standalone mode: make relative imports (from .utilities import ...) work
# without Calibre by installing a meta_path hook that maps dedrm.X -> X.
import types as _types

_dedrm_pkg_name = "dedrm"

class _DeDRMFinder:
"""Acts as both finder and loader.
Intercepts 'import dedrm.X' and redirects it to the flat module 'X',
so that relative imports (from .utilities import ...) work standalone."""

def find_spec(self, fullname, path, target=None):
import importlib.util as _ilu
if fullname == _dedrm_pkg_name or fullname.startswith(_dedrm_pkg_name + "."):
return _ilu.spec_from_loader(fullname, loader=self,
is_package=(fullname == _dedrm_pkg_name))
return None

def create_module(self, spec):
if spec.name == _dedrm_pkg_name:
return sys.modules[_dedrm_pkg_name]
# For dedrm.X: import X as a top-level module first, then reuse it
subname = spec.name[len(_dedrm_pkg_name) + 1:]
if subname not in sys.modules:
import importlib as _il
_il.import_module(subname)
# Return a fresh module; exec_module will copy attrs from top-level
import types as _t
return _t.ModuleType(spec.name)

def exec_module(self, module):
if module.__name__ == _dedrm_pkg_name:
return # stub package — nothing to execute
subname = module.__name__[len(_dedrm_pkg_name) + 1:]
if subname in sys.modules:
_skip = {'__name__', '__spec__', '__loader__',
'__package__', '__file__', '__cached__', '__builtins__'}
for _k, _v in sys.modules[subname].__dict__.items():
if _k not in _skip:
module.__dict__[_k] = _v

if _dedrm_pkg_name not in sys.modules:
_dedrm_pkg = _types.ModuleType(_dedrm_pkg_name)
_dedrm_pkg.__path__ = []
_dedrm_pkg.__package__ = _dedrm_pkg_name
_dedrm_pkg.__spec__ = None
sys.modules[_dedrm_pkg_name] = _dedrm_pkg

if not any(type(f).__name__ == "_DeDRMFinder" for f in sys.meta_path):
sys.meta_path.append(_DeDRMFinder())

__package__ = _dedrm_pkg_name

#@@CALIBRE_COMPAT_CODE_END@@
8 changes: 7 additions & 1 deletion DeDRM_plugin/prefs.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@
except:
from standalone.jsonconfig import JSONConfig

from __init__ import PLUGIN_NAME
try:
from __version__ import PLUGIN_NAME
except ImportError:
try:
from __init__ import PLUGIN_NAME # type: ignore
except ImportError:
PLUGIN_NAME = "DeDRM" # standalone fallback

class DeDRM_Prefs():
def __init__(self, json_path=None):
Expand Down
6 changes: 3 additions & 3 deletions DeDRM_plugin/standalone/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,10 @@ def execute_action(action, filenames, params):

elif action == "remove_drm":
if not os.path.isfile(os.path.abspath(config_file_path)):
print("Config file missing ...")
print("Config file not found — will use defaults and auto-discover keys.")

from standalone.remove_drm import perform_action
perform_action(params, filenames)
sys.exit(perform_action(params, filenames))

elif action == "config":
import prefs
Expand Down
Loading