personal_knowledge_library 3.1.1__py3-none-any.whl → 3.2.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.

Potentially problematic release.


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

@@ -0,0 +1,168 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright © 2024-present Wacom. All rights reserved.
3
+ import gzip
4
+ import json
5
+ import logging
6
+ import re
7
+ from json import JSONDecodeError
8
+ from pathlib import Path
9
+ from typing import List, Dict, Any
10
+
11
+ import loguru
12
+
13
+ from knowledge.base.ontology import ThingObject, OntologyPropertyReference
14
+
15
+ logger = loguru.logger
16
+
17
+
18
+ def is_http_url(url: str) -> bool:
19
+ """Check if a string is an HTTP(S) URL.
20
+ Parameters
21
+ ----------
22
+ url: str
23
+ The URL to check.
24
+
25
+ Returns
26
+ -------
27
+ bool
28
+ True if the URL is HTTP(S), False otherwise.
29
+ """
30
+ return bool(re.match(r"^(https?://)", url, re.IGNORECASE))
31
+
32
+
33
+ def is_local_url(url: str) -> bool:
34
+ """Check if a string is a local file path or relative URL.
35
+ Parameters
36
+ ----------
37
+ url: str
38
+ The URL to check.
39
+
40
+ Returns
41
+ -------
42
+ bool
43
+ True if the URL is a local file path or relative URL, False otherwise.
44
+ """
45
+ return bool(re.match(r"^(file://|/|\.{1,2}/)", url, re.IGNORECASE))
46
+
47
+
48
+ def __import_format_to_thing__(line: str) -> ThingObject:
49
+ """
50
+ Convert a line of JSON to a ThingObject.
51
+ Parameters
52
+ ----------
53
+ line: str
54
+ The line of JSON to convert.
55
+
56
+ Returns
57
+ -------
58
+ entity: ThingObject
59
+ The ThingObject created from the JSON line.
60
+
61
+ Raises
62
+ ------
63
+ JSONDecodeError
64
+ If the line is not valid JSON.
65
+ """
66
+ thing_dict: Dict[str, Any] = json.loads(line)
67
+ entity: ThingObject = ThingObject.from_import_dict(thing_dict)
68
+ if entity.image:
69
+ if not is_local_url(entity.image) and not is_http_url(entity.image):
70
+ path: Path = Path(entity.image)
71
+ if not path.exists():
72
+ entity.image = path.absolute().as_uri()
73
+ else:
74
+ logger.warning(f"Image path {path} does not exist. Setting to None.")
75
+ entity.image = None
76
+ remove_props: List[OntologyPropertyReference] = []
77
+ # Remove empty properties
78
+ for obj_prop, value in entity.object_properties.items():
79
+ if len(value.incoming_relations) == 0 and len(value.outgoing_relations) == 0:
80
+ remove_props.append(obj_prop)
81
+ for prop in remove_props:
82
+ del entity.object_properties[prop]
83
+ return entity
84
+
85
+
86
+ def load_import_format(file_path: Path) -> List[ThingObject]:
87
+ """
88
+ Load the import format file.
89
+ Parameters
90
+ ----------
91
+ file_path: Path
92
+ The path to the file.
93
+
94
+ Returns
95
+ -------
96
+ entity_list: List[ThingObject]
97
+ The list of entities.
98
+
99
+ Raises
100
+ ------
101
+ FileNotFoundError
102
+ If the file does not exist or is not a file.
103
+ """
104
+ if not file_path.exists():
105
+ logger.error(f"File {file_path} does not exist.")
106
+ raise FileNotFoundError(f"File {file_path} does not exist.")
107
+ if not file_path.is_file():
108
+ logger.error(f"Path {file_path} is not a file.")
109
+ raise FileNotFoundError(f"Path {file_path} is not a file.")
110
+ cached_entities: List[ThingObject] = []
111
+ if file_path.suffix == ".gz":
112
+ with gzip.open(file_path, "rt", encoding="utf-8") as f_gz:
113
+ for line_number, line in enumerate(f_gz):
114
+ stripped_line: str = line.strip()
115
+ if not stripped_line:
116
+ continue # Skip empty lines
117
+ if line_number == 0:
118
+ # Skip the first line (header)
119
+ continue
120
+ try:
121
+ cached_entities.append(__import_format_to_thing__(line))
122
+ except JSONDecodeError as e:
123
+ logging.error(f"Error decoding JSON: {e}. Line: {line}")
124
+ else:
125
+ with file_path.open(encoding="utf8") as f:
126
+ # Skip the first line
127
+ for line in f.readlines():
128
+ try:
129
+ cached_entities.append(__import_format_to_thing__(line))
130
+ except JSONDecodeError as e:
131
+ logging.error(f"Error decoding JSON: {e}. Line: {line}")
132
+ return cached_entities
133
+
134
+
135
+ def save_import_format(file_path: Path, entities: List[ThingObject]) -> None:
136
+ """
137
+ Save the import format file.
138
+ Parameters
139
+ ----------
140
+ file_path: Path
141
+ The path to the file.
142
+ entities: List[ThingObject]
143
+ The list of entities.
144
+ """
145
+ # Create the directory if it does not exist
146
+ file_path.parent.mkdir(parents=True, exist_ok=True)
147
+ if file_path.suffix == ".gz":
148
+ with gzip.open(file_path, "wt", encoding="utf-8") as fp_thing:
149
+ for entity in entities:
150
+ fp_thing.write(f"{json.dumps(entity.__import_format_dict__(), ensure_ascii=False)}\n")
151
+ elif file_path.suffix == ".ndjson":
152
+ with file_path.open("w", encoding="utf-8") as fp_thing:
153
+ for entity in entities:
154
+ fp_thing.write(f"{json.dumps(entity.__import_format_dict__(), ensure_ascii=False)}\n")
155
+
156
+
157
+ def append_import_format(file_path: Path, entity: ThingObject) -> None:
158
+ """
159
+ Append to the import format file.
160
+ Parameters
161
+ ----------
162
+ file_path: Path
163
+ The path to the file.
164
+ entity: ThingObject
165
+ The entity to append.
166
+ """
167
+ with file_path.open("a", encoding="utf-8") as fp_thing:
168
+ fp_thing.write(f"{json.dumps(entity.__import_format_dict__(), ensure_ascii=False)}\n")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: personal_knowledge_library
3
- Version: 3.1.1
3
+ Version: 3.2.0
4
4
  Summary: Library to access Wacom's Personal Knowledge graph.
