update refactoring and add new features
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
from CLI import MedeiaLexer
|
||||
|
||||
|
||||
class DummyDocument:
|
||||
def __init__(self, lines):
|
||||
self.lines = list(lines)
|
||||
|
||||
lexer = MedeiaLexer()
|
||||
doc = DummyDocument([r'C:\path\to\file'])
|
||||
print(lexer.lex_document(doc)(0))
|
||||
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/env python3
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
sys.path.insert(0, r'C:\Forgejo\Medios-Macina')
|
||||
from tests.test_cli_parsing import *
|
||||
|
||||
failed = 0
|
||||
tests = [(n, o) for n, o in globals().items() if n.startswith('test_') and callable(o)]
|
||||
for n, o in tests:
|
||||
try:
|
||||
o()
|
||||
print(n, 'OK')
|
||||
except Exception as e:
|
||||
print(n, 'FAIL', e)
|
||||
traceback.print_exc()
|
||||
failed += 1
|
||||
|
||||
if failed:
|
||||
sys.exit(1)
|
||||
print('All tests passed')
|
||||
@@ -0,0 +1,10 @@
|
||||
import importlib
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
try:
|
||||
importlib.import_module("CLI")
|
||||
print("CLI imported OK")
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
@@ -0,0 +1,23 @@
|
||||
from pathlib import Path
|
||||
p = Path('Store/registry.py')
|
||||
lines = p.read_text(encoding='utf-8').splitlines()
|
||||
stack = [0]
|
||||
for i, line in enumerate(lines, start=1):
|
||||
if not line.strip():
|
||||
continue
|
||||
leading = len(line) - len(line.lstrip(' '))
|
||||
if leading > stack[-1]:
|
||||
# increased indent -> push
|
||||
stack.append(leading)
|
||||
else:
|
||||
# dedent: must match an existing level
|
||||
if leading != stack[-1]:
|
||||
if leading in stack:
|
||||
# pop until match
|
||||
while stack and stack[-1] != leading:
|
||||
stack.pop()
|
||||
else:
|
||||
print(f"Line {i}: inconsistent indent {leading}, stack levels {stack}")
|
||||
print(repr(line))
|
||||
break
|
||||
print('Done')
|
||||
@@ -0,0 +1,19 @@
|
||||
import re
|
||||
from pathlib import Path
|
||||
p = Path(r'c:\Forgejo\Medios-Macina\CLI.py')
|
||||
s = p.read_text(encoding='utf-8')
|
||||
pattern = re.compile(r'(?s)if False:\s*class _OldPipelineExecutor:.*?from rich\\.markdown import Markdown\\s*')
|
||||
m = pattern.search(s)
|
||||
print('found', bool(m))
|
||||
if m:
|
||||
print('start', m.start(), 'end', m.end())
|
||||
print('snippet:', s[m.start():m.start()+120])
|
||||
else:
|
||||
# print a slice around the if False for debugging
|
||||
i = s.find('if False:')
|
||||
print('if False index', i)
|
||||
print('around if False:', s[max(0,i-50):i+200])
|
||||
j = s.find('from rich.markdown import Markdown', i)
|
||||
print('next from rich index after if False', j)
|
||||
if j!=-1:
|
||||
print('around that:', s[j-50:j+80])
|
||||
@@ -0,0 +1,12 @@
|
||||
import traceback
|
||||
|
||||
try:
|
||||
from PluginCore.backend_registry import BackendRegistry
|
||||
s = BackendRegistry(config={}, suppress_debug=True)
|
||||
print('INSTANCE TYPE:', type(s))
|
||||
print('HAS is_available:', hasattr(s, 'is_available'))
|
||||
if hasattr(s, 'is_available'):
|
||||
print('is_available callable:', callable(getattr(s, 'is_available')))
|
||||
print('DIR:', sorted([n for n in dir(s) if not n.startswith('__')]))
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
@@ -0,0 +1,35 @@
|
||||
from pathlib import Path
|
||||
p=Path('SYS/pipeline.py')
|
||||
s=p.read_text(encoding='utf-8')
|
||||
lines=s.splitlines()
|
||||
stack=[]
|
||||
for i,l in enumerate(lines,1):
|
||||
stripped=l.strip()
|
||||
# Skip commented lines
|
||||
if stripped.startswith('#'):
|
||||
continue
|
||||
# compute indent as leading spaces (tabs are converted)
|
||||
indent = len(l) - len(l.lstrip(' '))
|
||||
if stripped.startswith('try:'):
|
||||
stack.append((indent, i))
|
||||
if stripped.startswith('except ') or stripped=='except:' or stripped.startswith('finally:'):
|
||||
# find the most recent try with same indent
|
||||
for idx in range(len(stack)-1, -1, -1):
|
||||
if stack[idx][0] == indent:
|
||||
stack.pop(idx)
|
||||
break
|
||||
else:
|
||||
# no matching try at same indent
|
||||
print(f"Found {stripped.split()[0]} at line {i} with no matching try at same indent")
|
||||
|
||||
print('Unmatched try count', len(stack))
|
||||
if stack:
|
||||
print('Unmatched try positions (indent, line):', stack)
|
||||
for indent, lineno in stack:
|
||||
start = max(1, lineno - 10)
|
||||
end = min(len(lines), lineno + 10)
|
||||
print(f"Context around line {lineno}:")
|
||||
for i in range(start, end + 1):
|
||||
print(f"{i:5d}: {lines[i-1]}")
|
||||
else:
|
||||
print("All try statements appear matched")
|
||||
+9
-85
@@ -8,7 +8,7 @@ running from a development checkout (by importing the top-level
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional, List, Tuple
|
||||
from typing import Optional, List
|
||||
import importlib
|
||||
import importlib.util
|
||||
import os
|
||||
@@ -64,91 +64,32 @@ def _ensure_repo_root_on_sys_path(pkg_file: Optional[Path] = None) -> Optional[P
|
||||
return None
|
||||
|
||||
|
||||
def _parse_mode_and_strip_args(args: List[str]) -> Tuple[Optional[str], List[str]]:
|
||||
"""Parse --gui/--cli/--mode flags and return (mode, cleaned_args).
|
||||
def _strip_mode_args(args: List[str]) -> List[str]:
|
||||
"""Strip --gui/--cli/--mode flags from argument list.
|
||||
|
||||
The function removes any mode flags from the argument list so the selected
|
||||
runner can receive the remaining arguments untouched.
|
||||
|
||||
Supported forms:
|
||||
--gui, -g, --gui=true
|
||||
--cli, -c, --cli=true
|
||||
--mode=gui|cli
|
||||
--mode gui|cli
|
||||
|
||||
Raises ValueError on conflicting or invalid flags.
|
||||
The GUI/TUI mode has been discontinued. Any mode flags are silently
|
||||
consumed so they don't interfere with remaining argument parsing.
|
||||
"""
|
||||
mode: Optional[str] = None
|
||||
out: List[str] = []
|
||||
i = 0
|
||||
while i < len(args):
|
||||
a = args[i]
|
||||
la = a.lower()
|
||||
|
||||
# --gui / -g
|
||||
if la in ("--gui", "-g"):
|
||||
if mode and mode != "gui":
|
||||
raise ValueError("Conflicting mode flags: found both 'gui' and 'cli'")
|
||||
mode = "gui"
|
||||
if la in ("--gui", "-g", "--cli", "-c"):
|
||||
i += 1
|
||||
continue
|
||||
if la.startswith("--gui="):
|
||||
val = la.split("=", 1)[1]
|
||||
if val and val not in ("0", "false", "no", "off"):
|
||||
if mode and mode != "gui":
|
||||
raise ValueError(
|
||||
"Conflicting mode flags: found both 'gui' and 'cli'"
|
||||
)
|
||||
mode = "gui"
|
||||
if la.startswith("--gui=") or la.startswith("--cli="):
|
||||
i += 1
|
||||
continue
|
||||
|
||||
# --cli / -c
|
||||
if la in ("--cli", "-c"):
|
||||
if mode and mode != "cli":
|
||||
raise ValueError("Conflicting mode flags: found both 'gui' and 'cli'")
|
||||
mode = "cli"
|
||||
i += 1
|
||||
continue
|
||||
if la.startswith("--cli="):
|
||||
val = la.split("=", 1)[1]
|
||||
if val and val not in ("0", "false", "no", "off"):
|
||||
if mode and mode != "cli":
|
||||
raise ValueError(
|
||||
"Conflicting mode flags: found both 'gui' and 'cli'"
|
||||
)
|
||||
mode = "cli"
|
||||
i += 1
|
||||
continue
|
||||
|
||||
# --mode
|
||||
if la.startswith("--mode="):
|
||||
val = la.split("=", 1)[1]
|
||||
val = val.lower()
|
||||
if val not in ("gui", "cli"):
|
||||
raise ValueError("--mode must be 'gui' or 'cli'")
|
||||
if mode and mode != val:
|
||||
raise ValueError("Conflicting mode flags: found both 'gui' and 'cli'")
|
||||
mode = val
|
||||
i += 1
|
||||
continue
|
||||
if la == "--mode":
|
||||
if i + 1 >= len(args):
|
||||
raise ValueError("--mode requires a value ('gui' or 'cli')")
|
||||
val = args[i + 1].lower()
|
||||
if val not in ("gui", "cli"):
|
||||
raise ValueError("--mode must be 'gui' or 'cli'")
|
||||
if mode and mode != val:
|
||||
raise ValueError("Conflicting mode flags: found both 'gui' and 'cli'")
|
||||
mode = val
|
||||
i += 2
|
||||
continue
|
||||
|
||||
# Not a mode flag; keep it
|
||||
out.append(a)
|
||||
i += 1
|
||||
|
||||
return mode, out
|
||||
return out
|
||||
|
||||
|
||||
def _run_cli(clean_args: List[str]) -> int:
|
||||
@@ -221,15 +162,6 @@ def _run_cli(clean_args: List[str]) -> int:
|
||||
return int(getattr(exc, "code", 0) or 0)
|
||||
|
||||
|
||||
def _run_gui(clean_args: List[str]) -> int:
|
||||
"""Report that the discontinued GUI/TUI mode is no longer available."""
|
||||
_ = clean_args
|
||||
print(
|
||||
"Error: GUI/TUI mode has been discontinued and is no longer available.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 2
|
||||
|
||||
|
||||
def main(argv: Optional[List[str]] = None) -> int:
|
||||
"""Entry point for console_scripts.
|
||||
@@ -239,11 +171,7 @@ def main(argv: Optional[List[str]] = None) -> int:
|
||||
"""
|
||||
args = list(argv) if argv is not None else list(sys.argv[1:])
|
||||
|
||||
try:
|
||||
mode, clean_args = _parse_mode_and_strip_args(args)
|
||||
except ValueError as exc:
|
||||
print(f"Error parsing mode flags: {exc}", file=sys.stderr)
|
||||
return 2
|
||||
clean_args = _strip_mode_args(args)
|
||||
|
||||
# Early environment sanity check to detect urllib3/urllib3-future conflicts.
|
||||
# When a broken urllib3 is detected we print an actionable message and
|
||||
@@ -262,10 +190,6 @@ def main(argv: Optional[List[str]] = None) -> int:
|
||||
# startup; we'll continue and let normal import errors surface.
|
||||
pass
|
||||
|
||||
# If GUI requested, delegate directly (GUI may decide to honor any args itself)
|
||||
if mode == "gui":
|
||||
return _run_gui(clean_args)
|
||||
|
||||
# Support quoting a pipeline (or even a single full command) on the command line.
|
||||
#
|
||||
# - If the user provides a single argument that contains a pipe character,
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
import importlib
|
||||
import traceback
|
||||
|
||||
try:
|
||||
m = importlib.import_module('Provider.vimm')
|
||||
print('Imported', m)
|
||||
print('Vimm class:', getattr(m, 'Vimm', None))
|
||||
except Exception as e:
|
||||
print('Import failed:', e)
|
||||
traceback.print_exc()
|
||||
@@ -0,0 +1,6 @@
|
||||
from pathlib import Path
|
||||
p = Path('Store/registry.py')
|
||||
for i, line in enumerate(p.read_text(encoding='utf-8').splitlines(), start=1):
|
||||
leading = len(line) - len(line.lstrip(' '))
|
||||
if leading > 20:
|
||||
print(i, leading, repr(line))
|
||||
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Format all tracked Python files using the repo's YAPF style.
|
||||
|
||||
This script intentionally formats only files tracked by git to avoid touching
|
||||
files that are ignored (e.g., venv, site-packages).
|
||||
"""
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
try:
|
||||
out = subprocess.check_output(["git", "ls-files", "*.py"]).decode("utf-8")
|
||||
except subprocess.CalledProcessError as exc:
|
||||
print("Failed to get tracked files from git:", exc, file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
files = [f for f in (line.strip() for line in out.splitlines()) if f]
|
||||
print(f"Formatting {len(files)} tracked python files...")
|
||||
if not files:
|
||||
print("No tracked python files found.")
|
||||
sys.exit(0)
|
||||
|
||||
for path in files:
|
||||
print(path)
|
||||
subprocess.run([sys.executable, "-m", "yapf", "-i", "--style", ".style.yapf", path], check=False)
|
||||
|
||||
print("Done")
|
||||
@@ -0,0 +1,11 @@
|
||||
import pathlib
|
||||
p = pathlib.Path('Store/registry.py')
|
||||
with p.open('r', encoding='utf-8') as f:
|
||||
lines = f.readlines()
|
||||
for i in range(312, 328):
|
||||
if i-1 < len(lines):
|
||||
line = lines[i-1]
|
||||
leading = line[:len(line)-len(line.lstrip('\t '))]
|
||||
print(f"{i}: {repr(line.rstrip())} | leading={repr(leading)} len={len(leading)} chars={[ord(c) for c in leading]}")
|
||||
else:
|
||||
print(f"{i}: <EOF>")
|
||||
@@ -0,0 +1,10 @@
|
||||
from pathlib import Path
|
||||
p = Path('Store/registry.py')
|
||||
counts = {}
|
||||
for i, line in enumerate(p.read_text(encoding='utf-8').splitlines(), start=1):
|
||||
if not line.strip():
|
||||
continue
|
||||
leading = len(line) - len(line.lstrip(' '))
|
||||
counts[leading] = counts.get(leading, 0) + 1
|
||||
for k in sorted(counts.keys()):
|
||||
print(k, counts[k])
|
||||
@@ -0,0 +1,3 @@
|
||||
from PluginCore.registry import list_plugins
|
||||
|
||||
print('All plugins:', list_plugins())
|
||||
@@ -1,197 +0,0 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=65.0", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "medeia-macina"
|
||||
version = "0.1.0"
|
||||
description = "Comprehensive media management and search platform with support for local files, Hydrus database, torrents, books, and P2P networks"
|
||||
requires-python = ">=3.9,<3.14"
|
||||
license = {text = "MIT"}
|
||||
authors = [
|
||||
{name = "Your Name", email = "your.email@example.com"}
|
||||
]
|
||||
keywords = ["media", "search", "management", "hydrus", "download", "cli", "tui"]
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Environment :: Console",
|
||||
"Intended Audience :: End Users/Desktop",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Operating System :: OS Independent",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.9",
|
||||
"Programming Language :: Python :: 3.10",
|
||||
"Programming Language :: Python :: 3.11",
|
||||
"Programming Language :: Python :: 3.12",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Topic :: Multimedia",
|
||||
"Topic :: Internet",
|
||||
]
|
||||
|
||||
dependencies = [
|
||||
# Core CLI and TUI frameworks
|
||||
"typer>=0.9.0",
|
||||
"prompt-toolkit>=3.0.0",
|
||||
"textual>=0.30.0",
|
||||
|
||||
# Media processing and downloading
|
||||
"yt-dlp[default]>=2023.11.0",
|
||||
"yt-dlp-ejs", # EJS challenge solver scripts for YouTube JavaScript challenges
|
||||
"requests>=2.31.0",
|
||||
"charset-normalizer>=3.2.0",
|
||||
"certifi>=2024.12.0",
|
||||
"httpx>=0.25.0",
|
||||
|
||||
# Document and data handling
|
||||
"pypdf>=3.0.0",
|
||||
"mutagen>=1.46.0",
|
||||
"cbor2>=4.0",
|
||||
"zstandard>=0.23.0",
|
||||
|
||||
# Image and media support
|
||||
"Pillow>=10.0.0",
|
||||
"python-bidi>=0.4.2",
|
||||
"ffmpeg-python>=0.2.0",
|
||||
|
||||
# Metadata extraction and processing
|
||||
"musicbrainzngs>=0.7.0",
|
||||
"lxml>=4.9.0",
|
||||
|
||||
# Advanced searching and libraries
|
||||
# Optional Soulseek support installs aioslsk>=1.6.0 when [provider=soulseek] is configured.
|
||||
"imdbinfo>=0.1.10",
|
||||
|
||||
# Encryption and security
|
||||
"pycryptodome>=3.18.0",
|
||||
|
||||
# Data processing
|
||||
"bencode3",
|
||||
"tqdm>=4.66.0",
|
||||
|
||||
# Browser automation
|
||||
"playwright>=1.40.0",
|
||||
"paramiko>=3.5.0",
|
||||
"scp>=0.15.0",
|
||||
|
||||
# Development and utilities
|
||||
"python-dateutil>=2.8.0",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
# Testing
|
||||
"pytest>=7.4.0",
|
||||
"pytest-cov>=4.1.0",
|
||||
"pytest-asyncio>=0.21.0",
|
||||
|
||||
# Code quality
|
||||
"black>=23.11.0",
|
||||
"flake8>=6.1.0",
|
||||
"isort>=5.12.0",
|
||||
"mypy>=1.7.0",
|
||||
"pylint>=3.0.0",
|
||||
|
||||
# Documentation
|
||||
"sphinx>=7.2.0",
|
||||
"sphinx-rtd-theme>=1.3.0",
|
||||
|
||||
# Debugging and profiling
|
||||
"ipython>=8.17.0",
|
||||
"ipdb>=0.13.0",
|
||||
"memory-profiler>=0.61.0",
|
||||
|
||||
# Version control and CI/CD helpers
|
||||
"pre-commit>=3.5.0",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
mm = "scripts.cli_entry:main"
|
||||
medeia = "scripts.cli_entry:main"
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/yourusername/medeia-macina"
|
||||
Documentation = "https://medeia-macina.readthedocs.io"
|
||||
Repository = "https://github.com/yourusername/medeia-macina.git"
|
||||
Issues = "https://github.com/yourusername/medeia-macina/issues"
|
||||
|
||||
[tool.setuptools]
|
||||
packages = [
|
||||
"scripts",
|
||||
"cmdlet",
|
||||
"cmdnat",
|
||||
"API",
|
||||
"PluginCore",
|
||||
"SYS",
|
||||
]
|
||||
package-dir = {"" = ".."}
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
scripts = ["*.py"]
|
||||
|
||||
|
||||
[tool.black]
|
||||
line-length = 100
|
||||
target-version = ['py39', 'py310', 'py311', 'py312']
|
||||
include = '\\.pyi?$'
|
||||
extend-exclude = '''
|
||||
/(
|
||||
# directories
|
||||
\.eggs
|
||||
| \.git
|
||||
| \.hg
|
||||
| \.mypy_cache
|
||||
| \.tox
|
||||
| \.venv
|
||||
| _build
|
||||
| buck-out
|
||||
| build
|
||||
| dist
|
||||
| __pycache__
|
||||
)/
|
||||
'''
|
||||
|
||||
[tool.isort]
|
||||
profile = "black"
|
||||
line_length = 100
|
||||
target_version = ["py39", "py310", "py311", "py312"]
|
||||
|
||||
[tool.mypy]
|
||||
python_version = "3.9"
|
||||
warn_return_any = true
|
||||
warn_unused_configs = true
|
||||
disallow_untyped_defs = false
|
||||
disallow_incomplete_defs = false
|
||||
check_untyped_defs = false
|
||||
no_implicit_optional = true
|
||||
warn_redundant_casts = true
|
||||
warn_unused_ignores = true
|
||||
warn_no_return = true
|
||||
|
||||
[tool.pylint.messages_control]
|
||||
disable = [
|
||||
"C0330", "C0326", # Bad whitespace
|
||||
"R0913", # Too many arguments
|
||||
"R0914", # Too many local variables
|
||||
]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["tests"]
|
||||
python_files = ["test_*.py", "*_test.py"]
|
||||
addopts = "-v --cov=. --cov-report=html --cov-report=term-missing"
|
||||
|
||||
[tool.coverage.run]
|
||||
branch = true
|
||||
omit = [
|
||||
"*/tests/*",
|
||||
"*/__main__.py",
|
||||
]
|
||||
|
||||
[tool.coverage.report]
|
||||
exclude_lines = [
|
||||
"pragma: no cover",
|
||||
"def __repr__",
|
||||
"raise AssertionError",
|
||||
"raise NotImplementedError",
|
||||
"if __name__ == .__main__.:",
|
||||
"if TYPE_CHECKING:",
|
||||
]
|
||||
@@ -14,6 +14,7 @@ charset-normalizer>=3.2.0
|
||||
certifi>=2024.12.0
|
||||
# Optional Telegram support installs telethon>=1.36.0 when [provider=telegram] is configured.
|
||||
internetarchive>=4.1.0
|
||||
yt-dlp-ejs
|
||||
|
||||
# Document and data handling
|
||||
pypdf>=3.0.0
|
||||
@@ -44,7 +45,8 @@ tqdm>=4.66.0
|
||||
|
||||
# Browser automation (for web scraping if needed)
|
||||
playwright>=1.40.0
|
||||
paramiko>=3.5.0
|
||||
scp>=0.15.0
|
||||
|
||||
# Development and utilities
|
||||
python-dateutil>=2.8.0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user