makememe 0.1.4__tar.gz → 0.1.6__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.
- {makememe-0.1.4 → makememe-0.1.6}/PKG-INFO +3 -1
- {makememe-0.1.4 → makememe-0.1.6}/README.md +2 -0
- {makememe-0.1.4 → makememe-0.1.6}/pyproject.toml +1 -1
- {makememe-0.1.4 → makememe-0.1.6}/src/memecli/SKILL.md +15 -8
- {makememe-0.1.4 → makememe-0.1.6}/src/memecli/cli.py +33 -4
- {makememe-0.1.4 → makememe-0.1.6}/tests/test_cli.py +11 -0
- {makememe-0.1.4 → makememe-0.1.6}/.github/workflows/publish.yml +0 -0
- {makememe-0.1.4 → makememe-0.1.6}/.github/workflows/tests.yml +0 -0
- {makememe-0.1.4 → makememe-0.1.6}/.gitignore +0 -0
- {makememe-0.1.4 → makememe-0.1.6}/LICENSE +0 -0
- {makememe-0.1.4 → makememe-0.1.6}/src/memecli/__init__.py +0 -0
- {makememe-0.1.4 → makememe-0.1.6}/src/memecli/__main__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: makememe
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: A tiny zero-dependency CLI for generating memes via the free memegen.link API. Agent-friendly.
|
|
5
5
|
Project-URL: Homepage, https://pypi.org/project/makememe/
|
|
6
6
|
Project-URL: memegen.link API, https://api.memegen.link
|
|
@@ -67,10 +67,12 @@ meme <template> "top line" "bottom line" [-o out.png]
|
|
|
67
67
|
|
|
68
68
|
| Flag | Meaning |
|
|
69
69
|
|------|---------|
|
|
70
|
+
| `-t, --template` | template id as a flag (alternative to the positional). Agents should use this so a single permission approval covers every template |
|
|
70
71
|
| `-o, --out` | output file (default: a unique file in a temp folder, so it never writes into your current directory) |
|
|
71
72
|
| `--bg URL` | use a custom background image instead of a template |
|
|
72
73
|
| `--ext` | `png` (default), `jpg`, `webp`, or `gif` |
|
|
73
74
|
| `--style` / `--font` | template style variant / font override |
|
|
75
|
+
| `--open` | open the finished image in your default viewer |
|
|
74
76
|
| `--print-url` | print the image URL, don't download |
|
|
75
77
|
| `--json` | machine-readable output (for scripts/agents) |
|
|
76
78
|
| `--list` | list available template ids |
|
|
@@ -48,10 +48,12 @@ meme <template> "top line" "bottom line" [-o out.png]
|
|
|
48
48
|
|
|
49
49
|
| Flag | Meaning |
|
|
50
50
|
|------|---------|
|
|
51
|
+
| `-t, --template` | template id as a flag (alternative to the positional). Agents should use this so a single permission approval covers every template |
|
|
51
52
|
| `-o, --out` | output file (default: a unique file in a temp folder, so it never writes into your current directory) |
|
|
52
53
|
| `--bg URL` | use a custom background image instead of a template |
|
|
53
54
|
| `--ext` | `png` (default), `jpg`, `webp`, or `gif` |
|
|
54
55
|
| `--style` / `--font` | template style variant / font override |
|
|
56
|
+
| `--open` | open the finished image in your default viewer |
|
|
55
57
|
| `--print-url` | print the image URL, don't download |
|
|
56
58
|
| `--json` | machine-readable output (for scripts/agents) |
|
|
57
59
|
| `--list` | list available template ids |
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "makememe"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.6"
|
|
8
8
|
description = "A tiny zero-dependency CLI for generating memes via the free memegen.link API. Agent-friendly."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -34,11 +34,15 @@ uv tool install makememe
|
|
|
34
34
|
**Always verify an id with `meme --list --json` before using it** — guessing
|
|
35
35
|
ids (e.g. `buttons`, `twobuttons`) leads to 404s. When unsure, list first.
|
|
36
36
|
|
|
37
|
-
2. **Generate.** Pass the template id
|
|
38
|
-
|
|
37
|
+
2. **Generate.** Pass the template id with `-t` (as a flag, not the leading
|
|
38
|
+
word) then the caption lines in order. Always use `--json` (reliable output
|
|
39
|
+
path) and `--open` (opens the finished meme in the user's default viewer).
|
|
40
|
+
|
|
41
|
+
Using `-t` matters: every call starts with the same `meme -t ...` prefix, so
|
|
42
|
+
the user only has to approve the command **once** — not once per template.
|
|
39
43
|
|
|
40
44
|
```bash
|
|
41
|
-
meme drake "writing code by hand" "asking the meme cli" --json
|
|
45
|
+
meme -t drake "writing code by hand" "asking the meme cli" --json --open
|
|
42
46
|
```
|
|
43
47
|
|
|
44
48
|
Output:
|
|
@@ -47,7 +51,8 @@ uv tool install makememe
|
|
|
47
51
|
{ "path": "/tmp/makememe/meme-ab12cd.png", "bytes": 12345, "url": "https://api.memegen.link/..." }
|
|
48
52
|
```
|
|
49
53
|
|
|
50
|
-
3. **Tell the user the path
|
|
54
|
+
3. **Tell the user the path.** The `--open` flag already popped the image open
|
|
55
|
+
for them; just report where it was saved.
|
|
51
56
|
|
|
52
57
|
## Key flags
|
|
53
58
|
|
|
@@ -58,6 +63,8 @@ uv tool install makememe
|
|
|
58
63
|
- `--bg <image-url>` — use a custom background image instead of a template;
|
|
59
64
|
pass caption lines as usual.
|
|
60
65
|
- `--ext png|jpg|webp|gif` — output format.
|
|
66
|
+
- `--open` — open the finished image in the user's default viewer (use this so
|
|
67
|
+
they can see the meme).
|
|
61
68
|
- `--print-url` — get the image URL without downloading.
|
|
62
69
|
- `--json` — machine-readable output (always prefer this when scripting).
|
|
63
70
|
|
|
@@ -77,8 +84,8 @@ uv tool install makememe
|
|
|
77
84
|
## Examples
|
|
78
85
|
|
|
79
86
|
```bash
|
|
80
|
-
meme drake "old way" "new way"
|
|
81
|
-
meme same "after I sold" "if I held" "same picture" --json
|
|
82
|
-
meme cmm "tabs are better than spaces" --json
|
|
83
|
-
meme --bg https://example.com/cat.png "_" "DEPLOY ON FRIDAY" --json
|
|
87
|
+
meme -t drake "old way" "new way" --json --open
|
|
88
|
+
meme -t same "after I sold" "if I held" "same picture" --json --open
|
|
89
|
+
meme -t cmm "tabs are better than spaces" --json --open
|
|
90
|
+
meme --bg https://example.com/cat.png "_" "DEPLOY ON FRIDAY" --json --open
|
|
84
91
|
```
|
|
@@ -22,6 +22,8 @@ Find templates: https://api.memegen.link/templates/ (or `meme --list`)
|
|
|
22
22
|
import argparse
|
|
23
23
|
import json
|
|
24
24
|
import os
|
|
25
|
+
import shutil
|
|
26
|
+
import subprocess
|
|
25
27
|
import sys
|
|
26
28
|
import tempfile
|
|
27
29
|
import urllib.parse
|
|
@@ -30,6 +32,21 @@ import urllib.request
|
|
|
30
32
|
API = "https://api.memegen.link"
|
|
31
33
|
|
|
32
34
|
|
|
35
|
+
def open_file(path):
|
|
36
|
+
"""Open a file with the OS default viewer. Best-effort; never raises."""
|
|
37
|
+
try:
|
|
38
|
+
if sys.platform == "darwin":
|
|
39
|
+
subprocess.run(["open", path], check=False)
|
|
40
|
+
elif sys.platform.startswith("win"):
|
|
41
|
+
os.startfile(path) # noqa: B606 (Windows only)
|
|
42
|
+
else:
|
|
43
|
+
opener = shutil.which("xdg-open")
|
|
44
|
+
if opener:
|
|
45
|
+
subprocess.run([opener, path], check=False)
|
|
46
|
+
except Exception:
|
|
47
|
+
pass
|
|
48
|
+
|
|
49
|
+
|
|
33
50
|
def default_output(ext):
|
|
34
51
|
"""A unique output path in a grouped temp folder, so we never write into the
|
|
35
52
|
user's project/root dir and never clobber a previous meme."""
|
|
@@ -145,6 +162,9 @@ def build_parser():
|
|
|
145
162
|
ap.add_argument("template", nargs="?",
|
|
146
163
|
help="template id (see --list), or any id when using --bg")
|
|
147
164
|
ap.add_argument("lines", nargs="*", help="text lines, in order")
|
|
165
|
+
ap.add_argument("-t", "--template", dest="template_flag",
|
|
166
|
+
help="template id as a flag (keeps a constant command prefix, "
|
|
167
|
+
"so one permission approval covers every template)")
|
|
148
168
|
ap.add_argument("-o", "--out", default=None,
|
|
149
169
|
help="output file (default: a temp folder, not your current dir)")
|
|
150
170
|
ap.add_argument("--bg",
|
|
@@ -152,6 +172,8 @@ def build_parser():
|
|
|
152
172
|
ap.add_argument("--ext", default="png", choices=["png", "jpg", "webp", "gif"])
|
|
153
173
|
ap.add_argument("--style", help="template style variant, if any")
|
|
154
174
|
ap.add_argument("--font", help="font name (see /fonts/)")
|
|
175
|
+
ap.add_argument("--open", action="store_true", dest="open_after",
|
|
176
|
+
help="open the saved image in the OS default viewer")
|
|
155
177
|
ap.add_argument("--print-url", action="store_true",
|
|
156
178
|
help="print the URL and exit, no download")
|
|
157
179
|
ap.add_argument("--json", action="store_true",
|
|
@@ -181,16 +203,20 @@ def _run(argv=None):
|
|
|
181
203
|
sys.exit(f"could not fetch templates: {e}")
|
|
182
204
|
return
|
|
183
205
|
|
|
184
|
-
if not args.template and not args.bg:
|
|
206
|
+
if not args.template and not args.template_flag and not args.bg:
|
|
185
207
|
ap.error("a template id is required (or use --bg for a custom background)")
|
|
186
208
|
|
|
187
|
-
# with --bg
|
|
209
|
+
# with --bg or -t the template isn't the leading positional, so fold the
|
|
210
|
+
# positional back into the text lines.
|
|
188
211
|
if args.bg:
|
|
189
|
-
lines = ([args.template] if args.template else []) + args.lines
|
|
190
212
|
template = "custom"
|
|
213
|
+
lines = ([args.template] if args.template else []) + args.lines
|
|
214
|
+
elif args.template_flag:
|
|
215
|
+
template = args.template_flag
|
|
216
|
+
lines = ([args.template] if args.template else []) + args.lines
|
|
191
217
|
else:
|
|
192
|
-
lines = args.lines
|
|
193
218
|
template = args.template
|
|
219
|
+
lines = args.lines
|
|
194
220
|
|
|
195
221
|
url = build_url(template, lines, args.ext, args.bg, args.style, args.font)
|
|
196
222
|
|
|
@@ -222,6 +248,9 @@ def _run(argv=None):
|
|
|
222
248
|
msg += f"\nhint: {hint}"
|
|
223
249
|
sys.exit(msg)
|
|
224
250
|
|
|
251
|
+
if args.open_after:
|
|
252
|
+
open_file(out)
|
|
253
|
+
|
|
225
254
|
if args.json:
|
|
226
255
|
print(json.dumps({"path": out, "bytes": n, "url": url}))
|
|
227
256
|
else:
|
|
@@ -84,6 +84,17 @@ class TestCrashSafety(unittest.TestCase):
|
|
|
84
84
|
cli.main(["drake", "a", "b", "--print-url"])
|
|
85
85
|
self.assertIn("api.memegen.link/images/drake/a/b.png", buf.getvalue())
|
|
86
86
|
|
|
87
|
+
def test_template_flag_matches_positional(self):
|
|
88
|
+
def url_for(argv):
|
|
89
|
+
buf = io.StringIO()
|
|
90
|
+
with redirect_stdout(buf):
|
|
91
|
+
cli.main(argv)
|
|
92
|
+
return buf.getvalue().strip()
|
|
93
|
+
self.assertEqual(
|
|
94
|
+
url_for(["-t", "drake", "a", "b", "--print-url"]),
|
|
95
|
+
url_for(["drake", "a", "b", "--print-url"]),
|
|
96
|
+
)
|
|
97
|
+
|
|
87
98
|
def test_keyboard_interrupt_becomes_130(self):
|
|
88
99
|
orig = cli.download
|
|
89
100
|
cli.download = lambda *a, **k: (_ for _ in ()).throw(KeyboardInterrupt())
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|