5
5
  License: Apache-2.0
6
6
  Keywords: semantic-knowledge,knowledge-graph
@@ -1,43 +1,46 @@
1
- knowledge/__init__.py,sha256=UL4La2Ep9cXbMd4imaLqt6UCqBhjLjusWHDZXU8Pc8s,2680
2
- knowledge/base/__init__.py,sha256=q0NJRQLhfZ8khE-uZCK0SVA38dzbaMomcgL5Olnjtio,895
1
+ knowledge/__init__.py,sha256=xx1SZgmFpjbHD3ZgpA9Bdbh5YaadA-vu2Y6MPsu6rvY,2680
2
+ knowledge/base/__init__.py,sha256=rgAcl0azO6eoVk1gK9z0UFNlTHj3AN88k6LG-GdATFk,1079
3
3
  knowledge/base/access.py,sha256=BSh-6QbeHOCu55XTxA-p3DwEyRzgtN8TSxtcn6UvmZo,4411
4
4
  knowledge/base/entity.py,sha256=b-Ana_H_WI2-AT_n-V_HzUL6W9Ri16DcZFS3q4ziI94,8445
5
- knowledge/base/language.py,sha256=QHNafhiwg9UPaQS1svzsSz7T2L-VAKlQwd1n5w0HaI8,1500
6
- knowledge/base/ontology.py,sha256=-v5g_0H-naeGBbYDDRenm0rTvkGFnW9ZWPdYK7xqwZs,95395
5
+ knowledge/base/language.py,sha256=L4VAKRuFRQxE0BfzxkQUeChyhvLKoZM7ooqxm0dACO4,1478
6
+ knowledge/base/ontology.py,sha256=UMgJS2QVBskOiTFYbjNUxx1tY3jJZV-STF3UYf4ofKM,95435
7
+ knowledge/base/response.py,sha256=dqdskdcjKnM142nX_8sDVs8v7xTQjiVY1MqJCI-Dfkc,10918
7
8
  knowledge/base/search.py,sha256=J1PSVpTU2JKF9xSZLZZvAbJfFy1HiMPJRzPjHhR7IQM,14722
