EagleWrapper 1.2.0__tar.gz → 2.0.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.
Files changed (37) hide show
  1. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/MANIFEST.in +0 -4
  2. {eaglewrapper-1.2.0/src/EagleWrapper.egg-info → eaglewrapper-2.0.0}/PKG-INFO +120 -4
  3. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/README.md +117 -2
  4. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/setup.py +24 -15
  5. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0/src/EagleWrapper.egg-info}/PKG-INFO +120 -4
  6. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/src/EagleWrapper.egg-info/SOURCES.txt +3 -2
  7. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/src/eaglewrapper/__init__.py +5 -2
  8. eaglewrapper-2.0.0/src/eaglewrapper/_apis.py +62 -0
  9. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/src/eaglewrapper/client.py +13 -4
  10. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/src/eaglewrapper/eagle.py +57 -65
  11. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/src/eaglewrapper/v2.py +30 -29
  12. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/tests/fakes.py +5 -2
  13. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/tests/test_api_requests.py +11 -18
  14. eaglewrapper-2.0.0/tests/test_apis.py +67 -0
  15. eaglewrapper-2.0.0/tests/test_readme.py +36 -0
  16. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/tests/test_v2.py +14 -0
  17. eaglewrapper-1.2.0/reinstall.bat +0 -1
  18. eaglewrapper-1.2.0/reinstall.sh +0 -2
  19. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/LICENSE +0 -0
  20. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/doc/add-from-url.png +0 -0
  21. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/doc/api-overview.png +0 -0
  22. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/doc/repo-logo.png +0 -0
  23. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/pyproject.toml +0 -0
  24. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/setup.cfg +0 -0
  25. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/src/EagleWrapper.egg-info/dependency_links.txt +0 -0
  26. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/src/EagleWrapper.egg-info/requires.txt +0 -0
  27. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/src/EagleWrapper.egg-info/top_level.txt +0 -0
  28. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/src/eaglewrapper/_library.py +0 -0
  29. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/src/eaglewrapper/errors.py +0 -0
  30. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/src/eaglewrapper/py.typed +0 -0
  31. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/tests/__init__.py +0 -0
  32. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/tests/test_compat.py +0 -0
  33. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/tests/test_connection_options.py +0 -0
  34. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/tests/test_eagle.py +0 -0
  35. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/tests/test_errors.py +0 -0
  36. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/tests/test_library_folder.py +0 -0
  37. {eaglewrapper-1.2.0 → eaglewrapper-2.0.0}/tests/test_v1_additions.py +0 -0
@@ -1,10 +1,6 @@
1
1
  include pyproject.toml
2
2
  include *.md
3
- include *.sh
4
- include *.bat
5
3
  include LICENSE
6
4
  include src/eaglewrapper/py.typed
7
- recursive-include test *.py
8
5
  recursive-include tests *.py
9
6
  recursive-include doc *.png
10
- recursive-include doc *.jpg
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: EagleWrapper
3
- Version: 1.2.0
3
+ Version: 2.0.0
4
4
  Summary: A wrapper for the local HTTP API (V1 and Web API V2) of Eagle, an image management app.
5
5
  Home-page: https://github.com/NatLee/eagle-wrapper
6
6
  Author: Nat Lee
@@ -13,7 +13,8 @@ Project-URL: Eagle Web API V2, https://developer.eagle.cool/web-api
13
13
  Keywords: eagle,eagle api,eagle web api,image management,asset management,wrapper
14
14
  Classifier: Development Status :: 5 - Production/Stable
15
15
  Classifier: Intended Audience :: Developers
16
- Classifier: Topic :: Software Development :: Build Tools
16
+ Classifier: Topic :: Multimedia :: Graphics
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
18
  Classifier: Programming Language :: Python :: 3
18
19
  Classifier: Programming Language :: Python :: 3.6
19
20
  Classifier: Programming Language :: Python :: 3.7
@@ -94,6 +95,7 @@ pip install EagleWrapper
94
95
 
95
96
  Python 3.6 or later. Eagle must be running for everything except the library-folder reader.
96
97
  Web API V2, the connection options and the new exceptions arrived in 1.2.0.
