python-documentcloud 4.5.0__tar.gz → 4.6.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.
- {python_documentcloud-4.5.0/python_documentcloud.egg-info → python_documentcloud-4.6.0}/PKG-INFO +1 -1
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/documentcloud/addon.py +20 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/documentcloud/documents.py +1 -5
- python_documentcloud-4.6.0/documentcloud/exceptions.py +15 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0/python_documentcloud.egg-info}/PKG-INFO +1 -1
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/python_documentcloud.egg-info/SOURCES.txt +1 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/setup.py +1 -1
- python_documentcloud-4.6.0/tests/test_addon.py +141 -0
- python_documentcloud-4.5.0/documentcloud/exceptions.py +0 -12
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/LICENSE +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/README.md +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/documentcloud/__init__.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/documentcloud/annotations.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/documentcloud/base.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/documentcloud/client.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/documentcloud/constants.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/documentcloud/organizations.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/documentcloud/projects.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/documentcloud/sections.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/documentcloud/toolbox.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/documentcloud/users.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/python_documentcloud.egg-info/dependency_links.txt +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/python_documentcloud.egg-info/requires.txt +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/python_documentcloud.egg-info/top_level.txt +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/setup.cfg +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/tests/test_annotations.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/tests/test_base.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/tests/test_client.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/tests/test_documents.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/tests/test_organizations.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/tests/test_projects.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/tests/test_sections.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/tests/test_toolbox.py +0 -0
- {python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/tests/test_users.py +0 -0
|
@@ -182,6 +182,26 @@ class AddOn(BaseAddOn):
|
|
|
182
182
|
f"addon_runs/{self.id}/", json={"file_name": file_name}
|
|
183
183
|
)
|
|
184
184
|
|
|
185
|
+
def load_run_data(self):
|
|
186
|
+
"Load persistent data from this run"
|
|
187
|
+
if not self.id:
|
|
188
|
+
return {}
|
|
189
|
+
|
|
190
|
+
response = self.client.get(f"addon_runs/{self.id}/")
|
|
191
|
+
response.raise_for_status()
|
|
192
|
+
return response.json().get("data", {})
|
|
193
|
+
|
|
194
|
+
def store_run_data(self, data):
|
|
195
|
+
"Store persistent data for this run"
|
|
196
|
+
if not self.id:
|
|
197
|
+
print("Run ID not set. Try again later or check if something went wrong.")
|
|
198
|
+
return None
|
|
199
|
+
|
|
200
|
+
if not isinstance(data, dict):
|
|
201
|
+
raise TypeError("Invalid data")
|
|
202
|
+
|
|
203
|
+
return self.client.patch(f"addon_runs/{self.id}/", json={"data": data})
|
|
204
|
+
|
|
185
205
|
def load_event_data(self):
|
|
186
206
|
"""Load persistent data for this event"""
|
|
187
207
|
if not self.event_id:
|
|
@@ -9,6 +9,7 @@ import os
|
|
|
9
9
|
import re
|
|
10
10
|
import warnings
|
|
11
11
|
from functools import partial
|
|
12
|
+
from urllib.parse import urlparse
|
|
12
13
|
|
|
13
14
|
# Third Party
|
|
14
15
|
from requests.exceptions import RequestException
|
|
@@ -23,11 +24,6 @@ from .sections import SectionClient
|
|
|
23
24
|
from .toolbox import grouper, is_url, merge_dicts, requests_retry_session
|
|
24
25
|
from .users import User
|
|
25
26
|
|
|
26
|
-
try:
|
|
27
|
-
from urllib.parse import urlparse
|
|
28
|
-
except ImportError:
|
|
29
|
-
from urlparse import urlparse
|
|
30
|
-
|
|
31
27
|
logger = logging.getLogger("documentcloud")
|
|
32
28
|
|
|
33
29
|
IMAGE_SIZES = ["thumbnail", "small", "normal", "large", "xlarge"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Custom exceptions for python-documentcloud
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
# Third Party
|
|
6
|
+
# pylint: disable=unused-import
|
|
7
|
+
# Import exceptions from python-squarelet
|
|
8
|
+
from squarelet.exceptions import (
|
|
9
|
+
APIError,
|
|
10
|
+
CredentialsFailedError,
|
|
11
|
+
DoesNotExistError,
|
|
12
|
+
DuplicateObjectError,
|
|
13
|
+
MultipleObjectsReturnedError,
|
|
14
|
+
SquareletError as DocumentCloudError,
|
|
15
|
+
)
|
{python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/python_documentcloud.egg-info/SOURCES.txt
RENAMED
|
@@ -20,6 +20,7 @@ python_documentcloud.egg-info/SOURCES.txt
|
|
|
20
20
|
python_documentcloud.egg-info/dependency_links.txt
|
|
21
21
|
python_documentcloud.egg-info/requires.txt
|
|
22
22
|
python_documentcloud.egg-info/top_level.txt
|
|
23
|
+
tests/test_addon.py
|
|
23
24
|
tests/test_annotations.py
|
|
24
25
|
tests/test_base.py
|
|
25
26
|
tests/test_client.py
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Standard Library
|
|
2
|
+
from unittest.mock import MagicMock
|
|
3
|
+
|
|
4
|
+
# Third Party
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
# DocumentCloud
|
|
8
|
+
from documentcloud.addon import AddOn
|
|
9
|
+
|
|
10
|
+
# pylint: disable=redefined-outer-name
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.fixture
|
|
14
|
+
def addon():
|
|
15
|
+
"""An AddOn instance built without invoking argparse or constructing a real client.
|
|
16
|
+
|
|
17
|
+
Tests can override `.id`, `.event_id`, `.client`, etc. as needed.
|
|
18
|
+
"""
|
|
19
|
+
instance = AddOn.__new__(AddOn)
|
|
20
|
+
instance.id = "run-123"
|
|
21
|
+
instance.addon_id = "addon-1"
|
|
22
|
+
instance.event_id = None
|
|
23
|
+
instance.documents = None
|
|
24
|
+
instance.query = None
|
|
25
|
+
instance.user_id = None
|
|
26
|
+
instance.org_id = None
|
|
27
|
+
instance.data = {}
|
|
28
|
+
instance.title = "Test AddOn"
|
|
29
|
+
instance.client = MagicMock()
|
|
30
|
+
return instance
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TestLoadRunData:
|
|
34
|
+
def test_returns_data_when_run_id_set(self, addon):
|
|
35
|
+
addon.client.get.return_value.json.return_value = {"data": {"foo": "bar"}}
|
|
36
|
+
|
|
37
|
+
result = addon.load_run_data()
|
|
38
|
+
|
|
39
|
+
addon.client.get.assert_called_once_with("addon_runs/run-123/")
|
|
40
|
+
assert result == {"foo": "bar"}
|
|
41
|
+
|
|
42
|
+
def test_returns_empty_dict_when_no_run_id(self, addon):
|
|
43
|
+
addon.id = None
|
|
44
|
+
|
|
45
|
+
assert addon.load_run_data() == {}
|
|
46
|
+
addon.client.get.assert_not_called()
|
|
47
|
+
|
|
48
|
+
def test_returns_empty_dict_when_data_missing_from_response(self, addon):
|
|
49
|
+
addon.client.get.return_value.json.return_value = {}
|
|
50
|
+
|
|
51
|
+
assert addon.load_run_data() == {}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class TestStoreRunData:
|
|
55
|
+
def test_patches_run_with_data(self, addon):
|
|
56
|
+
addon.store_run_data({"foo": "bar"})
|
|
57
|
+
|
|
58
|
+
addon.client.patch.assert_called_once_with(
|
|
59
|
+
"addon_runs/run-123/", json={"data": {"foo": "bar"}}
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
def test_no_op_when_no_run_id(self, addon, capsys):
|
|
63
|
+
addon.id = None
|
|
64
|
+
|
|
65
|
+
result = addon.store_run_data({"foo": "bar"})
|
|
66
|
+
|
|
67
|
+
assert result is None
|
|
68
|
+
addon.client.patch.assert_not_called()
|
|
69
|
+
assert "Run ID not set" in capsys.readouterr().out
|
|
70
|
+
|
|
71
|
+
def test_rejects_non_dict_data(self, addon):
|
|
72
|
+
with pytest.raises(TypeError):
|
|
73
|
+
addon.store_run_data("not a dict")
|
|
74
|
+
|
|
75
|
+
addon.client.patch.assert_not_called()
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
class TestLoadEventData:
|
|
79
|
+
def test_returns_scratch_when_event_id_set(self, addon):
|
|
80
|
+
addon.event_id = "evt-9"
|
|
81
|
+
addon.client.get.return_value.json.return_value = {"scratch": {"x": 1}}
|
|
82
|
+
|
|
83
|
+
result = addon.load_event_data()
|
|
84
|
+
|
|
85
|
+
addon.client.get.assert_called_once_with("addon_events/evt-9/")
|
|
86
|
+
assert result == {"x": 1}
|
|
87
|
+
|
|
88
|
+
def test_returns_none_when_no_event_id(self, addon):
|
|
89
|
+
assert addon.load_event_data() is None
|
|
90
|
+
addon.client.get.assert_not_called()
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class TestStoreEventData:
|
|
94
|
+
def test_patches_event_with_scratch(self, addon):
|
|
95
|
+
addon.event_id = "evt-9"
|
|
96
|
+
|
|
97
|
+
addon.store_event_data({"x": 1})
|
|
98
|
+
|
|
99
|
+
addon.client.patch.assert_called_once_with(
|
|
100
|
+
"addon_events/evt-9/", json={"scratch": {"x": 1}}
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
def test_no_op_when_no_event_id(self, addon):
|
|
104
|
+
assert addon.store_event_data({"x": 1}) is None
|
|
105
|
+
addon.client.patch.assert_not_called()
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@pytest.fixture
|
|
109
|
+
def real_addon(client, addon_run):
|
|
110
|
+
"""An AddOn wired to the real `client` fixture and a freshly created run."""
|
|
111
|
+
instance = AddOn.__new__(AddOn)
|
|
112
|
+
instance.id = addon_run
|
|
113
|
+
instance.addon_id = None
|
|
114
|
+
instance.event_id = None
|
|
115
|
+
instance.documents = None
|
|
116
|
+
instance.query = None
|
|
117
|
+
instance.user_id = None
|
|
118
|
+
instance.org_id = None
|
|
119
|
+
instance.data = {}
|
|
120
|
+
instance.title = "Test AddOn"
|
|
121
|
+
instance.client = client
|
|
122
|
+
return instance
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class TestRunDataVCR:
|
|
126
|
+
"""VCR-recorded round-trip tests against the dev DC.
|
|
127
|
+
|
|
128
|
+
Recording: set DC_TEST_ADDON_RUN_ID to an existing AddOnRun UUID on your
|
|
129
|
+
local dev DC, then run `make test-dev` (or `pytest --record-mode=new_episodes`).
|
|
130
|
+
"""
|
|
131
|
+
|
|
132
|
+
def test_load_run_data_returns_dict(self, real_addon):
|
|
133
|
+
result = real_addon.load_run_data()
|
|
134
|
+
assert isinstance(result, dict)
|
|
135
|
+
|
|
136
|
+
def test_store_then_load_run_data_round_trip(self, real_addon):
|
|
137
|
+
payload = {"foo": "bar", "n": 42}
|
|
138
|
+
real_addon.store_run_data(payload)
|
|
139
|
+
loaded = real_addon.load_run_data()
|
|
140
|
+
assert loaded.get("foo") == "bar"
|
|
141
|
+
assert loaded.get("n") == 42
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Custom exceptions for python-documentcloud
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
# pylint: disable=unused-import
|
|
6
|
-
# Import exceptions from python-squarelet
|
|
7
|
-
from squarelet.exceptions import SquareletError as DocumentCloudError
|
|
8
|
-
from squarelet.exceptions import DuplicateObjectError
|
|
9
|
-
from squarelet.exceptions import CredentialsFailedError
|
|
10
|
-
from squarelet.exceptions import APIError
|
|
11
|
-
from squarelet.exceptions import DoesNotExistError
|
|
12
|
-
from squarelet.exceptions import MultipleObjectsReturnedError
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_documentcloud-4.5.0 → python_documentcloud-4.6.0}/python_documentcloud.egg-info/requires.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|