Skip to content

Commit 9512d8b

Browse files
Create a package with all WOQL words for ease of query construction (#342)
* Example WOQL syntax module * Explicitly export only defined functions * Fix deprecation warnings * Don't load re at all * Satisfy linter * Adding documentation * Need to export combinator functions * Fix function creation * Fix tests for new query syntax
1 parent f9822bb commit 9512d8b

File tree

4 files changed

+185
-16
lines changed

4 files changed

+185
-16
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .query_syntax import * # noqa
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
from ..woqlquery import WOQLQuery, Var, Doc # noqa
2+
import re
3+
import sys
4+
5+
__BARRED = ['re', 'vars']
6+
__ALLOWED = ['__and__', '__or__', '__add__']
7+
__module = sys.modules[__name__]
8+
__exported = ['Var', 'Doc']
9+
10+
11+
def __create_a_function(attribute):
12+
def __woql_fun(*args, **kwargs):
13+
obj = WOQLQuery()
14+
func = getattr(obj, attribute)
15+
return func(*args, **kwargs)
16+
return __woql_fun
17+
18+
19+
for attribute in dir(WOQLQuery()):
20+
if (isinstance(attribute, str) and (re.match('^[^_].*', attribute)
21+
or attribute in __ALLOWED)
22+
and attribute not in __BARRED):
23+
24+
__exported.append(attribute)
25+
26+
setattr(__module, attribute, __create_a_function(attribute))
27+
28+
__all__ = __exported
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from .woql_query import WOQLQuery # noqa
1+
from .woql_query import WOQLQuery, Var, Doc # noqa

terminusdb_client/woqlquery/woql_query.py

Lines changed: 155 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,20 @@ def __or__(self, other):
178178
"""
179179
return WOQLQuery().woql_or(self, other)
180180

181+
def __invert__(self):
182+
"""Creates a logical Not with the argument passed, for WOQLQueries.
183+
184+
Parameters
185+
----------
186+
other : WOQLQuery object
187+
188+
Returns
189+
-------
190+
WOQLQuery object
191+
query object that can be chained and/or execute
192+
"""
193+
return WOQLQuery().woql_not(self)
194+
181195
def _add_sub_query(self, sub_query=None):
182196
"""Internal library function which adds a subquery and sets the cursor"""
183197
if sub_query:
@@ -695,6 +709,18 @@ def _wrap_cursor_with_and(self):
695709
self._cursor = self._cursor["and"][1]
696710

697711
def using(self, collection, subq=None):
712+
"""Use a specific data product for the enclosed query
713+
714+
Parameters
715+
----------
716+
collection : str
717+
the name of the data product
718+
Returns
719+
-------
720+
WOQLQuery object
721+
query object that can be chained and/or execute
722+
"""
723+
698724
if collection and collection == "args":
699725
return ["collection", "query"]
700726
if self._cursor.get("@type"):
@@ -1242,8 +1268,7 @@ def substr(self, string, length, substring, before=0, after=0):
12421268

12431269
def update_object(self, docjson):
12441270
warnings.warn(
1245-
"update_object() is deprecated; use update_document()",
1246-
warnings.DeprecationWarning,
1271+
DeprecationWarning("update_object() is deprecated; use update_document()")
12471272
)
12481273
return self.update_document(docjson)
12491274
# if docjson and docjson == "args":
@@ -1259,6 +1284,19 @@ def update_object(self, docjson):
12591284
# return self._updated()
12601285

12611286
def update_document(self, docjson, json_or_iri=None):
1287+
"""Update a document in the database
1288+
1289+
Parameters
1290+
----------
1291+
docjson : JSON
1292+
object to be updated
1293+
json_or_iri : str
1294+
the output ID, or a JSON to compare the ID against
1295+
Returns
1296+
-------
1297+
WOQLQuery object
1298+
query object that can be chained and/or execute
1299+
"""
12621300
if docjson and docjson == "args":
12631301
return ["document"]
12641302
if self._cursor.get("@type"):
@@ -1274,6 +1312,19 @@ def update_document(self, docjson, json_or_iri=None):
12741312
return self._updated()
12751313

12761314
def insert_document(self, docjson, json_or_iri=None):
1315+
"""Insert a document into the database
1316+
1317+
Parameters
1318+
----------
1319+
docjson : JSON
1320+
object to be inserted
1321+
json_or_iri : str
1322+
the output ID, or a JSON to compare the ID against
1323+
Returns
1324+
-------
1325+
WOQLQuery object
1326+
query object that can be chained and/or execute
1327+
"""
12771328
if docjson and docjson == "args":
12781329
return ["document"]
12791330
if self._cursor.get("@type"):
@@ -1290,19 +1341,24 @@ def insert_document(self, docjson, json_or_iri=None):
12901341

12911342
def delete_object(self, json_or_iri):
12921343
warnings.warn(
1293-
"delete_object() is deprecated; use delete_document()",
1294-
warnings.DeprecationWarning,
1344+
DeprecationWarning("delete_object() is deprecated; use delete_document()")
12951345
)
12961346
return self.delete_document(json_or_iri)
1297-
# if json_or_iri and json_or_iri == "args":
1298-
# return ["document"]
1299-
# if self._cursor.get("@type"):
1300-
# self._wrap_cursor_with_and()
1301-
# self._cursor["@type"] = "DeleteObject"
1302-
# self._cursor["document_uri"] = self._clean_node_value(json_or_iri)
1303-
# return self._updated()
13041347

13051348
def delete_document(self, json_or_iri):
1349+
"""Delete a document into the database
1350+
1351+
Parameters
1352+
----------
1353+
docjson : JSON
1354+
object to be deleted
1355+
json_or_iri : str
1356+
the output ID, or a JSON to compare the ID against
1357+
Returns
1358+
-------
1359+
WOQLQuery object
1360+
query object that can be chained and/or execute
1361+
"""
13061362
if json_or_iri and json_or_iri == "args":
13071363
return ["document"]
13081364
if self._cursor.get("@type"):
@@ -1313,8 +1369,7 @@ def delete_document(self, json_or_iri):
13131369

13141370
def read_object(self, iri, output_var):
13151371
warnings.warn(
1316-
"read_object() is deprecated; use read_document()",
1317-
warnings.DeprecationWarning,
1372+
DeprecationWarning("read_object() is deprecated; use read_document()")
13181373
)
13191374
return self.read_document(iri, output_var)
13201375
# if iri and iri == "args":
@@ -1327,6 +1382,25 @@ def read_object(self, iri, output_var):
13271382
# return self
13281383

13291384
def read_document(self, iri, output_var):
1385+
"""Read a document from the database
1386+
1387+
Parameters
1388+
----------
1389+
iri : str
1390+
object to be deleted
1391+
output_var : str
1392+
the document as JSON
1393+
Returns
1394+
-------
1395+
WOQLQuery object
1396+
query object that can be chained and/or execute
1397+
Example
1398+
-------
1399+
>>> query = (WOQLQuery().triple('v:TermId', 'rdf:type', '@schema:Term') &
1400+
WOQLQuery().triple('v:TermCountId','term','v:TermId') &
1401+
WOQLQuery().triple('v:DocumentId', 'terms', 'v:TermCountId') &
1402+
WOQLQuery().read_document('v:TermId','v:TermDoc'))
1403+
"""
13301404
if iri and iri == "args":
13311405
return ["document"]
13321406
if self._cursor.get("@type"):
@@ -1941,6 +2015,21 @@ def isa(self, element, of_type):
19412015
return self
19422016

19432017
def like(self, left, right, dist):
2018+
"""Matches left string to right string with a distance
2019+
2020+
Parameters
2021+
----------
2022+
left : str
2023+
first string to compare
2024+
right : str
2025+
second string to compare
2026+
dist : str
2027+
Hamming distance between left and right
2028+
Returns
2029+
-------
2030+
WOQLQuery object
2031+
query object that can be chained and/or execute
2032+
"""
19442033
if left and left == "args":
19452034
return ["left", "right", "similarity"]
19462035
if self._cursor.get("@type"):
@@ -2125,6 +2214,20 @@ def random_idgen(self, prefix, key_list, uri):
21252214
return self
21262215

21272216
def upper(self, left, right):
2217+
"""Changes a string to upper-case - input is in left, output in right
2218+
2219+
Parameters
2220+
----------
2221+
left : str
2222+
input string
2223+
right : str
2224+
stores output
2225+
2226+
Returns
2227+
-------
2228+
WOQLQuery object
2229+
query object that can be chained and/or execute
2230+
"""
21282231
if left and left == "args":
21292232
return ["left", "right"]
21302233
if self._cursor.get("@type"):
@@ -2408,9 +2511,15 @@ def limit(self, limit, query=None):
24082511
return self._add_sub_query(query)
24092512

24102513
def re(self, pattern, reg_str, reg_list):
2514+
warnings.warn(
2515+
DeprecationWarning("re() is deprecated; use regexp()")
2516+
)
2517+
return self.regexp(pattern, reg_str, reg_list)
2518+
2519+
def regexp(self, pattern, reg_str, reg_list):
24112520
"""Regular Expression Call
2412-
p is a regex pattern (.*) using normal regular expression syntax, the only unusual thing is that special characters have to be escaped twice, s is the string to be matched and m is a list of matches:
2413-
e.g. WOQL.re("(.).*", "hello", ["v:All", "v:Sub"])
2521+
pattern is a regex pattern (.*) using normal regular expression syntax, the only unusual thing is that special characters have to be escaped twice, s is the string to be matched and m is a list of matches:
2522+
e.g. WOQLQuery().regexp("(.).*", "hello", ["v:All", "v:Sub"])
24142523
24152524
Parameters
24162525
----------
@@ -2437,6 +2546,21 @@ def re(self, pattern, reg_str, reg_list):
24372546
return self
24382547

24392548
def length(self, var_list, var_len):
2549+
"""Length
2550+
Calculates the length of a list
2551+
2552+
Parameters
2553+
----------
2554+
var_list : list
2555+
list of elements
2556+
var_len : num
2557+
number of eleemnts
2558+
2559+
Returns
2560+
-------
2561+
WOQLQuery object
2562+
query object that can be chained and/or execute
2563+
"""
24402564
if var_list and var_list == "args":
24412565
return ["list", "length"]
24422566
if self._cursor.get("@type"):
@@ -2983,3 +3107,19 @@ def vars(self, *args):
29833107
if len(vars_tuple) == 1:
29843108
vars_tuple = vars_tuple[0]
29853109
return vars_tuple
3110+
3111+
def variables(self, *args):
3112+
"""Generate variables to be used in WOQLQueries
3113+
Parameters
3114+
----------
3115+
args
3116+
string arguments
3117+
Returns
3118+
-------
3119+
tuple/string
3120+
args prefixed with "v:"
3121+
"""
3122+
vars_tuple = tuple(Var(arg) for arg in args)
3123+
if len(vars_tuple) == 1:
3124+
vars_tuple = vars_tuple[0]
3125+
return vars_tuple

0 commit comments

Comments
 (0)