feat: Add package structure for TheChart, implement entry points for console scripts and module execution
This commit is contained in:
@@ -8,6 +8,8 @@ make install
|
||||
|
||||
# Run the application
|
||||
make run
|
||||
# Or use the package entry point
|
||||
python -m thechart
|
||||
|
||||
# Run tests (consolidated test suite)
|
||||
make test
|
||||
@@ -96,8 +98,9 @@ python -m venv .venv
|
||||
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Run the application
|
||||
# Run the application (any of the following)
|
||||
python src/main.py
|
||||
python -m thechart
|
||||
```
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
@@ -15,6 +15,9 @@ dependencies = [
|
||||
"ttkthemes>=3.2.2",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
thechart = "thechart.__main__:main"
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"pre-commit>=4.2.0",
|
||||
@@ -104,3 +107,15 @@ indent-style = "space" # Use spaces for indentation
|
||||
|
||||
[tool.ruff.lint.pycodestyle]
|
||||
max-line-length = 88
|
||||
|
||||
[build-system]
|
||||
requires = ["setuptools>=68", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.setuptools]
|
||||
package-dir = { "" = "src" }
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["src"]
|
||||
include = ["thechart*"]
|
||||
exclude = ["tests*"]
|
||||
|
||||
+11
-2
@@ -1675,7 +1675,16 @@ Use Ctrl+S to save entries and Ctrl+Q to quit."""
|
||||
logger.error(f"Error updating tree efficiently: {e}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
def run() -> None:
|
||||
"""Start the TheChart Tkinter application.
|
||||
|
||||
Provided to support `python -m thechart` and a console-script entry point
|
||||
without changing import-time behavior (tests patch symbols on `main`).
|
||||
"""
|
||||
root: tk.Tk = tk.Tk()
|
||||
app: MedTrackerApp = MedTrackerApp(root)
|
||||
_ = MedTrackerApp(root)
|
||||
root.mainloop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
run()
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
"""TheChart package.
|
||||
|
||||
This package provides the main application and components for the
|
||||
TheChart (medication tracker) desktop app.
|
||||
|
||||
Notes
|
||||
-----
|
||||
- This package layer is introduced to follow Python packaging best
|
||||
practices while keeping backward compatibility with existing
|
||||
imports used in tests (e.g., ``src.*``). The original modules under
|
||||
``src/`` remain available; this package enables ``python -m thechart``
|
||||
and console-script usage.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from importlib import metadata as _metadata
|
||||
|
||||
try: # Prefer installed package version if available
|
||||
__version__ = _metadata.version("thechart")
|
||||
except Exception: # Fallback in editable/dev mode
|
||||
__version__ = "0.0.0.dev"
|
||||
|
||||
__all__ = [
|
||||
"__version__",
|
||||
]
|
||||
@@ -0,0 +1,64 @@
|
||||
"""Module entry-point for `python -m thechart` and console scripts.
|
||||
|
||||
This dynamically locates and runs the existing application start-up code
|
||||
without imposing a hard packaging dependency on the development layout.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import os
|
||||
import tkinter as tk
|
||||
|
||||
|
||||
def _load_main_module():
|
||||
"""Load the existing main module from common locations.
|
||||
|
||||
Tries in order:
|
||||
- importlib.import_module("src.main")
|
||||
- importlib.import_module("main")
|
||||
- Load from file path next to this package (.. / main.py)
|
||||
"""
|
||||
|
||||
try:
|
||||
return importlib.import_module("src.main")
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
return importlib.import_module("main")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# File-based fallback for src layout in editable/dev mode
|
||||
try:
|
||||
from importlib.machinery import SourceFileLoader
|
||||
|
||||
here = os.path.dirname(__file__)
|
||||
candidate = os.path.abspath(os.path.join(here, os.pardir, "main.py"))
|
||||
if os.path.exists(candidate):
|
||||
return SourceFileLoader("main", candidate).load_module() # type: ignore[deprecated-import]
|
||||
except Exception:
|
||||
pass
|
||||
raise ImportError("Could not locate application main module")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
"""Start the TheChart application."""
|
||||
mod = _load_main_module()
|
||||
# Prefer a run() entry if available
|
||||
try:
|
||||
run_fn = mod.run # type: ignore[attr-defined]
|
||||
except AttributeError:
|
||||
run_fn = None # type: ignore[assignment]
|
||||
if callable(run_fn): # type: ignore[truthy-function]
|
||||
run_fn()
|
||||
return
|
||||
# Very old fallback: directly instantiate if run() is absent
|
||||
root = tk.Tk()
|
||||
app_cls = mod.MedTrackerApp # type: ignore[attr-defined]
|
||||
_ = app_cls(root)
|
||||
root.mainloop()
|
||||
|
||||
|
||||
if __name__ == "__main__": # pragma: no cover - simple dispatcher
|
||||
main()
|
||||
@@ -1,5 +1,5 @@
|
||||
version = 1
|
||||
revision = 3
|
||||
revision = 2
|
||||
requires-python = ">=3.13"
|
||||
|
||||
[[package]]
|
||||
@@ -758,7 +758,7 @@ wheels = [
|
||||
[[package]]
|
||||
name = "thechart"
|
||||
version = "1.14.9"
|
||||
source = { virtual = "." }
|
||||
source = { editable = "." }
|
||||
dependencies = [
|
||||
{ name = "colorlog" },
|
||||
{ name = "dotenv" },
|
||||
|
||||
Reference in New Issue
Block a user