8
9
  knowledge/base/tenant.py,sha256=f2Z_LjUcjIt5J2_Rse9aQyTzJ0sSyVvCzlm8PP3PqY8,6084
9
10
  knowledge/nel/__init__.py,sha256=eTT88LV_KQ-Ku-a4RnTv_TUCNogl357ui4KT1pEKMuQ,330
10
11
  knowledge/nel/base.py,sha256=bsUj9PwoZoJWW33RfoYmQHbFhArKH1kMOsDgU3yj0T8,15032
11
12
  knowledge/nel/engine.py,sha256=qvQkfsdeYPWJ_5m8mmGFw1tvd699vOQ3IKoBIwALRWk,5347
12
- knowledge/ontomapping/__init__.py,sha256=9E-rZpxQPfukjDz_0ymrRieYDpv_e3tvpqDfkWzPJy0,18846
13
+ knowledge/ontomapping/__init__.py,sha256=u_t6i5a6pYYnf43Q_S6sG7NRLeGuKmahIHW6TFGHqOk,18848
13
14
  knowledge/ontomapping/manager.py,sha256=pXBwRGSTcS731df5vewNv6oMgP18HzvnjZqiUgyFIhI,13361
14
15
  knowledge/public/__init__.py,sha256=FrW5sqJGVcIfg5IVpt_g7qlWiIYNGA370jkE5mJDhoo,812
15
16
  knowledge/public/cache.py,sha256=uKEuW9WN9xPmY-fwWPLSxmdEP6xg-XG3g8fKAmGZgBQ,14510
16
- knowledge/public/client.py,sha256=KA8EwLHAjn1-ggT8keUMaKIJnbJDlFEp0j8V0RT_32I,15437
17
+ knowledge/public/client.py,sha256=7Z-nYhYIni_jKDWJw18CvuUxuOCns74l8XjeEEJXl_Y,15437
17
18
  knowledge/public/helper.py,sha256=PDsInMHMHgP8rMvcFk5E47afdE3rC7V3BzPS-DdOsww,13238
18
19
  knowledge/public/relations.py,sha256=DrL-rYuwLzaE2H2TOM2gG1TGqHbkcPL4EsRD54LQqLs,4182
19
20
  knowledge/public/wikidata.py,sha256=LwMP2kq2mH5Oi9JhPvG8lN9pZMDlQvxgaZgQKQO3kaM,36683
20
- knowledge/services/__init__.py,sha256=FQMTLg7RYglLwCtEO0sOrgj55YrzSNqJV-yj3aqttb8,3490
21
+ knowledge/services/__init__.py,sha256=Pg4Pd9cCRiQ4-v3E0WCqldOhJFcMmkZrQHA7BY1Z1K8,3604
21
22
  knowledge/services/asyncio/__init__.py,sha256=dq9yGTxg_hoQb8E1kEtY4AeB8zrdJfw3-XlPoYn2j5U,225
22
23
  knowledge/services/asyncio/base.py,sha256=im6J1CWOp1N1tt6WdJ1uU0R-VFpvdYc6lZu8TyPrU5A,16222
23
- knowledge/services/asyncio/graph.py,sha256=ix3_JzTBlN4dTFH2UlGkB956U8S0T5qQz7o3ZgTmvaU,57551
24
+ knowledge/services/asyncio/graph.py,sha256=BRU8kLgKt7KNuyzlgT2PEVwa7ig-S-sR0AWMTYkp5NE,62401
24
25
  knowledge/services/asyncio/group.py,sha256=UKbk8vnPqqAkuc5gAd6g3IVOKmUJNqG2lreZM0O-hRg,18356
25
26
  knowledge/services/asyncio/search.py,sha256=_ESVbNGLYbo7EmyMLtsh0pRiRHIyGeBicrcD2JKbFwY,16215
26
27
  knowledge/services/asyncio/users.py,sha256=NJ7xagjr4gF6yKJXdwa0bz0eaYlQDee5RCEpfQJEHWk,10274
