personal_knowledge_library 3.2.2__tar.gz → 3.3.1__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.

Potentially problematic release.


This version of personal_knowledge_library might be problematic. Click here for more details.

Files changed (46) hide show
  1. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/PKG-INFO +4 -3
  2. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/__init__.py +1 -1
  3. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/base/ontology.py +1 -1
  4. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/nel/base.py +19 -0
  5. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/nel/engine.py +2 -0
  6. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/asyncio/graph.py +223 -0
  7. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/graph.py +59 -0
  8. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/pyproject.toml +1 -1
  9. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/LICENSE +0 -0
  10. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/README.md +0 -0
  11. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/base/__init__.py +0 -0
  12. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/base/access.py +0 -0
  13. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/base/entity.py +0 -0
  14. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/base/language.py +0 -0
  15. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/base/response.py +0 -0
  16. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/base/search.py +0 -0
  17. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/base/tenant.py +0 -0
  18. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/nel/__init__.py +0 -0
  19. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/ontomapping/__init__.py +0 -0
  20. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/ontomapping/manager.py +0 -0
  21. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/public/__init__.py +0 -0
  22. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/public/cache.py +0 -0
  23. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/public/client.py +0 -0
  24. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/public/helper.py +0 -0
  25. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/public/relations.py +0 -0
  26. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/public/wikidata.py +0 -0
  27. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/__init__.py +0 -0
  28. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/asyncio/__init__.py +0 -0
  29. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/asyncio/base.py +0 -0
  30. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/asyncio/group.py +0 -0
  31. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/asyncio/search.py +0 -0
  32. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/asyncio/users.py +0 -0
  33. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/base.py +0 -0
  34. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/group.py +0 -0
  35. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/helper.py +0 -0
  36. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/ontology.py +0 -0
  37. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/search.py +0 -0
  38. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/session.py +0 -0
  39. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/tenant.py +0 -0
  40. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/services/users.py +0 -0
  41. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/utils/__init__.py +0 -0
  42. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/utils/diff.py +0 -0
  43. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/utils/graph.py +0 -0
  44. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/utils/import_format.py +0 -0
  45. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/utils/wikidata.py +0 -0
  46. {personal_knowledge_library-3.2.2 → personal_knowledge_library-3.3.1}/knowledge/utils/wikipedia.py +0 -0
@@ -1,8 +1,9 @@
1
- Metadata-Version: 2.3
1
+ Metadata-Version: 2.4
2
2
  Name: personal_knowledge_library
3
- Version: 3.2.2
3
+ Version: 3.3.1
4
4
  Summary: Library to access Wacom's Personal Knowledge graph.
5
- License: Apache-2.0
5
+ License-Expression: Apache-2.0
6
+ License-File: LICENSE
6
7
  Keywords: semantic-knowledge,knowledge-graph
7
8
  Author: Markus Weber
8
9
  Author-email: markus.weber@wacom.com
@@ -17,7 +17,7 @@ __license__ = "Wacom"
17
17
  __maintainer__ = ["Markus Weber"]
18
18
  __email__ = "markus.weber@wacom.com"
19
19
  __status__ = "beta"
20
- __version__ = "3.2.2"
20
+ __version__ = "3.3.1"
21
21
 
22
22
  import loguru
23
23
 
@@ -1494,7 +1494,7 @@ class Ontology:
1494
1494
  return f"<Ontology> : classes:= {self.classes}"
1495
1495
 
1496
1496
 
1497
- class ThingObject(abc.ABC):
1497
+ class ThingObject(object):
1498
1498
  """
1499
1499
  ThingObject
1500
1500
  -----------
@@ -162,6 +162,10 @@ class KnowledgeGraphEntity(NamedEntity):
162
162
  List of ontology types (class names)
163
163
  entity_type: EntityType
164
164
  Type of the entity.
165
+ tokens: Optional[List[str]] (default:=None)
166
+ List of tokens used to identify the entity.
167
+ token_indexes: Optional[List[int]] (default:=None)
168
+ List of token indexes used to identify the entity.
165
169
  """
166
170
 
167
171
  def __init__(
@@ -175,6 +179,9 @@ class KnowledgeGraphEntity(NamedEntity):
175
179
  content_link: str,
176
180
  ontology_types: List[str],
177
181
  entity_type: EntityType = EntityType.PUBLIC_ENTITY,
182
+ tokens: Optional[List[str]] = None,
183
+ token_indexes: Optional[List[int]] = None,
184
+
178
185
  ):
