nucliadb-utils 4.0.3.post573__py3-none-any.whl → 4.0.3.post576__py3-none-any.whl

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.
@@ -1,57 +0,0 @@
1
- # Copyright (C) 2021 Bosutech XXI S.L.
2
- #
3
- # nucliadb is offered under the AGPL v3.0 and as commercial software.
4
- # For commercial licensing, contact us at info@nuclia.com.
5
- #
6
- # AGPL:
7
- # This program is free software: you can redistribute it and/or modify
8
- # it under the terms of the GNU Affero General Public License as
9
- # published by the Free Software Foundation, either version 3 of the
10
- # License, or (at your option) any later version.
11
- #
12
- # This program is distributed in the hope that it will be useful,
13
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- # GNU Affero General Public License for more details.
16
- #
17
- # You should have received a copy of the GNU Affero General Public License
18
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
-
20
- import asyncio
21
- from unittest.mock import AsyncMock, MagicMock, patch
22
-
23
- import pytest
24
-
25
- from nucliadb_utils import run
26
-
27
- pytestmark = pytest.mark.asyncio
28
-
29
-
30
- async def test_run_until_exit():
31
- loop = MagicMock()
32
- with patch("nucliadb_utils.run.asyncio.get_running_loop", return_value=loop):
33
- finalizer = AsyncMock()
34
- asyncio.create_task(run.run_until_exit([finalizer], sleep=0.01))
35
-
36
- await asyncio.sleep(0.05)
37
-
38
- assert len(loop.add_signal_handler.mock_calls) == 2
39
- callback = loop.add_signal_handler.mock_calls[0].args[1]
40
- callback() # cause exit
41
-
42
- await asyncio.sleep(0.05)
43
-
44
- finalizer.assert_called_once()
45
-
46
-
47
- async def test_run_until_exit_handles_hard_exit():
48
- loop = MagicMock()
49
- with patch("nucliadb_utils.run.asyncio.get_running_loop", return_value=loop):
50
- finalizer = AsyncMock(side_effect=Exception())
51
- task = asyncio.create_task(run.run_until_exit([finalizer]))
52
-
53
- await asyncio.sleep(0.05)
54
- task.cancel()
55
- await asyncio.sleep(0.05)
56
-
57
- finalizer.assert_called_once()
@@ -1,81 +0,0 @@
1
- # Copyright (C) 2021 Bosutech XXI S.L.
2
- #
3
- # nucliadb is offered under the AGPL v3.0 and as commercial software.
4
- # For commercial licensing, contact us at info@nuclia.com.
5
- #
6
- # AGPL:
7
- # This program is free software: you can redistribute it and/or modify
8
- # it under the terms of the GNU Affero General Public License as
9
- # published by the Free Software Foundation, either version 3 of the
10
- # License, or (at your option) any later version.
11
- #
12
- # This program is distributed in the hope that it will be useful,
13
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- # GNU Affero General Public License for more details.
16
- #
17
- # You should have received a copy of the GNU Affero General Public License
18
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
-
20
- from dataclasses import dataclass
21
- from unittest.mock import AsyncMock, patch
22
-
23
- import pytest
24
-
25
- from nucliadb_utils.signals import Signal
26
-
27
-
28
- class TestSignals:
29
- @dataclass
30
- class TestPayload:
31
- payload: int
32
-
33
- @pytest.fixture
34
- def signal(self):
35
- yield Signal(payload_model=TestSignals.TestPayload)
36
-
37
- @pytest.fixture
38
- def payload(self):
39
- yield TestSignals.TestPayload(payload=1)
40
-
41
- @pytest.fixture
42
- def listener(self):
43
- yield AsyncMock()
44
-
45
- # Tests
46
-
47
- def test_add_same_listener_twice_fails(self, signal, listener):
48
- id = "test-listener"
49
- signal.add_listener(id, listener)
50
- with pytest.raises(ValueError):
51
- signal.add_listener(id, listener)
52
-
53
- async def test_signal_dispatch(self, signal, listener, payload):
54
- id = "test-listener"
55
- signal.add_listener(id, listener)
56
- await signal.dispatch(payload)
57
- assert listener.await_count == 1
58
-
59
- async def test_signal_despatch_with_failure(self, signal, listener, payload):
60
- ok_listener = AsyncMock()
61
- signal.add_listener("ok-listener", ok_listener)
62
- nok_listener = AsyncMock(side_effect=Exception)
63
- signal.add_listener("nok-listener", nok_listener)
64
-
65
- with patch("nucliadb_utils.signals.capture_exception") as mock:
66
- await signal.dispatch(payload)
67
- assert mock.call_count == 1
68
-
69
- assert ok_listener.await_count == 1
70
- assert nok_listener.await_count == 1
71
-
72
- async def test_remove_listener(self, signal, listener, payload):
73
- id = "test-listener"
74
-
75
- signal.add_listener(id, listener)
76
- await signal.dispatch(payload)
77
- assert listener.await_count == 1
78
-
79
- signal.remove_listener(id)
80
- await signal.dispatch(payload)
81
- assert listener.await_count == 1
@@ -1,27 +0,0 @@
1
- # Copyright (C) 2021 Bosutech XXI S.L.
2
- #
3
- # nucliadb is offered under the AGPL v3.0 and as commercial software.
4
- # For commercial licensing, contact us at info@nuclia.com.
5
- #
6
- # AGPL:
7
- # This program is free software: you can redistribute it and/or modify
8
- # it under the terms of the GNU Affero General Public License as
9
- # published by the Free Software Foundation, either version 3 of the
10
- # License, or (at your option) any later version.
11
- #
12
- # This program is distributed in the hope that it will be useful,
13
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- # GNU Affero General Public License for more details.
16
- #
17
- # You should have received a copy of the GNU Affero General Public License
18
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
-
20
- from nucliadb_utils.tests import asyncbenchmark # noqa: F401
21
- from nucliadb_utils.tests import indexing # noqa: F401
22
- from nucliadb_utils.tests import nats # noqa: F401
23
-
24
- # placeholder for test modules
25
- # AND these test modules do not get coverage
26
- # but we don't want to be penalized for them
27
- # AND we don't want to deal with test config files not working
@@ -1,119 +0,0 @@
1
- # Copyright (C) 2021 Bosutech XXI S.L.
2
- #
3
- # nucliadb is offered under the AGPL v3.0 and as commercial software.
4
- # For commercial licensing, contact us at info@nuclia.com.
5
- #
6
- # AGPL:
7
- # This program is free software: you can redistribute it and/or modify
8
- # it under the terms of the GNU Affero General Public License as
9
- # published by the Free Software Foundation, either version 3 of the
10
- # License, or (at your option) any later version.
11
- #
12
- # This program is distributed in the hope that it will be useful,
13
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- # GNU Affero General Public License for more details.
16
- #
17
- # You should have received a copy of the GNU Affero General Public License
18
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
-
20
- import asyncio
21
- from unittest import mock
22
-
23
- import pytest
24
- from nucliadb_protos.writer_pb2 import BrokerMessage, Notification
25
-
26
- from nucliadb_utils.transaction import (
27
- TransactionCommitTimeoutError,
28
- TransactionUtility,
29
- WaitFor,
30
- )
31
-
32
-
33
- @pytest.fixture()
34
- def pubsub():
35
- pubsub = mock.AsyncMock()
36
- pubsub.parse = lambda msg: msg.data
37
- with mock.patch("nucliadb_utils.transaction.get_pubsub", return_value=pubsub):
38
- yield pubsub
39
-
40
-
41
- @pytest.fixture()
42
- async def txn(pubsub):
43
- nats_conn = mock.AsyncMock()
44
- with mock.patch("nucliadb_utils.transaction.nats.connect", return_value=nats_conn):
45
- txn = TransactionUtility(nats_servers=["foobar"])
46
- await txn.initialize()
47
- yield txn
48
- await txn.finalize()
49
-
50
-
51
- @pytest.mark.asyncio
52
- async def test_wait_for_commited(txn: TransactionUtility, pubsub):
53
- waiting_for = WaitFor(uuid="foo")
54
- request_id = "request1"
55
- kbid = "kbid"
56
- notification = Notification()
57
- notification.uuid = waiting_for.uuid
58
- notification.action = Notification.Action.COMMIT
59
-
60
- async def _subscribe(handler, key, subscription_id):
61
- # call it immediately
62
- handler(mock.Mock(data=notification.SerializeToString()))
63
-
64
- pubsub.subscribe.side_effect = _subscribe
65
-
66
- await (await txn.wait_for_commited(kbid, waiting_for, request_id=request_id)).wait()
67
-
68
-
69
- @pytest.mark.asyncio
70
- async def test_wait_for_indexed(txn: TransactionUtility, pubsub):
71
- waiting_for = WaitFor(uuid="foo")
72
- request_id = "request1"
73
- kbid = "kbid"
74
- notification = Notification()
75
- notification.uuid = waiting_for.uuid
76
- notification.action = Notification.Action.INDEXED
77
-
78
- async def _subscribe(handler, key, subscription_id):
79
- # call it immediately
80
- handler(mock.Mock(data=notification.SerializeToString()))
81
-
82
- pubsub.subscribe.side_effect = _subscribe
83
-
84
- with mock.patch("nucliadb_utils.transaction.has_feature", return_value=True):
85
- await (
86
- await txn.wait_for_commited(kbid, waiting_for, request_id=request_id)
87
- ).wait()
88
-
89
-
90
- @pytest.mark.asyncio
91
- async def test_wait_for_commit_stop_waiting(txn: TransactionUtility, pubsub):
92
- pubsub.unsubscribe.side_effect = [
93
- "sub_id",
94
- KeyError(),
95
- ] # second call raises KeyError
96
-
97
- waiting_for = WaitFor(uuid="foo", seq=1)
98
- request_id = "request1"
99
- kbid = "kbid"
100
-
101
- _ = await txn.wait_for_commited(kbid, waiting_for, request_id=request_id)
102
-
103
- await txn.stop_waiting(kbid, request_id=request_id)
104
-
105
- # Unsubscribing twice with the same request_id should raise KeyError
106
- with pytest.raises(KeyError):
107
- await txn.stop_waiting(kbid, request_id=request_id)
108
-
109
-
110
- @pytest.mark.asyncio
111
- async def test_commit_timeout(txn: TransactionUtility, pubsub):
112
- txn.js = mock.AsyncMock()
113
- bm = BrokerMessage()
114
-
115
- waiting_event = mock.Mock(wait=mock.Mock(side_effect=asyncio.TimeoutError))
116
- txn.wait_for_commited = mock.AsyncMock(return_value=waiting_event) # type: ignore
117
-
118
- with pytest.raises(TransactionCommitTimeoutError):
119
- await txn.commit(bm, 1, wait=True, target_subject="foo")
@@ -1,173 +0,0 @@
1
- # Copyright (C) 2021 Bosutech XXI S.L.
2
- #
3
- # nucliadb is offered under the AGPL v3.0 and as commercial software.
4
- # For commercial licensing, contact us at info@nuclia.com.
5
- #
6
- # AGPL:
7
- # This program is free software: you can redistribute it and/or modify
8
- # it under the terms of the GNU Affero General Public License as
9
- # published by the Free Software Foundation, either version 3 of the
10
- # License, or (at your option) any later version.
11
- #
12
- # This program is distributed in the hope that it will be useful,
13
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
- # GNU Affero General Public License for more details.
16
- #
17
- # You should have received a copy of the GNU Affero General Public License
18
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
-
20
- import hashlib
21
- from unittest.mock import AsyncMock, MagicMock, patch
22
-
23
- import pytest
24
-
25
- from nucliadb_utils import featureflagging, utilities
26
- from nucliadb_utils.exceptions import ConfigurationError
27
- from nucliadb_utils.settings import FileBackendConfig
28
-
29
-
30
- @pytest.fixture(autouse=True)
31
- def reset_main():
32
- utilities.MAIN.clear()
33
-
34
-
35
- def test_clean_utility():
36
- utilities.set_utility(utilities.Utility.PUBSUB, "test")
37
- assert utilities.get_utility(utilities.Utility.PUBSUB) == "test"
38
- utilities.clean_utility(utilities.Utility.PUBSUB)
39
- assert utilities.get_utility(utilities.Utility.PUBSUB) is None
40
-
41
-
42
- @pytest.mark.asyncio
43
- async def test_get_storage_s3():
44
- s3 = AsyncMock()
45
- with (
46
- patch.object(
47
- utilities.storage_settings, "file_backend", FileBackendConfig("s3")
48
- ),
49
- patch("nucliadb_utils.storages.s3.S3Storage", return_value=s3),
50
- ):
51
- assert await utilities.get_storage() == s3
52
-
53
-
54
- @pytest.mark.asyncio
55
- async def test_get_storage_gcs():
56
- gcs = AsyncMock()
57
- with (
58
- patch.object(
59
- utilities.storage_settings, "file_backend", FileBackendConfig("gcs")
60
- ),
61
- patch("nucliadb_utils.storages.gcs.GCSStorage", return_value=gcs),
62
- ):
63
- assert await utilities.get_storage() == gcs
64
-
65
-
66
- @pytest.mark.asyncio
67
- async def test_get_storage_pg():
68
- pg = AsyncMock()
69
- with (
70
- patch.object(
71
- utilities.storage_settings, "file_backend", FileBackendConfig("pg")
72
- ),
73
- patch("nucliadb_utils.storages.pg.PostgresStorage", return_value=pg),
74
- ):
75
- assert await utilities.get_storage() == pg
76
-
77
-
78
- @pytest.mark.asyncio
79
- async def test_get_storage_local():
80
- local = AsyncMock()
81
- with (
82
- patch.object(
83
- utilities.storage_settings, "file_backend", FileBackendConfig("local")
84
- ),
85
- patch.object(utilities.storage_settings, "local_files", "/files"),
86
- patch("nucliadb_utils.storages.local.LocalStorage", return_value=local),
87
- ):
88
- assert await utilities.get_storage() == local
89
-
90
-
91
- @pytest.mark.asyncio
92
- async def test_get_storage_missing():
93
- with patch.object(utilities.storage_settings, "file_backend", "missing"):
94
- with pytest.raises(ConfigurationError):
95
- await utilities.get_storage()
96
-
97
-
98
- @pytest.mark.asyncio
99
- async def test_get_local_storage():
100
- assert utilities.get_local_storage() is not None
101
-
102
-
103
- @pytest.mark.asyncio
104
- async def test_get_nuclia_storage():
105
- assert await utilities.get_nuclia_storage() is not None
106
-
107
-
108
- @pytest.mark.asyncio
109
- async def test_get_pubsub():
110
- with patch("nucliadb_utils.utilities.NatsPubsub", return_value=AsyncMock()):
111
- assert await utilities.get_pubsub() is not None
112
-
113
-
114
- @pytest.mark.asyncio
115
- async def test_finalize_utilities():
116
- util = AsyncMock()
117
- utilities.MAIN["test"] = util
118
-
119
- await utilities.finalize_utilities()
120
-
121
- util.finalize.assert_called_once()
122
- assert len(utilities.MAIN) == 0
123
-
124
-
125
- @pytest.mark.asyncio
126
- async def test_start_audit_utility():
127
- with (
128
- patch("nucliadb_utils.utilities.NatsPubsub", return_value=AsyncMock()),
129
- patch("nucliadb_utils.utilities.StreamAuditStorage", return_value=AsyncMock()),
130
- ):
131
- await utilities.start_audit_utility("service")
132
-
133
- assert "audit" in utilities.MAIN
134
-
135
-
136
- @pytest.mark.asyncio
137
- async def test_stop_audit_utility():
138
- with (
139
- patch("nucliadb_utils.utilities.NatsPubsub", return_value=AsyncMock()),
140
- patch("nucliadb_utils.utilities.StreamAuditStorage", return_value=AsyncMock()),
141
- ):
142
- await utilities.start_audit_utility("service")
143
- await utilities.stop_audit_utility()
144
-
145
- assert "audit" not in utilities.MAIN
146
-
147
-
148
- def test_get_feature_flags():
149
- ff = utilities.get_feature_flags()
150
- assert ff is not None
151
- assert isinstance(ff, featureflagging.FlagService)
152
-
153
-
154
- def test_has_feature():
155
- ff = MagicMock()
156
- headers = {
157
- utilities.X_USER_HEADER: "user",
158
- utilities.X_ACCOUNT_HEADER: "account",
159
- utilities.X_ACCOUNT_TYPE_HEADER: "account-type",
160
- }
161
- with patch("nucliadb_utils.utilities.get_feature_flags", return_value=ff):
162
- ff.enabled.return_value = True
163
- assert utilities.has_feature("test", default=False, headers=headers)
164
-
165
- ff.enabled.assert_called_once_with(
166
- "test",
167
- default=False,
168
- context={
169
- "user_id_md5": hashlib.md5(b"user").hexdigest(),
170
- "account_id_md5": hashlib.md5(b"account").hexdigest(),
171
- "account_type": "account-type",
172
- },
173
- )