ricgraph 3.1__tar.gz → 3.3__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.
- {ricgraph-3.1/ricgraph.egg-info → ricgraph-3.3}/PKG-INFO +1 -1
- {ricgraph-3.1 → ricgraph-3.3}/README.md +34 -54
- {ricgraph-3.1 → ricgraph-3.3}/pyproject.toml +1 -1
- {ricgraph-3.1 → ricgraph-3.3}/ricgraph/ricgraph.py +47 -38
- {ricgraph-3.1 → ricgraph-3.3}/ricgraph/ricgraph_cache.py +45 -32
- ricgraph-3.3/ricgraph/ricgraph_constants.py +454 -0
- {ricgraph-3.1 → ricgraph-3.3}/ricgraph/ricgraph_cypher.py +464 -292
- {ricgraph-3.1 → ricgraph-3.3}/ricgraph/ricgraph_file.py +77 -36
- {ricgraph-3.1 → ricgraph-3.3}/ricgraph/ricgraph_graphdb.py +133 -90
- ricgraph-3.3/ricgraph/ricgraph_harvest.py +608 -0
- {ricgraph-3.1 → ricgraph-3.3}/ricgraph/ricgraph_researchinfo.py +45 -23
- {ricgraph-3.1 → ricgraph-3.3}/ricgraph/ricgraph_restapi.py +1 -1
- {ricgraph-3.1 → ricgraph-3.3}/ricgraph/ricgraph_utils.py +390 -21
- {ricgraph-3.1 → ricgraph-3.3/ricgraph.egg-info}/PKG-INFO +1 -1
- ricgraph-3.1/ricgraph/ricgraph_constants.py +0 -190
- ricgraph-3.1/ricgraph/ricgraph_harvest.py +0 -176
- {ricgraph-3.1 → ricgraph-3.3}/LICENSE +0 -0
- {ricgraph-3.1 → ricgraph-3.3}/README-PyPI.md +0 -0
- {ricgraph-3.1 → ricgraph-3.3}/ricgraph/__init__.py +0 -0
- {ricgraph-3.1 → ricgraph-3.3}/ricgraph.egg-info/SOURCES.txt +0 -0
- {ricgraph-3.1 → ricgraph-3.3}/ricgraph.egg-info/dependency_links.txt +0 -0
- {ricgraph-3.1 → ricgraph-3.3}/ricgraph.egg-info/requires.txt +0 -0
- {ricgraph-3.1 → ricgraph-3.3}/ricgraph.egg-info/top_level.txt +0 -0
- {ricgraph-3.1 → ricgraph-3.3}/setup.cfg +0 -0
|
@@ -23,7 +23,9 @@ We use color=#4c1 (green), that color is used by the 'repo status' badge.
|
|
|
23
23
|
Documentation about the Podman badges can be found here: https://github.com/eggplants/ghcr-badge.
|
|
24
24
|
--->
|
|
25
25
|
|
|
26
|
-
>
|
|
26
|
+
> [Use Ricgraph](https://www.ricgraph.eu/pilot-project-open-ricgraph-demo-server.html).
|
|
27
|
+
> [Read news about Ricgraph](https://www.ricgraph.eu/ricgraph-news.html).
|
|
28
|
+
> Read the [Tutorial](https://docs.ricgraph.eu/docs/ricgraph_tutorial.html).
|
|
27
29
|
> Go to the [Documentation website](https://docs.ricgraph.eu).
|
|
28
30
|
> Consult the [Table of contents](docs/ricgraph_toc_documentation.md#table-of-contents-ricgraph-documentation),
|
|
29
31
|
> or the [Index](docs/ricgraph_index_documentation.md#index-ricgraph-documentation).
|
|
@@ -57,57 +59,32 @@ adapted to new application areas.
|
|
|
57
59
|
Throughout this documentation, we illustrate how Ricgraph works by applying
|
|
58
60
|
it to the application area research information.
|
|
59
61
|
|
|
60
|
-
## Ricgraph
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
and then insert (enrich) those items into Pure.
|
|
87
|
-
The result is a more complete overview of research at that organization.
|
|
88
|
-
Status: experimental stage (beta).
|
|
89
|
-
* A chatbot that allows you to "talk" to Ricgraph. You can formulate questions in
|
|
90
|
-
plain English, such as "Please give me the research results of the Geosciences
|
|
91
|
-
faculty of Utrecht University?"
|
|
92
|
-
or "With what organizations does that faculty collaborate?".
|
|
93
|
-
It uses a local Large Language Model.
|
|
94
|
-
Status: planning stage (pre-alpha).
|
|
95
|
-
* A project with six students from the University of Applied Sciences, Utrecht, that aims to
|
|
96
|
-
[create a general harvester for
|
|
97
|
-
Ricgraph](docs/ricgraph_outreach.md#ricgraph-projects-with-students).
|
|
98
|
-
It will remove a lot of code duplication in the harvest scripts, and will
|
|
99
|
-
make it easier to add new harvest sources.
|
|
100
|
-
Status: planning stage (pre-alpha).
|
|
101
|
-
* A project with a student from the University of Applied Sciences, Utrecht, that aims to use
|
|
102
|
-
[AI and Large Language Models to find topics and visualize large amounts of research
|
|
103
|
-
information](docs/ricgraph_outreach.md#ricgraph-projects-with-students).
|
|
104
|
-
It assigns *topics* to publications,
|
|
105
|
-
data sets, and software. By selecting a number of topics, research results are
|
|
106
|
-
grouped, and possibly experts on these topics can be found.
|
|
107
|
-
Status: planning stage (pre-alpha).
|
|
108
|
-
* A tool that helps Pure administrators to clean up "external organizations" in Pure.
|
|
109
|
-
Status: planning stage (pre-alpha).
|
|
110
|
-
|
|
62
|
+
## Ricgraph introduction videos
|
|
63
|
+
|
|
64
|
+
You may want to watch the following videos about Ricgraph. The left one is a
|
|
65
|
+
short video, only including the Ricgraph use cases. The right one is a more
|
|
66
|
+
extensive one (also including the use cases).
|
|
67
|
+
|
|
68
|
+
<table>
|
|
69
|
+
<tr>
|
|
70
|
+
<td style="width:50%;"><b>Ricgraph use cases video (1m30s)</b></td>
|
|
71
|
+
<td style="width:50%;"><b>Ricgraph introduction video including use cases (2m28s)</b></td>
|
|
72
|
+
</tr>
|
|
73
|
+
<tr>
|
|
74
|
+
<td><video src="docs/videos/ricgraph_usecases.mp4" controls width="90%">Ricgraph use cases video (1m30s)</video></td>
|
|
75
|
+
<td><video src="docs/videos/ricgraph_intro_usecases.mp4" controls width="90%">Ricgraph introduction video including use cases (2m28s)</video></td>
|
|
76
|
+
</tr>
|
|
77
|
+
<tr>
|
|
78
|
+
<td>
|
|
79
|
+
<a href="https://docs.ricgraph.eu/docs/videos/ricgraph_usecases.mp4" target="_blank">
|
|
80
|
+
Click to play or download the Ricgraph use cases video</a>.
|
|
81
|
+
</td>
|
|
82
|
+
<td>
|
|
83
|
+
<a href="https://docs.ricgraph.eu/docs/videos/ricgraph_intro_usecases.mp4" target="_blank">
|
|
84
|
+
Click to play or download the Ricgraph introduction video</a>.
|
|
85
|
+
</td>
|
|
86
|
+
</tr>
|
|
87
|
+
</table>
|
|
111
88
|
|
|
112
89
|
## Motivation
|
|
113
90
|
|
|
@@ -321,6 +298,8 @@ The following figure shows how three persons have contributed to one research ou
|
|
|
321
298
|
|
|
322
299
|
* Explore the full documentation of Ricgraph on
|
|
323
300
|
[https://docs.ricgraph.eu](https://docs.ricgraph.eu).
|
|
301
|
+
* Play the [Ricgraph use cases video](docs/videos/ricgraph_usecases.mp4), or the
|
|
302
|
+
[Ricgraph introduction video](docs/videos/ricgraph_intro_usecases.mp4).
|
|
324
303
|
* For a gentle introduction in Ricgraph, read the reference publication:
|
|
325
304
|
Rik D.T. Janssen (2024). *Ricgraph: A flexible and extensible graph to explore research in
|
|
326
305
|
context from various systems*. SoftwareX, 26(101736).
|
|
@@ -374,7 +353,8 @@ The following figure shows how three persons have contributed to one research ou
|
|
|
374
353
|
|
|
375
354
|
### Steps to take if you would like to use Ricgraph
|
|
376
355
|
|
|
377
|
-
* Use
|
|
356
|
+
* [Use Ricgraph](https://www.ricgraph.eu/pilot-project-open-ricgraph-demo-server.html).
|
|
357
|
+
* Read more about [Ricgraph Explorer](docs/ricgraph_explorer.md#ricgraph-explorer),
|
|
378
358
|
the exploration tool for Ricgraph.
|
|
379
359
|
* Use the [Ricgraph REST API](docs/ricgraph_restapi.md#ricgraph-rest-api),
|
|
380
360
|
the REST API for Ricgraph.
|
|
@@ -420,4 +400,4 @@ please let me know by creating a GitHub *Issue* at the top left of that page.
|
|
|
420
400
|
<!-- Do not change the lines below. The version number will be
|
|
421
401
|
modified by script maintenance/update_version.bash -->
|
|
422
402
|
This README.md file is part of the
|
|
423
|
-
documentation for version 3.
|
|
403
|
+
documentation for version 3.3 of Ricgraph - Research in context graph.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
#
|
|
7
7
|
# MIT License
|
|
8
8
|
#
|
|
9
|
-
# Copyright (c) 2023
|
|
9
|
+
# Copyright (c) 2023 - 2026 Rik D.T. Janssen
|
|
10
10
|
#
|
|
11
11
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
12
12
|
# of this software and associated documentation files (the "Software"), to deal
|
|
@@ -90,7 +90,7 @@ In the default configuration of Ricgraph, the following properties are included:
|
|
|
90
90
|
|
|
91
91
|
- url_other: other URL for a node, pointing to e.g. the originating record in a source system.
|
|
92
92
|
|
|
93
|
-
- year: year of a research
|
|
93
|
+
- year: year of a research result.
|
|
94
94
|
|
|
95
95
|
- source_event: an event to be added to the _source list.
|
|
96
96
|
|
|
@@ -100,15 +100,19 @@ In the default configuration of Ricgraph, the following properties are included:
|
|
|
100
100
|
|
|
101
101
|
from numpy import nan
|
|
102
102
|
from pandas import DataFrame, concat, set_option
|
|
103
|
-
|
|
104
|
-
from .
|
|
103
|
+
|
|
104
|
+
from .ricgraph_constants import PERSON_CATEGORY_PERSON
|
|
105
|
+
from .ricgraph_utils import (timestamp, timestamp_posix,
|
|
106
|
+
print_records_per_minute,
|
|
107
|
+
print_progress)
|
|
105
108
|
from .ricgraph_graphdb import (create_update_node, create_two_nodes_and_edge,
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
get_ricgraph_nodeadd_mode,
|
|
110
|
+
get_ricgraph_properties_standard,
|
|
111
|
+
get_ricgraph_properties_additional)
|
|
108
112
|
|
|
109
113
|
|
|
110
114
|
__author__ = 'Rik D.T. Janssen'
|
|
111
|
-
__copyright__ = 'Copyright (c) 2023
|
|
115
|
+
__copyright__ = 'Copyright (c) 2023 - 2026 Rik D.T. Janssen'
|
|
112
116
|
__email__ = ''
|
|
113
117
|
__license__ = 'MIT License'
|
|
114
118
|
__package__ = 'Ricgraph'
|
|
@@ -116,7 +120,7 @@ __package__ = 'Ricgraph'
|
|
|
116
120
|
# __version__ should be placed here instead of in __init__.py.
|
|
117
121
|
# If not here, it cannot be found when executing something like
|
|
118
122
|
# PYTHONPATH=../ricgraph ../bin/python ricgraph_explorer.py
|
|
119
|
-
__version__ = '3.
|
|
123
|
+
__version__ = '3.3'
|
|
120
124
|
|
|
121
125
|
|
|
122
126
|
# ##############################################################################
|
|
@@ -148,30 +152,31 @@ def update_nodes_df(nodes: DataFrame) -> None:
|
|
|
148
152
|
nodes_clean.drop_duplicates(keep='first', inplace=True, ignore_index=True)
|
|
149
153
|
|
|
150
154
|
print('There are ' + str(len(nodes_clean)) + ' nodes ('
|
|
151
|
-
+ timestamp() + '), updating node:
|
|
155
|
+
+ timestamp() + '), updating node:')
|
|
152
156
|
count = 0
|
|
157
|
+
start_ts = timestamp_posix()
|
|
153
158
|
columns = nodes_clean.columns
|
|
154
159
|
for row in nodes_clean.itertuples():
|
|
155
|
-
count
|
|
156
|
-
if count % 250 == 0:
|
|
157
|
-
print(count, ' ', end='', flush=True)
|
|
158
|
-
if count % 2500 == 0:
|
|
159
|
-
print('(' + timestamp() + ')\n', end='', flush=True)
|
|
160
|
-
|
|
160
|
+
count = print_progress(count=count, interval=250)
|
|
161
161
|
node_properties = {}
|
|
162
|
-
for prop_name in
|
|
162
|
+
for prop_name in get_ricgraph_properties_additional():
|
|
163
163
|
for other_name in columns:
|
|
164
164
|
if prop_name == other_name:
|
|
165
165
|
node_properties[prop_name] = getattr(row, other_name)
|
|
166
166
|
|
|
167
|
-
create_update_node(name=row.name, category=row.category,
|
|
167
|
+
create_update_node(name=str(row.name), category=str(row.category),
|
|
168
|
+
value=str(row.value),
|
|
168
169
|
other_properties=node_properties)
|
|
169
170
|
|
|
170
|
-
|
|
171
|
+
print_progress(count=count, now=True)
|
|
172
|
+
end_ts = timestamp_posix()
|
|
173
|
+
print_records_per_minute(start_ts=start_ts, end_ts=end_ts,
|
|
174
|
+
nr_records=count,
|
|
175
|
+
what='Updated')
|
|
171
176
|
return
|
|
172
177
|
|
|
173
178
|
|
|
174
|
-
def create_nodepairs_and_edges_df(left_and_right_nodepairs: DataFrame) -> None:
|
|
179
|
+
def create_nodepairs_and_edges_df(left_and_right_nodepairs: DataFrame | None) -> None:
|
|
175
180
|
"""Create two nodes (called 'node pairs') and two directed edges between those nodes.
|
|
176
181
|
This is done for all the nodes passed. The nodes are specified in a DataFrame.
|
|
177
182
|
One row in the DataFrame contains two nodes which are to be connected.
|
|
@@ -183,19 +188,17 @@ def create_nodepairs_and_edges_df(left_and_right_nodepairs: DataFrame) -> None:
|
|
|
183
188
|
:param left_and_right_nodepairs: the node pairs in a DataFrame.
|
|
184
189
|
:return: None.
|
|
185
190
|
"""
|
|
191
|
+
if left_and_right_nodepairs is None or left_and_right_nodepairs.empty:
|
|
192
|
+
return
|
|
186
193
|
print('There are ' + str(len(left_and_right_nodepairs)) + ' rows ('
|
|
187
|
-
+ timestamp() + '), creating nodes and edges for row:
|
|
194
|
+
+ timestamp() + '), creating nodes and edges for row:')
|
|
188
195
|
count = 0
|
|
196
|
+
start_ts = timestamp_posix()
|
|
189
197
|
columns = left_and_right_nodepairs.columns
|
|
190
198
|
for row in left_and_right_nodepairs.itertuples():
|
|
191
|
-
count
|
|
192
|
-
if count % 250 == 0:
|
|
193
|
-
print(count, ' ', end='', flush=True)
|
|
194
|
-
if count % 2500 == 0:
|
|
195
|
-
print('(' + timestamp() + ')\n', end='', flush=True)
|
|
196
|
-
|
|
199
|
+
count = print_progress(count=count, interval=250)
|
|
197
200
|
node_properties = {}
|
|
198
|
-
for prop_name in
|
|
201
|
+
for prop_name in get_ricgraph_properties_additional():
|
|
199
202
|
for other_name in columns:
|
|
200
203
|
if prop_name + '1' == other_name:
|
|
201
204
|
node_properties[prop_name + '1'] = getattr(row, other_name)
|
|
@@ -203,16 +206,22 @@ def create_nodepairs_and_edges_df(left_and_right_nodepairs: DataFrame) -> None:
|
|
|
203
206
|
if prop_name + '2' == other_name:
|
|
204
207
|
node_properties[prop_name + '2'] = getattr(row, other_name)
|
|
205
208
|
|
|
206
|
-
create_two_nodes_and_edge(name1=row.name1, category1=row.category1,
|
|
207
|
-
|
|
209
|
+
create_two_nodes_and_edge(name1=str(row.name1), category1=str(row.category1),
|
|
210
|
+
value1=str(row.value1),
|
|
211
|
+
name2=str(row.name2), category2=str(row.category2),
|
|
212
|
+
value2=str(row.value2),
|
|
208
213
|
**node_properties)
|
|
209
|
-
|
|
214
|
+
print_progress(count=count, now=True)
|
|
215
|
+
end_ts = timestamp_posix()
|
|
216
|
+
print_records_per_minute(start_ts=start_ts, end_ts=end_ts,
|
|
217
|
+
nr_records=count,
|
|
218
|
+
what='Created')
|
|
210
219
|
return
|
|
211
220
|
|
|
212
221
|
|
|
213
|
-
def create_nodepairs_and_edges_params(name1:
|
|
214
|
-
name2:
|
|
215
|
-
**other_properties:
|
|
222
|
+
def create_nodepairs_and_edges_params(name1: dict | str, category1: dict | str, value1: dict | str,
|
|
223
|
+
name2: dict | str, category2: dict | str, value2: dict | str,
|
|
224
|
+
**other_properties: dict | str) -> None:
|
|
216
225
|
"""Create two nodes (called 'node pairs') and two directed edges between those nodes.
|
|
217
226
|
This is done for all the nodes passed. The nodes are specified by values passed to this function.
|
|
218
227
|
Each value can be either a string or a dict containing strings.
|
|
@@ -242,7 +251,7 @@ def create_nodepairs_and_edges_params(name1: Union[dict, str], category1: Union[
|
|
|
242
251
|
left_and_right_nodepairs.rename(columns={value1.name: 'value1'}, inplace=True)
|
|
243
252
|
|
|
244
253
|
# This makes programming more efficient
|
|
245
|
-
allowed_properties =
|
|
254
|
+
allowed_properties = get_ricgraph_properties_additional() + get_ricgraph_properties_standard()
|
|
246
255
|
ext_other_properties = other_properties.copy()
|
|
247
256
|
ext_other_properties['name1'] = name1
|
|
248
257
|
ext_other_properties['name2'] = name2
|
|
@@ -281,7 +290,7 @@ def create_nodepairs_and_edges_params(name1: Union[dict, str], category1: Union[
|
|
|
281
290
|
|
|
282
291
|
|
|
283
292
|
def unify_personal_identifiers(personal_identifiers: DataFrame,
|
|
284
|
-
source_event:
|
|
293
|
+
source_event: dict | str, history_event: dict | str) -> None:
|
|
285
294
|
"""Unify a collection of personal identifiers (e.g. ORCID, ISNI, etc.).
|
|
286
295
|
That means that every column is unified to every other column.
|
|
287
296
|
The identifiers are specified as columns in a DataFrame.
|
|
@@ -310,7 +319,7 @@ def unify_personal_identifiers(personal_identifiers: DataFrame,
|
|
|
310
319
|
identifiers.dropna(axis=0, how='any', inplace=True)
|
|
311
320
|
identifiers.drop_duplicates(keep='first', inplace=True, ignore_index=True)
|
|
312
321
|
|
|
313
|
-
if
|
|
322
|
+
if get_ricgraph_nodeadd_mode() == 'strict':
|
|
314
323
|
# Remove rows which have a cell value that occurs more than once.
|
|
315
324
|
# There are two situations: (1) nodes with unique value; (2) nodes with non-unique value.
|
|
316
325
|
# (1) We assume that in one source system, always the same ID is used to connect to
|
|
@@ -339,9 +348,9 @@ def unify_personal_identifiers(personal_identifiers: DataFrame,
|
|
|
339
348
|
identifiers.rename(columns={column1: 'value1',
|
|
340
349
|
column2: 'value2'}, inplace=True)
|
|
341
350
|
new_identifiers_columns = {'name1': column1,
|
|
342
|
-
'category1':
|
|
351
|
+
'category1': PERSON_CATEGORY_PERSON,
|
|
343
352
|
'name2': column2,
|
|
344
|
-
'category2':
|
|
353
|
+
'category2': PERSON_CATEGORY_PERSON,
|
|
345
354
|
'source_event1': source_event,
|
|
346
355
|
'history_event1': history_event,
|
|
347
356
|
'source_event2': source_event,
|
|
@@ -43,10 +43,10 @@
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
from sys import getsizeof
|
|
46
|
-
from typing import Optional
|
|
46
|
+
from typing import Optional, Tuple
|
|
47
47
|
from pymemcache.client.base import Client
|
|
48
48
|
from .ricgraph_constants import MAX_NODES_CACHE_KEY_ID
|
|
49
|
-
from .ricgraph_utils import (
|
|
49
|
+
from .ricgraph_utils import (get_configfile_key_memcached_parameters,
|
|
50
50
|
serialize_value, deserialize_value)
|
|
51
51
|
|
|
52
52
|
|
|
@@ -70,19 +70,21 @@ def memcached_open_connection() -> None:
|
|
|
70
70
|
If Memcached is not available, then return None.
|
|
71
71
|
Set the Memcached client in a global variable.
|
|
72
72
|
"""
|
|
73
|
-
global _MEMCACHED_HOST, _MEMCACHED_PORT
|
|
74
73
|
global _memcached_available, _memcached_client
|
|
75
74
|
|
|
76
|
-
|
|
75
|
+
memcached_to_be_used, memcached_host, memcached_port = get_configfile_key_memcached_parameters()
|
|
76
|
+
if memcached_to_be_used:
|
|
77
|
+
_memcached_available = True
|
|
78
|
+
else:
|
|
77
79
|
_memcached_available = False
|
|
78
80
|
return
|
|
79
81
|
|
|
80
|
-
if
|
|
82
|
+
if memcached_host == '':
|
|
81
83
|
_memcached_available = False
|
|
82
84
|
return
|
|
83
85
|
|
|
84
86
|
try:
|
|
85
|
-
memcached_client = Client(server=(
|
|
87
|
+
memcached_client = Client(server=(memcached_host, memcached_port),
|
|
86
88
|
allow_unicode_keys=True)
|
|
87
89
|
|
|
88
90
|
# Test connection by setting and deleting a test key.
|
|
@@ -93,6 +95,8 @@ def memcached_open_connection() -> None:
|
|
|
93
95
|
_memcached_client = memcached_client
|
|
94
96
|
return
|
|
95
97
|
except:
|
|
98
|
+
print('memcached_open_connection(): Warning: could not reach Memcached cache daemon,')
|
|
99
|
+
print(' it is probably not running, continuing with local cache.')
|
|
96
100
|
_memcached_available = False
|
|
97
101
|
_memcached_client = None
|
|
98
102
|
return
|
|
@@ -122,12 +126,14 @@ def nodes_cache_key_id_create(key: str, elementid: str) -> None:
|
|
|
122
126
|
:param elementid: id of a node.
|
|
123
127
|
:return: None.
|
|
124
128
|
"""
|
|
125
|
-
global _nodes_cache_key_id, _memcached_available
|
|
129
|
+
global _nodes_cache_key_id, _memcached_available, _memcached_client
|
|
126
130
|
|
|
127
131
|
if key == '' or elementid == '':
|
|
128
132
|
return
|
|
129
133
|
|
|
130
134
|
if memcached_check_available():
|
|
135
|
+
if _memcached_client is None:
|
|
136
|
+
return
|
|
131
137
|
# The docs are unclear whether I need to serialize the key if I
|
|
132
138
|
# use flag allow_unicode_keys=True in Client() above.
|
|
133
139
|
# So I do serialize to be sure. Since keys cannot have spaces,
|
|
@@ -163,12 +169,14 @@ def nodes_cache_key_id_read(key: str) -> str:
|
|
|
163
169
|
:param key: _key of a node.
|
|
164
170
|
:return: The id of the node, or '' if not present.
|
|
165
171
|
"""
|
|
166
|
-
global _nodes_cache_key_id, _memcached_available
|
|
172
|
+
global _nodes_cache_key_id, _memcached_available, _memcached_client
|
|
167
173
|
|
|
168
174
|
if key == '':
|
|
169
175
|
return ''
|
|
170
176
|
|
|
171
177
|
if memcached_check_available():
|
|
178
|
+
if _memcached_client is None:
|
|
179
|
+
return ''
|
|
172
180
|
key_serialized = serialize_value(value=key.replace(' ', '_'))
|
|
173
181
|
try:
|
|
174
182
|
elementid_serialized = _memcached_client.get(key=key_serialized)
|
|
@@ -197,12 +205,14 @@ def nodes_cache_key_id_delete_key(key: str) -> None:
|
|
|
197
205
|
:param key: _key of a node.
|
|
198
206
|
:return: None.
|
|
199
207
|
"""
|
|
200
|
-
global _nodes_cache_key_id, _memcached_available
|
|
208
|
+
global _nodes_cache_key_id, _memcached_available, _memcached_client
|
|
201
209
|
|
|
202
210
|
if key == '':
|
|
203
211
|
return
|
|
204
212
|
|
|
205
213
|
if memcached_check_available():
|
|
214
|
+
if _memcached_client is None:
|
|
215
|
+
return
|
|
206
216
|
key_serialized = serialize_value(value=key.replace(' ', '_'))
|
|
207
217
|
try:
|
|
208
218
|
# Works regardless whether the key is present or not.
|
|
@@ -226,9 +236,11 @@ def nodes_cache_key_id_empty() -> None:
|
|
|
226
236
|
|
|
227
237
|
:return: None.
|
|
228
238
|
"""
|
|
229
|
-
global _nodes_cache_key_id, _memcached_available
|
|
239
|
+
global _nodes_cache_key_id, _memcached_available, _memcached_client
|
|
230
240
|
|
|
231
241
|
if memcached_check_available():
|
|
242
|
+
if _memcached_client is None:
|
|
243
|
+
return
|
|
232
244
|
try:
|
|
233
245
|
_memcached_client.flush_all()
|
|
234
246
|
except:
|
|
@@ -243,44 +255,45 @@ def nodes_cache_key_id_empty() -> None:
|
|
|
243
255
|
return
|
|
244
256
|
|
|
245
257
|
|
|
246
|
-
def
|
|
258
|
+
def nodes_cache_key_id_size() -> Tuple[int, float]:
|
|
247
259
|
"""Return the size of the cache for node id's.
|
|
248
260
|
'id' in this sentence is the id assigned by de graph database.
|
|
249
261
|
|
|
250
|
-
:return: a
|
|
262
|
+
:return: a tuple with number of items and size in kB.
|
|
251
263
|
"""
|
|
252
|
-
global _nodes_cache_key_id
|
|
264
|
+
global _nodes_cache_key_id, _memcached_client
|
|
253
265
|
|
|
254
266
|
if memcached_check_available():
|
|
255
|
-
|
|
267
|
+
if _memcached_client is None:
|
|
268
|
+
return 0, 0.0
|
|
256
269
|
try:
|
|
257
270
|
stats = _memcached_client.stats()
|
|
258
|
-
|
|
271
|
+
nr_items = int(stats.get(b'curr_items', 0))
|
|
259
272
|
bytes_used = int(stats.get(b'bytes', 0))
|
|
260
273
|
size_kb = round(bytes_used / 1000, 1)
|
|
261
274
|
except:
|
|
262
275
|
# In case the connection to Memcached is lost, we will also end up here,
|
|
263
276
|
# and we just continue.
|
|
264
|
-
|
|
277
|
+
nr_items = 0
|
|
265
278
|
size_kb = 0.0
|
|
266
279
|
else:
|
|
267
|
-
|
|
268
|
-
items = len(_nodes_cache_key_id)
|
|
280
|
+
nr_items = len(_nodes_cache_key_id)
|
|
269
281
|
size_kb = round(getsizeof(_nodes_cache_key_id) / 1000, 1)
|
|
282
|
+
return nr_items, size_kb
|
|
270
283
|
|
|
271
|
-
result += 'This cache has ' + str(items) + ' elements, and its size is '
|
|
272
|
-
result += str(size_kb) + ' kB.'
|
|
273
|
-
return result
|
|
274
284
|
|
|
285
|
+
def nodes_cache_key_id_type_size() -> str:
|
|
286
|
+
"""Return the size of the cache for node id's.
|
|
287
|
+
'id' in this sentence is the id assigned by de graph database.
|
|
288
|
+
|
|
289
|
+
:return: a sentence with the length of the cache and its size.
|
|
290
|
+
"""
|
|
291
|
+
nr_items, size_kb = nodes_cache_key_id_size()
|
|
292
|
+
if memcached_check_available():
|
|
293
|
+
result = 'Ricgraph uses Memcached as cache. '
|
|
294
|
+
else:
|
|
295
|
+
result = 'Ricgraph uses a local cache. '
|
|
275
296
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
# This will be executed on module initialization
|
|
280
|
-
_MEMCACHED_HOST = get_configfile_key(section='Memcached',
|
|
281
|
-
key='memcached_host')
|
|
282
|
-
# This returns a str, will be converted to int later on.
|
|
283
|
-
_MEMCACHED_PORT = get_configfile_key(section='Memcached',
|
|
284
|
-
key='memcached_port')
|
|
285
|
-
_MEMCACHED_TO_BE_USED = get_configfile_key(section='Memcached',
|
|
286
|
-
key='ricgraph_explorer_uses_memcached')
|
|
297
|
+
result += 'This cache has ' + str(nr_items) + ' elements, and its size is '
|
|
298
|
+
result += str(size_kb) + ' kB.'
|
|
299
|
+
return result
|