27
28
  knowledge/services/base.py,sha256=gXBIkbk7wXGrm_hZGfLvft7-E8fcSMjl-HIsLxfRZ6c,17849
28
- knowledge/services/graph.py,sha256=lYMiLC9ArtSj9ZI-pNQYLI2H7-AgrbjIyhs_y_FQrDY,77104
29
+ knowledge/services/graph.py,sha256=XhbB2-3CUkQ9-NdVoW9pcQfnItaX6H07WVTsK3ynZ5I,86888
29
30
  knowledge/services/group.py,sha256=b8dBBrHXqgwpJ7BtUqqweoR_WQH5MZ0aLh0fBBTyHUI,30698
30
31
  knowledge/services/helper.py,sha256=NYhRkYXtiFgovsXaQr6rBVN2mjBwOT7cSSuLTyjvzKA,4990
31
32
  knowledge/services/ontology.py,sha256=u89S3GV0C2FWAviQxd5fvoCQWzo8EhYix7fQc1bEEc0,51534
32
- knowledge/services/search.py,sha256=atwvcqagA6yZkzKiad6Yjn3cKu7L5LpKiVJsxKKOY5g,19131
33
+ knowledge/services/search.py,sha256=-qB9J1pyqoq3RlH7iDlgozBImKFzTx1p1kC0XKWAPEs,19147
33
34
  knowledge/services/session.py,sha256=y8uTETRMDOBbC30UAlrrtWTN7Zgs2klqHsoMjLO2tq0,14145
34
- knowledge/services/tenant.py,sha256=4pyQCYlwvREfmRcXRn47irIsFMCia_c-LVvFysDypkI,11691
35
- knowledge/services/users.py,sha256=uus66ijd1OAN-gJqP95zmhDL31xje3gHBfF4rMnMjM0,16436
36
- knowledge/utils/__init__.py,sha256=rgLqdgZwjuCnqA4NEY9echbGFaJ5YUhqBEkyVv9R9CM,255
35
+ knowledge/services/tenant.py,sha256=rQsUe8qNFTt_WZG4XBTg8QSLoyavuCWLWk3QhU1fBG8,11728
36
+ knowledge/services/users.py,sha256=nOwyZhqERTNFPTN21c_q7-6XaEMb3SnHfnXr4Kf22qk,16594
37
+ knowledge/utils/__init__.py,sha256=7unsBV5ge6eIyicKCIc_C4OroD-zkKRMVE0jXcH6EOw,313
38
+ knowledge/utils/diff.py,sha256=HrU03qGvkirPqC0vRRZRLA49eI08o-JI3dcHS5-uv4g,26647
37
39
  knowledge/utils/graph.py,sha256=kuPZEGhexVN9McoT8JK2ViIrfXTh-nFPv_8XPfG0wlA,12318
40
+ knowledge/utils/import_format.py,sha256=fjuWpd91eAs7MbqSpLrFgdRvFaHK0nzV1L83ByjTmV0,5277
38
41
  knowledge/utils/wikidata.py,sha256=vRH-4AMR-3xywyvmDqbjI4KSw4tF4TEYqUGCJmUMqK8,5512
39
42
  knowledge/utils/wikipedia.py,sha256=rBuFqYVM58JCj5ISLxuhYVVl2gOIlPLWx7_CghyQgvE,5052
40
- personal_knowledge_library-3.1.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
41
- personal_knowledge_library-3.1.1.dist-info/METADATA,sha256=kJZ15MOIszkwgs8hv6YMnKXLc0RKNyFfYz9X4r1l6f0,57087
42
- personal_knowledge_library-3.1.1.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
43
- personal_knowledge_library-3.1.1.dist-info/RECORD,,
43
+ personal_knowledge_library-3.2.0.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
44
+ personal_knowledge_library-3.2.0.dist-info/METADATA,sha256=4RhzFCxjAyhFmnRavgdpwY5x-9PWs9p08tEqd9j1f6U,57087
45
+ personal_knowledge_library-3.2.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
46
+ personal_knowledge_library-3.2.0.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 2.1.1
2
+ Generator: poetry-core 2.1.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any