179
186
  super().__init__(ref_text, start_idx, end_idx, entity_type)
180
187
  self.__source: EntitySource = source
@@ -185,6 +192,8 @@ class KnowledgeGraphEntity(NamedEntity):
185
192
  self.__thumbnail: Optional[str] = None
186
193
  self.__ontology_types: List[str] = ontology_types
187
194
  self.__relevant_type: OntologyClassReference = THING_CLASS
195
+ self.__tokens: Optional[List[str]] = tokens
196
+ self.__token_indexes: Optional[List[int]] = token_indexes
188
197
 
189
198
  @property
190
199
  def entity_source(self) -> EntitySource:
@@ -242,6 +251,16 @@ class KnowledgeGraphEntity(NamedEntity):
242
251
  def relevant_type(self, value: OntologyClassReference):
243
252
  self.__relevant_type = value
244
253
 
254
+ @property
255
+ def tokens(self) -> Optional[List[str]]:
256
+ """List of tokens used to identify the entity."""
257
+ return self.__tokens
258
+
259
+ @property
260
+ def token_indexes(self) -> Optional[List[int]]:
261
+ """List of token indexes used to identify the entity."""
262
+ return self.__token_indexes
263
+
245
264
  def __repr__(self):
246
265
  return f"{self.ref_text} [{self.start_idx}-{self.end_idx}] -> {self.entity_source} [{self.entity_type}]"
247
266
 
@@ -116,6 +116,8 @@ class WacomEntityLinkingEngine(PersonalEntityLinkingProcessor):
116
116
  content_link="",
117
117
  ontology_types=entity_types,
118
118
  entity_type=EntityType.PERSONAL_ENTITY,
119
+ tokens=e.get("tokens"),
120
+ token_indexes=e.get("tokenIndexes"),
119
121
  )
120
122
  ne.relevant_type = OntologyClassReference.parse(e["type"])
121
123
  named_entities.append(ne)
@@ -1,6 +1,8 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  # Copyright © 2024-present Wacom. All rights reserved.
3
3
  import asyncio
4
+ import gzip
5
+ import json
4
6
  import logging
5
7
  import os
6
8
  import urllib
@@ -35,6 +37,7 @@ from knowledge.base.ontology import (
35
37
  OntologyClassReference,
36
38
  ObjectProperty,
37
39
  )
40
+ from knowledge.base.response import JobStatus, ErrorLogResponse, NewEntityUrisResponse
38
41
  from knowledge.nel.base import KnowledgeGraphEntity, EntityType, KnowledgeSource, EntitySource
39
42
  from knowledge.services import AUTHORIZATION_HEADER_FLAG, IS_OWNER_PARAM, IndexType
