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
|
# Run the application
|
||||||
make run
|
make run
|
||||||
|
# Or use the package entry point
|
||||||
|
python -m thechart
|
||||||
|
|
||||||
# Run tests (consolidated test suite)
|
# Run tests (consolidated test suite)
|
||||||
make test
|
make test
|
||||||
@@ -96,8 +98,9 @@ python -m venv .venv
|
|||||||
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
|
||||||
# Run the application
|
# Run the application (any of the following)
|
||||||
python src/main.py
|
python src/main.py
|
||||||
|
python -m thechart
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🧪 Testing
|
## 🧪 Testing
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ dependencies = [
|
|||||||
"ttkthemes>=3.2.2",
|
"ttkthemes>=3.2.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
thechart = "thechart.__main__:main"
|
||||||
|
|
||||||
[dependency-groups]
|
[dependency-groups]
|
||||||
dev = [
|
dev = [
|
||||||
"pre-commit>=4.2.0",
|
"pre-commit>=4.2.0",
|
||||||
@@ -104,3 +107,15 @@ indent-style = "space" # Use spaces for indentation
|
|||||||
|
|
||||||
[tool.ruff.lint.pycodestyle]
|
[tool.ruff.lint.pycodestyle]
|
||||||
max-line-length = 88
|
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}")
|
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()
|
root: tk.Tk = tk.Tk()
|
||||||
app: MedTrackerApp = MedTrackerApp(root)
|
_ = MedTrackerApp(root)
|
||||||
root.mainloop()
|
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
|
version = 1
|
||||||
revision = 3
|
revision = 2
|
||||||
requires-python = ">=3.13"
|
requires-python = ">=3.13"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -758,7 +758,7 @@ wheels = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "thechart"
|
name = "thechart"
|
||||||
version = "1.14.9"
|
version = "1.14.9"
|
||||||
source = { virtual = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
{ name = "colorlog" },
|
{ name = "colorlog" },
|
||||||
{ name = "dotenv" },
|
{ name = "dotenv" },
|
||||||
|
|||||||
Reference in New Issue
Block a user