Gather the CLI command modules into a commands sub-package

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-17 22:38:26 +08:00
co-authored by Claude Fable 5
parent 396848e898
commit b727284ef3
17 changed files with 128 additions and 82 deletions
+8
View File
@@ -245,3 +245,11 @@
故檔案可再生,依 commit 判準不進 git(且含歌詞全文, 故檔案可再生,依 commit 判準不進 git(且含歌詞全文,
版權亦不許);固定匯出全部歌曲,缺歌詞即失敗;單一 版權亦不許);固定匯出全部歌曲,缺歌詞即失敗;單一
位置引數收輸出檔路徑,文件範例輸出至 `tools/instance/` 位置引數收輸出檔路徑,文件範例輸出至 `tools/instance/`
- **指令模組集中為 `commands` sub-package**:五個子命令模組
移入 `pop_fem_audit_tools.commands``__init__`
`from .run_llm import main as run_llm_command` 逐條登記為
指令清單,`__main__` 只消費此 façade`_command` 後綴避免
與子模組同名遮蔽,測試仍以模組屬性風格使用;基礎設施模組
configdatabasemodelsutils)留頂層。理由:「指令
vs 共用底層」由目錄結構直接表達,與「哪個函式屬哪個工作」
的歸屬原則同型。
+14 -13
View File
@@ -34,21 +34,22 @@ pop-fem-audit/
│ │ # gitignored;含歌詞全文) │ │ # gitignored;含歌詞全文)
│ ├── src/pop_fem_audit_tools/ │ ├── src/pop_fem_audit_tools/
│ │ ├── __main__.py # 套件 CLI 進入點(分派子命令) │ │ ├── __main__.py # 套件 CLI 進入點(分派子命令)
│ │ ├── build_db.py # build the SQLite working store │ │ ├── commands/ # CLI 子命令模組(登記於 __init__)
│ │ │ # from the inputs │ │ │ ├── build_db.py # build the SQLite working store
│ │ ├── config.py # pydantic-settings 設定(.env │ │ │ │ # from the inputs
│ │ ├── database.py # SQLAlchemy engine / session / Base │ │ │ ├── export_llm_input.py # export the LLM input JSONL
│ │ ├── export_llm_input.py # export the LLM input JSONL │ │ │ │ # (lyrics only) from the
│ │ │ # (lyrics only) from the working │ │ │ # working store
│ │ │ # store │ │ │ ├── fetch_artists.py # fetch artist metadata from
│ │ ├── fetch_artists.py # fetch artist metadata from │ │ │ │ # Wikidata into the snapshot CSV
│ │ │ # Wikidata into the snapshot CSV │ │ │ ├── fetch_lyrics.py # fetch missing lyrics from the
│ │ ├── fetch_lyrics.py # fetch missing lyrics from the │ │ │ │ # public APIs into the lyrics dir
│ │ │ # public APIs into the lyrics dir │ │ │ └── run_llm.py # API runner2+1 協定、Batch API、
│ │ ├── models.py # SQLAlchemy ORM 資料模型
│ │ ├── run_llm.py # API runner2+1 協定、Batch API、
│ │ │ # 寫入引數指定的 runs 目錄;執行 │ │ │ # 寫入引數指定的 runs 目錄;執行
│ │ │ # 方式 pop-fem-audit-tools run-llm │ │ │ # 方式 pop-fem-audit-tools run-llm
│ │ ├── config.py # pydantic-settings 設定(.env
│ │ ├── database.py # SQLAlchemy engine / session / Base
│ │ ├── models.py # SQLAlchemy ORM 資料模型
│ │ └── utils.py # 共用工具(format_duration │ │ └── utils.py # 共用工具(format_duration
│ └── tests/ # 單元測試(unittest │ └── tests/ # 單元測試(unittest
├── runs/ # 每次執行的完整稽核紀錄(進 git) ├── runs/ # 每次執行的完整稽核紀錄(進 git)
@@ -0,0 +1,53 @@
pop\_fem\_audit\_tools.commands package
=======================================
Submodules
----------
pop\_fem\_audit\_tools.commands.build\_db module
------------------------------------------------
.. automodule:: pop_fem_audit_tools.commands.build_db
:members:
:show-inheritance:
:undoc-members:
pop\_fem\_audit\_tools.commands.export\_llm\_input module
---------------------------------------------------------
.. automodule:: pop_fem_audit_tools.commands.export_llm_input
:members:
:show-inheritance:
:undoc-members:
pop\_fem\_audit\_tools.commands.fetch\_artists module
-----------------------------------------------------
.. automodule:: pop_fem_audit_tools.commands.fetch_artists
:members:
:show-inheritance:
:undoc-members:
pop\_fem\_audit\_tools.commands.fetch\_lyrics module
----------------------------------------------------
.. automodule:: pop_fem_audit_tools.commands.fetch_lyrics
:members:
:show-inheritance:
:undoc-members:
pop\_fem\_audit\_tools.commands.run\_llm module
-----------------------------------------------
.. automodule:: pop_fem_audit_tools.commands.run_llm
:members:
:show-inheritance:
:undoc-members:
Module contents
---------------
.. automodule:: pop_fem_audit_tools.commands
:members:
:show-inheritance:
:undoc-members:
+8 -40
View File
@@ -1,17 +1,17 @@
pop\_fem\_audit\_tools package pop\_fem\_audit\_tools package
============================== ==============================
Subpackages
-----------
.. toctree::
:maxdepth: 4
pop_fem_audit_tools.commands
Submodules Submodules
---------- ----------
pop\_fem\_audit\_tools.build\_db module
---------------------------------------
.. automodule:: pop_fem_audit_tools.build_db
:members:
:show-inheritance:
:undoc-members:
pop\_fem\_audit\_tools.config module pop\_fem\_audit\_tools.config module
------------------------------------ ------------------------------------
@@ -28,30 +28,6 @@ pop\_fem\_audit\_tools.database module
:show-inheritance: :show-inheritance:
:undoc-members: :undoc-members:
pop\_fem\_audit\_tools.export\_llm\_input module
------------------------------------------------
.. automodule:: pop_fem_audit_tools.export_llm_input
:members:
:show-inheritance:
:undoc-members:
pop\_fem\_audit\_tools.fetch\_artists module
--------------------------------------------
.. automodule:: pop_fem_audit_tools.fetch_artists
:members:
:show-inheritance:
:undoc-members:
pop\_fem\_audit\_tools.fetch\_lyrics module
-------------------------------------------
.. automodule:: pop_fem_audit_tools.fetch_lyrics
:members:
:show-inheritance:
:undoc-members:
pop\_fem\_audit\_tools.models module pop\_fem\_audit\_tools.models module
------------------------------------ ------------------------------------
@@ -60,14 +36,6 @@ pop\_fem\_audit\_tools.models module
:show-inheritance: :show-inheritance:
:undoc-members: :undoc-members:
pop\_fem\_audit\_tools.run\_llm module
--------------------------------------
.. automodule:: pop_fem_audit_tools.run_llm
:members:
:show-inheritance:
:undoc-members:
pop\_fem\_audit\_tools.utils module pop\_fem\_audit\_tools.utils module
----------------------------------- -----------------------------------
+11 -11
View File
@@ -15,23 +15,23 @@ from collections.abc import Callable
from importlib.machinery import ModuleSpec from importlib.machinery import ModuleSpec
from types import ModuleType from types import ModuleType
from pop_fem_audit_tools import ( from .commands import (
build_db, build_db_command,
export_llm_input, export_llm_input_command,
fetch_artists, fetch_artists_command,
fetch_lyrics, fetch_lyrics_command,
run_llm, run_llm_command,
) )
MODULE_PROG: str = "python -m pop_fem_audit_tools" MODULE_PROG: str = "python -m pop_fem_audit_tools"
"""The program name when run with ``python -m``.""" """The program name when run with ``python -m``."""
SUBCOMMANDS: dict[str, Callable[[list[str] | None], int]] = { SUBCOMMANDS: dict[str, Callable[[list[str] | None], int]] = {
"build-db": build_db.main, "build-db": build_db_command,
"export-llm-input": export_llm_input.main, "export-llm-input": export_llm_input_command,
"fetch-artists": fetch_artists.main, "fetch-artists": fetch_artists_command,
"fetch-lyrics": fetch_lyrics.main, "fetch-lyrics": fetch_lyrics_command,
"run-llm": run_llm.main, "run-llm": run_llm_command,
} }
"""The dispatch table from the subcommand name to the tool main.""" """The dispatch table from the subcommand name to the tool main."""
@@ -0,0 +1,10 @@
# Tools for A Feminist Audit of Pop Music.
# Copyright 2026 imacat. All rights reserved.
# Authors:
# imacat@mail.imacat.idv.tw (imacat), 2026/8/4
"""The registry of the CLI subcommands."""
from .build_db import main as build_db_command
from .export_llm_input import main as export_llm_input_command
from .fetch_artists import main as fetch_artists_command
from .fetch_lyrics import main as fetch_lyrics_command
from .run_llm import main as run_llm_command
@@ -59,8 +59,8 @@ from typing import Any, Self
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from .database import Base, ds from ..database import Base, ds
from .models import ( from ..models import (
Artist, Artist,
ChartEntry, ChartEntry,
Role, Role,
@@ -19,8 +19,8 @@ from pathlib import Path
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from .database import ds from ..database import ds
from .models import Song from ..models import Song
def parse_args(argv: list[str] | None) -> argparse.Namespace: def parse_args(argv: list[str] | None) -> argparse.Namespace:
@@ -34,10 +34,10 @@ from typing import Any, Literal, TextIO
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from . import VERSION from .. import VERSION
from .database import ds from ..database import ds
from .models import Artist, Song, SongArtist from ..models import Artist, Song, SongArtist
from .utils import format_duration from ..utils import format_duration
API_URL: str = "https://www.wikidata.org/w/api.php" API_URL: str = "https://www.wikidata.org/w/api.php"
"""The URL of the Wikidata API endpoint.""" """The URL of the Wikidata API endpoint."""
@@ -36,14 +36,14 @@ from typing import Any
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from .database import ds from ..database import ds
from .models import ( from ..models import (
Artist, Artist,
Role, Role,
Song, Song,
SongArtist, SongArtist,
) )
from .utils import format_duration from ..utils import format_duration
PROVENANCE_FIELDS: Sequence[str] = ( PROVENANCE_FIELDS: Sequence[str] = (
"song_id", "source", "method", "acquired_at", "note") "song_id", "source", "method", "acquired_at", "note")
@@ -26,7 +26,7 @@ from typing import Any, Self
import anthropic import anthropic
from .config import get_settings from ..config import get_settings
MODEL: str = "claude-sonnet-4-6" MODEL: str = "claude-sonnet-4-6"
TEMPERATURE: float = 0.0 TEMPERATURE: float = 0.0
+2 -1
View File
@@ -15,7 +15,8 @@ from unittest import mock
import sqlalchemy as sa import sqlalchemy as sa
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from pop_fem_audit_tools import build_db, config from pop_fem_audit_tools import config
from pop_fem_audit_tools.commands import build_db
from pop_fem_audit_tools.database import DataSource from pop_fem_audit_tools.database import DataSource
from pop_fem_audit_tools.models import ( from pop_fem_audit_tools.models import (
Artist, Artist,
+2 -1
View File
@@ -14,7 +14,8 @@ from unittest import mock
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from pop_fem_audit_tools import config, export_llm_input from pop_fem_audit_tools import config
from pop_fem_audit_tools.commands import export_llm_input
from pop_fem_audit_tools.database import Base, DataSource from pop_fem_audit_tools.database import Base, DataSource
from pop_fem_audit_tools.models import ( from pop_fem_audit_tools.models import (
Artist, Artist,
+2 -1
View File
@@ -16,7 +16,8 @@ from unittest import mock
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from pop_fem_audit_tools import config, fetch_artists from pop_fem_audit_tools import config
from pop_fem_audit_tools.commands import fetch_artists
from pop_fem_audit_tools.database import Base, DataSource from pop_fem_audit_tools.database import Base, DataSource
from pop_fem_audit_tools.models import Artist, Role, Song, SongArtist from pop_fem_audit_tools.models import Artist, Role, Song, SongArtist
+2 -1
View File
@@ -16,7 +16,8 @@ from unittest import mock
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from pop_fem_audit_tools import config, fetch_lyrics from pop_fem_audit_tools import config
from pop_fem_audit_tools.commands import fetch_lyrics
from pop_fem_audit_tools.database import Base, DataSource from pop_fem_audit_tools.database import Base, DataSource
from pop_fem_audit_tools.models import ( from pop_fem_audit_tools.models import (
Artist, Artist,
+2 -1
View File
@@ -11,7 +11,8 @@ import unittest
from contextlib import redirect_stderr, redirect_stdout from contextlib import redirect_stderr, redirect_stdout
from unittest import mock from unittest import mock
from pop_fem_audit_tools import __main__, run_llm from pop_fem_audit_tools import __main__
from pop_fem_audit_tools.commands import run_llm
class TestDispatcher(unittest.TestCase): class TestDispatcher(unittest.TestCase):
+2 -1
View File
@@ -14,7 +14,8 @@ from pathlib import Path
from typing import Any from typing import Any
from unittest import mock from unittest import mock
from pop_fem_audit_tools import config, run_llm from pop_fem_audit_tools import config
from pop_fem_audit_tools.commands import run_llm
class RunLLMTestCase(unittest.TestCase): class RunLLMTestCase(unittest.TestCase):