snowloader 0.2.2__tar.gz → 0.2.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {snowloader-0.2.2 → snowloader-0.2.4}/CHANGELOG.md +18 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/PKG-INFO +1 -1
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/conf.py +1 -1
- {snowloader-0.2.2 → snowloader-0.2.4}/pyproject.toml +1 -1
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/__init__.py +1 -1
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/async_connection.py +54 -13
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/connection.py +1 -1
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_async_connection.py +61 -13
- {snowloader-0.2.2 → snowloader-0.2.4}/.github/workflows/ci.yml +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/.github/workflows/docs.yml +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/.github/workflows/publish.yml +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/.gitignore +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/.readthedocs.yaml +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/LICENSE +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/README.md +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/_static/logo.png +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/adapters.rst +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/advanced.rst +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/api.rst +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/async.rst +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/attachments.rst +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/authentication.rst +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/changelog.rst +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/configuration.rst +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/getting-started.rst +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/index.rst +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/loaders.rst +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/docs/roadmap.rst +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/examples/01_basic_incidents.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/examples/02_langchain_rag.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/examples/03_llamaindex_rag.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/examples/04_delta_sync.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/examples/05_cmdb_graph.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/integrations/langchain-docs/snowloader.ipynb +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/.github/workflows/publish.yml +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/.gitignore +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/LICENSE +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/Makefile +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/README.md +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/llama_index/__init__.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/llama_index/readers/__init__.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/llama_index/readers/snowloader/__init__.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/llama_index/readers/snowloader/base.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/pyproject.toml +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/tests/__init__.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/tests/test_readers_snowloader.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/adapters/__init__.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/adapters/langchain.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/adapters/llamaindex.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/async_models.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/loaders/__init__.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/loaders/_field_utils.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/loaders/attachments.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/loaders/catalog.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/loaders/changes.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/loaders/cmdb.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/loaders/incidents.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/loaders/knowledge_base.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/loaders/problems.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/models.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/py.typed +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/utils/__init__.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/utils/html_cleaner.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/src/snowloader/utils/parsing.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/__init__.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/integration/__init__.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/integration/test_live.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/__init__.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_async_loaders.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_attachments.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_catalog.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_changes.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_cmdb.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_connection.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_field_utils.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_html_cleaner.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_incidents.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_kb.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_langchain_adapter.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_llamaindex_adapter.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_models.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_problems.py +0 -0
- {snowloader-0.2.2 → snowloader-0.2.4}/tests/unit/test_smoke_e2e.py +0 -0
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to snowloader are documented here. This project follows [Semantic Versioning](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## [0.2.4] - 2026-04-28
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Truncated or malformed JSON responses are now treated as transient failures and retried up to `max_retries` instead of raising immediately. Some ServiceNow front ends occasionally return cut-off response bodies under sustained concurrent load; this change keeps long extractions alive through those blips.
|
|
10
|
+
|
|
11
|
+
## [0.2.3] - 2026-04-28
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- `AsyncSnowConnection` now uses `force_close=True` and `limit_per_host=concurrency` on its `aiohttp.TCPConnector`. Each request gets a fresh TCP connection, which avoids the connection-reuse failures some ServiceNow instances exhibit under sustained concurrent load.
|
|
16
|
+
- Non-object JSON bodies (e.g. `null` or a list returned with HTTP 200) are now treated as transient failures: the SDK retries up to `max_retries` and raises `SnowConnectionError` if the issue persists. Previously the v0.2.2 fallback silently treated them as empty pages, which would lose data.
|
|
17
|
+
- HTTP 500 added to the default retryable status code set on both `SnowConnection` and `AsyncSnowConnection`. ServiceNow 500s are typically transient overload, not deterministic bugs.
|
|
18
|
+
|
|
19
|
+
### Fixed
|
|
20
|
+
|
|
21
|
+
- `AsyncSnowConnection.aget_records` no longer crashes with `AttributeError` when a page returns a non-object JSON body. The retry-then-raise behavior surfaces the failure clearly instead of silently dropping data.
|
|
22
|
+
|
|
5
23
|
## [0.2.2] - 2026-04-28
|
|
6
24
|
|
|
7
25
|
### Fixed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: snowloader
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Comprehensive ServiceNow data loader for AI/LLM pipelines - Incidents, CMDB, KB, Changes, Catalog & more. Works with LangChain & LlamaIndex.
|
|
5
5
|
Project-URL: Homepage, https://github.com/ronidas39/snowloader
|
|
6
6
|
Project-URL: Documentation, https://snowloader.readthedocs.io
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "snowloader"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.4"
|
|
8
8
|
description = "Comprehensive ServiceNow data loader for AI/LLM pipelines - Incidents, CMDB, KB, Changes, Catalog & more. Works with LangChain & LlamaIndex."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = {text = "MIT"}
|
|
@@ -21,7 +21,7 @@ from snowloader.loaders.problems import ProblemLoader
|
|
|
21
21
|
from snowloader.models import BaseSnowLoader, SnowDocument
|
|
22
22
|
from snowloader.utils.parsing import parse_labelled_int
|
|
23
23
|
|
|
24
|
-
__version__ = "0.2.
|
|
24
|
+
__version__ = "0.2.4"
|
|
25
25
|
|
|
26
26
|
try:
|
|
27
27
|
from snowloader.async_connection import AsyncSnowConnection # noqa: F401
|
|
@@ -42,7 +42,7 @@ logger = logging.getLogger(__name__)
|
|
|
42
42
|
|
|
43
43
|
_DEFAULT_MAX_RETRIES = 3
|
|
44
44
|
_DEFAULT_RETRY_BACKOFF = 1.0
|
|
45
|
-
_RETRYABLE_STATUS_CODES = {429, 502, 503, 504}
|
|
45
|
+
_RETRYABLE_STATUS_CODES = {429, 500, 502, 503, 504}
|
|
46
46
|
_MAX_PAGE_SIZE = 10000
|
|
47
47
|
_MIN_PAGE_SIZE = 1
|
|
48
48
|
_DEFAULT_CONCURRENCY = 16
|
|
@@ -210,9 +210,18 @@ class AsyncSnowConnection:
|
|
|
210
210
|
|
|
211
211
|
async def _ensure_session(self) -> aiohttp.ClientSession:
|
|
212
212
|
if self._session is None or self._session.closed:
|
|
213
|
+
# force_close=True disables HTTP keep-alive: each request gets a
|
|
214
|
+
# fresh TCP connection. Some ServiceNow front ends (and shared
|
|
215
|
+
# WAF/proxy layers in front of them) silently return empty / null
|
|
216
|
+
# response bodies on reused connections under concurrent load,
|
|
217
|
+
# which corrupts paginated reads. Trading a small amount of
|
|
218
|
+
# connection-setup overhead for correctness is the right call
|
|
219
|
+
# for a data-extraction SDK where missing pages are unacceptable.
|
|
213
220
|
connector = aiohttp.TCPConnector(
|
|
214
221
|
limit=self.concurrency * 2,
|
|
222
|
+
limit_per_host=self.concurrency,
|
|
215
223
|
ssl=self._verify_ssl,
|
|
224
|
+
force_close=True,
|
|
216
225
|
)
|
|
217
226
|
timeout_cfg = aiohttp.ClientTimeout(total=self.timeout)
|
|
218
227
|
auth = None
|
|
@@ -378,25 +387,57 @@ class AsyncSnowConnection:
|
|
|
378
387
|
try:
|
|
379
388
|
parsed = await resp.json(content_type=None)
|
|
380
389
|
except (aiohttp.ContentTypeError, ValueError) as exc:
|
|
390
|
+
# Truncated or malformed JSON happens occasionally
|
|
391
|
+
# under sustained concurrent load (server-side write
|
|
392
|
+
# gets cut off). Retry like a transient failure.
|
|
393
|
+
if attempt < self.max_retries:
|
|
394
|
+
logger.warning(
|
|
395
|
+
"API returned non-JSON / truncated response "
|
|
396
|
+
"for %s %s: %s; retrying (attempt %d/%d)",
|
|
397
|
+
method,
|
|
398
|
+
url,
|
|
399
|
+
exc,
|
|
400
|
+
attempt + 1,
|
|
401
|
+
self.max_retries,
|
|
402
|
+
)
|
|
403
|
+
await asyncio.sleep(backoff)
|
|
404
|
+
attempt += 1
|
|
405
|
+
backoff *= 2
|
|
406
|
+
continue
|
|
381
407
|
raise SnowConnectionError(
|
|
382
|
-
f"API returned non-JSON response for {method} {url}"
|
|
408
|
+
f"API returned non-JSON response for {method} {url} "
|
|
409
|
+
f"after {self.max_retries} retries",
|
|
383
410
|
status_code=resp.status,
|
|
384
411
|
detail=last_body,
|
|
385
412
|
) from exc
|
|
386
413
|
|
|
387
414
|
if not isinstance(parsed, dict):
|
|
388
|
-
#
|
|
389
|
-
#
|
|
390
|
-
#
|
|
391
|
-
#
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
415
|
+
# ServiceNow occasionally returns ``null`` or a list
|
|
416
|
+
# body on a 200 response when something upstream
|
|
417
|
+
# drops the payload (typically a connection-reuse
|
|
418
|
+
# issue under concurrent load). Silently treating
|
|
419
|
+
# this as an empty page would lose data, so retry
|
|
420
|
+
# the request as if it were a transient 5xx.
|
|
421
|
+
if attempt < self.max_retries:
|
|
422
|
+
logger.warning(
|
|
423
|
+
"API returned non-object JSON for %s %s (type=%s); "
|
|
424
|
+
"retrying (attempt %d/%d)",
|
|
425
|
+
method,
|
|
426
|
+
url,
|
|
427
|
+
type(parsed).__name__,
|
|
428
|
+
attempt + 1,
|
|
429
|
+
self.max_retries,
|
|
430
|
+
)
|
|
431
|
+
await asyncio.sleep(backoff)
|
|
432
|
+
attempt += 1
|
|
433
|
+
backoff *= 2
|
|
434
|
+
continue
|
|
435
|
+
raise SnowConnectionError(
|
|
436
|
+
f"API returned non-object JSON for {method} {url} "
|
|
437
|
+
f"after {self.max_retries} retries",
|
|
438
|
+
status_code=resp.status,
|
|
439
|
+
detail=f"Got {type(parsed).__name__} instead of dict",
|
|
398
440
|
)
|
|
399
|
-
return {"result": []}
|
|
400
441
|
return cast(dict[str, Any], parsed)
|
|
401
442
|
except aiohttp.ClientError as exc:
|
|
402
443
|
if attempt < self.max_retries:
|
|
@@ -34,7 +34,7 @@ logger = logging.getLogger(__name__)
|
|
|
34
34
|
# Retry defaults
|
|
35
35
|
_DEFAULT_MAX_RETRIES = 3
|
|
36
36
|
_DEFAULT_RETRY_BACKOFF = 1.0 # seconds, doubles each attempt
|
|
37
|
-
_RETRYABLE_STATUS_CODES = {429, 502, 503, 504}
|
|
37
|
+
_RETRYABLE_STATUS_CODES = {429, 500, 502, 503, 504}
|
|
38
38
|
_MAX_PAGE_SIZE = 10000
|
|
39
39
|
_MIN_PAGE_SIZE = 1
|
|
40
40
|
|
|
@@ -255,12 +255,8 @@ async def test_aget_attachment_returns_bytes() -> None:
|
|
|
255
255
|
|
|
256
256
|
|
|
257
257
|
@pytest.mark.asyncio
|
|
258
|
-
async def
|
|
259
|
-
"""
|
|
260
|
-
|
|
261
|
-
Previously this crashed aget_records on ``data.get('result')``. Now we
|
|
262
|
-
log a warning and treat it as an empty result.
|
|
263
|
-
"""
|
|
258
|
+
async def test_request_retries_malformed_json_then_raises() -> None:
|
|
259
|
+
"""Truncated or malformed JSON triggers retry, then raises after max_retries."""
|
|
264
260
|
with aioresponses() as m:
|
|
265
261
|
m.get(
|
|
266
262
|
_stats_url(),
|
|
@@ -270,7 +266,7 @@ async def test_request_treats_null_body_as_empty_result() -> None:
|
|
|
270
266
|
)
|
|
271
267
|
m.get(
|
|
272
268
|
_table_url(),
|
|
273
|
-
body="
|
|
269
|
+
body='{"result": [{"sys_id": "abc"', # truncated mid-string
|
|
274
270
|
status=200,
|
|
275
271
|
content_type="application/json",
|
|
276
272
|
repeat=True,
|
|
@@ -280,14 +276,23 @@ async def test_request_treats_null_body_as_empty_result() -> None:
|
|
|
280
276
|
username="u",
|
|
281
277
|
password="p",
|
|
282
278
|
page_size=10,
|
|
279
|
+
max_retries=2,
|
|
280
|
+
retry_backoff=0.0,
|
|
283
281
|
) as conn:
|
|
284
|
-
|
|
285
|
-
|
|
282
|
+
with pytest.raises(SnowConnectionError) as exc_info:
|
|
283
|
+
async for _ in conn.aget_records("incident"):
|
|
284
|
+
pass
|
|
285
|
+
assert "non-JSON" in str(exc_info.value)
|
|
286
286
|
|
|
287
287
|
|
|
288
288
|
@pytest.mark.asyncio
|
|
289
|
-
async def
|
|
290
|
-
"""
|
|
289
|
+
async def test_request_retries_null_body_then_raises() -> None:
|
|
290
|
+
"""ServiceNow occasionally returns 200 with a ``null`` body under load.
|
|
291
|
+
|
|
292
|
+
The SDK must NOT silently treat this as an empty page (that would lose
|
|
293
|
+
data). Instead it retries up to ``max_retries`` and raises if the issue
|
|
294
|
+
persists, so the caller knows something is wrong.
|
|
295
|
+
"""
|
|
291
296
|
with aioresponses() as m:
|
|
292
297
|
m.get(
|
|
293
298
|
_stats_url(),
|
|
@@ -297,18 +302,61 @@ async def test_request_treats_list_body_as_empty_result() -> None:
|
|
|
297
302
|
)
|
|
298
303
|
m.get(
|
|
299
304
|
_table_url(),
|
|
300
|
-
|
|
305
|
+
body="null",
|
|
306
|
+
status=200,
|
|
307
|
+
content_type="application/json",
|
|
308
|
+
repeat=True,
|
|
309
|
+
)
|
|
310
|
+
async with AsyncSnowConnection(
|
|
311
|
+
instance_url=INSTANCE,
|
|
312
|
+
username="u",
|
|
313
|
+
password="p",
|
|
314
|
+
page_size=10,
|
|
315
|
+
max_retries=2,
|
|
316
|
+
retry_backoff=0.0,
|
|
317
|
+
) as conn:
|
|
318
|
+
with pytest.raises(SnowConnectionError) as exc_info:
|
|
319
|
+
async for _ in conn.aget_records("incident"):
|
|
320
|
+
pass
|
|
321
|
+
assert "non-object JSON" in str(exc_info.value)
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
@pytest.mark.asyncio
|
|
325
|
+
async def test_request_recovers_when_null_body_then_valid() -> None:
|
|
326
|
+
"""When a transient null body is followed by a valid response, the SDK
|
|
327
|
+
must recover (return the valid data) rather than fail or skip."""
|
|
328
|
+
payload = {"result": [{"sys_id": "abc", "number": "INC1"}]}
|
|
329
|
+
call_count = {"n": 0}
|
|
330
|
+
|
|
331
|
+
def callback(url: str, **kwargs: object) -> object:
|
|
332
|
+
call_count["n"] += 1
|
|
333
|
+
if call_count["n"] == 1:
|
|
334
|
+
from aioresponses.core import CallbackResult
|
|
335
|
+
|
|
336
|
+
return CallbackResult(status=200, body="null", content_type="application/json")
|
|
337
|
+
from aioresponses.core import CallbackResult
|
|
338
|
+
|
|
339
|
+
return CallbackResult(status=200, payload=payload)
|
|
340
|
+
|
|
341
|
+
with aioresponses() as m:
|
|
342
|
+
m.get(
|
|
343
|
+
_stats_url(),
|
|
344
|
+
payload={"result": {"stats": {"count": "1"}}},
|
|
301
345
|
status=200,
|
|
302
346
|
repeat=True,
|
|
303
347
|
)
|
|
348
|
+
m.get(_table_url(), callback=callback, repeat=True)
|
|
304
349
|
async with AsyncSnowConnection(
|
|
305
350
|
instance_url=INSTANCE,
|
|
306
351
|
username="u",
|
|
307
352
|
password="p",
|
|
308
353
|
page_size=10,
|
|
354
|
+
max_retries=3,
|
|
355
|
+
retry_backoff=0.0,
|
|
309
356
|
) as conn:
|
|
310
357
|
records = [rec async for rec in conn.aget_records("incident")]
|
|
311
|
-
assert records ==
|
|
358
|
+
assert len(records) == 1
|
|
359
|
+
assert records[0]["sys_id"] == "abc"
|
|
312
360
|
|
|
313
361
|
|
|
314
362
|
@pytest.mark.asyncio
|
|
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
|
|
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
|
|
File without changes
|
{snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/.gitignore
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
|
{snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/pyproject.toml
RENAMED
|
File without changes
|
{snowloader-0.2.2 → snowloader-0.2.4}/integrations/llama-index-readers-snowloader/tests/__init__.py
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
|
|
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
|
|
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
|
|
File without changes
|