passiveaggressive 0.1.0__tar.gz

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.
@@ -0,0 +1,19 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here.
4
+ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
5
+ versioning follows [SemVer](https://semver.org/).
6
+
7
+ ## [0.1.0] - 2026-07-24
8
+
9
+ ### Added
10
+
11
+ - Initial release.
12
+ - `translate()` / `rewrite()` with six styles (`coworker`, `manager`,
13
+ `customer_support`, `british`, `parent`, `teacher`) and five intensity
14
+ levels.
15
+ - `email()`, `subject()`, and `signoff()` helpers.
16
+ - Deterministic output via an optional `seed` argument.
17
+ - `passiveaggressive` CLI.
18
+ - Full type hints (`py.typed`), 100% handcrafted templates, zero runtime
19
+ dependencies.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 passiveaggressive contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,4 @@
1
+ include README.md
2
+ include LICENSE
3
+ include CHANGELOG.md
4
+ recursive-include passiveaggressive py.typed
@@ -0,0 +1,220 @@
1
+ Metadata-Version: 2.4
2
+ Name: passiveaggressive
3
+ Version: 0.1.0
4
+ Summary: Convert polite messages into subtly passive-aggressive ones.
5
+ Author: passiveaggressive contributors
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/example/passiveaggressive
8
+ Project-URL: Repository, https://github.com/example/passiveaggressive
9
+ Project-URL: Changelog, https://github.com/example/passiveaggressive/blob/main/CHANGELOG.md
10
+ Keywords: humor,text,office,email,cli
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Communications :: Email
20
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
+ Classifier: Topic :: Text Processing :: Linguistic
22
+ Classifier: Typing :: Typed
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Provides-Extra: dev
27
+ Requires-Dist: pytest>=7.0; extra == "dev"
28
+ Requires-Dist: mypy>=1.8; extra == "dev"
29
+ Requires-Dist: ruff>=0.4; extra == "dev"
30
+ Requires-Dist: black>=24.0; extra == "dev"
31
+ Dynamic: license-file
32
+
33
+ # passiveaggressive
34
+
35
+ [![CI](https://github.com/example/passiveaggressive/actions/workflows/ci.yml/badge.svg)](https://github.com/example/passiveaggressive/actions/workflows/ci.yml)
36
+ [![PyPI](https://img.shields.io/pypi/v/passiveaggressive.svg)](https://pypi.org/project/passiveaggressive/)
37
+ [![Python versions](https://img.shields.io/pypi/pyversions/passiveaggressive.svg)](https://pypi.org/project/passiveaggressive/)
38
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
39
+
40
+ Convert polite messages into subtly passive-aggressive ones — the kind of
41
+ message you might get from an overly polite coworker, manager, or customer
42
+ support rep. Funny without being mean, office-friendly, and built entirely
43
+ from handcrafted phrase templates — no AI, no network calls, no runtime
44
+ dependencies.
45
+
46
+ ```python
47
+ >>> from passiveaggressive import translate
48
+ >>> translate("Please update the documentation.") # one possible output
49
+ 'Just a gentle reminder, update the documentation, if time allows. Thanks in advance.'
50
+ ```
51
+
52
+ ## Installation
53
+
54
+ ```bash
55
+ pip install passiveaggressive
56
+ ```
57
+
58
+ Or, for local development:
59
+
60
+ ```bash
61
+ git clone https://github.com/example/passiveaggressive.git
62
+ cd passiveaggressive
63
+ pip install -e ".[dev]"
64
+ ```
65
+
66
+ Requires Python 3.10+.
67
+
68
+ ## Usage
69
+
70
+ ### Basic translation
71
+
72
+ ```python
73
+ from passiveaggressive import translate
74
+
75
+ translate("Send me the report.")
76
+ # "Whenever you have a moment, it would be appreciated if the report
77
+ # could finally be sent over."
78
+ ```
79
+
80
+ ### Styles
81
+
82
+ Choose the personality delivering the message:
83
+
84
+ ```python
85
+ translate(text, style="coworker") # default
86
+ translate(text, style="manager")
87
+ translate(text, style="customer_support")
88
+ translate(text, style="british")
89
+ translate(text, style="parent")
90
+ translate(text, style="teacher")
91
+ ```
92
+
93
+ | Style | Example output |
94
+ |-------------------|-----------------|
95
+ | `coworker` | "Just circling back on the PR. Thanks in advance." |
96
+ | `manager` | "Just checking in on this again since I haven't seen an update." |
97
+ | `customer_support`| "We wanted to follow up on your request. Much appreciated." |
98
+ | `british` | "Not to be a bother, but I was wondering whether this might be looked at when convenient." |
99
+ | `parent` | "I'll just leave this here in case anyone remembers." |
100
+ | `teacher` | "A gentle reminder, this was mentioned in class." |
101
+
102
+ ### Intensity
103
+
104
+ Dial the annoyance from 1 (barely-there politeness) to 5 (maximum office
105
+ sarcasm):
106
+
107
+ ```python
108
+ translate(text, intensity=1) # "Whenever you have a chance..."
109
+ translate(text, intensity=3) # "Just following up since this seems to have been overlooked."
110
+ translate(text, intensity=5) # "No rush at all—as always—but it would be wonderful if this
111
+ # could happen sometime this century."
112
+ ```
113
+
114
+ ### Randomization & determinism
115
+
116
+ Repeated calls vary naturally:
117
+
118
+ ```python
119
+ translate("Please review the PR.")
120
+ # "Just circling back on the PR."
121
+ # "Thought I'd mention this again in case it slipped through."
122
+ # "Whenever convenient, the PR is still waiting."
123
+ ```
124
+
125
+ Pass a `seed` for reproducible output:
126
+
127
+ ```python
128
+ translate("Please review the PR.", seed=42)
129
+ ```
130
+
131
+ ### Extra functions
132
+
133
+ ```python
134
+ from passiveaggressive import rewrite, email, subject, signoff
135
+
136
+ rewrite(text) # alias of translate()
137
+ email(text) # adds email-specific phrasing
138
+ subject() # e.g. "Gentle Reminder", "Following Up (Again)"
139
+ signoff() # e.g. "Kind regards,", "As always,"
140
+ ```
141
+
142
+ ## CLI
143
+
144
+ Installing the package also installs the `passiveaggressive` command:
145
+
146
+ ```bash
147
+ $ passiveaggressive "Please send the invoice."
148
+ Just checking in regarding the invoice whenever convenient.
149
+
150
+ $ passiveaggressive "Fix the bug" --style british --intensity 4
151
+ $ passiveaggressive "Reply to my email" --seed 10
152
+ ```
153
+
154
+ Flags:
155
+
156
+ - `--style {coworker,manager,customer_support,british,parent,teacher}`
157
+ - `--intensity {1,2,3,4,5}`
158
+ - `--seed <int>`
159
+
160
+ ## API documentation
161
+
162
+ ### `translate(text, style="coworker", intensity=3, seed=None) -> str`
163
+
164
+ Transforms `text` into a passive-aggressive message.
165
+
166
+ - `text` (`str`, required) — the original message. Must be non-empty.
167
+ - `style` (`str`) — one of the six supported styles.
168
+ - `intensity` (`int`) — 1–5.
169
+ - `seed` (`int | None`) — optional seed for deterministic output.
170
+
171
+ Raises `TypeError` if `text` isn't a string, and `ValueError` if `text` is
172
+ empty/whitespace, `style` is unrecognized, or `intensity` is out of range.
173
+
174
+ ### `rewrite(text, style="coworker", intensity=3, seed=None) -> str`
175
+
176
+ Alias of `translate()`.
177
+
178
+ ### `email(text, style="coworker", intensity=3, seed=None) -> str`
179
+
180
+ Like `translate()`, but layers in additional email-specific phrasing
181
+ (e.g. "Looking forward to hearing from you.").
182
+
183
+ ### `subject(seed=None) -> str`
184
+
185
+ Generates a passive-aggressive email subject line.
186
+
187
+ ### `signoff(seed=None) -> str`
188
+
189
+ Generates a passive-aggressive email signoff.
190
+
191
+ ## Random examples
192
+
193
+ ```
194
+ "Just circling back on the PR."
195
+ "Thought I'd mention this again in case it slipped through."
196
+ "Whenever convenient, the PR is still waiting."
197
+ "The PR continues to exist, should anyone be interested."
198
+ ```
199
+
200
+ ## Design philosophy
201
+
202
+ - Funny without being cruel
203
+ - Predictable and reproducible (via `seed`)
204
+ - Lightweight, pure Python, zero runtime dependencies
205
+ - Easy to extend with additional styles or phrases
206
+ - Beginner-friendly
207
+
208
+ ## Contributing
209
+
210
+ New styles are the most fun thing to add. See [CONTRIBUTING.md](CONTRIBUTING.md)
211
+ for setup instructions and the checklist to run before opening a PR.
212
+
213
+ ## Changelog
214
+
215
+ See [CHANGELOG.md](CHANGELOG.md).
216
+
217
+ ## License
218
+
219
+ MIT — see [LICENSE](LICENSE).
220
+ "# PassiveAggressive"
@@ -0,0 +1,188 @@
1
+ # passiveaggressive
2
+
3
+ [![CI](https://github.com/example/passiveaggressive/actions/workflows/ci.yml/badge.svg)](https://github.com/example/passiveaggressive/actions/workflows/ci.yml)
4
+ [![PyPI](https://img.shields.io/pypi/v/passiveaggressive.svg)](https://pypi.org/project/passiveaggressive/)
5
+ [![Python versions](https://img.shields.io/pypi/pyversions/passiveaggressive.svg)](https://pypi.org/project/passiveaggressive/)
6
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
7
+
8
+ Convert polite messages into subtly passive-aggressive ones — the kind of
9
+ message you might get from an overly polite coworker, manager, or customer
10
+ support rep. Funny without being mean, office-friendly, and built entirely
11
+ from handcrafted phrase templates — no AI, no network calls, no runtime
12
+ dependencies.
13
+
14
+ ```python
15
+ >>> from passiveaggressive import translate
16
+ >>> translate("Please update the documentation.") # one possible output
17
+ 'Just a gentle reminder, update the documentation, if time allows. Thanks in advance.'
18
+ ```
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ pip install passiveaggressive
24
+ ```
25
+
26
+ Or, for local development:
27
+
28
+ ```bash
29
+ git clone https://github.com/example/passiveaggressive.git
30
+ cd passiveaggressive
31
+ pip install -e ".[dev]"
32
+ ```
33
+
34
+ Requires Python 3.10+.
35
+
36
+ ## Usage
37
+
38
+ ### Basic translation
39
+
40
+ ```python
41
+ from passiveaggressive import translate
42
+
43
+ translate("Send me the report.")
44
+ # "Whenever you have a moment, it would be appreciated if the report
45
+ # could finally be sent over."
46
+ ```
47
+
48
+ ### Styles
49
+
50
+ Choose the personality delivering the message:
51
+
52
+ ```python
53
+ translate(text, style="coworker") # default
54
+ translate(text, style="manager")
55
+ translate(text, style="customer_support")
56
+ translate(text, style="british")
57
+ translate(text, style="parent")
58
+ translate(text, style="teacher")
59
+ ```
60
+
61
+ | Style | Example output |
62
+ |-------------------|-----------------|
63
+ | `coworker` | "Just circling back on the PR. Thanks in advance." |
64
+ | `manager` | "Just checking in on this again since I haven't seen an update." |
65
+ | `customer_support`| "We wanted to follow up on your request. Much appreciated." |
66
+ | `british` | "Not to be a bother, but I was wondering whether this might be looked at when convenient." |
67
+ | `parent` | "I'll just leave this here in case anyone remembers." |
68
+ | `teacher` | "A gentle reminder, this was mentioned in class." |
69
+
70
+ ### Intensity
71
+
72
+ Dial the annoyance from 1 (barely-there politeness) to 5 (maximum office
73
+ sarcasm):
74
+
75
+ ```python
76
+ translate(text, intensity=1) # "Whenever you have a chance..."
77
+ translate(text, intensity=3) # "Just following up since this seems to have been overlooked."
78
+ translate(text, intensity=5) # "No rush at all—as always—but it would be wonderful if this
79
+ # could happen sometime this century."
80
+ ```
81
+
82
+ ### Randomization & determinism
83
+
84
+ Repeated calls vary naturally:
85
+
86
+ ```python
87
+ translate("Please review the PR.")
88
+ # "Just circling back on the PR."
89
+ # "Thought I'd mention this again in case it slipped through."
90
+ # "Whenever convenient, the PR is still waiting."
91
+ ```
92
+
93
+ Pass a `seed` for reproducible output:
94
+
95
+ ```python
96
+ translate("Please review the PR.", seed=42)
97
+ ```
98
+
99
+ ### Extra functions
100
+
101
+ ```python
102
+ from passiveaggressive import rewrite, email, subject, signoff
103
+
104
+ rewrite(text) # alias of translate()
105
+ email(text) # adds email-specific phrasing
106
+ subject() # e.g. "Gentle Reminder", "Following Up (Again)"
107
+ signoff() # e.g. "Kind regards,", "As always,"
108
+ ```
109
+
110
+ ## CLI
111
+
112
+ Installing the package also installs the `passiveaggressive` command:
113
+
114
+ ```bash
115
+ $ passiveaggressive "Please send the invoice."
116
+ Just checking in regarding the invoice whenever convenient.
117
+
118
+ $ passiveaggressive "Fix the bug" --style british --intensity 4
119
+ $ passiveaggressive "Reply to my email" --seed 10
120
+ ```
121
+
122
+ Flags:
123
+
124
+ - `--style {coworker,manager,customer_support,british,parent,teacher}`
125
+ - `--intensity {1,2,3,4,5}`
126
+ - `--seed <int>`
127
+
128
+ ## API documentation
129
+
130
+ ### `translate(text, style="coworker", intensity=3, seed=None) -> str`
131
+
132
+ Transforms `text` into a passive-aggressive message.
133
+
134
+ - `text` (`str`, required) — the original message. Must be non-empty.
135
+ - `style` (`str`) — one of the six supported styles.
136
+ - `intensity` (`int`) — 1–5.
137
+ - `seed` (`int | None`) — optional seed for deterministic output.
138
+
139
+ Raises `TypeError` if `text` isn't a string, and `ValueError` if `text` is
140
+ empty/whitespace, `style` is unrecognized, or `intensity` is out of range.
141
+
142
+ ### `rewrite(text, style="coworker", intensity=3, seed=None) -> str`
143
+
144
+ Alias of `translate()`.
145
+
146
+ ### `email(text, style="coworker", intensity=3, seed=None) -> str`
147
+
148
+ Like `translate()`, but layers in additional email-specific phrasing
149
+ (e.g. "Looking forward to hearing from you.").
150
+
151
+ ### `subject(seed=None) -> str`
152
+
153
+ Generates a passive-aggressive email subject line.
154
+
155
+ ### `signoff(seed=None) -> str`
156
+
157
+ Generates a passive-aggressive email signoff.
158
+
159
+ ## Random examples
160
+
161
+ ```
162
+ "Just circling back on the PR."
163
+ "Thought I'd mention this again in case it slipped through."
164
+ "Whenever convenient, the PR is still waiting."
165
+ "The PR continues to exist, should anyone be interested."
166
+ ```
167
+
168
+ ## Design philosophy
169
+
170
+ - Funny without being cruel
171
+ - Predictable and reproducible (via `seed`)
172
+ - Lightweight, pure Python, zero runtime dependencies
173
+ - Easy to extend with additional styles or phrases
174
+ - Beginner-friendly
175
+
176
+ ## Contributing
177
+
178
+ New styles are the most fun thing to add. See [CONTRIBUTING.md](CONTRIBUTING.md)
179
+ for setup instructions and the checklist to run before opening a PR.
180
+
181
+ ## Changelog
182
+
183
+ See [CHANGELOG.md](CHANGELOG.md).
184
+
185
+ ## License
186
+
187
+ MIT — see [LICENSE](LICENSE).
188
+ "# PassiveAggressive"
@@ -0,0 +1,21 @@
1
+ """passiveaggressive — turn polite messages into subtly passive-aggressive ones.
2
+
3
+ >>> from passiveaggressive import translate
4
+ >>> translate("Please update the documentation.", seed=1) # doctest: +ELLIPSIS
5
+ '...documentation...'
6
+ """
7
+
8
+ from .templates import INTENSITIES, STYLES
9
+ from .translator import email, rewrite, signoff, subject, translate
10
+
11
+ __all__ = [
12
+ "translate",
13
+ "rewrite",
14
+ "email",
15
+ "subject",
16
+ "signoff",
17
+ "STYLES",
18
+ "INTENSITIES",
19
+ ]
20
+
21
+ __version__ = "0.1.0"
@@ -0,0 +1,64 @@
1
+ """Command-line entry point. Installed as the ``passiveaggressive`` script.
2
+
3
+ Run ``passiveaggressive --help`` for the full rundown.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ import argparse
9
+ import sys
10
+
11
+ from .templates import INTENSITIES, STYLES
12
+ from .translator import translate
13
+
14
+
15
+ def build_parser() -> argparse.ArgumentParser:
16
+ parser = argparse.ArgumentParser(
17
+ prog="passiveaggressive",
18
+ description="Convert a polite message into a subtly passive-aggressive one.",
19
+ )
20
+ parser.add_argument("text", help="The original, polite message to transform.")
21
+ parser.add_argument(
22
+ "--style",
23
+ choices=STYLES,
24
+ default="coworker",
25
+ help="Who's supposedly sending this (default: coworker).",
26
+ )
27
+ parser.add_argument(
28
+ "--intensity",
29
+ type=int,
30
+ choices=INTENSITIES,
31
+ default=3,
32
+ help="How annoyed they are, 1-5 (default: 3).",
33
+ )
34
+ parser.add_argument(
35
+ "--seed",
36
+ type=int,
37
+ default=None,
38
+ help="Set this to get the same output every time.",
39
+ )
40
+ return parser
41
+
42
+
43
+ def main(argv: list[str] | None = None) -> int:
44
+ """Parse args, translate, print. Returns an exit code."""
45
+ parser = build_parser()
46
+ args = parser.parse_args(argv)
47
+
48
+ try:
49
+ result = translate(
50
+ args.text,
51
+ style=args.style,
52
+ intensity=args.intensity,
53
+ seed=args.seed,
54
+ )
55
+ except (TypeError, ValueError) as exc:
56
+ print(f"Error: {exc}", file=sys.stderr)
57
+ return 1
58
+
59
+ print(result)
60
+ return 0
61
+
62
+
63
+ if __name__ == "__main__":
64
+ sys.exit(main())
File without changes