makememe 0.1.3__tar.gz → 0.1.4__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.3 → makememe-0.1.4}/PKG-INFO +3 -3
- {makememe-0.1.3 → makememe-0.1.4}/README.md +2 -2
- {makememe-0.1.3 → makememe-0.1.4}/pyproject.toml +1 -1
- {makememe-0.1.3 → makememe-0.1.4}/src/memecli/SKILL.md +5 -3
- {makememe-0.1.3 → makememe-0.1.4}/src/memecli/cli.py +21 -8
- {makememe-0.1.3 → makememe-0.1.4}/tests/test_cli.py +22 -0
- {makememe-0.1.3 → makememe-0.1.4}/.github/workflows/publish.yml +0 -0
- {makememe-0.1.3 → makememe-0.1.4}/.github/workflows/tests.yml +0 -0
- {makememe-0.1.3 → makememe-0.1.4}/.gitignore +0 -0
- {makememe-0.1.3 → makememe-0.1.4}/LICENSE +0 -0
- {makememe-0.1.3 → makememe-0.1.4}/src/memecli/__init__.py +0 -0
- {makememe-0.1.3 → makememe-0.1.4}/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.4
|
|
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,7 +67,7 @@ meme <template> "top line" "bottom line" [-o out.png]
|
|
|
67
67
|
|
|
68
68
|
| Flag | Meaning |
|
|
69
69
|
|------|---------|
|
|
70
|
-
| `-o, --out` | output file (default
|
|
70
|
+
| `-o, --out` | output file (default: a unique file in a temp folder, so it never writes into your current directory) |
|
|
71
71
|
| `--bg URL` | use a custom background image instead of a template |
|
|
72
72
|
| `--ext` | `png` (default), `jpg`, `webp`, or `gif` |
|
|
73
73
|
| `--style` / `--font` | template style variant / font override |
|
|
@@ -106,7 +106,7 @@ The tool is designed to be parsed:
|
|
|
106
106
|
- **`--json` mode** prints a single JSON object:
|
|
107
107
|
|
|
108
108
|
```json
|
|
109
|
-
{ "path": "meme.png", "bytes": 12345, "url": "https://api.memegen.link/..." }
|
|
109
|
+
{ "path": "/tmp/makememe/meme-ab12cd.png", "bytes": 12345, "url": "https://api.memegen.link/..." }
|
|
110
110
|
```
|
|
111
111
|
|
|
112
112
|
`--list --json` returns the template catalog as JSON; `--print-url --json`
|
|
@@ -48,7 +48,7 @@ meme <template> "top line" "bottom line" [-o out.png]
|
|
|
48
48
|
|
|
49
49
|
| Flag | Meaning |
|
|
50
50
|
|------|---------|
|
|
51
|
-
| `-o, --out` | output file (default
|
|
51
|
+
| `-o, --out` | output file (default: a unique file in a temp folder, so it never writes into your current directory) |
|
|
52
52
|
| `--bg URL` | use a custom background image instead of a template |
|
|
53
53
|
| `--ext` | `png` (default), `jpg`, `webp`, or `gif` |
|
|
54
54
|
| `--style` / `--font` | template style variant / font override |
|
|
@@ -87,7 +87,7 @@ The tool is designed to be parsed:
|
|
|
87
87
|
- **`--json` mode** prints a single JSON object:
|
|
88
88
|
|
|
89
89
|
```json
|
|
90
|
-
{ "path": "meme.png", "bytes": 12345, "url": "https://api.memegen.link/..." }
|
|
90
|
+
{ "path": "/tmp/makememe/meme-ab12cd.png", "bytes": 12345, "url": "https://api.memegen.link/..." }
|
|
91
91
|
```
|
|
92
92
|
|
|
93
93
|
`--list --json` returns the template catalog as JSON; `--print-url --json`
|
|
@@ -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.4"
|
|
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"
|
|
@@ -44,15 +44,17 @@ uv tool install makememe
|
|
|
44
44
|
Output:
|
|
45
45
|
|
|
46
46
|
```json
|
|
47
|
-
{ "path": "meme.png", "bytes": 12345, "url": "https://api.memegen.link/..." }
|
|
47
|
+
{ "path": "/tmp/makememe/meme-ab12cd.png", "bytes": 12345, "url": "https://api.memegen.link/..." }
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
3. **Tell the user the path** (and show the image if the surface supports it).
|
|
51
51
|
|
|
52
52
|
## Key flags
|
|
53
53
|
|
|
54
|
-
-
|
|
55
|
-
|
|
54
|
+
- By default the image is saved to a temp folder (`<tmp>/makememe/`) with a
|
|
55
|
+
unique name, so it never clutters the user's working directory. The path is
|
|
56
|
+
in the output — report it to the user. Use `-o path.png` only if the user
|
|
57
|
+
wants it saved somewhere specific.
|
|
56
58
|
- `--bg <image-url>` — use a custom background image instead of a template;
|
|
57
59
|
pass caption lines as usual.
|
|
58
60
|
- `--ext png|jpg|webp|gif` — output format.
|
|
@@ -23,12 +23,23 @@ import argparse
|
|
|
23
23
|
import json
|
|
24
24
|
import os
|
|
25
25
|
import sys
|
|
26
|
+
import tempfile
|
|
26
27
|
import urllib.parse
|
|
27
28
|
import urllib.request
|
|
28
29
|
|
|
29
30
|
API = "https://api.memegen.link"
|
|
30
31
|
|
|
31
32
|
|
|
33
|
+
def default_output(ext):
|
|
34
|
+
"""A unique output path in a grouped temp folder, so we never write into the
|
|
35
|
+
user's project/root dir and never clobber a previous meme."""
|
|
36
|
+
d = os.path.join(tempfile.gettempdir(), "makememe")
|
|
37
|
+
os.makedirs(d, exist_ok=True)
|
|
38
|
+
fd, path = tempfile.mkstemp(prefix="meme-", suffix=f".{ext}", dir=d)
|
|
39
|
+
os.close(fd)
|
|
40
|
+
return path
|
|
41
|
+
|
|
42
|
+
|
|
32
43
|
def get_version():
|
|
33
44
|
"""Read the installed package version; fall back gracefully from source."""
|
|
34
45
|
try:
|
|
@@ -134,8 +145,8 @@ def build_parser():
|
|
|
134
145
|
ap.add_argument("template", nargs="?",
|
|
135
146
|
help="template id (see --list), or any id when using --bg")
|
|
136
147
|
ap.add_argument("lines", nargs="*", help="text lines, in order")
|
|
137
|
-
ap.add_argument("-o", "--out", default=
|
|
138
|
-
help="output file (default
|
|
148
|
+
ap.add_argument("-o", "--out", default=None,
|
|
149
|
+
help="output file (default: a temp folder, not your current dir)")
|
|
139
150
|
ap.add_argument("--bg",
|
|
140
151
|
help="custom background image URL (uses the 'custom' template)")
|
|
141
152
|
ap.add_argument("--ext", default="png", choices=["png", "jpg", "webp", "gif"])
|
|
@@ -190,8 +201,10 @@ def _run(argv=None):
|
|
|
190
201
|
print(url)
|
|
191
202
|
return
|
|
192
203
|
|
|
204
|
+
out = args.out if args.out else default_output(args.ext)
|
|
205
|
+
|
|
193
206
|
try:
|
|
194
|
-
n = download(url,
|
|
207
|
+
n = download(url, out)
|
|
195
208
|
except Exception as e:
|
|
196
209
|
# a 404 almost always means a bad template id — point the user/agent at --list
|
|
197
210
|
hint = None
|
|
@@ -199,10 +212,10 @@ def _run(argv=None):
|
|
|
199
212
|
hint = (f"template '{template}' not found (404). "
|
|
200
213
|
"Run `meme --list` to find the correct id.")
|
|
201
214
|
if args.json:
|
|
202
|
-
|
|
215
|
+
payload = {"error": str(e), "url": url}
|
|
203
216
|
if hint:
|
|
204
|
-
|
|
205
|
-
print(json.dumps(
|
|
217
|
+
payload["hint"] = hint
|
|
218
|
+
print(json.dumps(payload))
|
|
206
219
|
sys.exit(1)
|
|
207
220
|
msg = f"download failed: {e}\nurl was: {url}"
|
|
208
221
|
if hint:
|
|
@@ -210,9 +223,9 @@ def _run(argv=None):
|
|
|
210
223
|
sys.exit(msg)
|
|
211
224
|
|
|
212
225
|
if args.json:
|
|
213
|
-
print(json.dumps({"path":
|
|
226
|
+
print(json.dumps({"path": out, "bytes": n, "url": url}))
|
|
214
227
|
else:
|
|
215
|
-
print(
|
|
228
|
+
print(out) # stdout: just the path, easy to capture
|
|
216
229
|
print(f"saved {n} bytes from {url}", file=sys.stderr)
|
|
217
230
|
|
|
218
231
|
|
|
@@ -116,6 +116,28 @@ class TestCrashSafety(unittest.TestCase):
|
|
|
116
116
|
cli.download = orig
|
|
117
117
|
|
|
118
118
|
|
|
119
|
+
class TestDefaultOutput(unittest.TestCase):
|
|
120
|
+
def test_default_is_in_tempdir_not_cwd(self):
|
|
121
|
+
import tempfile
|
|
122
|
+
p = cli.default_output("png")
|
|
123
|
+
self.assertTrue(p.startswith(tempfile.gettempdir()))
|
|
124
|
+
self.assertTrue(p.endswith(".png"))
|
|
125
|
+
# cleanup the empty file mkstemp created
|
|
126
|
+
try:
|
|
127
|
+
os.remove(p)
|
|
128
|
+
except OSError:
|
|
129
|
+
pass
|
|
130
|
+
|
|
131
|
+
def test_default_paths_are_unique(self):
|
|
132
|
+
a, b = cli.default_output("png"), cli.default_output("png")
|
|
133
|
+
self.assertNotEqual(a, b)
|
|
134
|
+
for p in (a, b):
|
|
135
|
+
try:
|
|
136
|
+
os.remove(p)
|
|
137
|
+
except OSError:
|
|
138
|
+
pass
|
|
139
|
+
|
|
140
|
+
|
|
119
141
|
class TestNewCommands(unittest.TestCase):
|
|
120
142
|
def test_version_flag_prints_and_exits(self):
|
|
121
143
|
buf = io.StringIO()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|