40
43
  from knowledge.services import (
@@ -114,6 +117,8 @@ class AsyncWacomKnowledgeService(AsyncServiceAPIClient):
114
117
  SEARCH_DESCRIPTION_ENDPOINT: str = "semantic-search/description"
115
118
  SEARCH_RELATION_ENDPOINT: str = "semantic-search/relation"
116
119
  ONTOLOGY_UPDATE_ENDPOINT: str = "ontology-update"
120
+ IMPORT_ENTITIES_ENDPOINT: str = "import"
121
+ IMPORT_ERROR_LOG_ENDPOINT: str = "import/errorlog"
117
122
 
118
123
  def __init__(
119
124
  self,
@@ -588,6 +593,222 @@ class AsyncWacomKnowledgeService(AsyncServiceAPIClient):
588
593
  await asyncio.sleep(0.25 if self.use_graceful_shutdown else 0.0)
589
594
  return uri
590
595
 
596
+ async def import_entities(
597
+ self,
598
+ entities: List[ThingObject],
599
+ auth_key: Optional[str] = None,
600
+ timeout: int = DEFAULT_TIMEOUT
601
+ ) -> str:
602
+ """Import entities to the graph.
603
+
604
+ Parameters
605
+ ----------
606
+ entities: List[ThingObject]
607
+ List of entities to import.
608
+ auth_key: Optional[str] = None
609
+ If the auth key is set the logged-in user (if any) will be ignored and the auth key will be used.
610
+ timeout: int
611
+ Timeout for the request (default: 60 seconds)
612
+
613
+ Returns
614
+ -------
615
+ job_id: str
616
+ ID of the job
617
+
618
+ Raises
619
+ ------
620
+ WacomServiceException
621
+ If the graph service returns an error code.
622
+ """
623
+ if auth_key is None:
624
+ auth_key, _ = await self.handle_token()
625
+ headers: dict = {USER_AGENT_HEADER_FLAG: self.user_agent, AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
626
+ ndjson_lines: List[str] = []
627
+ for obj in entities:
628
+ data_dict = obj.__import_format_dict__()
629
+ ndjson_lines.append(json.dumps(data_dict)) # Convert each dict to a JSON string
630
+
631
+ ndjson_content = "\n".join(ndjson_lines) # Join JSON strings with newline
632
+
633
+ # Compress the NDJSON string to a gzip byte array
634
+ compressed_data: bytes = gzip.compress(ndjson_content.encode("utf-8"))
635
+ url: str = f"{self.service_base_url}{self.IMPORT_ENTITIES_ENDPOINT}"
636
+ data: aiohttp.FormData = aiohttp.FormData()
637
+ data.add_field("file", compressed_data, filename="import.njson.gz", content_type="application/x-gzip")
638
+ async with AsyncServiceAPIClient.__async_session__() as session:
639
+ async with session.post(
640
+ url, headers=headers, data=data, timeout=timeout, verify_ssl=self.verify_calls
641
+ ) as response:
642
+ if response.ok:
643
+ structure: Dict[str, Any] = await response.json(loads=orjson.loads)
644
+ return structure["jobId"]
645
+ raise await handle_error("Import endpoint returns an error.", response)
646
+
647
+ async def import_entities_from_file(
648
+ self,
649
+ file_path: Path,
650
+ auth_key: Optional[str] = None,
651
+ timeout: int = DEFAULT_TIMEOUT
652
+ ) -> str:
653
+ """Import entities from a file to the graph.
654
+
655
+ Parameters
656
+ ----------
657
+ file_path: Path
658
+ Path to the file containing entities in NDJSON format.
659
+ auth_key: Optional[str] = None
660
+ If the auth key is set the logged-in user (if any) will be ignored and the auth key will be used.
661
+ timeout: int
662
+ Timeout for the request (default: 60 seconds)
663
+
664
+ Returns
665
+ -------
666
+ job_id: str
667
+ ID of the job
668
+
669
+ Raises
670
+ ------
671
+ WacomServiceException
672
+ If the graph service returns an error code.
673
+ """
674
+ if not file_path.exists():
675
+ raise FileNotFoundError(f"The file {file_path} does not exist.")
676
+ if auth_key is None:
677
+ auth_key, _ = await self.handle_token()
678
+ headers: dict = {USER_AGENT_HEADER_FLAG: self.user_agent, AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
679
+ with file_path.open("rb") as file:
680
+ # Compress the NDJSON string to a gzip byte array
681
+ compressed_data: bytes = file.read()
682
+ data: aiohttp.FormData = aiohttp.FormData()
683
+ data.add_field("file", compressed_data, filename="import.njson.gz",
684
+ content_type="application/x-gzip")
685
+ url: str = f"{self.service_base_url}{self.IMPORT_ENTITIES_ENDPOINT}"
686
+ async with AsyncServiceAPIClient.__async_session__() as session:
687
+ async with session.post(
688
+ url, headers=headers, data=data, timeout=timeout, verify_ssl=self.verify_calls
689
+ ) as response:
690
+ if response.ok:
691
+ structure: Dict[str, Any] = await response.json(loads=orjson.loads)
692
+ return structure["jobId"]
693
+ raise await handle_error("Import endpoint returns an error.", response)
694
+
695
+ async def job_status(
696
+ self,
697
+ job_id: str,
698
+ auth_key: Optional[str] = None,
699
+ timeout: int = DEFAULT_TIMEOUT
700
+ ) -> JobStatus:
701
+ """
702
+ Retrieve the status of the job.
703
+
704
+ Parameters
705
+ ----------
706
+ job_id: str
707
+ ID of the job
708
+ auth_key: Optional[str] = None
709
+ If the auth key is set the logged-in user (if any) will be ignored and the auth key will be used.
710
+ timeout: int
711
+ Timeout for the request (default: 60 seconds)
712
+
713
+ Returns
714
+ -------
715
+ job_status: JobStatus
716
+ Status of the job
717
+ """
718
+ if auth_key is None:
719
+ auth_key, _ = await self.handle_token()
720
+ headers: dict = {USER_AGENT_HEADER_FLAG: self.user_agent, AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
721
+ url: str = f"{self.service_base_url}{self.IMPORT_ENTITIES_ENDPOINT}/{job_id}"
722
+ async with AsyncServiceAPIClient.__async_session__() as session:
723
+ async with session.get(
724
+ url, headers=headers, timeout=timeout, verify_ssl=self.verify_calls
725
+ ) as response:
726
+ if response.ok:
727
+ structure: Dict[str, Any] = await response.json(loads=orjson.loads)
728
+ return JobStatus.from_dict(structure)
729
+ raise await handle_error(f"Retrieving job status for {job_id} failed.", response, headers=headers)
730
+
731
+ async def import_error_log(
732
+ self,
733
+ job_id: str,
734
+ auth_key: Optional[str] = None,
735
+ next_page_id: Optional[str] = None,
736
+ timeout: int = DEFAULT_TIMEOUT
737
+ ) -> ErrorLogResponse:
738
+ """
739
+ Retrieve the error log of the job.
740
+
741
+ Parameters
742
+ ----------
743
+ job_id: str
744
+ ID of the job
745
+ next_page_id: Optional[str] = None
746
+ ID of the next page within pagination.
747
+ auth_key: Optional[str] = None
748
+ If the auth key is set the logged-in user (if any) will be ignored and the auth key will be used.
749
+ timeout: int
750
+ Timeout for the request (default: 60 seconds)
751
+
752
+ Returns
753
+ -------
754
+ error: ErrorLogResponse
755
+ Error log of the job
756
+ """
757
+ if auth_key is None:
758
+ auth_key, _ = await self.handle_token()
759
+ headers: dict = {USER_AGENT_HEADER_FLAG: self.user_agent, AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
760
+ url: str = f"{self.service_base_url}{self.IMPORT_ERROR_LOG_ENDPOINT}/{job_id}"
761
+ params: Dict[str, str] = {NEXT_PAGE_ID_TAG: next_page_id} if next_page_id else {}
762
+ async with AsyncServiceAPIClient.__async_session__() as session:
763
+ async with session.get(
764
+ url, headers=headers, params=params, timeout=timeout, verify_ssl=self.verify_calls
765
+ ) as response:
766
+ if response.ok:
767
+ structure: Dict[str, Any] = await response.json(loads=orjson.loads)
768
+ return ErrorLogResponse.from_dict(structure)
769
+ raise await handle_error(f"Retrieving job status for {job_id} failed.", response)
770
+
771
+ async def import_new_uris(
772
+ self,
773
+ job_id: str,
774
+ auth_key: Optional[str] = None,
775
+ next_page_id: Optional[str] = None,
776
+ timeout: int = DEFAULT_TIMEOUT
777
+ ) -> NewEntityUrisResponse:
778
+ """
779
+ Retrieve the new entity uris from the job.
780
+
781
+ Parameters
782
+ ----------
783
+ job_id: str
784
+ ID of the job
785
+ next_page_id: Optional[str] = None
786
+ ID of the next page within pagination.
787
+ auth_key: Optional[str] = None
788
+ If the auth key is set the logged-in user (if any) will be ignored and the auth key will be used.
789
+ timeout: int
790
+ Timeout for the request (default: 60 seconds)
791
+
792
+ Returns
793
+ -------
794
+ response: NewEntityUrisResponse
795
+ New entity uris of the job.
796
+ """
797
+ if auth_key is None:
798
+ auth_key, _ = await self.handle_token()
799
+ headers: dict = {USER_AGENT_HEADER_FLAG: self.user_agent, AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
800
+ url: str = f"{self.service_base_url}{self.IMPORT_ENTITIES_ENDPOINT}/{job_id}/new-entities"
801
+ params: Dict[str, str] = {NEXT_PAGE_ID_TAG: next_page_id} if next_page_id else {}
802
+ async with AsyncServiceAPIClient.__async_session__() as session:
803
+ async with session.get(
804
+ url, headers=headers, params=params, timeout=timeout, verify_ssl=self.verify_calls
805
+ ) as response:
806
+ if response.ok:
807
+ structure: Dict[str, Any] = await response.json(loads=orjson.loads)
808
+ return NewEntityUrisResponse.from_dict(structure)
809
+ raise await handle_error(f"Retrieving job status for {job_id} failed.", response)
810
+
811
+
591
812
  async def update_entity(self, entity: ThingObject, auth_key: Optional[str] = None):
592
813
  """
593
814
  Updates entity in graph.
@@ -1576,6 +1797,8 @@ class AsyncWacomKnowledgeService(AsyncServiceAPIClient):
1576
1797
  content_link="",
1577
1798
  ontology_types=entity_types,
1578
1799
  entity_type=EntityType.PERSONAL_ENTITY,
1800
+ tokens=e.get("tokens"),
1801
+ token_indexes=e.get("tokenIndexes"),
1579
1802
  )
1580
1803
  ne.relevant_type = OntologyClassReference.parse(e["type"])
1581
1804
  named_entities.append(ne)
@@ -575,6 +575,8 @@ class WacomKnowledgeService(WacomServiceAPIClient):
575
575
  if entity.image is not None and entity.image.startswith("file:"):
576
576
  p = urlparse(entity.image)
577
577
  self.set_entity_image_local(uri, Path(p.path), auth_key=auth_key)
578
+ elif entity.image is not None and entity.image.startswith("/"):
579
+ self.set_entity_image_local(uri, Path(entity.image), auth_key=auth_key)
578
580
  elif entity.image is not None and entity.image != "":
579
581
  self.set_entity_image_url(uri, entity.image, auth_key=auth_key)
580
582
  except WacomServiceException as _:
@@ -1879,6 +1881,63 @@ class WacomKnowledgeService(WacomServiceAPIClient):
1879
1881
  return response.json()["jobId"]
1880
1882
  raise handle_error("Import endpoint returns an error.", response)
1881
1883
 
1884
+ def import_entities_from_file(
1885
+ self,
1886
+ file_path: Path,
1887
+ auth_key: Optional[str] = None,
1888
+ timeout: int = DEFAULT_TIMEOUT,
1889
+ max_retries: int = DEFAULT_MAX_RETRIES,
1890
+ backoff_factor: float = DEFAULT_BACKOFF_FACTOR,
1891
+ ) -> str:
1892
+ """Import entities from a file to the graph.
1893
+
1894
+ Parameters
1895
+ ----------
1896
+ file_path: Path
1897
+ Path to the file containing entities in NDJSON format.
1898
+ auth_key: Optional[str] = None
1899
+ If the auth key is set the logged-in user (if any) will be ignored and the auth key will be used.
1900
+ timeout: int
1901
+ Timeout for the request (default: 60 seconds)
1902
+ max_retries: int
1903
+ Maximum number of retries
1904
+ backoff_factor: float
1905
+ A backoff factor to apply between attempts after the second try (most errors are resolved immediately by a
1906
+ second try without a delay)
1907
+
1908
+ Returns
1909
+ -------
1910
+ job_id: str
1911
+ ID of the job
1912
+
1913
+ Raises
1914
+ ------
1915
+ WacomServiceException
1916
+ If the graph service returns an error code.
1917
+ """
1918
+ if not file_path.exists():
1919
+ raise FileNotFoundError(f"The file {file_path} does not exist.")
1920
+ if auth_key is None:
1921
+ auth_key, _ = self.handle_token()
1922
+ headers: dict = {USER_AGENT_HEADER_FLAG: self.user_agent, AUTHORIZATION_HEADER_FLAG: f"Bearer {auth_key}"}
1923
+ with file_path.open("rb") as file:
1924
+ # Compress the NDJSON string to a gzip byte array
1925
+ compressed_data: bytes = file.read()
1926
+ files: List[Tuple[str, Tuple[str, bytes, str]]] = [
1927
+ ("file", ("import.njson.gz", compressed_data, "application/x-gzip"))
1928
+ ]
1929
+ url: str = f"{self.service_base_url}{self.IMPORT_ENTITIES_ENDPOINT}"
1930
+ mount_point: str = "https://" if self.service_url.startswith("https") else "http://"
1931
+ with requests.Session() as session:
1932
+ retries: Retry = Retry(total=max_retries, backoff_factor=backoff_factor, status_forcelist=STATUS_FORCE_LIST)
1933
+ session.mount(mount_point, HTTPAdapter(max_retries=retries))
1934
+ response: Response = session.post(
1935
+ url, headers=headers, files=files, timeout=timeout, verify=self.verify_calls
1936
+ )
1937
+ if response.ok:
1938
+ return response.json()["jobId"]
1939
+ raise handle_error("Import endpoint returns an error.", response)
1940
+
1882
1941
  def job_status(
1883
1942
  self,
1884
1943
  job_id: str,
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "personal_knowledge_library"
3
- version = "3.2.2"
3
+ version = "3.3.1"
4
4
  description = "Library to access Wacom's Personal Knowledge graph."
5
5
  authors = [{ name = "Markus Weber", email = "markus.weber@wacom.com" }]
6
6
  license = "Apache-2.0"