Gather the CLI command modules into a commands sub-package
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -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` 後綴避免
|
||||||
|
與子模組同名遮蔽,測試仍以模組屬性風格使用;基礎設施模組
|
||||||
|
(config/database/models/utils)留頂層。理由:「指令
|
||||||
|
vs 共用底層」由目錄結構直接表達,與「哪個函式屬哪個工作」
|
||||||
|
的歸屬原則同型。
|
||||||
|
|||||||
+14
-13
@@ -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 runner:2+1 協定、Batch API、
|
||||||
│ │ ├── models.py # SQLAlchemy ORM 資料模型
|
|
||||||
│ │ ├── run_llm.py # API runner:2+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:
|
||||||
@@ -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
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
+2
-2
@@ -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,
|
||||||
+2
-2
@@ -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:
|
||||||
+4
-4
@@ -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."""
|
||||||
+3
-3
@@ -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")
|
||||||
+1
-1
@@ -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
|
||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
Reference in New Issue
Block a user