btx-lib-mail 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- btx_lib_mail/__init__.py +24 -0
- btx_lib_mail/__init__conf__.py +67 -0
- btx_lib_mail/__main__.py +92 -0
- btx_lib_mail/behaviors.py +133 -0
- btx_lib_mail/cli.py +734 -0
- btx_lib_mail/lib_mail.py +770 -0
- btx_lib_mail/py.typed +0 -0
- btx_lib_mail-1.0.0.dist-info/METADATA +341 -0
- btx_lib_mail-1.0.0.dist-info/RECORD +12 -0
- btx_lib_mail-1.0.0.dist-info/WHEEL +4 -0
- btx_lib_mail-1.0.0.dist-info/entry_points.txt +3 -0
- btx_lib_mail-1.0.0.dist-info/licenses/LICENSE +22 -0
btx_lib_mail/__init__.py
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Public package surface exposing greeting, failure, and metadata hooks."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .behaviors import (
|
|
6
|
+
CANONICAL_GREETING,
|
|
7
|
+
emit_greeting,
|
|
8
|
+
noop_main,
|
|
9
|
+
raise_intentional_failure,
|
|
10
|
+
)
|
|
11
|
+
from .lib_mail import ConfMail, conf, logger, send
|
|
12
|
+
from .__init__conf__ import print_info
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"CANONICAL_GREETING",
|
|
16
|
+
"emit_greeting",
|
|
17
|
+
"noop_main",
|
|
18
|
+
"print_info",
|
|
19
|
+
"raise_intentional_failure",
|
|
20
|
+
"ConfMail",
|
|
21
|
+
"conf",
|
|
22
|
+
"send",
|
|
23
|
+
"logger",
|
|
24
|
+
]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Static package metadata surfaced to CLI commands and documentation.
|
|
2
|
+
|
|
3
|
+
Purpose
|
|
4
|
+
-------
|
|
5
|
+
Expose the current project metadata as simple constants. These values are kept
|
|
6
|
+
in sync with ``pyproject.toml`` by development automation (tests, push
|
|
7
|
+
pipelines), so runtime code does not query packaging metadata.
|
|
8
|
+
|
|
9
|
+
Contents
|
|
10
|
+
--------
|
|
11
|
+
* Module-level constants describing the published package.
|
|
12
|
+
* :func:`print_info` rendering the constants for the CLI ``info`` command.
|
|
13
|
+
|
|
14
|
+
System Role
|
|
15
|
+
-----------
|
|
16
|
+
Lives in the adapters/platform layer; CLI transports import these constants to
|
|
17
|
+
present authoritative project information without invoking packaging APIs.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from __future__ import annotations
|
|
21
|
+
|
|
22
|
+
#: Distribution name declared in ``pyproject.toml``.
|
|
23
|
+
name = "btx_lib_mail"
|
|
24
|
+
#: Human-readable summary shown in CLI help output.
|
|
25
|
+
title = "Template for python apps with registered cli commands"
|
|
26
|
+
#: Current release version pulled from ``pyproject.toml`` by automation.
|
|
27
|
+
version = "1.0.0"
|
|
28
|
+
#: Repository homepage presented to users.
|
|
29
|
+
homepage = "https://github.com/bitranox/btx_lib_mail"
|
|
30
|
+
#: Author attribution surfaced in CLI output.
|
|
31
|
+
author = "bitranox"
|
|
32
|
+
#: Contact email surfaced in CLI output.
|
|
33
|
+
author_email = "bitranox@gmail.com"
|
|
34
|
+
#: Console-script name published by the package.
|
|
35
|
+
shell_command = "btx-lib-mail"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def print_info() -> None:
|
|
39
|
+
"""Print the summarised metadata block used by the CLI ``info`` command.
|
|
40
|
+
|
|
41
|
+
Why
|
|
42
|
+
Provides a single, auditable rendering function so documentation and
|
|
43
|
+
CLI output always match the system design reference.
|
|
44
|
+
|
|
45
|
+
Side Effects
|
|
46
|
+
Writes to ``stdout``.
|
|
47
|
+
|
|
48
|
+
Examples
|
|
49
|
+
--------
|
|
50
|
+
>>> print_info() # doctest: +ELLIPSIS
|
|
51
|
+
Info for btx_lib_mail:
|
|
52
|
+
...
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
fields = [
|
|
56
|
+
("name", name),
|
|
57
|
+
("title", title),
|
|
58
|
+
("version", version),
|
|
59
|
+
("homepage", homepage),
|
|
60
|
+
("author", author),
|
|
61
|
+
("author_email", author_email),
|
|
62
|
+
("shell_command", shell_command),
|
|
63
|
+
]
|
|
64
|
+
pad = max(len(label) for label, _ in fields)
|
|
65
|
+
lines = [f"Info for {name}:", ""]
|
|
66
|
+
lines.extend(f" {label.ljust(pad)} = {value}" for label, value in fields)
|
|
67
|
+
print("\n".join(lines))
|
btx_lib_mail/__main__.py
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
"""## btx_lib_mail.__main__ {#module-btx-lib-mail-main}
|
|
2
|
+
|
|
3
|
+
**Purpose:** Provide the `python -m btx_lib_mail` entry point mandated by the
|
|
4
|
+
packaging guidelines, delegating to `btx_lib_mail.cli.main` so exit semantics
|
|
5
|
+
remain identical to the console script.
|
|
6
|
+
|
|
7
|
+
**Contents:** `_open_cli_session`, `_command_to_run`, `_command_name`, and
|
|
8
|
+
`_module_main` — the helpers that compose module execution with
|
|
9
|
+
`lib_cli_exit_tools`.
|
|
10
|
+
|
|
11
|
+
**System Role:** Mirrors the description in
|
|
12
|
+
`docs/systemdesign/module_reference.md#module-main-session-helpers`, ensuring
|
|
13
|
+
module execution shares the same traceback limits and command wiring as the CLI.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from collections.abc import Callable
|
|
19
|
+
from contextlib import AbstractContextManager
|
|
20
|
+
from typing import Final
|
|
21
|
+
|
|
22
|
+
from lib_cli_exit_tools import cli_session
|
|
23
|
+
import rich_click as click
|
|
24
|
+
|
|
25
|
+
from . import __init__conf__, cli
|
|
26
|
+
|
|
27
|
+
TRACEBACK_SUMMARY_LIMIT: Final[int] = cli.TRACEBACK_SUMMARY_LIMIT
|
|
28
|
+
"""Character budget for truncated tracebacks when running via module entry."""
|
|
29
|
+
TRACEBACK_VERBOSE_LIMIT: Final[int] = cli.TRACEBACK_VERBOSE_LIMIT
|
|
30
|
+
"""Character budget for verbose tracebacks when running via module entry."""
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
CommandRunner = Callable[..., int]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _open_cli_session() -> AbstractContextManager[CommandRunner]:
|
|
37
|
+
"""### _open_cli_session() -> AbstractContextManager[CommandRunner] {#module-main-open-cli-session}
|
|
38
|
+
|
|
39
|
+
**Purpose:** Provide a context manager wired with the agreed traceback
|
|
40
|
+
limits so module execution mirrors the CLI.
|
|
41
|
+
|
|
42
|
+
**Returns:** Context manager yielding the callable that invokes the Click
|
|
43
|
+
command via `lib_cli_exit_tools.cli_session`.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
return cli_session(
|
|
47
|
+
summary_limit=TRACEBACK_SUMMARY_LIMIT,
|
|
48
|
+
verbose_limit=TRACEBACK_VERBOSE_LIMIT,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _command_to_run() -> click.Command:
|
|
53
|
+
"""### _command_to_run() -> click.Command {#module-main-command-to-run}
|
|
54
|
+
|
|
55
|
+
**Purpose:** Identify the root Click command used by module execution.
|
|
56
|
+
|
|
57
|
+
**Returns:** `click.Command` referencing `btx_lib_mail.cli.cli`.
|
|
58
|
+
"""
|
|
59
|
+
|
|
60
|
+
return cli.cli
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def _command_name() -> str:
|
|
64
|
+
"""### _command_name() -> str {#module-main-command-name}
|
|
65
|
+
|
|
66
|
+
**Purpose:** Provide the console-script name announced by the session so
|
|
67
|
+
tests can assert against a single source of truth.
|
|
68
|
+
|
|
69
|
+
**Returns:** `str` containing `__init__conf__.shell_command`.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
return __init__conf__.shell_command
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _module_main() -> int:
|
|
76
|
+
"""### _module_main() -> int {#module-main-module-main}
|
|
77
|
+
|
|
78
|
+
**Purpose:** Implement `python -m btx_lib_mail` by delegating to the CLI
|
|
79
|
+
while preserving traceback limits.
|
|
80
|
+
|
|
81
|
+
**Returns:** `int` exit code produced by the CLI run.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
with _open_cli_session() as runner:
|
|
85
|
+
return runner(
|
|
86
|
+
_command_to_run(),
|
|
87
|
+
prog_name=_command_name(),
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
if __name__ == "__main__":
|
|
92
|
+
raise SystemExit(_module_main())
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"""## btx_lib_mail.behaviors {#module-btx-lib-mail-behaviors}
|
|
2
|
+
|
|
3
|
+
**Purpose:** Gather the domain-placeholder helpers that back the CLI scaffold so
|
|
4
|
+
each behaviour has a single, well-documented home. Keeping the trio together
|
|
5
|
+
lets adapter layers evolve without rewriting domain stubs.
|
|
6
|
+
|
|
7
|
+
**Contents:**
|
|
8
|
+
- `emit_greeting` — success-path helper that emits the canonical message.
|
|
9
|
+
- `raise_intentional_failure` — deterministic failure hook for exercising error paths.
|
|
10
|
+
- `noop_main` — placeholder entry point for transports expecting a `main`.
|
|
11
|
+
|
|
12
|
+
**System Role:** Described in
|
|
13
|
+
`docs/systemdesign/module_reference.md#feature-cli-behavior-scaffold`; this
|
|
14
|
+
module represents the current domain surface for the template while richer
|
|
15
|
+
features incubate elsewhere.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
from typing import Final, TextIO
|
|
21
|
+
|
|
22
|
+
import sys
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
CANONICAL_GREETING: Final[str] = "Hello World"
|
|
26
|
+
"""Canonical greeting line shared across CLI and smoke tests."""
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _target_stream(preferred: TextIO | None) -> TextIO:
|
|
30
|
+
"""Return the stream that should hear the greeting."""
|
|
31
|
+
|
|
32
|
+
return preferred if preferred is not None else sys.stdout
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _greeting_line() -> str:
|
|
36
|
+
"""Return the greeting exactly as it should appear."""
|
|
37
|
+
|
|
38
|
+
return f"{CANONICAL_GREETING}\n"
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def _flush_if_possible(stream: TextIO) -> None:
|
|
42
|
+
"""Flush the stream when the stream knows how to flush."""
|
|
43
|
+
|
|
44
|
+
flush = getattr(stream, "flush", None)
|
|
45
|
+
if callable(flush):
|
|
46
|
+
flush()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def emit_greeting(*, stream: TextIO | None = None) -> None:
|
|
50
|
+
"""### emit_greeting(stream: TextIO | None = None) {#behaviors-emit-greeting}
|
|
51
|
+
|
|
52
|
+
**Purpose:** Offer a deterministic success story that documentation, tests,
|
|
53
|
+
and CLI commands can reuse while the real domain behaviour is still under
|
|
54
|
+
construction.
|
|
55
|
+
|
|
56
|
+
**What:** Writes `CANONICAL_GREETING` followed by a newline to the selected
|
|
57
|
+
text stream and flushes the stream when a `flush` method exists.
|
|
58
|
+
|
|
59
|
+
**Parameters:**
|
|
60
|
+
- `stream: TextIO | None = None` — Optional destination. When `None`, the
|
|
61
|
+
helper targets `sys.stdout`.
|
|
62
|
+
|
|
63
|
+
**Returns:** `None`.
|
|
64
|
+
|
|
65
|
+
**Raises:** No new exceptions are raised; any stream failures bubble up.
|
|
66
|
+
|
|
67
|
+
**Example:**
|
|
68
|
+
>>> from io import StringIO
|
|
69
|
+
>>> buffer = StringIO()
|
|
70
|
+
>>> emit_greeting(stream=buffer)
|
|
71
|
+
>>> buffer.getvalue()
|
|
72
|
+
'Hello World\\n'
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
target = _target_stream(stream)
|
|
76
|
+
target.write(_greeting_line())
|
|
77
|
+
_flush_if_possible(target)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def raise_intentional_failure() -> None:
|
|
81
|
+
"""### raise_intentional_failure() {#behaviors-raise-intentional-failure}
|
|
82
|
+
|
|
83
|
+
**Purpose:** Provide a guaranteed failure hook so transports and tests can
|
|
84
|
+
assert traceback and exit-code behaviour without introducing ad-hoc errors.
|
|
85
|
+
|
|
86
|
+
**What:** Always raises `RuntimeError('I should fail')`.
|
|
87
|
+
|
|
88
|
+
**Parameters:** None.
|
|
89
|
+
|
|
90
|
+
**Returns:** This helper never returns.
|
|
91
|
+
|
|
92
|
+
**Raises:** `RuntimeError` — unconditionally, with the canonical message.
|
|
93
|
+
|
|
94
|
+
**Example:**
|
|
95
|
+
>>> try:
|
|
96
|
+
... raise_intentional_failure()
|
|
97
|
+
... except RuntimeError as exc:
|
|
98
|
+
... exc.args[0]
|
|
99
|
+
'I should fail'
|
|
100
|
+
"""
|
|
101
|
+
|
|
102
|
+
raise RuntimeError("I should fail")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def noop_main() -> None:
|
|
106
|
+
"""### noop_main() {#behaviors-noop-main}
|
|
107
|
+
|
|
108
|
+
**Purpose:** Honour tooling contracts that expect a `main` callable even
|
|
109
|
+
while the real domain implementation is pending.
|
|
110
|
+
|
|
111
|
+
**What:** Performs no work and returns immediately so callers can treat the
|
|
112
|
+
placeholder as a benign default.
|
|
113
|
+
|
|
114
|
+
**Parameters:** None.
|
|
115
|
+
|
|
116
|
+
**Returns:** `None`.
|
|
117
|
+
|
|
118
|
+
**Raises:** No exceptions.
|
|
119
|
+
|
|
120
|
+
**Example:**
|
|
121
|
+
>>> noop_main() is None
|
|
122
|
+
True
|
|
123
|
+
"""
|
|
124
|
+
|
|
125
|
+
return None
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
__all__ = [
|
|
129
|
+
"CANONICAL_GREETING",
|
|
130
|
+
"emit_greeting",
|
|
131
|
+
"raise_intentional_failure",
|
|
132
|
+
"noop_main",
|
|
133
|
+
]
|