Tidy up pyLD

main
Bob Mottram 2020-10-11 17:39:30 +01:00
parent ae0b6d32c5
commit 65f4e3ad41
1 changed files with 87 additions and 75 deletions

View File

@ -468,7 +468,7 @@ def prepend_base(base, iri):
# per RFC3986 5.2.2 # per RFC3986 5.2.2
transform = { transform = {
'scheme': base.scheme 'scheme': base.scheme
}; }
if rel.authority is not None: if rel.authority is not None:
transform['authority'] = rel.authority transform['authority'] = rel.authority
@ -479,7 +479,7 @@ def prepend_base(base, iri):
if rel.path == '': if rel.path == '':
transform['path'] = base.path transform['path'] = base.path
if rel.query != None: if rel.query is not None:
transform['query'] = rel.query transform['query'] = rel.query
else: else:
transform['query'] = base.query transform['query'] = base.query
@ -491,7 +491,8 @@ def prepend_base(base, iri):
# merge paths # merge paths
path = base.path path = base.path
# append relative path to the end of the last directory from base # append relative path to the end of the last
# directory from base
if rel.path != '': if rel.path != '':
path = path[0:path.rfind('/') + 1] path = path[0:path.rfind('/') + 1]
if len(path) > 0 and not path.endswith('/'): if len(path) > 0 and not path.endswith('/'):
@ -571,6 +572,7 @@ def remove_base(base, iri):
ParsedUrl = namedtuple( ParsedUrl = namedtuple(
'ParsedUrl', ['scheme', 'authority', 'path', 'query', 'fragment']) 'ParsedUrl', ['scheme', 'authority', 'path', 'query', 'fragment'])
def parse_url(url): def parse_url(url):
# regex from RFC 3986 # regex from RFC 3986
p = r'^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?' p = r'^(?:([^:/?#]+):)?(?://([^/?#]*))?([^?#]*)(?:\?([^#]*))?(?:#(.*))?'
@ -652,7 +654,7 @@ class JsonLdProcessor(object):
options.setdefault('skipExpansion', False) options.setdefault('skipExpansion', False)
options.setdefault('activeCtx', False) options.setdefault('activeCtx', False)
options.setdefault('documentLoader', _default_document_loader) options.setdefault('documentLoader', _default_document_loader)
options.setdefault('link', False); options.setdefault('link', False)
if options['link']: if options['link']:
# force skip expansion when linking, "link" is not part of the # force skip expansion when linking, "link" is not part of the
# public API, it should only be called from framing # public API, it should only be called from framing
@ -1047,9 +1049,9 @@ class JsonLdProcessor(object):
if 'format' in options: if 'format' in options:
# supported formats (processor-specific and global) # supported formats (processor-specific and global)
if ((self.rdf_parsers is not None and if ((self.rdf_parsers is not None and
not options['format'] in self.rdf_parsers) or not options['format'] in self.rdf_parsers) or
(self.rdf_parsers is None and (self.rdf_parsers is None and
not options['format'] in _rdf_parsers)): not options['format'] in _rdf_parsers)):
raise JsonLdError( raise JsonLdError(
'Unknown input format.', 'Unknown input format.',
'jsonld.UnknownFormat', {'format': options['format']}) 'jsonld.UnknownFormat', {'format': options['format']})
@ -1246,8 +1248,9 @@ class JsonLdProcessor(object):
JsonLdProcessor.add_value(subject, property, v, options) JsonLdProcessor.add_value(subject, property, v, options)
elif property in subject: elif property in subject:
# check if subject already has value if duplicates not allowed # check if subject already has value if duplicates not allowed
has_value = (not options['allowDuplicate'] and has_value = \
JsonLdProcessor.has_value(subject, property, value)) (not options['allowDuplicate'] and
JsonLdProcessor.has_value(subject, property, value))
# make property an array if value not present or always an array # make property an array if value not present or always an array
if (not _is_array(subject[property]) and if (not _is_array(subject[property]) and
@ -1469,12 +1472,16 @@ class JsonLdProcessor(object):
triple['object'] = {'type': 'blank node', 'value': match[4]} triple['object'] = {'type': 'blank node', 'value': match[4]}
else: else:
triple['object'] = {'type': 'literal'} triple['object'] = {'type': 'literal'}
unescaped = (match[5] replacements = {
.replace('\\"', '\"') '\\"': '\"',
.replace('\\t', '\t') '\\t': '\t',
.replace('\\n', '\n') '\\n': '\n',
.replace('\\r', '\r') '\\r': '\r',
.replace('\\\\', '\\')) '\\\\': '\\'
}
unescaped = match[5]
for match, repl in replacements.items():
unescaped = unescaped.replace(match, repl)
if match[6] is not None: if match[6] is not None:
triple['object']['datatype'] = match[6] triple['object']['datatype'] = match[6]
elif match[7] is not None: elif match[7] is not None:
@ -1580,12 +1587,16 @@ class JsonLdProcessor(object):
else: else:
quad += o['value'] quad += o['value']
else: else:
escaped = (o['value'] replacements = {
.replace('\\', '\\\\') '\\': '\\\\',
.replace('\t', '\\t') '\t': '\\t',
.replace('\n', '\\n') '\n': '\\n',
.replace('\r', '\\r') '\r': '\\r',
.replace('\"', '\\"')) '\"': '\\"'
}
escaped = o['value']
for match, repl in replacements.items():
escaped = escaped.replace(match, repl)
quad += '"' + escaped + '"' quad += '"' + escaped + '"'
if o['datatype'] == RDF_LANGSTRING: if o['datatype'] == RDF_LANGSTRING:
if o['language']: if o['language']:
@ -1717,7 +1728,7 @@ class JsonLdProcessor(object):
# use keyword alias and add value # use keyword alias and add value
alias = self._compact_iri(active_ctx, expanded_property) alias = self._compact_iri(active_ctx, expanded_property)
is_array = (_is_array(compacted_value) and is_array = (_is_array(compacted_value) and
len(compacted_value) == 0) len(compacted_value) == 0)
JsonLdProcessor.add_value( JsonLdProcessor.add_value(
rval, alias, compacted_value, rval, alias, compacted_value,
{'propertyIsArray': is_array}) {'propertyIsArray': is_array})
@ -1738,7 +1749,7 @@ class JsonLdProcessor(object):
container = JsonLdProcessor.get_context_value( container = JsonLdProcessor.get_context_value(
active_ctx, compacted_property, '@container') active_ctx, compacted_property, '@container')
use_array = (container == '@set' or use_array = (container == '@set' or
not options['compactArrays']) not options['compactArrays'])
JsonLdProcessor.add_value( JsonLdProcessor.add_value(
rval, compacted_property, value, rval, compacted_property, value,
{'propertyIsArray': use_array}) {'propertyIsArray': use_array})
@ -1765,7 +1776,8 @@ class JsonLdProcessor(object):
JsonLdProcessor.add_value(rval, alias, expanded_value) JsonLdProcessor.add_value(rval, alias, expanded_value)
continue continue
# skip array processing for keywords that aren't @graph or @list # skip array processing for keywords that aren't
# @graph or @list
if(expanded_property != '@graph' and if(expanded_property != '@graph' and
expanded_property != '@list' and expanded_property != '@list' and
_is_keyword(expanded_property)): _is_keyword(expanded_property)):
@ -1856,11 +1868,12 @@ class JsonLdProcessor(object):
# @container is @set or @list, value is an empty # @container is @set or @list, value is an empty
# array, or key is @graph # array, or key is @graph
is_array = (not options['compactArrays'] or is_array = (not options['compactArrays'] or
container == '@set' or container == '@list' or container == '@set' or
(_is_array(compacted_item) and container == '@list' or
len(compacted_item) == 0) or (_is_array(compacted_item) and
expanded_property == '@list' or len(compacted_item) == 0) or
expanded_property == '@graph') expanded_property == '@list' or
expanded_property == '@graph')
# add compact value # add compact value
JsonLdProcessor.add_value( JsonLdProcessor.add_value(
@ -1947,8 +1960,8 @@ class JsonLdProcessor(object):
# drop non-absolute IRI keys that aren't keywords # drop non-absolute IRI keys that aren't keywords
if (expanded_property is None or not if (expanded_property is None or not
(_is_absolute_iri(expanded_property) or (_is_absolute_iri(expanded_property) or
_is_keyword(expanded_property))): _is_keyword(expanded_property))):
continue continue
if _is_keyword(expanded_property): if _is_keyword(expanded_property):
@ -2030,10 +2043,9 @@ class JsonLdProcessor(object):
# properties double-reversed # properties double-reversed
if '@reverse' in expanded_value: if '@reverse' in expanded_value:
for rproperty, rvalue in ( for rprop, rvalue in expanded_value['@reverse'].items():
expanded_value['@reverse'].items()):
JsonLdProcessor.add_value( JsonLdProcessor.add_value(
rval, rproperty, rvalue, rval, rprop, rvalue,
{'propertyIsArray': True}) {'propertyIsArray': True})
# merge in all reversed properties # merge in all reversed properties
@ -2132,7 +2144,7 @@ class JsonLdProcessor(object):
# add value for property, use an array exception for certain # add value for property, use an array exception for certain
# key words # key words
use_array = (expanded_property not in ['@index', '@id', '@type', use_array = (expanded_property not in ['@index', '@id', '@type',
'@value', '@language']) '@value', '@language'])
JsonLdProcessor.add_value( JsonLdProcessor.add_value(
rval, expanded_property, expanded_value, rval, expanded_property, expanded_value,
{'propertyIsArray': use_array}) {'propertyIsArray': use_array})
@ -2172,7 +2184,7 @@ class JsonLdProcessor(object):
'language-tagged.', 'jsonld.SyntaxError', 'language-tagged.', 'jsonld.SyntaxError',
{'element': rval}, code='invalid language-tagged value') {'element': rval}, code='invalid language-tagged value')
elif ('@type' in rval and (not _is_absolute_iri(rval['@type']) or elif ('@type' in rval and (not _is_absolute_iri(rval['@type']) or
rval['@type'].startswith('_:'))): rval['@type'].startswith('_:'))):
raise JsonLdError( raise JsonLdError(
'Invalid JSON-LD syntax; an element containing "@value" ' 'Invalid JSON-LD syntax; an element containing "@value" '
'and "@type" must have an absolute IRI for the value ' 'and "@type" must have an absolute IRI for the value '
@ -2200,8 +2212,8 @@ class JsonLdProcessor(object):
# drop certain top-level objects that do not occur in lists # drop certain top-level objects that do not occur in lists
if (_is_object(rval) and not options.get('keepFreeFloatingNodes') and if (_is_object(rval) and not options.get('keepFreeFloatingNodes') and
not inside_list and (active_property is None or not inside_list and (active_property is None or
expanded_active_property == '@graph')): expanded_active_property == '@graph')):
# drop empty object or top-level @value/@list, # drop empty object or top-level @value/@list,
# or object with only @id # or object with only @id
if (count == 0 or '@value' in rval or '@list' in rval or if (count == 0 or '@value' in rval or '@list' in rval or
@ -2236,7 +2248,7 @@ class JsonLdProcessor(object):
# produce flattened output # produce flattened output
return [value for key, value in sorted(default_graph.items()) return [value for key, value in sorted(default_graph.items())
if not _is_subject_reference(value)] if not _is_subject_reference(value)]
def _frame(self, input_, frame, options): def _frame(self, input_, frame, options):
""" """
@ -2416,7 +2428,7 @@ class JsonLdProcessor(object):
node = node_map.setdefault(s, {'@id': s}) node = node_map.setdefault(s, {'@id': s})
object_is_id = (o['type'] == 'IRI' or object_is_id = (o['type'] == 'IRI' or
o['type'] == 'blank node') o['type'] == 'blank node')
if object_is_id and o['value'] not in node_map: if object_is_id and o['value'] not in node_map:
node_map[o['value']] = {'@id': o['value']} node_map[o['value']] = {'@id': o['value']}
@ -2445,14 +2457,14 @@ class JsonLdProcessor(object):
}) })
# object referenced more than once # object referenced more than once
elif o['value'] in referenced_once: elif o['value'] in referenced_once:
referenced_once[o['value']] = False referenced_once[o['value']] = False
# track single reference # track single reference
else: else:
referenced_once[o['value']] = { referenced_once[o['value']] = {
'node': node, 'node': node,
'property': p, 'property': p,
'value': value 'value': value
} }
# convert linked lists to @list arrays # convert linked lists to @list arrays
for name, graph_object in graph_map.items(): for name, graph_object in graph_map.items():
@ -2477,15 +2489,15 @@ class JsonLdProcessor(object):
# and, optionally, @type where the value is rdf:List. # and, optionally, @type where the value is rdf:List.
node_key_count = len(node.keys()) node_key_count = len(node.keys())
while(property == RDF_REST and while(property == RDF_REST and
_is_object(referenced_once.get(node['@id'])) and _is_object(referenced_once.get(node['@id'])) and
_is_array(node[RDF_FIRST]) and _is_array(node[RDF_FIRST]) and
len(node[RDF_FIRST]) == 1 and len(node[RDF_FIRST]) == 1 and
_is_array(node[RDF_REST]) and _is_array(node[RDF_REST]) and
len(node[RDF_REST]) == 1 and len(node[RDF_REST]) == 1 and
(node_key_count == 3 or (node_key_count == 4 and (node_key_count == 3 or (node_key_count == 4 and
_is_array(node.get('@type')) and _is_array(node.get('@type')) and
len(node['@type']) == 1 and len(node['@type']) == 1 and
node['@type'][0] == RDF_LIST))): node['@type'][0] == RDF_LIST))):
list_.append(node[RDF_FIRST][0]) list_.append(node[RDF_FIRST][0])
list_nodes.append(node['@id']) list_nodes.append(node['@id'])
@ -2564,7 +2576,6 @@ class JsonLdProcessor(object):
# reset to initial context # reset to initial context
if ctx is None: if ctx is None:
rval = active_ctx = self._get_initial_context(options) rval = active_ctx = self._get_initial_context(options)
must_clone = False
continue continue
# dereference @context key if present # dereference @context key if present
@ -2708,7 +2719,7 @@ class JsonLdProcessor(object):
# do @id expansion (automatic for @graph) # do @id expansion (automatic for @graph)
if (type_ == '@id' or (expanded_property == '@graph' if (type_ == '@id' or (expanded_property == '@graph'
and _is_string(value))): and _is_string(value))):
return {'@id': self._expand_iri(active_ctx, value, base=True)} return {'@id': self._expand_iri(active_ctx, value, base=True)}
# do @id expansion w/vocab # do @id expansion w/vocab
if type_ == '@vocab': if type_ == '@vocab':
@ -2859,7 +2870,7 @@ class JsonLdProcessor(object):
elif _is_double(value) or datatype == XSD_DOUBLE: elif _is_double(value) or datatype == XSD_DOUBLE:
# canonical double representation # canonical double representation
object['value'] = re.sub(r'(\d)0*E\+?0*(\d)', r'\1E\2', object['value'] = re.sub(r'(\d)0*E\+?0*(\d)', r'\1E\2',
('%1.15E' % value)) ('%1.15E' % value))
object['datatype'] = datatype or XSD_DOUBLE object['datatype'] = datatype or XSD_DOUBLE
elif _is_integer(value): elif _is_integer(value):
object['value'] = str(value) object['value'] = str(value)
@ -2923,7 +2934,7 @@ class JsonLdProcessor(object):
rval['@value'] = float(rval['@value']) rval['@value'] = float(rval['@value'])
# do not add native type # do not add native type
if type_ not in [XSD_BOOLEAN, XSD_INTEGER, XSD_DOUBLE, if type_ not in [XSD_BOOLEAN, XSD_INTEGER, XSD_DOUBLE,
XSD_STRING]: XSD_STRING]:
rval['@type'] = type_ rval['@type'] = type_
elif type_ != XSD_STRING: elif type_ != XSD_STRING:
rval['@type'] = type_ rval['@type'] = type_
@ -3315,7 +3326,7 @@ class JsonLdProcessor(object):
# ducktyping) # ducktyping)
if ('@type' in frame and if ('@type' in frame and
not (len(frame['@type']) == 1 and not (len(frame['@type']) == 1 and
_is_object(frame['@type'][0]))): _is_object(frame['@type'][0]))):
types = frame['@type'] types = frame['@type']
for t in types: for t in types:
# any matching @type is a match # any matching @type is a match
@ -3354,7 +3365,7 @@ class JsonLdProcessor(object):
# all properties must match to be a duck unless a @default is # all properties must match to be a duck unless a @default is
# specified # specified
has_default = (_is_array(v) and len(v) == 1 and has_default = (_is_array(v) and len(v) == 1 and
_is_object(v[0]) and '@default' in v[0]) _is_object(v[0]) and '@default' in v[0])
if flags['requireAll'] and not has_default: if flags['requireAll'] and not has_default:
return False return False
@ -3382,7 +3393,6 @@ class JsonLdProcessor(object):
for i, parent in enumerate(embed['parent']): for i, parent in enumerate(embed['parent']):
if JsonLdProcessor.compare_values(parent, subject): if JsonLdProcessor.compare_values(parent, subject):
embed['parent'][i] = subject embed['parent'][i] = subject
foo = True
break break
else: else:
# replace subject with reference # replace subject with reference
@ -3470,7 +3480,7 @@ class JsonLdProcessor(object):
idx = options['link'][id_].index(input_) idx = options['link'][id_].index(input_)
# already visited # already visited
return options['link'][id_][idx] return options['link'][id_][idx]
except: except BaseException:
# prevent circular visitation # prevent circular visitation
options['link'][id_].append(input_) options['link'][id_].append(input_)
else: else:
@ -3839,7 +3849,8 @@ class JsonLdProcessor(object):
# select curie if it is shorter or the same length but # select curie if it is shorter or the same length but
# lexicographically less than the current choice # lexicographically less than the current choice
if (is_usable_curie and (candidate is None or if (is_usable_curie and (candidate is None or
_compare_shortest_least(curie, candidate) < 0)): _compare_shortest_least(curie,
candidate) < 0)):
candidate = curie candidate = curie
# return curie candidate # return curie candidate
@ -3878,8 +3889,8 @@ class JsonLdProcessor(object):
if not preserve_index: if not preserve_index:
# matching @type or @language specified in context, compact # matching @type or @language specified in context, compact
if (('@type' in value and value['@type'] == type_) or if (('@type' in value and value['@type'] == type_) or
('@language' in value and ('@language' in value and
value['@language'] == language)): value['@language'] == language)):
return value['@value'] return value['@value']
# return just the value of @value if all are true: # return just the value of @value if all are true:
@ -3887,8 +3898,9 @@ class JsonLdProcessor(object):
# 2. there is no default language or @value is not a string or # 2. there is no default language or @value is not a string or
# the key has a mapping with a null @language # the key has a mapping with a null @language
key_count = len(value) key_count = len(value)
is_value_only_key = (key_count == 1 or (key_count == 2 and is_value_only_key = \
'@index' in value and not preserve_index)) (key_count == 1 or (key_count == 2 and
'@index' in value and not preserve_index))
has_default_language = '@language' in active_ctx has_default_language = '@language' in active_ctx
is_value_string = _is_string(value['@value']) is_value_string = _is_string(value['@value'])
has_null_mapping = ( has_null_mapping = (
@ -3982,7 +3994,7 @@ class JsonLdProcessor(object):
# clear context entry # clear context entry
if (value is None or (_is_object(value) and '@id' in value and if (value is None or (_is_object(value) and '@id' in value and
value['@id'] is None)): value['@id'] is None)):
active_ctx['mappings'][term] = None active_ctx['mappings'][term] = None
defined[term] = True defined[term] = True
return return
@ -4058,7 +4070,7 @@ class JsonLdProcessor(object):
if active_ctx['mappings'].get(prefix) is not None: if active_ctx['mappings'].get(prefix) is not None:
suffix = term[colon + 1:] suffix = term[colon + 1:]
mapping['@id'] = (active_ctx['mappings'][prefix]['@id'] + mapping['@id'] = (active_ctx['mappings'][prefix]['@id'] +
suffix) suffix)
# term is an absolute IRI # term is an absolute IRI
else: else:
mapping['@id'] = term mapping['@id'] = term
@ -4557,7 +4569,7 @@ def permutations(elements):
is_left = left[e] is_left = left[e]
if((k is None or e > k) and if((k is None or e > k) and
((is_left and i > 0 and e > elements[i - 1]) or ((is_left and i > 0 and e > elements[i - 1]) or
(not is_left and i < last and e > elements[i + 1]))): (not is_left and i < last and e > elements[i + 1]))):
k, pos = e, i k, pos = e, i
# no more permutations # no more permutations
@ -4800,7 +4812,7 @@ def _is_bnode(v):
rval = v['@id'].startswith('_:') rval = v['@id'].startswith('_:')
else: else:
rval = (len(v) == 0 or not rval = (len(v) == 0 or not
('@value' in v or '@set' in v or '@list' in v)) ('@value' in v or '@set' in v or '@list' in v))
return rval return rval
@ -4857,10 +4869,10 @@ class VerifiedHTTPSConnection(HTTPSConnection):
self._tunnel() self._tunnel()
# wrap the socket using verification with trusted_root_certs # wrap the socket using verification with trusted_root_certs
self.sock = ssl.wrap_socket(sock, self.sock = ssl.wrap_socket(sock,
self.key_file, self.key_file,
self.cert_file, self.cert_file,
cert_reqs=ssl.CERT_REQUIRED, cert_reqs=ssl.CERT_REQUIRED,
ca_certs=_trust_root_certificates) ca_certs=_trust_root_certificates)
class VerifiedHTTPSHandler(HTTPSHandler): class VerifiedHTTPSHandler(HTTPSHandler):