98
+ Which release speaks which Eagle API, and what to pin: see [Versioning](#versioning).
97
99
 
98
100
  ## Quick start
99
101
 
@@ -243,8 +245,25 @@ These are the methods of 1.1.1, unchanged, plus `star`, `get_library_icon` and `
243
245
  | **No API** | `get_img_info_from_lib_path(library_path, name_start_filters, max_workers, match)` | reads the library folder | list |
244
246
  | **Helpers** | `supports_v2()` · `check_success(response_or_dict)` | | bool |
245
247
 
246
- `add_from_path` returns Eagle's whole reply, not a bool, because 1.1.1 did. A dict is always truthy, so check
247
- `eagle.check_success(reply)` (or use `raise_errors=True`) instead of `if eagle.add_from_path(...)`.
248
+ `add_from_path` returns Eagle's whole reply (a dict such as `{'status': 'success'}`), not a bool, because
249
+ 1.1.1 did and scripts may read it. A dict is always truthy, so `if eagle.add_from_path(...)` passes even when Eagle
250
+ refused the file. Check the reply, or let failures raise:
251
+
252
+ ```python
253
+ from eaglewrapper import Eagle, EagleAPIError
254
+
255
+ eagle = Eagle()
256
+ reply = eagle.add_from_path('/path/to/cat.jpg', 'Cat')
257
+ if eagle.check_success(reply): # True only for {'status': 'success', ...}
258
+ print('added')
259
+ else:
260
+ print('Eagle said no:', reply)
261
+
262
+ try:
263
+ Eagle(raise_errors=True).add_from_path('/path/to/cat.jpg', 'Cat')
264
+ except EagleAPIError as e:
265
+ print('Eagle said no:', e.message)
266
+ ```
248
267
 
249
268
  ## Reading a library folder without Eagle
250
269
 
@@ -299,6 +318,87 @@ Moving a V1 script to V2 when your Eagle is 4.0 Build 21 or later:
299
318
  | `get_application_info()` | `v2.app.info()` | |
300
319
  | `get_thumbnail_path(id)` | none | keep using V1 |
301
320
 
321
+ ## Versioning
322
+
323
+ The version number follows Eagle's API. The major number is the newest Eagle API generation a release
324
+ speaks: 1 for V1, Eagle's original `/api/` API, and 2 for Web API V2 (`/api/v2/`). A test keeps the two in
325
+ step. Minor releases wrap more
326
+ of that API (often what a new Eagle build added) or add options to the package, and patch releases fix bugs.
327
+ Code that works with one release keeps working with later releases that have the same major number.
328
+ One slip from the early days: 1.1.0 renamed two arguments of 1.0.0 and changed what `add_from_url` and
329
+ `set_tag_with_id` return.
330
+
331
+ Eagle numbers its API only as V1 and V2. Whatever it adds inside a generation is tied to the Eagle build
332
+ that brought it (see the [V1 changelog](https://api.eagle.cool/changelog) and the
333
+ [V2 changelog](https://developer.eagle.cool/web-api/changelog)), so each release says which builds it covers:
334
+
335
+ | EagleWrapper | Eagle APIs | What it wraps |
336
+ |---|---|---|
337
+ | 1.0.0 (April 2023) | V1 | 3 endpoints (add from URL, list items, update item) and the library-folder reader |
338
+ | 1.1.0, 1.1.1 (April 2023) | V1 | all 21 endpoints documented at the time |
339
+ | 1.2.0 (November 2026) | V1 and Web API V2 | V1 up to its last change (Eagle 3.0 Build 23) plus `/api/library/icon`; V2 up to Eagle 4.0 Build 22 (smart folders, comments) |
340
+ | 2.0.0 (November 2026) | V1 and Web API V2 | the same as 1.2.0, plus `SUPPORTED_APIS` (below) |
341
+
342
+ 1.2.0 is the odd one out. It was the first release that speaks Web API V2, but it came out as 1.2.0,
343
+ before this rule was written down, because nothing changed for code written against V1. 2.0.0 puts the
344
+ number back on the rule. It is the 1.2.0 code with this versioning written down and `SUPPORTED_APIS`
345
+ added, so going from 1.2.0 to 2.0.0 needs no change in your code.
346
+
347
+ The installed package knows what it covers:
348
+
349
+ ```python
350
+ import eaglewrapper
351
+
352
+ for api in eaglewrapper.SUPPORTED_APIS:
353
+ print(f'{api.name}: {api.prefix}... needs Eagle {api.since}+, wrapped up to Eagle {api.covered_up_to}')
354
+ ```
355
+
356
+ ```text
357
+ V1: /api/... needs Eagle 1.11 Build 21+, wrapped up to Eagle 3.0 Build 23
358
+ Web API V2: /api/v2/... needs Eagle 4.0 Build 21+, wrapped up to Eagle 4.0 Build 22
359
+ ```
360
+
361
+ To see what your Eagle has, `Eagle().get_application_info()` returns its `version` and `buildVersion`,
362
+ and `Eagle().supports_v2()` says whether Web API V2 is there. Endpoints that Eagle adds after the covered
363
+ build are one call away with `eagle.v2.request('GET', 'section/endpoint')`. So are `item/open`,
364
+ `item/select` and `folder/open`: the V2 changelog lists them, but the docs have no page for them yet, so
365
+ they are not wrapped.
366
+
367
+ What to pin: the major number, `EagleWrapper~=2.0` (that is `>=2.0, <3`). You get fixes and newly
368
+ wrapped endpoints, and you move to another API generation only when you change the pin. The 1.x line gets
369
+ no more releases: if you pinned `~=1.2`, change it to `~=2.0`; nothing else to do. `eagle.v2` needs
370
+ 1.2.0 or later. Scripts that only use the V1 methods run on 1.1.0 and later, but 1.2.0 fixed several bugs
371
+ (see [Upgrading from 1.1.1](#upgrading-from-111)).
372
+
373
+ ## Plugins and related projects
374
+
375
+ Not every job needs a script. A few things worth knowing about before you write one:
376
+
377
+ From Eagle:
378
+
379
+ - [Plugin Center](https://community-en.eagle.cool/plugins): plugins you install inside Eagle. The batch job
380
+ you are about to script may already exist as one.
381
+ - [API Playground](https://developer.eagle.cool/web-api/get-started/playground): with Eagle open, visit
382
+ `http://localhost:41595/api/v2/playground` to try any Web API V2 endpoint from a form and see Eagle's real
383
+ reply before you write the Python call. It works on your real library, so writes there are real too.
384
+ - [Plugin API](https://developer.eagle.cool/plugin-api) and the
385
+ [official plugin examples](https://github.com/eagle-app/eagle-plugin-examples): for code that should run
386
+ inside Eagle (a window, a background service, support for a new file format, an inspector panel) rather
387
+ than talk to it from outside. The examples have one small working plugin per type.
388
+ - [AI Search](https://eagle.cool/support/article/ai-search): Eagle's offline search by description or by
389
+ similar image. `eagle.v2.ai_search` only works with this plugin installed.
390
+ - [Eagle Skill / MCP](https://en.eagle.cool/blog/post/eagle-plugin-mcp-skill): lets an AI agent clean up
391
+ tags, plan folders and rewrite names and descriptions in your library. Worth a look when the hard part is
392
+ deciding what to change, not making the calls.
393
+
394
+ Built on EagleWrapper:
395
+
396
+ - [yande-and-konachan-to-eagle](https://github.com/NatLee/yande-and-konachan-to-eagle): fetches images and
397
+ their tags from yande.re and konachan.com and adds them to Eagle with `add_from_url`. A complete,
398
+ small downloader to copy from.
399
+
400
+ Built something with EagleWrapper? Open an issue or a pull request and it can go on this list.
401
+
302
402
  ## Development
303
403
 
304
404
  The tests replace the HTTP calls with mocks, so Eagle does not need to be running.
@@ -308,6 +408,13 @@ pip install -e . pytest
308
408
  pytest tests
309
409
  ```
310
410
 
411
+ The editable install picks up your edits right away. To reinstall a regular copy from the checkout instead
412
+ (what the old `reinstall.sh` and `reinstall.bat` did with the retired `setup.py install`):
413
+
414
+ ```bash
415
+ python -m pip install --force-reinstall .
416
+ ```
417
+
311
418
  `tox -e py` runs the same tests plus a check of the source distribution. CI runs them on Linux with
312
419
  Python 3.6 to 3.14, and on Windows and macOS with Python 3.14.
313
420
 
@@ -319,8 +426,17 @@ How the code is laid out (`src/eaglewrapper/`):
319
426
  | `eagle.py` | `Eagle`: the V1 methods, kept compatible with 1.1.1 |
320
427
  | `v2.py` | `EagleV2` and its sections (`item`, `folder`, `tag`, ...), plus pagination |
321
428
  | `_library.py` | reads `metadata.json` files from a library folder |
429
+ | `_apis.py` | which Eagle APIs and builds this release covers (`SUPPORTED_APIS`); the code, `setup.py` and the README test read it |
322
430
  | `errors.py` | the exceptions |
323
431
 
432
+ ## Support
433
+
434
+ EagleWrapper is free and kept up in spare time. If it saved you an afternoon, you can buy me a coffee on
435
+ Ko-fi or chip in on Liberapay. Bug reports and pull requests help just as much.
436
+
437
+ [![Ko-fi](https://img.shields.io/badge/Ko--fi-natlee__-FF5E5B?logo=ko-fi&logoColor=white)](https://ko-fi.com/natlee_)
438
+ [![Liberapay](https://img.shields.io/badge/Liberapay-natlee-F6C915?logo=liberapay&logoColor=black)](https://liberapay.com/natlee)
439
+
324
440
  ## Contributor
325
441
 
326
442
  <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
@@ -44,6 +44,7 @@ pip install EagleWrapper
44
44
 
45
45
  Python 3.6 or later. Eagle must be running for everything except the library-folder reader.
46
46
  Web API V2, the connection options and the new exceptions arrived in 1.2.0.
47
+ Which release speaks which Eagle API, and what to pin: see [Versioning](#versioning).
47
48
 
48
49
  ## Quick start
49
50
 
@@ -193,8 +194,25 @@ These are the methods of 1.1.1, unchanged, plus `star`, `get_library_icon` and `
193
194
  | **No API** | `get_img_info_from_lib_path(library_path, name_start_filters, max_workers, match)` | reads the library folder | list |
194
195
  | **Helpers** | `supports_v2()` · `check_success(response_or_dict)` | | bool |
195
196
 
196
- `add_from_path` returns Eagle's whole reply, not a bool, because 1.1.1 did. A dict is always truthy, so check
197
- `eagle.check_success(reply)` (or use `raise_errors=True`) instead of `if eagle.add_from_path(...)`.
197
+ `add_from_path` returns Eagle's whole reply (a dict such as `{'status': 'success'}`), not a bool, because
198
+ 1.1.1 did and scripts may read it. A dict is always truthy, so `if eagle.add_from_path(...)` passes even when Eagle
199
+ refused the file. Check the reply, or let failures raise:
200
+
201
+ ```python
202
+ from eaglewrapper import Eagle, EagleAPIError
203
+
204
+ eagle = Eagle()
205
+ reply = eagle.add_from_path('/path/to/cat.jpg', 'Cat')
206
+ if eagle.check_success(reply): # True only for {'status': 'success', ...}
207
+ print('added')
208
+ else:
209
+ print('Eagle said no:', reply)
210
+
211
+ try:
212
+ Eagle(raise_errors=True).add_from_path('/path/to/cat.jpg', 'Cat')
213
+ except EagleAPIError as e:
214
+ print('Eagle said no:', e.message)
215
+ ```
198
216
 
199
217
  ## Reading a library folder without Eagle
200
218
 
@@ -249,6 +267,87 @@ Moving a V1 script to V2 when your Eagle is 4.0 Build 21 or later:
249
267
  | `get_application_info()` | `v2.app.info()` | |
250
268
  | `get_thumbnail_path(id)` | none | keep using V1 |
251
269
 
270
+ ## Versioning
271
+
272
+ The version number follows Eagle's API. The major number is the newest Eagle API generation a release
273
+ speaks: 1 for V1, Eagle's original `/api/` API, and 2 for Web API V2 (`/api/v2/`). A test keeps the two in
274
+ step. Minor releases wrap more
275
+ of that API (often what a new Eagle build added) or add options to the package, and patch releases fix bugs.
276
+ Code that works with one release keeps working with later releases that have the same major number.
277
+ One slip from the early days: 1.1.0 renamed two arguments of 1.0.0 and changed what `add_from_url` and
278
+ `set_tag_with_id` return.
279
+
280
+ Eagle numbers its API only as V1 and V2. Whatever it adds inside a generation is tied to the Eagle build
281
+ that brought it (see the [V1 changelog](https://api.eagle.cool/changelog) and the
282
+ [V2 changelog](https://developer.eagle.cool/web-api/changelog)), so each release says which builds it covers:
283
+
284
+ | EagleWrapper | Eagle APIs | What it wraps |
285
+ |---|---|---|
286
+ | 1.0.0 (April 2023) | V1 | 3 endpoints (add from URL, list items, update item) and the library-folder reader |
287
+ | 1.1.0, 1.1.1 (April 2023) | V1 | all 21 endpoints documented at the time |
288
+ | 1.2.0 (November 2026) | V1 and Web API V2 | V1 up to its last change (Eagle 3.0 Build 23) plus `/api/library/icon`; V2 up to Eagle 4.0 Build 22 (smart folders, comments) |
289
+ | 2.0.0 (November 2026) | V1 and Web API V2 | the same as 1.2.0, plus `SUPPORTED_APIS` (below) |
290
+
291
+ 1.2.0 is the odd one out. It was the first release that speaks Web API V2, but it came out as 1.2.0,
292
+ before this rule was written down, because nothing changed for code written against V1. 2.0.0 puts the
293
+ number back on the rule. It is the 1.2.0 code with this versioning written down and `SUPPORTED_APIS`
294
+ added, so going from 1.2.0 to 2.0.0 needs no change in your code.
295
+
296
+ The installed package knows what it covers:
297
+
298
+ ```python
299
+ import eaglewrapper
300
+
301
+ for api in eaglewrapper.SUPPORTED_APIS:
302
+ print(f'{api.name}: {api.prefix}... needs Eagle {api.since}+, wrapped up to Eagle {api.covered_up_to}')
303
+ ```
304
+
305
+ ```text
306
+ V1: /api/... needs Eagle 1.11 Build 21+, wrapped up to Eagle 3.0 Build 23
307
+ Web API V2: /api/v2/... needs Eagle 4.0 Build 21+, wrapped up to Eagle 4.0 Build 22
308
+ ```
309
+
310
+ To see what your Eagle has, `Eagle().get_application_info()` returns its `version` and `buildVersion`,
311
+ and `Eagle().supports_v2()` says whether Web API V2 is there. Endpoints that Eagle adds after the covered
312
+ build are one call away with `eagle.v2.request('GET', 'section/endpoint')`. So are `item/open`,
313
+ `item/select` and `folder/open`: the V2 changelog lists them, but the docs have no page for them yet, so
314
+ they are not wrapped.
315
+
316
+ What to pin: the major number, `EagleWrapper~=2.0` (that is `>=2.0, <3`). You get fixes and newly
317
+ wrapped endpoints, and you move to another API generation only when you change the pin. The 1.x line gets
318
+ no more releases: if you pinned `~=1.2`, change it to `~=2.0`; nothing else to do. `eagle.v2` needs
319
+ 1.2.0 or later. Scripts that only use the V1 methods run on 1.1.0 and later, but 1.2.0 fixed several bugs
320
+ (see [Upgrading from 1.1.1](#upgrading-from-111)).
321
+
322
+ ## Plugins and related projects
323
+
324
+ Not every job needs a script. A few things worth knowing about before you write one:
325
+
326
+ From Eagle:
327
+
328
+ - [Plugin Center](https://community-en.eagle.cool/plugins): plugins you install inside Eagle. The batch job
329
+ you are about to script may already exist as one.
330
+ - [API Playground](https://developer.eagle.cool/web-api/get-started/playground): with Eagle open, visit
331
+ `http://localhost:41595/api/v2/playground` to try any Web API V2 endpoint from a form and see Eagle's real
332
+ reply before you write the Python call. It works on your real library, so writes there are real too.
333
+ - [Plugin API](https://developer.eagle.cool/plugin-api) and the
334
+ [official plugin examples](https://github.com/eagle-app/eagle-plugin-examples): for code that should run
335
+ inside Eagle (a window, a background service, support for a new file format, an inspector panel) rather
336
+ than talk to it from outside. The examples have one small working plugin per type.
337
+ - [AI Search](https://eagle.cool/support/article/ai-search): Eagle's offline search by description or by
338
+ similar image. `eagle.v2.ai_search` only works with this plugin installed.
339
+ - [Eagle Skill / MCP](https://en.eagle.cool/blog/post/eagle-plugin-mcp-skill): lets an AI agent clean up
340
+ tags, plan folders and rewrite names and descriptions in your library. Worth a look when the hard part is
341
+ deciding what to change, not making the calls.
342
+
343
+ Built on EagleWrapper:
344
+
345
+ - [yande-and-konachan-to-eagle](https://github.com/NatLee/yande-and-konachan-to-eagle): fetches images and
346
+ their tags from yande.re and konachan.com and adds them to Eagle with `add_from_url`. A complete,
347
+ small downloader to copy from.
348
+
349
+ Built something with EagleWrapper? Open an issue or a pull request and it can go on this list.
350
+
252
351
  ## Development
253
352
 
254
353
  The tests replace the HTTP calls with mocks, so Eagle does not need to be running.
@@ -258,6 +357,13 @@ pip install -e . pytest
258
357
  pytest tests
259
358
  ```
260
359
 
360
+ The editable install picks up your edits right away. To reinstall a regular copy from the checkout instead
361
+ (what the old `reinstall.sh` and `reinstall.bat` did with the retired `setup.py install`):
362
+
363
+ ```bash
364
+ python -m pip install --force-reinstall .
365
+ ```
366
+
261
367
  `tox -e py` runs the same tests plus a check of the source distribution. CI runs them on Linux with
262
368
  Python 3.6 to 3.14, and on Windows and macOS with Python 3.14.
263
369
 
@@ -269,8 +375,17 @@ How the code is laid out (`src/eaglewrapper/`):
269
375
  | `eagle.py` | `Eagle`: the V1 methods, kept compatible with 1.1.1 |
270
376
  | `v2.py` | `EagleV2` and its sections (`item`, `folder`, `tag`, ...), plus pagination |
271
377
  | `_library.py` | reads `metadata.json` files from a library folder |
378
+ | `_apis.py` | which Eagle APIs and builds this release covers (`SUPPORTED_APIS`); the code, `setup.py` and the README test read it |
272
379
  | `errors.py` | the exceptions |
273
380
 
381
+ ## Support
382
+
383
+ EagleWrapper is free and kept up in spare time. If it saved you an afternoon, you can buy me a coffee on
384
+ Ko-fi or chip in on Liberapay. Bug reports and pull requests help just as much.
385
+
386
+ [![Ko-fi](https://img.shields.io/badge/Ko--fi-natlee__-FF5E5B?logo=ko-fi&logoColor=white)](https://ko-fi.com/natlee_)
387
+ [![Liberapay](https://img.shields.io/badge/Liberapay-natlee-F6C915?logo=liberapay&logoColor=black)](https://liberapay.com/natlee)
388
+
274
389
  ## Contributor
275
390
 
276
391
  <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
@@ -1,23 +1,36 @@
1
+ import os
2
+ import runpy
3
+
1
4
  import setuptools
2
5
 
3
- with open('README.md', 'r', encoding='utf-8') as fh:
6
+ HERE = os.path.dirname(os.path.abspath(__file__))
7
+
8
+ with open(os.path.join(HERE, 'README.md'), 'r', encoding='utf-8') as fh:
4
9
  long_description = fh.read()
5
10
 
11
+ # The Eagle APIs this release speaks (names, docs links) come from the package itself.
12
+ # The file is loaded on its own because importing the package would need its dependencies.
13
+ APIS = runpy.run_path(os.path.join(HERE, 'src', 'eaglewrapper', '_apis.py'))
14
+ API_V1, API_V2 = APIS['API_V1'], APIS['API_V2']
15
+
16
+ REPO = 'https://github.com/NatLee/eagle-wrapper'
17
+
6
18
  setuptools.setup(
7
19
  name='EagleWrapper',
8
20
  author='Nat Lee',
9
21
  author_email='natlee.work@gmail.com',
10
- description='A wrapper for the local HTTP API (V1 and Web API V2) of Eagle, an image management app.',
22
+ description='A wrapper for the local HTTP API ({}) of Eagle, an image management app.'.format(
23
+ ' and '.join(api.name for api in APIS['SUPPORTED_APIS'])),
11
24
  keywords='eagle, eagle api, eagle web api, image management, asset management, wrapper',
12
25
  long_description=long_description,
13
26
  long_description_content_type='text/markdown',
14
- url='https://github.com/NatLee/eagle-wrapper',
27
+ url=REPO,
15
28
  project_urls={
16
- 'Documentation': 'https://github.com/NatLee/eagle-wrapper',
17
- 'Bug Reports': 'https://github.com/NatLee/eagle-wrapper/issues',
18
- 'Source Code': 'https://github.com/NatLee/eagle-wrapper',
19
- 'Official API Documentation': 'https://api.eagle.cool/',
20
- 'Eagle Web API V2': 'https://developer.eagle.cool/web-api',
29
+ 'Documentation': REPO,
30
+ 'Bug Reports': REPO + '/issues',
31
+ 'Source Code': REPO,
32
+ 'Official API Documentation': API_V1.docs,
33
+ 'Eagle Web API V2': API_V2.docs,
21
34
  # 'Funding': '',
22
35
  # 'Say Thanks!': '',
23
36
  },
@@ -29,7 +42,8 @@ setuptools.setup(
29
42
  'Development Status :: 5 - Production/Stable',
30
43
 
31
44
  'Intended Audience :: Developers',
32
- 'Topic :: Software Development :: Build Tools',
45
+ 'Topic :: Multimedia :: Graphics',
46
+ 'Topic :: Software Development :: Libraries :: Python Modules',
33
47
 
34
48
  'Programming Language :: Python :: 3',
35
49
  'Programming Language :: Python :: 3.6',
@@ -49,10 +63,5 @@ setuptools.setup(
49
63
  install_requires=['requests', 'loguru'],
50
64
  extras_require={
51
65
  'dev': ['check-manifest'],
52
- # 'test': ['coverage'],
53
66
  },
54
- entry_points={
55
- 'console_scripts': [
56
- ]
57
- }
58
- )
67
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: EagleWrapper
3
- Version: 1.2.0
3
+ Version: 2.0.0
4
4
  Summary: A wrapper for the local HTTP API (V1 and Web API V2) of Eagle, an image management app.
5
5
  Home-page: https://github.com/NatLee/eagle-wrapper
6
6
  Author: Nat Lee
@@ -13,7 +13,8 @@ Project-URL: Eagle Web API V2, https://developer.eagle.cool/web-api
13
13
  Keywords: eagle,eagle api,eagle web api,image management,asset management,wrapper
14
14
  Classifier: Development Status :: 5 - Production/Stable
15
15
  Classifier: Intended Audience :: Developers
16
- Classifier: Topic :: Software Development :: Build Tools
16
+ Classifier: Topic :: Multimedia :: Graphics
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
17
18
  Classifier: Programming Language :: Python :: 3
18
19
  Classifier: Programming Language :: Python :: 3.6
19
20
  Classifier: Programming Language :: Python :: 3.7
@@ -94,6 +95,7 @@ pip install EagleWrapper
94
95
 
95
96
  Python 3.6 or later. Eagle must be running for everything except the library-folder reader.
96
97
  Web API V2, the connection options and the new exceptions arrived in 1.2.0.
98
+ Which release speaks which Eagle API, and what to pin: see [Versioning](#versioning).
97
99
 
98
100
  ## Quick start
99
101
 
@@ -243,8 +245,25 @@ These are the methods of 1.1.1, unchanged, plus `star`, `get_library_icon` and `
243
245
  | **No API** | `get_img_info_from_lib_path(library_path, name_start_filters, max_workers, match)` | reads the library folder | list |
244
246
  | **Helpers** | `supports_v2()` · `check_success(response_or_dict)` | | bool |
245
247
 
246
- `add_from_path` returns Eagle's whole reply, not a bool, because 1.1.1 did. A dict is always truthy, so check
247
- `eagle.check_success(reply)` (or use `raise_errors=True`) instead of `if eagle.add_from_path(...)`.
248
+ `add_from_path` returns Eagle's whole reply (a dict such as `{'status': 'success'}`), not a bool, because
249
+ 1.1.1 did and scripts may read it. A dict is always truthy, so `if eagle.add_from_path(...)` passes even when Eagle
250
+ refused the file. Check the reply, or let failures raise:
251
+
252
+ ```python
253
+ from eaglewrapper import Eagle, EagleAPIError
254
+
255
+ eagle = Eagle()
256
+ reply = eagle.add_from_path('/path/to/cat.jpg', 'Cat')
257
+ if eagle.check_success(reply): # True only for {'status': 'success', ...}
258
+ print('added')
259
+ else:
260
+ print('Eagle said no:', reply)
261
+
262
+ try:
263
+ Eagle(raise_errors=True).add_from_path('/path/to/cat.jpg', 'Cat')
264
+ except EagleAPIError as e:
265
+ print('Eagle said no:', e.message)
266
+ ```
248
267
 
249
268
  ## Reading a library folder without Eagle
250
269
 
@@ -299,6 +318,87 @@ Moving a V1 script to V2 when your Eagle is 4.0 Build 21 or later:
299
318
  | `get_application_info()` | `v2.app.info()` | |
300
319
  | `get_thumbnail_path(id)` | none | keep using V1 |
301
320
 
321
+ ## Versioning
322
+
323
+ The version number follows Eagle's API. The major number is the newest Eagle API generation a release
324
+ speaks: 1 for V1, Eagle's original `/api/` API, and 2 for Web API V2 (`/api/v2/`). A test keeps the two in
325
+ step. Minor releases wrap more
326
+ of that API (often what a new Eagle build added) or add options to the package, and patch releases fix bugs.
327
+ Code that works with one release keeps working with later releases that have the same major number.
328
+ One slip from the early days: 1.1.0 renamed two arguments of 1.0.0 and changed what `add_from_url` and
329
+ `set_tag_with_id` return.
330
+
331
+ Eagle numbers its API only as V1 and V2. Whatever it adds inside a generation is tied to the Eagle build
332
+ that brought it (see the [V1 changelog](https://api.eagle.cool/changelog) and the
333
+ [V2 changelog](https://developer.eagle.cool/web-api/changelog)), so each release says which builds it covers:
334
+
335
+ | EagleWrapper | Eagle APIs | What it wraps |
336
+ |---|---|---|
337
+ | 1.0.0 (April 2023) | V1 | 3 endpoints (add from URL, list items, update item) and the library-folder reader |
338
+ | 1.1.0, 1.1.1 (April 2023) | V1 | all 21 endpoints documented at the time |
339
+ | 1.2.0 (November 2026) | V1 and Web API V2 | V1 up to its last change (Eagle 3.0 Build 23) plus `/api/library/icon`; V2 up to Eagle 4.0 Build 22 (smart folders, comments) |
340
+ | 2.0.0 (November 2026) | V1 and Web API V2 | the same as 1.2.0, plus `SUPPORTED_APIS` (below) |
341
+
342
+ 1.2.0 is the odd one out. It was the first release that speaks Web API V2, but it came out as 1.2.0,
343
+ before this rule was written down, because nothing changed for code written against V1. 2.0.0 puts the
344
+ number back on the rule. It is the 1.2.0 code with this versioning written down and `SUPPORTED_APIS`
345
+ added, so going from 1.2.0 to 2.0.0 needs no change in your code.
346
+
347
+ The installed package knows what it covers:
348
+
349
+ ```python
350
+ import eaglewrapper
351
+
352
+ for api in eaglewrapper.SUPPORTED_APIS:
353
+ print(f'{api.name}: {api.prefix}... needs Eagle {api.since}+, wrapped up to Eagle {api.covered_up_to}')
354
+ ```
355
+
356
+ ```text
357
+ V1: /api/... needs Eagle 1.11 Build 21+, wrapped up to Eagle 3.0 Build 23
358
+ Web API V2: /api/v2/... needs Eagle 4.0 Build 21+, wrapped up to Eagle 4.0 Build 22
359
+ ```
360
+
361
+ To see what your Eagle has, `Eagle().get_application_info()` returns its `version` and `buildVersion`,
362
+ and `Eagle().supports_v2()` says whether Web API V2 is there. Endpoints that Eagle adds after the covered
363
+ build are one call away with `eagle.v2.request('GET', 'section/endpoint')`. So are `item/open`,
364
+ `item/select` and `folder/open`: the V2 changelog lists them, but the docs have no page for them yet, so
365
+ they are not wrapped.
366
+
367
+ What to pin: the major number, `EagleWrapper~=2.0` (that is `>=2.0, <3`). You get fixes and newly
368
+ wrapped endpoints, and you move to another API generation only when you change the pin. The 1.x line gets
369
+ no more releases: if you pinned `~=1.2`, change it to `~=2.0`; nothing else to do. `eagle.v2` needs
370
+ 1.2.0 or later. Scripts that only use the V1 methods run on 1.1.0 and later, but 1.2.0 fixed several bugs
371
+ (see [Upgrading from 1.1.1](#upgrading-from-111)).
372
+
373
+ ## Plugins and related projects
374
+
375
+ Not every job needs a script. A few things worth knowing about before you write one:
376
+
377
+ From Eagle:
378
+
379
+ - [Plugin Center](https://community-en.eagle.cool/plugins): plugins you install inside Eagle. The batch job
380
+ you are about to script may already exist as one.
381
+ - [API Playground](https://developer.eagle.cool/web-api/get-started/playground): with Eagle open, visit
382
+ `http://localhost:41595/api/v2/playground` to try any Web API V2 endpoint from a form and see Eagle's real
383
+ reply before you write the Python call. It works on your real library, so writes there are real too.
384
+ - [Plugin API](https://developer.eagle.cool/plugin-api) and the
385
+ [official plugin examples](https://github.com/eagle-app/eagle-plugin-examples): for code that should run
386
+ inside Eagle (a window, a background service, support for a new file format, an inspector panel) rather
387
+ than talk to it from outside. The examples have one small working plugin per type.
388
+ - [AI Search](https://eagle.cool/support/article/ai-search): Eagle's offline search by description or by
389
+ similar image. `eagle.v2.ai_search` only works with this plugin installed.
390
+ - [Eagle Skill / MCP](https://en.eagle.cool/blog/post/eagle-plugin-mcp-skill): lets an AI agent clean up
391
+ tags, plan folders and rewrite names and descriptions in your library. Worth a look when the hard part is
392
+ deciding what to change, not making the calls.
393
+
394
+ Built on EagleWrapper:
395
+
396
+ - [yande-and-konachan-to-eagle](https://github.com/NatLee/yande-and-konachan-to-eagle): fetches images and
397
+ their tags from yande.re and konachan.com and adds them to Eagle with `add_from_url`. A complete,
398
+ small downloader to copy from.
399
+
400
+ Built something with EagleWrapper? Open an issue or a pull request and it can go on this list.
401
+
302
402
  ## Development
303
403
 
304
404
  The tests replace the HTTP calls with mocks, so Eagle does not need to be running.
@@ -308,6 +408,13 @@ pip install -e . pytest
308
408
  pytest tests
309
409
  ```
310
410
 
411
+ The editable install picks up your edits right away. To reinstall a regular copy from the checkout instead
412
+ (what the old `reinstall.sh` and `reinstall.bat` did with the retired `setup.py install`):
413
+
414
+ ```bash
415
+ python -m pip install --force-reinstall .
416
+ ```
417
+
311
418
  `tox -e py` runs the same tests plus a check of the source distribution. CI runs them on Linux with
312
419
  Python 3.6 to 3.14, and on Windows and macOS with Python 3.14.
313
420
 
@@ -319,8 +426,17 @@ How the code is laid out (`src/eaglewrapper/`):
319
426
  | `eagle.py` | `Eagle`: the V1 methods, kept compatible with 1.1.1 |
320
427
  | `v2.py` | `EagleV2` and its sections (`item`, `folder`, `tag`, ...), plus pagination |
321
428
  | `_library.py` | reads `metadata.json` files from a library folder |
429
+ | `_apis.py` | which Eagle APIs and builds this release covers (`SUPPORTED_APIS`); the code, `setup.py` and the README test read it |
322
430
  | `errors.py` | the exceptions |
323
431
 
432
+ ## Support
433
+
434
+ EagleWrapper is free and kept up in spare time. If it saved you an afternoon, you can buy me a coffee on
435
+ Ko-fi or chip in on Liberapay. Bug reports and pull requests help just as much.
436
+
437
+ [![Ko-fi](https://img.shields.io/badge/Ko--fi-natlee__-FF5E5B?logo=ko-fi&logoColor=white)](https://ko-fi.com/natlee_)
438
+ [![Liberapay](https://img.shields.io/badge/Liberapay-natlee-F6C915?logo=liberapay&logoColor=black)](https://liberapay.com/natlee)
439
+
324
440
  ## Contributor
325
441
 
326
442
  <!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
@@ -2,8 +2,6 @@ LICENSE
2
2
  MANIFEST.in
3
3
  README.md
4
4
  pyproject.toml
5
- reinstall.bat
6
- reinstall.sh
7
5
  setup.cfg
8
6
  setup.py
9
7
  doc/add-from-url.png
@@ -15,6 +13,7 @@ src/EagleWrapper.egg-info/dependency_links.txt
15
13
  src/EagleWrapper.egg-info/requires.txt
16
14
  src/EagleWrapper.egg-info/top_level.txt
17
15
  src/eaglewrapper/__init__.py
16
+ src/eaglewrapper/_apis.py
18
17
  src/eaglewrapper/_library.py
19
18
  src/eaglewrapper/client.py
20
19
  src/eaglewrapper/eagle.py
@@ -24,10 +23,12 @@ src/eaglewrapper/v2.py
24
23
  tests/__init__.py
25
24
  tests/fakes.py
26
25
  tests/test_api_requests.py
26
+ tests/test_apis.py
27
27
  tests/test_compat.py
28
28
  tests/test_connection_options.py
29
29
  tests/test_eagle.py
30
30
  tests/test_errors.py
31
31
  tests/test_library_folder.py
32
+ tests/test_readme.py
32
33
  tests/test_v1_additions.py
33
34
  tests/test_v2.py
@@ -1,11 +1,13 @@
1
1
  """A Python wrapper for the local HTTP API of Eagle, the image and design asset manager.
2
2
 
3
3
  * :class:`Eagle` - the V1 (legacy) API methods, the library-folder reader, and ``.v2``.
4
- * :class:`EagleV2` - the Web API V2 on its own (Eagle 4.0 Build 21 or later).
4
+ * :class:`EagleV2` - the Web API V2 on its own.
5
5
  * :mod:`eaglewrapper.errors` - the exceptions.
6
+ * :data:`SUPPORTED_APIS` - which Eagle APIs and Eagle builds this release covers.
6
7
  """
7
- __version__ = '1.2.0'
8
+ __version__ = '2.0.0'
8
9
 
10
+ from ._apis import API_V1, API_V2, SUPPORTED_APIS, EagleAPI
9
11
  from .client import EagleClient
10
12
  from .eagle import Eagle, ImageData
11
13
  from .errors import EagleAPIError, EagleConnectionError, EagleError, EagleResponseError
@@ -14,4 +16,5 @@ from .v2 import EagleV2
14
16
  __all__ = [
15
17
  'Eagle', 'EagleV2', 'EagleClient', 'ImageData',
16
18
  'EagleError', 'EagleAPIError', 'EagleConnectionError', 'EagleResponseError',
19
+ 'EagleAPI', 'API_V1', 'API_V2', 'SUPPORTED_APIS',
17
20
  ]