snowloader 0.1.0__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.
snowloader/__init__.py ADDED
@@ -0,0 +1,36 @@
1
+ """snowloader -- Comprehensive ServiceNow data loader for AI/LLM pipelines.
2
+
3
+ Provides a clean, Pythonic interface for pulling data out of ServiceNow tables
4
+ and converting it into document formats that LangChain, LlamaIndex, and other
5
+ LLM frameworks can work with directly. Built for production use with proper
6
+ pagination, delta sync, and memory-efficient streaming.
7
+
8
+ Author: Roni Das
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from snowloader.connection import SnowConnection, SnowConnectionError
14
+ from snowloader.loaders.catalog import CatalogLoader
15
+ from snowloader.loaders.changes import ChangeLoader
16
+ from snowloader.loaders.cmdb import CMDBLoader
17
+ from snowloader.loaders.incidents import IncidentLoader
18
+ from snowloader.loaders.knowledge_base import KnowledgeBaseLoader
19
+ from snowloader.loaders.problems import ProblemLoader
20
+ from snowloader.models import BaseSnowLoader, SnowDocument
21
+
22
+ __version__ = "0.1.0"
23
+
24
+ __all__ = [
25
+ "BaseSnowLoader",
26
+ "CatalogLoader",
27
+ "ChangeLoader",
28
+ "CMDBLoader",
29
+ "IncidentLoader",
30
+ "KnowledgeBaseLoader",
31
+ "ProblemLoader",
32
+ "SnowConnection",
33
+ "SnowConnectionError",
34
+ "SnowDocument",
35
+ "__version__",
36
+ ]
@@ -0,0 +1,16 @@
1
+ """Framework adapters for snowloader.
2
+
3
+ Thin wrappers that convert SnowDocument output from the core loaders into
4
+ document types expected by LangChain, LlamaIndex, or other LLM frameworks.
5
+ No business logic lives here. If you are looking for query building,
6
+ pagination, or field mapping, check the loaders package instead.
7
+
8
+ Import paths (adapters are not auto-imported to avoid pulling in optional
9
+ dependencies)::
10
+
11
+ # LangChain
12
+ from snowloader.adapters.langchain import ServiceNowIncidentLoader
13
+
14
+ # LlamaIndex
15
+ from snowloader.adapters.llamaindex import ServiceNowIncidentReader
16
+ """
@@ -0,0 +1,110 @@
1
+ """LangChain adapter for snowloader.
2
+
3
+ Thin wrappers that expose snowloader's core loaders through the standard
4
+ langchain_core BaseLoader interface. Each adapter delegates all the real
5
+ work to the underlying loader and just handles the conversion from
6
+ SnowDocument to langchain_core Document.
7
+
8
+ No business logic here. If you need to change how documents are built,
9
+ modify the core loaders instead.
10
+
11
+ Author: Roni Das
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import logging
17
+ from collections.abc import Iterator
18
+ from datetime import datetime
19
+ from typing import Any
20
+
21
+ try:
22
+ from langchain_core.document_loaders import BaseLoader
23
+ from langchain_core.documents import Document
24
+ except ImportError as exc:
25
+ raise ImportError(
26
+ "langchain-core is required for the LangChain adapter. "
27
+ "Install it with: pip install snowloader[langchain]"
28
+ ) from exc
29
+
30
+ from snowloader.connection import SnowConnection
31
+ from snowloader.loaders.catalog import CatalogLoader
32
+ from snowloader.loaders.changes import ChangeLoader
33
+ from snowloader.loaders.cmdb import CMDBLoader
34
+ from snowloader.loaders.incidents import IncidentLoader
35
+ from snowloader.loaders.knowledge_base import KnowledgeBaseLoader
36
+ from snowloader.loaders.problems import ProblemLoader
37
+ from snowloader.models import BaseSnowLoader
38
+
39
+ logger = logging.getLogger(__name__)
40
+
41
+
42
+ class _LangChainAdapter(BaseLoader):
43
+ """Base adapter that wraps any snowloader loader for LangChain.
44
+
45
+ Converts SnowDocument instances to LangChain Document objects.
46
+ Subclasses just set the _loader_class attribute.
47
+ """
48
+
49
+ _loader_class: type[BaseSnowLoader]
50
+
51
+ def __init__(self, connection: SnowConnection, **kwargs: Any) -> None:
52
+ self._loader = self._loader_class(connection=connection, **kwargs)
53
+
54
+ def lazy_load(self) -> Iterator[Document]:
55
+ """Yield LangChain Documents one at a time from the core loader."""
56
+ for snow_doc in self._loader.lazy_load():
57
+ yield Document(
58
+ page_content=snow_doc.page_content,
59
+ metadata=snow_doc.metadata,
60
+ )
61
+
62
+ def load_since(self, since: datetime) -> list[Document]:
63
+ """Fetch only records updated after the given datetime.
64
+
65
+ Args:
66
+ since: Cutoff datetime for delta sync.
67
+
68
+ Returns:
69
+ List of LangChain Document instances.
70
+ """
71
+ return [
72
+ Document(page_content=d.page_content, metadata=d.metadata)
73
+ for d in self._loader.load_since(since)
74
+ ]
75
+
76
+
77
+ class ServiceNowIncidentLoader(_LangChainAdapter):
78
+ """LangChain loader for ServiceNow incidents."""
79
+
80
+ _loader_class = IncidentLoader
81
+
82
+
83
+ class ServiceNowKBLoader(_LangChainAdapter):
84
+ """LangChain loader for ServiceNow Knowledge Base articles."""
85
+
86
+ _loader_class = KnowledgeBaseLoader
87
+
88
+
89
+ class ServiceNowCMDBLoader(_LangChainAdapter):
90
+ """LangChain loader for ServiceNow CMDB configuration items."""
91
+
92
+ _loader_class = CMDBLoader
93
+
94
+
95
+ class ServiceNowChangeLoader(_LangChainAdapter):
96
+ """LangChain loader for ServiceNow change requests."""
97
+
98
+ _loader_class = ChangeLoader
99
+
100
+
101
+ class ServiceNowProblemLoader(_LangChainAdapter):
102
+ """LangChain loader for ServiceNow problem records."""
103
+
104
+ _loader_class = ProblemLoader
105
+
106
+
107
+ class ServiceNowCatalogLoader(_LangChainAdapter):
108
+ """LangChain loader for ServiceNow service catalog items."""
109
+
110
+ _loader_class = CatalogLoader
@@ -0,0 +1,127 @@
1
+ """LlamaIndex adapter for snowloader.
2
+
3
+ Thin wrappers that expose snowloader's core loaders through the standard
4
+ llama_index BaseReader interface. Each adapter delegates all the real
5
+ work to the underlying loader and just handles the conversion from
6
+ SnowDocument to llama_index Document.
7
+
8
+ No business logic here. If you need to change how documents are built,
9
+ modify the core loaders instead.
10
+
11
+ Author: Roni Das
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import logging
17
+ from datetime import datetime
18
+ from typing import Any
19
+
20
+ try:
21
+ from llama_index.core.readers.base import BaseReader
22
+ from llama_index.core.schema import Document
23
+ except ImportError as exc:
24
+ raise ImportError(
25
+ "llama-index-core is required for the LlamaIndex adapter. "
26
+ "Install it with: pip install snowloader[llamaindex]"
27
+ ) from exc
28
+
29
+ from snowloader.connection import SnowConnection
30
+ from snowloader.loaders.catalog import CatalogLoader
31
+ from snowloader.loaders.changes import ChangeLoader
32
+ from snowloader.loaders.cmdb import CMDBLoader
33
+ from snowloader.loaders.incidents import IncidentLoader
34
+ from snowloader.loaders.knowledge_base import KnowledgeBaseLoader
35
+ from snowloader.loaders.problems import ProblemLoader
36
+ from snowloader.models import BaseSnowLoader, SnowDocument
37
+
38
+ logger = logging.getLogger(__name__)
39
+
40
+
41
+ class _LlamaIndexAdapter(BaseReader):
42
+ """Base adapter that wraps any snowloader loader for LlamaIndex.
43
+
44
+ Converts SnowDocument instances to LlamaIndex Document objects.
45
+ Subclasses just set the _loader_class attribute.
46
+ """
47
+
48
+ _loader_class: type[BaseSnowLoader]
49
+
50
+ _default_excluded_llm_keys: list[str] = ["sys_id"]
51
+
52
+ def __init__(
53
+ self,
54
+ connection: SnowConnection,
55
+ excluded_llm_metadata_keys: list[str] | None = None,
56
+ **kwargs: Any,
57
+ ) -> None:
58
+ super().__init__()
59
+ self._excluded_keys = (
60
+ excluded_llm_metadata_keys
61
+ if excluded_llm_metadata_keys is not None
62
+ else self._default_excluded_llm_keys
63
+ )
64
+ self._loader = self._loader_class(connection=connection, **kwargs)
65
+
66
+ def load_data(self) -> list[Document]:
67
+ """Return a list of LlamaIndex Documents from the core loader.
68
+
69
+ Returns:
70
+ List of LlamaIndex Document instances.
71
+ """
72
+ return [self._to_document(d) for d in self._loader.lazy_load()]
73
+
74
+ def load_data_since(self, since: datetime) -> list[Document]:
75
+ """Fetch only records updated after the given datetime.
76
+
77
+ Args:
78
+ since: Cutoff datetime for delta sync.
79
+
80
+ Returns:
81
+ List of LlamaIndex Document instances.
82
+ """
83
+ return [self._to_document(d) for d in self._loader.load_since(since)]
84
+
85
+ def _to_document(self, snow_doc: SnowDocument) -> Document:
86
+ """Convert a SnowDocument to a LlamaIndex Document."""
87
+ return Document(
88
+ text=snow_doc.page_content,
89
+ metadata=snow_doc.metadata,
90
+ excluded_llm_metadata_keys=self._excluded_keys,
91
+ )
92
+
93
+
94
+ class ServiceNowIncidentReader(_LlamaIndexAdapter):
95
+ """LlamaIndex reader for ServiceNow incidents."""
96
+
97
+ _loader_class = IncidentLoader
98
+
99
+
100
+ class ServiceNowKBReader(_LlamaIndexAdapter):
101
+ """LlamaIndex reader for ServiceNow Knowledge Base articles."""
102
+
103
+ _loader_class = KnowledgeBaseLoader
104
+
105
+
106
+ class ServiceNowCMDBReader(_LlamaIndexAdapter):
107
+ """LlamaIndex reader for ServiceNow CMDB configuration items."""
108
+
109
+ _loader_class = CMDBLoader
110
+
111
+
112
+ class ServiceNowChangeReader(_LlamaIndexAdapter):
113
+ """LlamaIndex reader for ServiceNow change requests."""
114
+
115
+ _loader_class = ChangeLoader
116
+
117
+
118
+ class ServiceNowProblemReader(_LlamaIndexAdapter):
119
+ """LlamaIndex reader for ServiceNow problem records."""
120
+
121
+ _loader_class = ProblemLoader
122
+
123
+
124
+ class ServiceNowCatalogReader(_LlamaIndexAdapter):
125
+ """LlamaIndex reader for ServiceNow service catalog items."""
126
+
127
+ _loader_class = CatalogLoader