karakeep-python-api 0.1.2__tar.gz → 0.1.3__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.
- {karakeep_python_api-0.1.2/karakeep_python_api.egg-info → karakeep_python_api-0.1.3}/PKG-INFO +41 -38
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/README.md +40 -37
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/karakeep_python_api/karakeep_api.py +6 -1
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/karakeep_python_api/openapi_reference.json +1 -1
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3/karakeep_python_api.egg-info}/PKG-INFO +41 -38
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/setup.py +1 -1
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/tests/test_karakeep_api.py +152 -144
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/LICENSE +0 -0
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/MANIFEST.in +0 -0
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/karakeep_python_api/__init__.py +0 -0
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/karakeep_python_api/__main__.py +0 -0
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/karakeep_python_api/datatypes.py +0 -0
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/karakeep_python_api.egg-info/SOURCES.txt +0 -0
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/karakeep_python_api.egg-info/dependency_links.txt +0 -0
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/karakeep_python_api.egg-info/entry_points.txt +0 -0
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/karakeep_python_api.egg-info/requires.txt +0 -0
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/karakeep_python_api.egg-info/top_level.txt +0 -0
- {karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/setup.cfg +0 -0
{karakeep_python_api-0.1.2/karakeep_python_api.egg-info → karakeep_python_api-0.1.3}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: karakeep_python_api
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Community python client for the Karakeep API.
|
|
5
5
|
Home-page: https://github.com/thiswillbeyourgithub/karakeep_python_api/
|
|
6
6
|
License: GPLv3
|
|
@@ -72,43 +72,46 @@ The development process involved:
|
|
|
72
72
|
|
|
73
73
|
## API Method Coverage
|
|
74
74
|
|
|
75
|
-
The following table lists the public methods available in the `KarakeepAPI` class
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
| `
|
|
89
|
-
| `
|
|
90
|
-
| `
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
94
|
-
| `
|
|
95
|
-
| `
|
|
96
|
-
| `
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `
|
|
108
|
-
| `
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
75
|
+
The following table lists the public methods available in the `KarakeepAPI` class.
|
|
76
|
+
* The "Pytest" column indicates whether the Python library method is covered by the automated test suite (`tests/test_karakeep_api.py`).
|
|
77
|
+
* The "CLI" column indicates whether the corresponding CLI command for that method is tested within the Pytest suite (typically via `subprocess`).
|
|
78
|
+
Methods or CLI commands marked with ❌ should be used with caution as their behavior has not been automatically verified within the test suite.
|
|
79
|
+
|
|
80
|
+
| Method Name | Pytest | CLI | Remarks |
|
|
81
|
+
| -------------------------------- | :----: | :--: | -------------------------------------------- |
|
|
82
|
+
| `get_all_bookmarks` | ✅ | ✅ | Tested with pagination. |
|
|
83
|
+
| `create_a_new_bookmark` | ✅ | ❌ | Pytest for `type="link"` via fixture. CLI not directly tested. |
|
|
84
|
+
| `search_bookmarks` | ✅ | ✅ | Seems to be nondeterministic and fails if using more than 3 words |
|
|
85
|
+
| `get_a_single_bookmark` | ✅ | ❌ | |
|
|
86
|
+
| `delete_a_bookmark` | ✅ | ❌ | |
|
|
87
|
+
| `update_a_bookmark` | ✅ | ✅ | Tested for title updates. |
|
|
88
|
+
| `summarize_a_bookmark` | ❌ | ❌ | |
|
|
89
|
+
| `attach_tags_to_a_bookmark` | ✅ | ❌ | |
|
|
90
|
+
| `detach_tags_from_a_bookmark` | ✅ | ❌ | |
|
|
91
|
+
| `get_highlights_of_a_bookmark` | ❌ | ❌ | Works from the CLI; not yet added to Pytest. |
|
|
92
|
+
| `attach_asset` | ❌ | ❌ | |
|
|
93
|
+
| `replace_asset` | ❌ | ❌ | |
|
|
94
|
+
| `detach_asset` | ❌ | ❌ | |
|
|
95
|
+
| `get_all_lists` | ✅ | ✅ | |
|
|
96
|
+
| `create_a_new_list` | ✅ | ❌ | |
|
|
97
|
+
| `get_a_single_list` | ✅ | ❌ | |
|
|
98
|
+
| `delete_a_list` | ✅ | ❌ | |
|
|
99
|
+
| `update_a_list` | ❌ | ❌ | |
|
|
100
|
+
| `get_a_bookmarks_in_a_list` | ❌ | ❌ | |
|
|
101
|
+
| `add_a_bookmark_to_a_list` | ❌ | ❌ | |
|
|
102
|
+
| `remove_a_bookmark_from_a_list` | ❌ | ❌ | |
|
|
103
|
+
| `get_all_tags` | ✅ | ✅ | |
|
|
104
|
+
| `get_a_single_tag` | ✅ | ❌ | |
|
|
105
|
+
| `delete_a_tag` | ✅ | ❌ | |
|
|
106
|
+
| `update_a_tag` | ✅ | ❌ | No output validation due to [server bug](https://github.com/karakeep-app/karakeep/issues/1365). |
|
|
107
|
+
| `get_a_bookmarks_with_the_tag` | ❌ | ❌ | |
|
|
108
|
+
| `get_all_highlights` | ✅ | ✅ | Tested with pagination. |
|
|
109
|
+
| `create_a_new_highlight` | ❌ | ❌ | |
|
|
110
|
+
| `get_a_single_highlight` | ❌ | ❌ | |
|
|
111
|
+
| `delete_a_highlight` | ❌ | ❌ | Works from the CLI; not yet added to Pytest. |
|
|
112
|
+
| `update_a_highlight` | ❌ | ❌ | |
|
|
113
|
+
| `get_current_user_info` | ✅ | ❌ | Pytest: Tested indirectly during client init. CLI not directly tested. |
|
|
114
|
+
| `get_current_user_stats` | ✅ | ✅ | |
|
|
112
115
|
|
|
113
116
|
## Installation
|
|
114
117
|
|
|
@@ -37,43 +37,46 @@ The development process involved:
|
|
|
37
37
|
|
|
38
38
|
## API Method Coverage
|
|
39
39
|
|
|
40
|
-
The following table lists the public methods available in the `KarakeepAPI` class
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
| `
|
|
48
|
-
| `
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
72
|
-
| `
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
40
|
+
The following table lists the public methods available in the `KarakeepAPI` class.
|
|
41
|
+
* The "Pytest" column indicates whether the Python library method is covered by the automated test suite (`tests/test_karakeep_api.py`).
|
|
42
|
+
* The "CLI" column indicates whether the corresponding CLI command for that method is tested within the Pytest suite (typically via `subprocess`).
|
|
43
|
+
Methods or CLI commands marked with ❌ should be used with caution as their behavior has not been automatically verified within the test suite.
|
|
44
|
+
|
|
45
|
+
| Method Name | Pytest | CLI | Remarks |
|
|
46
|
+
| -------------------------------- | :----: | :--: | -------------------------------------------- |
|
|
47
|
+
| `get_all_bookmarks` | ✅ | ✅ | Tested with pagination. |
|
|
48
|
+
| `create_a_new_bookmark` | ✅ | ❌ | Pytest for `type="link"` via fixture. CLI not directly tested. |
|
|
49
|
+
| `search_bookmarks` | ✅ | ✅ | Seems to be nondeterministic and fails if using more than 3 words |
|
|
50
|
+
| `get_a_single_bookmark` | ✅ | ❌ | |
|
|
51
|
+
| `delete_a_bookmark` | ✅ | ❌ | |
|
|
52
|
+
| `update_a_bookmark` | ✅ | ✅ | Tested for title updates. |
|
|
53
|
+
| `summarize_a_bookmark` | ❌ | ❌ | |
|
|
54
|
+
| `attach_tags_to_a_bookmark` | ✅ | ❌ | |
|
|
55
|
+
| `detach_tags_from_a_bookmark` | ✅ | ❌ | |
|
|
56
|
+
| `get_highlights_of_a_bookmark` | ❌ | ❌ | Works from the CLI; not yet added to Pytest. |
|
|
57
|
+
| `attach_asset` | ❌ | ❌ | |
|
|
58
|
+
| `replace_asset` | ❌ | ❌ | |
|
|
59
|
+
| `detach_asset` | ❌ | ❌ | |
|
|
60
|
+
| `get_all_lists` | ✅ | ✅ | |
|
|
61
|
+
| `create_a_new_list` | ✅ | ❌ | |
|
|
62
|
+
| `get_a_single_list` | ✅ | ❌ | |
|
|
63
|
+
| `delete_a_list` | ✅ | ❌ | |
|
|
64
|
+
| `update_a_list` | ❌ | ❌ | |
|
|
65
|
+
| `get_a_bookmarks_in_a_list` | ❌ | ❌ | |
|
|
66
|
+
| `add_a_bookmark_to_a_list` | ❌ | ❌ | |
|
|
67
|
+
| `remove_a_bookmark_from_a_list` | ❌ | ❌ | |
|
|
68
|
+
| `get_all_tags` | ✅ | ✅ | |
|
|
69
|
+
| `get_a_single_tag` | ✅ | ❌ | |
|
|
70
|
+
| `delete_a_tag` | ✅ | ❌ | |
|
|
71
|
+
| `update_a_tag` | ✅ | ❌ | No output validation due to [server bug](https://github.com/karakeep-app/karakeep/issues/1365). |
|
|
72
|
+
| `get_a_bookmarks_with_the_tag` | ❌ | ❌ | |
|
|
73
|
+
| `get_all_highlights` | ✅ | ✅ | Tested with pagination. |
|
|
74
|
+
| `create_a_new_highlight` | ❌ | ❌ | |
|
|
75
|
+
| `get_a_single_highlight` | ❌ | ❌ | |
|
|
76
|
+
| `delete_a_highlight` | ❌ | ❌ | Works from the CLI; not yet added to Pytest. |
|
|
77
|
+
| `update_a_highlight` | ❌ | ❌ | |
|
|
78
|
+
| `get_current_user_info` | ✅ | ❌ | Pytest: Tested indirectly during client init. CLI not directly tested. |
|
|
79
|
+
| `get_current_user_stats` | ✅ | ✅ | |
|
|
77
80
|
|
|
78
81
|
## Installation
|
|
79
82
|
|
|
@@ -85,7 +85,7 @@ class KarakeepAPI:
|
|
|
85
85
|
"""
|
|
86
86
|
|
|
87
87
|
# Version reflects the client library version, updated by bumpver
|
|
88
|
-
VERSION: str = "0.1.
|
|
88
|
+
VERSION: str = "0.1.3"
|
|
89
89
|
|
|
90
90
|
def __init__(
|
|
91
91
|
self,
|
|
@@ -1435,6 +1435,11 @@ class KarakeepAPI:
|
|
|
1435
1435
|
logger.debug("Skipping response validation as requested.")
|
|
1436
1436
|
return response_data
|
|
1437
1437
|
else:
|
|
1438
|
+
# As of version 0.24.1 of karakeep: we do not check the correct
|
|
1439
|
+
# validation type because there is an error on the
|
|
1440
|
+
# server side: https://github.com/karakeep-app/karakeep/issues/1365
|
|
1441
|
+
return response_data
|
|
1442
|
+
|
|
1438
1443
|
# Response should match Tag1 schema
|
|
1439
1444
|
return datatypes.Tag1.model_validate(response_data)
|
|
1440
1445
|
|
{karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3/karakeep_python_api.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: karakeep_python_api
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Community python client for the Karakeep API.
|
|
5
5
|
Home-page: https://github.com/thiswillbeyourgithub/karakeep_python_api/
|
|
6
6
|
License: GPLv3
|
|
@@ -72,43 +72,46 @@ The development process involved:
|
|
|
72
72
|
|
|
73
73
|
## API Method Coverage
|
|
74
74
|
|
|
75
|
-
The following table lists the public methods available in the `KarakeepAPI` class
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
|
81
|
-
|
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
| `
|
|
89
|
-
| `
|
|
90
|
-
| `
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
94
|
-
| `
|
|
95
|
-
| `
|
|
96
|
-
| `
|
|
97
|
-
| `
|
|
98
|
-
| `
|
|
99
|
-
| `
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
105
|
-
| `
|
|
106
|
-
| `
|
|
107
|
-
| `
|
|
108
|
-
| `
|
|
109
|
-
| `
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
75
|
+
The following table lists the public methods available in the `KarakeepAPI` class.
|
|
76
|
+
* The "Pytest" column indicates whether the Python library method is covered by the automated test suite (`tests/test_karakeep_api.py`).
|
|
77
|
+
* The "CLI" column indicates whether the corresponding CLI command for that method is tested within the Pytest suite (typically via `subprocess`).
|
|
78
|
+
Methods or CLI commands marked with ❌ should be used with caution as their behavior has not been automatically verified within the test suite.
|
|
79
|
+
|
|
80
|
+
| Method Name | Pytest | CLI | Remarks |
|
|
81
|
+
| -------------------------------- | :----: | :--: | -------------------------------------------- |
|
|
82
|
+
| `get_all_bookmarks` | ✅ | ✅ | Tested with pagination. |
|
|
83
|
+
| `create_a_new_bookmark` | ✅ | ❌ | Pytest for `type="link"` via fixture. CLI not directly tested. |
|
|
84
|
+
| `search_bookmarks` | ✅ | ✅ | Seems to be nondeterministic and fails if using more than 3 words |
|
|
85
|
+
| `get_a_single_bookmark` | ✅ | ❌ | |
|
|
86
|
+
| `delete_a_bookmark` | ✅ | ❌ | |
|
|
87
|
+
| `update_a_bookmark` | ✅ | ✅ | Tested for title updates. |
|
|
88
|
+
| `summarize_a_bookmark` | ❌ | ❌ | |
|
|
89
|
+
| `attach_tags_to_a_bookmark` | ✅ | ❌ | |
|
|
90
|
+
| `detach_tags_from_a_bookmark` | ✅ | ❌ | |
|
|
91
|
+
| `get_highlights_of_a_bookmark` | ❌ | ❌ | Works from the CLI; not yet added to Pytest. |
|
|
92
|
+
| `attach_asset` | ❌ | ❌ | |
|
|
93
|
+
| `replace_asset` | ❌ | ❌ | |
|
|
94
|
+
| `detach_asset` | ❌ | ❌ | |
|
|
95
|
+
| `get_all_lists` | ✅ | ✅ | |
|
|
96
|
+
| `create_a_new_list` | ✅ | ❌ | |
|
|
97
|
+
| `get_a_single_list` | ✅ | ❌ | |
|
|
98
|
+
| `delete_a_list` | ✅ | ❌ | |
|
|
99
|
+
| `update_a_list` | ❌ | ❌ | |
|
|
100
|
+
| `get_a_bookmarks_in_a_list` | ❌ | ❌ | |
|
|
101
|
+
| `add_a_bookmark_to_a_list` | ❌ | ❌ | |
|
|
102
|
+
| `remove_a_bookmark_from_a_list` | ❌ | ❌ | |
|
|
103
|
+
| `get_all_tags` | ✅ | ✅ | |
|
|
104
|
+
| `get_a_single_tag` | ✅ | ❌ | |
|
|
105
|
+
| `delete_a_tag` | ✅ | ❌ | |
|
|
106
|
+
| `update_a_tag` | ✅ | ❌ | No output validation due to [server bug](https://github.com/karakeep-app/karakeep/issues/1365). |
|
|
107
|
+
| `get_a_bookmarks_with_the_tag` | ❌ | ❌ | |
|
|
108
|
+
| `get_all_highlights` | ✅ | ✅ | Tested with pagination. |
|
|
109
|
+
| `create_a_new_highlight` | ❌ | ❌ | |
|
|
110
|
+
| `get_a_single_highlight` | ❌ | ❌ | |
|
|
111
|
+
| `delete_a_highlight` | ❌ | ❌ | Works from the CLI; not yet added to Pytest. |
|
|
112
|
+
| `update_a_highlight` | ❌ | ❌ | |
|
|
113
|
+
| `get_current_user_info` | ✅ | ❌ | Pytest: Tested indirectly during client init. CLI not directly tested. |
|
|
114
|
+
| `get_current_user_stats` | ✅ | ✅ | |
|
|
112
115
|
|
|
113
116
|
## Installation
|
|
114
117
|
|
|
@@ -7,7 +7,7 @@ with open("README.md", "r") as readme:
|
|
|
7
7
|
|
|
8
8
|
setup(
|
|
9
9
|
name="karakeep_python_api",
|
|
10
|
-
version="0.1.
|
|
10
|
+
version="0.1.3",
|
|
11
11
|
description="Community python client for the Karakeep API.", # Simplified description
|
|
12
12
|
long_description=long_description,
|
|
13
13
|
long_description_content_type="text/markdown",
|
|
@@ -340,55 +340,66 @@ def test_create_and_delete_list(karakeep_client: KarakeepAPI):
|
|
|
340
340
|
print("\nSkipping deletion because list creation failed or ID was not obtained.")
|
|
341
341
|
|
|
342
342
|
|
|
343
|
-
def test_create_and_delete_bookmark(karakeep_client: KarakeepAPI):
|
|
344
|
-
"""
|
|
345
|
-
|
|
346
|
-
|
|
343
|
+
def test_create_and_delete_bookmark(karakeep_client: KarakeepAPI, managed_bookmark: datatypes.Bookmark):
|
|
344
|
+
"""
|
|
345
|
+
Test verifying a created bookmark (via fixture) and searching for it.
|
|
346
|
+
The fixture handles creation and deletion.
|
|
347
|
+
"""
|
|
348
|
+
created_bookmark_id = managed_bookmark.id
|
|
349
|
+
test_url = managed_bookmark.content.url # Get URL from fixture
|
|
350
|
+
original_title = managed_bookmark.title # Get title from fixture
|
|
351
|
+
|
|
347
352
|
try:
|
|
348
|
-
# 1.
|
|
349
|
-
print(f"\
|
|
353
|
+
# 1. Bookmark is already created by the 'managed_bookmark' fixture.
|
|
354
|
+
print(f"\nUsing managed bookmark ID: {created_bookmark_id}, URL: '{test_url}', Title: '{original_title}'")
|
|
350
355
|
|
|
351
|
-
# 2.
|
|
352
|
-
# Call the method with keyword arguments matching its signature
|
|
353
|
-
created_bookmark = karakeep_client.create_a_new_bookmark(
|
|
354
|
-
type="link", url=test_url
|
|
355
|
-
)
|
|
356
|
-
assert isinstance(
|
|
357
|
-
created_bookmark, datatypes.Bookmark
|
|
358
|
-
), "Response should be a Bookmark model"
|
|
359
|
-
assert created_bookmark.content.url == test_url, "Created bookmark URL should match"
|
|
360
|
-
assert created_bookmark.id, "Created bookmark must have an ID"
|
|
361
|
-
created_bookmark_id = created_bookmark.id
|
|
362
|
-
print(f"✓ Successfully created bookmark with ID: {created_bookmark_id}")
|
|
363
|
-
|
|
364
|
-
# 3. Verify the bookmark exists by getting it directly
|
|
356
|
+
# 2. Verify the bookmark exists by getting it directly
|
|
365
357
|
retrieved_bookmark = karakeep_client.get_a_single_bookmark(
|
|
366
358
|
bookmark_id=created_bookmark_id
|
|
367
359
|
)
|
|
368
360
|
assert isinstance(retrieved_bookmark, datatypes.Bookmark)
|
|
369
361
|
assert retrieved_bookmark.id == created_bookmark_id
|
|
370
362
|
assert retrieved_bookmark.content.url == test_url
|
|
371
|
-
|
|
363
|
+
assert retrieved_bookmark.title == original_title
|
|
364
|
+
print(f"✓ Successfully retrieved the managed bookmark by ID.")
|
|
372
365
|
|
|
373
|
-
# 4. Search for the created bookmark
|
|
374
|
-
print(f"\nAttempting to search for bookmark with query: 'wikipedia'")
|
|
375
|
-
search_query = "Example - Wikipedia"
|
|
376
|
-
search_results = karakeep_client.search_bookmarks(q=search_query, limit=50)
|
|
377
|
-
assert isinstance(
|
|
378
|
-
search_results, datatypes.PaginatedBookmarks
|
|
379
|
-
), "Search response should be PaginatedBookmarks model"
|
|
380
|
-
assert isinstance(
|
|
381
|
-
search_results.bookmarks, list
|
|
382
|
-
), "Search results bookmarks attribute should be a list"
|
|
383
|
-
assert any(
|
|
384
|
-
b.id == created_bookmark_id for b in search_results.bookmarks
|
|
385
|
-
), f"Created bookmark {created_bookmark_id} not found in search results for '{search_query}'"
|
|
386
|
-
print(f"✓ Found created bookmark in search results for '{search_query}'.")
|
|
387
366
|
|
|
388
|
-
#
|
|
389
|
-
|
|
367
|
+
# 3. Search for the created bookmark
|
|
368
|
+
# Use a search query that is likely to match the fixture's title
|
|
369
|
+
# The fixture title is "Managed Fixture Bookmark {timestamp}-{random_suffix}"
|
|
370
|
+
# A simple search for "Managed Fixture Bookmark" should work.
|
|
371
|
+
# If the title is very dynamic, searching by URL might be more robust if supported,
|
|
372
|
+
# or by a known part of the title.
|
|
373
|
+
|
|
374
|
+
# waiting a bit for the indexation just in case
|
|
375
|
+
time.sleep(30)
|
|
376
|
+
|
|
377
|
+
search_query_component = original_title.split(" ")[0] + " " + original_title.split(" ")[1]
|
|
378
|
+
print(f"\nAttempting to search for bookmark with query based on title: '{search_query_component}'. Retrying multiple times because search is nondeterministic.")
|
|
379
|
+
|
|
380
|
+
for trial in range(5):
|
|
381
|
+
search_results = karakeep_client.search_bookmarks(q=search_query_component, limit=100, include_content=False)
|
|
382
|
+
assert isinstance(
|
|
383
|
+
search_results, datatypes.PaginatedBookmarks
|
|
384
|
+
), "Search response should be PaginatedBookmarks model"
|
|
385
|
+
assert isinstance(
|
|
386
|
+
search_results.bookmarks, list
|
|
387
|
+
), "Search results bookmarks attribute should be a list"
|
|
388
|
+
|
|
389
|
+
titles_in_search = [b.title for b in search_results.bookmarks]
|
|
390
|
+
found_in_search = any(b.id == created_bookmark_id for b in search_results.bookmarks)
|
|
391
|
+
if found_in_search:
|
|
392
|
+
break
|
|
393
|
+
else:
|
|
394
|
+
time.sleep(3)
|
|
395
|
+
assert found_in_search, \
|
|
396
|
+
f"Managed bookmark {created_bookmark_id} (Title: '{original_title}') not found in {trial} different search results for '{search_query_component}'. Titles were: '{titles_in_search}'."
|
|
397
|
+
print(f"✓ Found managed bookmark in search results for '{search_query_component}'.")
|
|
398
|
+
|
|
399
|
+
# 4. Test CLI search equivalent
|
|
400
|
+
print(f"\n Running CLI equivalent: search-bookmarks --q '{search_query_component}' --limit 10 --include-content false")
|
|
390
401
|
try:
|
|
391
|
-
cli_search_command = f"python -m karakeep_python_api search-bookmarks --q '{
|
|
402
|
+
cli_search_command = f"python -m karakeep_python_api search-bookmarks --q '{search_query_component}' --limit 10 --include-content false"
|
|
392
403
|
search_cli_output = subprocess.run(
|
|
393
404
|
cli_search_command,
|
|
394
405
|
shell=True,
|
|
@@ -396,120 +407,41 @@ def test_create_and_delete_bookmark(karakeep_client: KarakeepAPI):
|
|
|
396
407
|
capture_output=True,
|
|
397
408
|
text=True,
|
|
398
409
|
)
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
assert created_bookmark_id in search_cli_output.stdout, f"Created bookmark ID {created_bookmark_id} not found in CLI search output for '{search_query}'"
|
|
410
|
+
assert created_bookmark_id in search_cli_output.stdout, \
|
|
411
|
+
f"Managed bookmark ID {created_bookmark_id} not found in CLI search output for '{search_query_component}'"
|
|
402
412
|
print("✓ CLI search command executed successfully and contained the bookmark ID.")
|
|
403
413
|
except subprocess.CalledProcessError as e:
|
|
404
414
|
print(f" CLI search command failed with exit code {e.returncode}")
|
|
405
415
|
print(f" Stdout: {e.stdout}")
|
|
406
416
|
print(f" Stderr: {e.stderr}")
|
|
407
|
-
pytest.fail(f"CLI command 'search-bookmarks --q {
|
|
417
|
+
pytest.fail(f"CLI command 'search-bookmarks --q \"{search_query_component}\"' failed: {e}")
|
|
408
418
|
except Exception as e:
|
|
409
419
|
pytest.fail(f"An unexpected error occurred running the CLI search command: {e}")
|
|
410
420
|
|
|
411
|
-
|
|
412
421
|
except (APIError, AuthenticationError) as e:
|
|
413
|
-
pytest.fail(f"API error during bookmark
|
|
422
|
+
pytest.fail(f"API error during bookmark verification/search: {e}")
|
|
414
423
|
except Exception as e:
|
|
415
424
|
pytest.fail(
|
|
416
|
-
f"An unexpected error occurred during bookmark
|
|
425
|
+
f"An unexpected error occurred during bookmark verification/search: {e}"
|
|
417
426
|
)
|
|
418
|
-
finally
|
|
419
|
-
|
|
420
|
-
if created_bookmark_id:
|
|
421
|
-
print(f"\nAttempting to delete bookmark with ID: {created_bookmark_id}")
|
|
422
|
-
try:
|
|
423
|
-
karakeep_client.delete_a_bookmark(bookmark_id=created_bookmark_id)
|
|
424
|
-
print(f"✓ Successfully deleted bookmark with ID: {created_bookmark_id}")
|
|
425
|
-
|
|
426
|
-
# 6. Verify the bookmark is gone by trying to get it (should fail)
|
|
427
|
-
try:
|
|
428
|
-
karakeep_client.get_a_single_bookmark(
|
|
429
|
-
bookmark_id=created_bookmark_id
|
|
430
|
-
)
|
|
431
|
-
pytest.fail(
|
|
432
|
-
f"Bookmark with ID {created_bookmark_id} should not exist after deletion, but get_a_single_bookmark succeeded."
|
|
433
|
-
)
|
|
434
|
-
except APIError as e:
|
|
435
|
-
assert (
|
|
436
|
-
e.status_code == 404
|
|
437
|
-
), f"Expected 404 Not Found when getting deleted bookmark, but got status {e.status_code}"
|
|
438
|
-
print(
|
|
439
|
-
f"✓ Confirmed bookmark {created_bookmark_id} is deleted via API (received 404)."
|
|
440
|
-
)
|
|
441
|
-
|
|
442
|
-
# 7. Attempt to delete the same bookmark via CLI (should ideally fail or do nothing)
|
|
443
|
-
print(f"\n Attempting CLI deletion for already deleted bookmark ID: {created_bookmark_id}")
|
|
444
|
-
try:
|
|
445
|
-
cli_delete_command = f"python -m karakeep_python_api delete-a-bookmark --bookmark-id {created_bookmark_id}"
|
|
446
|
-
subprocess.run(
|
|
447
|
-
cli_delete_command,
|
|
448
|
-
shell=True,
|
|
449
|
-
check=True, # Set to False if CLI errors on 404, True if it exits 0
|
|
450
|
-
capture_output=True,
|
|
451
|
-
text=True,
|
|
452
|
-
)
|
|
453
|
-
# If check=True and it succeeds, it means the CLI might not error on 404.
|
|
454
|
-
print(f" ✓ CLI delete command executed (check=True implies it might not error on 404).")
|
|
455
|
-
except subprocess.CalledProcessError as e:
|
|
456
|
-
# If check=True, this block means the CLI command failed, which *might* be expected if it errors on 404.
|
|
457
|
-
print(f" ✓ CLI delete command failed as expected (exit code {e.returncode}), likely because bookmark was already deleted.")
|
|
458
|
-
# Optional: Assert specific exit code if known
|
|
459
|
-
# assert e.returncode == EXPECTED_EXIT_CODE_FOR_NOT_FOUND
|
|
460
|
-
except Exception as cli_e:
|
|
461
|
-
pytest.fail(f"An unexpected error occurred running the CLI delete command: {cli_e}")
|
|
462
|
-
|
|
463
|
-
# 8. Verify again via API that the bookmark is still gone after CLI attempt
|
|
464
|
-
try:
|
|
465
|
-
karakeep_client.get_a_single_bookmark(bookmark_id=created_bookmark_id)
|
|
466
|
-
pytest.fail(
|
|
467
|
-
f"Bookmark {created_bookmark_id} should *still* not exist after CLI deletion attempt, but get_a_single_bookmark succeeded."
|
|
468
|
-
)
|
|
469
|
-
except APIError as e:
|
|
470
|
-
assert (
|
|
471
|
-
e.status_code == 404
|
|
472
|
-
), f"Expected 404 Not Found after CLI deletion attempt, but got status {e.status_code}"
|
|
473
|
-
print(
|
|
474
|
-
f"✓ Confirmed bookmark {created_bookmark_id} is *still* deleted after CLI attempt (received 404)."
|
|
475
|
-
)
|
|
427
|
+
# No 'finally' block for deletion needed, as 'managed_bookmark' fixture handles it.
|
|
428
|
+
# The fixture also handles verification of deletion.
|
|
476
429
|
|
|
477
|
-
except (APIError, AuthenticationError) as e:
|
|
478
|
-
# Catch errors from the initial Python API deletion or subsequent checks
|
|
479
|
-
pytest.fail(f"API error during bookmark deletion/verification: {e}")
|
|
480
|
-
except Exception as e:
|
|
481
|
-
pytest.fail(f"An unexpected error occurred during bookmark deletion: {e}")
|
|
482
|
-
else:
|
|
483
|
-
print(
|
|
484
|
-
"\nSkipping deletion because bookmark creation failed or ID was not obtained."
|
|
485
|
-
)
|
|
486
430
|
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
# Generate a unique suffix for the initial title to avoid collisions
|
|
492
|
-
timestamp = int(time.time())
|
|
493
|
-
random_suffix = "".join(random.choices(string.ascii_lowercase + string.digits, k=6))
|
|
494
|
-
original_title = f"Initial Test Title {timestamp}-{random_suffix}"
|
|
495
|
-
test_url = "https://en.wikipedia.org/wiki/PageForBookmarkUpdateTest" # A distinct URL for this test
|
|
431
|
+
def test_update_bookmark_title(karakeep_client: KarakeepAPI, managed_bookmark: datatypes.Bookmark):
|
|
432
|
+
"""Test updating a bookmark's title via API and CLI, using a managed bookmark."""
|
|
433
|
+
created_bookmark_id = managed_bookmark.id
|
|
434
|
+
original_title = managed_bookmark.title # Get the original title from the fixture
|
|
496
435
|
|
|
497
436
|
target_api_title = "this is a test title"
|
|
498
437
|
target_cli_title = "this is a test title (CLI)"
|
|
499
438
|
|
|
500
439
|
try:
|
|
501
|
-
#
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
type="link", url=test_url, title=original_title
|
|
505
|
-
)
|
|
506
|
-
assert isinstance(created_bookmark, datatypes.Bookmark), "Response should be a Bookmark model"
|
|
507
|
-
created_bookmark_id = created_bookmark.id
|
|
508
|
-
assert created_bookmark.id, "Created bookmark must have an ID"
|
|
509
|
-
assert created_bookmark.title == original_title, f"Initial title '{created_bookmark.title}' does not match expected '{original_title}'"
|
|
510
|
-
print(f"✓ Successfully created bookmark ID: {created_bookmark_id}, Title: '{created_bookmark.title}'")
|
|
440
|
+
# The bookmark is already created by the 'managed_bookmark' fixture.
|
|
441
|
+
# We have its ID in created_bookmark_id and its original title.
|
|
442
|
+
print(f"\nUsing managed bookmark ID: {created_bookmark_id}, Original Title: '{original_title}'")
|
|
511
443
|
|
|
512
|
-
#
|
|
444
|
+
# 1. Update the bookmark's title using the API client
|
|
513
445
|
print(f"\nAttempting to update bookmark ID {created_bookmark_id} title to: '{target_api_title}' via API")
|
|
514
446
|
update_payload_api = {"title": target_api_title}
|
|
515
447
|
updated_bookmark_partial = karakeep_client.update_a_bookmark(
|
|
@@ -520,7 +452,7 @@ def test_update_bookmark_title(karakeep_client: KarakeepAPI):
|
|
|
520
452
|
f"Partial response title '{updated_bookmark_partial.get('title')}' does not match target API title '{target_api_title}'"
|
|
521
453
|
print(f"✓ API call to update_a_bookmark successful. Partial response title: '{updated_bookmark_partial.get('title')}'")
|
|
522
454
|
|
|
523
|
-
#
|
|
455
|
+
# 2. Verify the API update by fetching the bookmark again
|
|
524
456
|
print(f"\nFetching bookmark ID {created_bookmark_id} to verify API title update.")
|
|
525
457
|
retrieved_bookmark_after_api_update = karakeep_client.get_a_single_bookmark(
|
|
526
458
|
bookmark_id=created_bookmark_id
|
|
@@ -530,7 +462,7 @@ def test_update_bookmark_title(karakeep_client: KarakeepAPI):
|
|
|
530
462
|
f"Retrieved bookmark title '{retrieved_bookmark_after_api_update.title}' does not match expected API-updated title '{target_api_title}'"
|
|
531
463
|
print(f"✓ Successfully verified bookmark title updated by API to: '{retrieved_bookmark_after_api_update.title}'")
|
|
532
464
|
|
|
533
|
-
#
|
|
465
|
+
# 3. Test CLI equivalent for updating the bookmark's title
|
|
534
466
|
print(f"\n Running CLI equivalent to update title to: '{target_cli_title}'")
|
|
535
467
|
cli_update_payload_json = json.dumps({"title": target_cli_title})
|
|
536
468
|
# Ensure the JSON string is properly quoted for the shell command
|
|
@@ -546,7 +478,7 @@ def test_update_bookmark_title(karakeep_client: KarakeepAPI):
|
|
|
546
478
|
)
|
|
547
479
|
print("✓ CLI update command executed successfully.")
|
|
548
480
|
|
|
549
|
-
#
|
|
481
|
+
# 4. Verify CLI update by fetching the bookmark again
|
|
550
482
|
print(f"\nFetching bookmark ID {created_bookmark_id} to verify CLI title update.")
|
|
551
483
|
retrieved_bookmark_after_cli_update = karakeep_client.get_a_single_bookmark(
|
|
552
484
|
bookmark_id=created_bookmark_id
|
|
@@ -569,18 +501,94 @@ def test_update_bookmark_title(karakeep_client: KarakeepAPI):
|
|
|
569
501
|
pytest.fail(f"API error during bookmark title update test: {e}")
|
|
570
502
|
except Exception as e:
|
|
571
503
|
pytest.fail(f"An unexpected error occurred during bookmark title update test: {e}")
|
|
504
|
+
# No finally block needed for deletion, as 'managed_bookmark' fixture handles it.
|
|
505
|
+
|
|
506
|
+
|
|
507
|
+
def test_tag_lifecycle_on_bookmark(karakeep_client: KarakeepAPI, managed_bookmark: datatypes.Bookmark):
|
|
508
|
+
"""
|
|
509
|
+
Test attaching a tag to a bookmark, updating the tag, detaching it, and deleting it.
|
|
510
|
+
Uses the managed_bookmark fixture.
|
|
511
|
+
"""
|
|
512
|
+
bookmark_id = managed_bookmark.id
|
|
513
|
+
timestamp = int(time.time())
|
|
514
|
+
random_chars = "".join(random.choices(string.ascii_lowercase + string.digits, k=6))
|
|
515
|
+
initial_tag_name = f"test-tag-{timestamp}-{random_chars}"
|
|
516
|
+
updated_tag_name = f"updated-tag-{timestamp}-{random_chars}"
|
|
517
|
+
tag_id_to_manage = None
|
|
518
|
+
|
|
519
|
+
try:
|
|
520
|
+
# 1. Attach a new tag by name to the bookmark
|
|
521
|
+
print(f"\nAttempting to attach tag '{initial_tag_name}' to bookmark {bookmark_id}")
|
|
522
|
+
attach_payload = {"tags": [{"tagName": initial_tag_name}]}
|
|
523
|
+
attach_response = karakeep_client.attach_tags_to_a_bookmark(
|
|
524
|
+
bookmark_id=bookmark_id, tags_data=attach_payload
|
|
525
|
+
)
|
|
526
|
+
assert "attached" in attach_response and len(attach_response["attached"]) == 1, \
|
|
527
|
+
"Failed to attach tag or response format incorrect"
|
|
528
|
+
tag_id_to_manage = attach_response["attached"][0]
|
|
529
|
+
assert isinstance(tag_id_to_manage, str), "Attached tag ID should be a string"
|
|
530
|
+
print(f"✓ Tag '{initial_tag_name}' attached with ID: {tag_id_to_manage}")
|
|
531
|
+
|
|
532
|
+
# 2. Update the tag's name
|
|
533
|
+
print(f"\nAttempting to update tag {tag_id_to_manage} to name '{updated_tag_name}'")
|
|
534
|
+
update_payload = {"name": updated_tag_name}
|
|
535
|
+
updated_tag = karakeep_client.update_a_tag(
|
|
536
|
+
tag_id=tag_id_to_manage, update_data=update_payload
|
|
537
|
+
)
|
|
538
|
+
# Do not check the type because karakeep 0.24.1 has a server side bug
|
|
539
|
+
# assert isinstance(updated_tag, datatypes.Tag1), "Update tag response should be Tag1 model"
|
|
540
|
+
# assert updated_tag.name == updated_tag_name, "Tag name was not updated as expected"
|
|
541
|
+
# print(f"✓ Tag {tag_id_to_manage} updated to name '{updated_tag.name}'")
|
|
542
|
+
assert updated_tag["name"] == updated_tag_name, "Tag name was not updated as expected"
|
|
543
|
+
print(f"✓ Tag {tag_id_to_manage} updated to name '{updated_tag['name']}'")
|
|
544
|
+
|
|
545
|
+
# 3. Verify tag update by getting it directly
|
|
546
|
+
print(f"\nFetching tag {tag_id_to_manage} to verify its name is '{updated_tag_name}'")
|
|
547
|
+
retrieved_tag = karakeep_client.get_a_single_tag(tag_id=tag_id_to_manage)
|
|
548
|
+
assert isinstance(retrieved_tag, datatypes.Tag1), "Get single tag response should be Tag1 model"
|
|
549
|
+
assert retrieved_tag.name == updated_tag_name, "Retrieved tag name does not match updated name"
|
|
550
|
+
assert retrieved_tag.id == tag_id_to_manage, "Retrieved tag ID does not match"
|
|
551
|
+
print(f"✓ Verified tag {tag_id_to_manage} has name '{retrieved_tag.name}'")
|
|
552
|
+
|
|
553
|
+
# 4. Detach the tag from the bookmark
|
|
554
|
+
print(f"\nAttempting to detach tag {tag_id_to_manage} from bookmark {bookmark_id}")
|
|
555
|
+
detach_payload = {"tags": [{"tagId": tag_id_to_manage}]}
|
|
556
|
+
detach_response = karakeep_client.detach_tags_from_a_bookmark(
|
|
557
|
+
bookmark_id=bookmark_id, tags_data=detach_payload
|
|
558
|
+
)
|
|
559
|
+
assert "detached" in detach_response and tag_id_to_manage in detach_response["detached"], \
|
|
560
|
+
"Failed to detach tag or response format incorrect"
|
|
561
|
+
print(f"✓ Tag {tag_id_to_manage} detached from bookmark {bookmark_id}")
|
|
562
|
+
|
|
563
|
+
except (APIError, AuthenticationError) as e:
|
|
564
|
+
pytest.fail(f"API error during tag lifecycle test: {e}")
|
|
565
|
+
except Exception as e:
|
|
566
|
+
pytest.fail(f"An unexpected error occurred during tag lifecycle test: {e}")
|
|
572
567
|
finally:
|
|
573
|
-
#
|
|
574
|
-
if
|
|
575
|
-
print(f"\nAttempting to delete
|
|
568
|
+
# 5. Delete the tag (ensure cleanup even if assertions fail mid-test)
|
|
569
|
+
if tag_id_to_manage:
|
|
570
|
+
print(f"\nAttempting to delete tag {tag_id_to_manage} (cleanup)")
|
|
576
571
|
try:
|
|
577
|
-
karakeep_client.
|
|
578
|
-
print(f"✓ Successfully deleted
|
|
572
|
+
karakeep_client.delete_a_tag(tag_id=tag_id_to_manage)
|
|
573
|
+
print(f"✓ Successfully deleted tag {tag_id_to_manage}")
|
|
574
|
+
|
|
575
|
+
# 6. Verify the tag is gone by trying to get it (should fail with 404)
|
|
576
|
+
try:
|
|
577
|
+
karakeep_client.get_a_single_tag(tag_id=tag_id_to_manage)
|
|
578
|
+
pytest.fail(
|
|
579
|
+
f"Tag {tag_id_to_manage} should not exist after deletion, but get_a_single_tag succeeded."
|
|
580
|
+
)
|
|
581
|
+
except APIError as e:
|
|
582
|
+
assert e.status_code == 404, \
|
|
583
|
+
f"Expected 404 Not Found when getting deleted tag, but got status {e.status_code}"
|
|
584
|
+
print(f"✓ Confirmed tag {tag_id_to_manage} is deleted (received 404).")
|
|
585
|
+
except (APIError, AuthenticationError) as e:
|
|
586
|
+
# Log error during cleanup but don't let it mask original test failure
|
|
587
|
+
print(f" API error during tag deletion (cleanup) for ID {tag_id_to_manage}: {e}")
|
|
579
588
|
except Exception as e:
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
# pytest.fail(f"Failed to delete bookmark {created_bookmark_id} during cleanup: {e}")
|
|
589
|
+
print(f" Unexpected error during tag deletion (cleanup) for ID {tag_id_to_manage}: {e}")
|
|
590
|
+
else:
|
|
591
|
+
print("\nSkipping tag deletion (cleanup) because tag_id was not obtained or test failed before creation.")
|
|
584
592
|
|
|
585
593
|
|
|
586
594
|
# --- Test User Info/Stats Endpoints ---
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/karakeep_python_api.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/karakeep_python_api.egg-info/requires.txt
RENAMED
|
File without changes
|
{karakeep_python_api-0.1.2 → karakeep_python_api-0.1.3}/karakeep_python_api.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|