Replace raised exceptions with logging

main
bashrc 2026-08-01 12:40:48 +01:00
parent 83f7748d57
commit 960302a865
1 changed files with 278 additions and 269 deletions

View File

@ -381,12 +381,10 @@ def load_document(url):
pieces.scheme not in ['http', 'https', 'hyper', 'ipfs', 'ipns'] or pieces.scheme not in ['http', 'https', 'hyper', 'ipfs', 'ipns'] or
set(pieces.netloc) > set( set(pieces.netloc) > set(
string.ascii_letters + string.digits + '-.:')): string.ascii_letters + string.digits + '-.:')):
raise JsonLdError( print('EX: pyjsonld/load_document ' +
'URL could not be dereferenced; only http/https/dat ' 'URL could not be dereferenced; only http/https/dat ' +
'URLs are supported.', 'URLs are supported. ' + str(url))
'jsonld.InvalidUrl', {'url': url}, return {}
code='loading document failed')
if url == 'https://w3id.org/identity/v1': if url == 'https://w3id.org/identity/v1':
doc = { doc = {
'contextUrl': None, 'contextUrl': None,
@ -483,12 +481,11 @@ def load_document(url):
return doc return doc
return None return None
except JsonLdError as ex: except JsonLdError as ex:
raise ex print('EX: Could not retrieve a JSON-LD document from the URL. ' +
str(url) + ' ' + str(ex))
except BaseException as cause: except BaseException as cause:
raise JsonLdError( print('EX: Could not retrieve a JSON-LD document from the URL. ' +
'Could not retrieve a JSON-LD document from the URL.', str(url) + ' ' + str(cause))
'jsonld.LoadDocumentError', code='loading document failed',
cause=cause)
def register_rdf_parser(content_type, parser): def register_rdf_parser(content_type, parser):
@ -710,9 +707,8 @@ class JsonLdProcessor(object):
:return: the compacted JSON-LD output. :return: the compacted JSON-LD output.
""" """
if ctx is None: if ctx is None:
raise JsonLdError( print('EX: The compaction context must not be null.')
'The compaction context must not be null.', return None
'jsonld.CompactError', code='invalid local context')
# nothing to compact # nothing to compact
if input_ is None: if input_ is None:
@ -739,18 +735,20 @@ class JsonLdProcessor(object):
try: try:
expanded = self.expand(input_, options) expanded = self.expand(input_, options)
except JsonLdError as cause: except JsonLdError as cause:
raise JsonLdError( print('EX: ' +
'Could not expand input before compaction.', 'Could not expand input before compaction. ' +
'jsonld.CompactError', cause=cause) str(cause))
return None
# process context # process context
active_ctx = self._get_initial_context(options) active_ctx = self._get_initial_context(options)
try: try:
active_ctx = self.process_context(active_ctx, ctx, options) active_ctx = self.process_context(active_ctx, ctx, options)
except JsonLdError as cause: except JsonLdError as cause:
raise JsonLdError( print('EX: ' +
'Could not process context before compaction.', 'Could not process context before compaction. ' +
'jsonld.CompactError', cause=cause) str(cause))
return None
# do compaction # do compaction
compacted = self._compact(active_ctx, None, expanded, options) compacted = self._compact(active_ctx, None, expanded, options)
@ -834,17 +832,16 @@ class JsonLdProcessor(object):
try: try:
if remote_doc['document'] is None: if remote_doc['document'] is None:
raise JsonLdError( print('EX: ' +
'No remote document found at the given URL.', 'No remote document found at the given URL.')
'jsonld.NullRemoteDocument') return None
if _is_string(remote_doc['document']): if _is_string(remote_doc['document']):
remote_doc['document'] = json.loads(remote_doc['document']) remote_doc['document'] = json.loads(remote_doc['document'])
except BaseException as cause: except BaseException as cause:
raise JsonLdError( print('EX: ' +
'Could not retrieve a JSON-LD document from the URL.', 'Could not retrieve a JSON-LD document from the URL. ' +
'jsonld.LoadDocumentError', str(cause))
{'remoteDoc': remote_doc}, code='loading document failed', return None
cause=cause)
# set default base # set default base
options.setdefault('base', remote_doc['documentUrl'] or '') options.setdefault('base', remote_doc['documentUrl'] or '')
@ -865,9 +862,9 @@ class JsonLdProcessor(object):
self._retrieve_context_urls( self._retrieve_context_urls(
input_, {}, options['documentLoader'], options['base']) input_, {}, options['documentLoader'], options['base'])
except BaseException as cause: except BaseException as cause:
raise JsonLdError( print('EX: ' +
'Could not perform JSON-LD expansion.', 'Could not perform JSON-LD expansion. ' + str(cause))
'jsonld.ExpandError', cause=cause) return None
active_ctx = self._get_initial_context(options) active_ctx = self._get_initial_context(options)
document = input_['document'] document = input_['document']
@ -914,9 +911,9 @@ class JsonLdProcessor(object):
# expand input # expand input
expanded = self.expand(input_, options) expanded = self.expand(input_, options)
except BaseException as cause: except BaseException as cause:
raise JsonLdError( print('EX: Could not expand input before flattening. ' +
'Could not expand input before flattening.', str(cause))
'jsonld.FlattenError', cause=cause) return {}
# do flattening # do flattening
flattened = self._flatten(expanded) flattened = self._flatten(expanded)
@ -930,9 +927,9 @@ class JsonLdProcessor(object):
try: try:
compacted = self.compact(flattened, ctx, options) compacted = self.compact(flattened, ctx, options)
except BaseException as cause: except BaseException as cause:
raise JsonLdError( print('EX: ' +
'Could not compact flattened output.', 'Could not compact flattened output. ' + str(cause))
'jsonld.FlattenError', cause=cause) return {}
return compacted return compacted
@ -977,17 +974,16 @@ class JsonLdProcessor(object):
try: try:
if remote_frame['document'] is None: if remote_frame['document'] is None:
raise JsonLdError( print('EX: ' +
'No remote document found at the given URL.', 'No remote document found at the given URL.')
'jsonld.NullRemoteDocument') return {}
if _is_string(remote_frame['document']): if _is_string(remote_frame['document']):
remote_frame['document'] = json.loads(remote_frame['document']) remote_frame['document'] = json.loads(remote_frame['document'])
except BaseException as cause: except BaseException as cause:
raise JsonLdError( print('EX: ' +
'Could not retrieve a JSON-LD document from the URL.', 'Could not retrieve a JSON-LD document from the URL. ' +
'jsonld.LoadDocumentError', str(cause))
{'remoteDoc': remote_frame}, code='loading document failed', return {}
cause=cause)
# preserve frame context # preserve frame context
frame = remote_frame['document'] frame = remote_frame['document']
@ -1005,19 +1001,18 @@ class JsonLdProcessor(object):
# expand input # expand input
expanded = self.expand(input_, options) expanded = self.expand(input_, options)
except JsonLdError as cause: except JsonLdError as cause:
raise JsonLdError( print('EX: ' +
'Could not expand input before framing.', 'Could not expand input before framing. ' + str(cause))
'jsonld.FrameError', cause=cause) return {}
try: try:
# expand frame # expand frame
opts = copy.deepcopy(options) opts = copy.deepcopy(options)
opts['keepFreeFloatingNodes'] = True opts['keepFreeFloatingNodes'] = True
expanded_frame = self.expand(frame, opts) expanded_frame = self.expand(frame, opts)
except JsonLdError as cause: except JsonLdError as cause:
raise JsonLdError( print('EX: ' +
'Could not expand frame before framing.', 'Could not expand frame before framing. ' + str(cause))
'jsonld.FrameError', cause=cause) return {}
# do framing # do framing
framed = self._frame(expanded, expanded_frame, options) framed = self._frame(expanded, expanded_frame, options)
@ -1031,9 +1026,9 @@ class JsonLdProcessor(object):
options['activeCtx'] = True options['activeCtx'] = True
result = self.compact(framed, ctx, options) result = self.compact(framed, ctx, options)
except JsonLdError as cause: except JsonLdError as cause:
raise JsonLdError( print('EX: ' +
'Could not compact framed output.', 'Could not compact framed output. ' + str(cause))
'jsonld.FrameError', cause=cause) return {}
compacted = result['compacted'] compacted = result['compacted']
active_ctx = result['activeCtx'] active_ctx = result['activeCtx']
@ -1072,9 +1067,10 @@ class JsonLdProcessor(object):
opts['produceGeneralizedRdf'] = False opts['produceGeneralizedRdf'] = False
dataset = self.to_rdf(input_, opts) dataset = self.to_rdf(input_, opts)
except JsonLdError as cause: except JsonLdError as cause:
raise JsonLdError( print('EX: ' +
'Could not convert input to RDF dataset before normalization.', 'Could not convert input to RDF dataset ' +
'jsonld.NormalizeError', cause=cause) 'before normalization. ' + str(cause))
return {}
# do normalization # do normalization
return self._normalize(dataset, options) return self._normalize(dataset, options)
@ -1112,9 +1108,9 @@ class JsonLdProcessor(object):
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( print('EX: ' +
'Unknown input format.', 'Unknown input format. ' + str(options['format']))
'jsonld.UnknownFormat', {'format': options['format']}) return {}
if self.rdf_parsers is not None: if self.rdf_parsers is not None:
parser = self.rdf_parsers[options['format']] parser = self.rdf_parsers[options['format']]
@ -1151,9 +1147,10 @@ class JsonLdProcessor(object):
# expand input # expand input
expanded = self.expand(input_, options) expanded = self.expand(input_, options)
except JsonLdError as cause: except JsonLdError as cause:
raise JsonLdError( print('EX: ' +
'Could not expand input before serialization to ' 'Could not expand input before serialization to RDF ' +
'RDF.', 'jsonld.RdfError', cause=cause) str(cause))
return {}
# create node map for default graph (and any named graphs) # create node map for default graph (and any named graphs)
namer = UniqueNamer('_:b') namer = UniqueNamer('_:b')
@ -1171,9 +1168,9 @@ class JsonLdProcessor(object):
if 'format' in options: if 'format' in options:
if options['format'] == 'application/nquads': if options['format'] == 'application/nquads':
return self.to_nquads(dataset) return self.to_nquads(dataset)
raise JsonLdError( print('EX: ' +
'Unknown output format.', 'Unknown output format. ' + str(options['format']))
'jsonld.UnknownFormat', {'format': options['format']}) return {}
return dataset return dataset
def process_context(self, active_ctx, local_ctx, options): def process_context(self, active_ctx, local_ctx, options):
@ -1207,9 +1204,9 @@ class JsonLdProcessor(object):
self._retrieve_context_urls( self._retrieve_context_urls(
local_ctx, {}, options['documentLoader'], options['base']) local_ctx, {}, options['documentLoader'], options['base'])
except BaseException as cause: except BaseException as cause:
raise JsonLdError( print('EX: ' +
'Could not process JSON-LD context.', 'Could not process JSON-LD context. ' + str(cause))
'jsonld.ContextError', cause=cause) return {}
# process context # process context
return self._process_context(active_ctx, local_ctx, options) return self._process_context(active_ctx, local_ctx, options)
@ -1508,9 +1505,10 @@ class JsonLdProcessor(object):
# parse quad # parse quad
ldmatch = re.search(quad, line) ldmatch = re.search(quad, line)
if ldmatch is None: if ldmatch is None:
raise JsonLdError( print('EX: ' +
'Error while parsing N-Quads invalid quad.', 'Error while parsing N-Quads invalid quad. ' +
'jsonld.ParseError', {'line': line_number}) str(line_number))
continue
ldmatch = ldmatch.groups() ldmatch = ldmatch.groups()
# create RDF triple # create RDF triple
@ -1865,14 +1863,14 @@ class JsonLdProcessor(object):
expanded_item['@index']) expanded_item['@index'])
# can't use @list container for more than 1 list # can't use @list container for more than 1 list
elif item_active_property in rval: elif item_active_property in rval:
raise JsonLdError( print('EX: ' +
'JSON-LD compact error; property has a ' 'JSON-LD compact error; property has a ' +
'"@list" @container rule but there is more ' '"@list" @container rule but there is ' +
'than a single @list that matches the ' 'more than a single @list that matches ' +
'compacted term in the document. Compaction ' 'the compacted term in the document. ' +
'might mix unwanted items into the list.', 'Compaction might mix unwanted items ' +
'jsonld.SyntaxError', 'into the list.')
code='compaction to list of lists') return {}
# handle language and index maps # handle language and index maps
if container == '@language' or container == '@index': if container == '@language' or container == '@index':
@ -1942,10 +1940,10 @@ class JsonLdProcessor(object):
active_ctx, active_property, e, options, inside_list) active_ctx, active_property, e, options, inside_list)
if inside_list and (_is_array(e) or _is_list(e)): if inside_list and (_is_array(e) or _is_list(e)):
# lists of lists are illegal # lists of lists are illegal
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; lists of lists are not ' 'Invalid JSON-LD syntax; lists of lists are not ' +
'permitted.', 'jsonld.SyntaxError', 'permitted.')
code='list of lists') return {}
# drop None values # drop None values
if e is not None: if e is not None:
if _is_array(e): if _is_array(e):
@ -1988,23 +1986,24 @@ class JsonLdProcessor(object):
if _is_keyword(expanded_property): if _is_keyword(expanded_property):
if expanded_property in rval: if expanded_property in rval:
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; colliding keywords detected.', 'Invalid JSON-LD syntax; ' +
'jsonld.SyntaxError', {'keyword': expanded_property}, 'colliding keywords detected.' +
code='colliding keywords') str(expanded_property))
return {}
# syntax error if @id is not a string # syntax error if @id is not a string
if expanded_property == '@id' and not _is_string(value): if expanded_property == '@id' and not _is_string(value):
if not options.get('isFrame'): if not options.get('isFrame'):
raise JsonLdError( print('EX: Invalid JSON-LD syntax; ' +
'Invalid JSON-LD syntax; "@id" value must a string.', '"@id" value must a string. ' +
'jsonld.SyntaxError', {'value': value}, str(value))
code='invalid @id value') return {}
if not _is_object(value): if not _is_object(value):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; "@id" value must be a ' 'Invalid JSON-LD syntax; "@id" value must be a ' +
'string or an object.', 'jsonld.SyntaxError', 'string or an object. ' + str(value))
{'value': value}, code='invalid @id value') return {}
if expanded_property == '@type': if expanded_property == '@type':
_validate_type_value(value) _validate_type_value(value)
@ -2012,10 +2011,10 @@ class JsonLdProcessor(object):
# @value must not be an object or an array # @value must not be an object or an array
if (expanded_property == '@value' and if (expanded_property == '@value' and
(_is_object(value) or _is_array(value))): (_is_object(value) or _is_array(value))):
raise JsonLdError( print('EX: Invalid JSON-LD syntax; ' +
'Invalid JSON-LD syntax; "@value" value must not be an ' '"@value" value must not be an ' +
'object or an array.', 'jsonld.SyntaxError', 'object or an array. ' + str(value))
{'value': value}, code='invalid value object value') return {}
# @language must be a string # @language must be a string
if expanded_property == '@language': if expanded_property == '@language':
@ -2024,19 +2023,18 @@ class JsonLdProcessor(object):
# didn't exist # didn't exist
continue continue
if not _is_string(value): if not _is_string(value):
raise JsonLdError( print('EX: Invalid JSON-LD syntax; ' +
'Invalid JSON-LD syntax; "@language" value must be ' '"@language" value must be a string. ' + str(value))
'a string.', 'jsonld.SyntaxError', {'value': value}, return {}
code='invalid language-tagged string')
# ensure language value is lowercase # ensure language value is lowercase
value = value.lower() value = value.lower()
# @index must be a string # @index must be a string
if expanded_property == '@index' and not _is_string(value): if expanded_property == '@index' and not _is_string(value):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; "@index" value must be ' 'Invalid JSON-LD syntax; "@index" value must be ' +
'a string.', 'jsonld.SyntaxError', {'value': value}, 'a string. ' + str(value))
code='invalid @index value') return {}
container = JsonLdProcessor.get_context_value( container = JsonLdProcessor.get_context_value(
active_ctx, key, '@container') active_ctx, key, '@container')
@ -2067,10 +2065,10 @@ class JsonLdProcessor(object):
active_ctx, next_active_property, value, options, active_ctx, next_active_property, value, options,
is_list) is_list)
if is_list and _is_list(expanded_value): if is_list and _is_list(expanded_value):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; lists of lists are ' 'Invalid JSON-LD syntax; lists of lists are ' +
'not permitted.', 'jsonld.SyntaxError', 'not permitted.')
code='list of lists') return {}
else: else:
# recursively expand value w/key as new active property # recursively expand value w/key as new active property
expanded_value = self._expand( expanded_value = self._expand(
@ -2102,11 +2100,11 @@ class JsonLdProcessor(object):
if '@value' in rval: if '@value' in rval:
# @value must only have @language or @type # @value must only have @language or @type
if '@type' in rval and '@language' in rval: if '@type' in rval and '@language' in rval:
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; an element containing ' 'Invalid JSON-LD syntax; an element containing ' +
'"@value" may not contain both "@type" and "@language".', '"@value" may not contain both ' +
'jsonld.SyntaxError', {'element': rval}, '"@type" and "@language". ' + str(rval))
code='invalid value object') return {}
valid_count = count - 1 valid_count = count - 1
if '@type' in rval: if '@type' in rval:
valid_count -= 1 valid_count -= 1
@ -2115,40 +2113,42 @@ class JsonLdProcessor(object):
if '@language' in rval: if '@language' in rval:
valid_count -= 1 valid_count -= 1
if valid_count != 0: if valid_count != 0:
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; an element containing "@value" ' 'Invalid JSON-LD syntax; ' +
'may only have an "@index" property and at most one other ' 'an element containing "@value" '
'property which can be "@type" or "@language".', 'may only have an "@index" ' +
'jsonld.SyntaxError', {'element': rval}, 'property and at most one other '
code='invalid value object') 'property which can be "@type" or "@language". ' +
str(rval))
return {}
# drop None @values # drop None @values
if rval['@value'] is None: if rval['@value'] is None:
rval = None rval = None
# if @language is present, @value must be a string # if @language is present, @value must be a string
elif '@language' in rval and not _is_string(rval['@value']): elif '@language' in rval and not _is_string(rval['@value']):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; only strings may be ' 'Invalid JSON-LD syntax; only strings may be '
'language-tagged.', 'jsonld.SyntaxError', 'language-tagged. ' + str(rval))
{'element': rval}, code='invalid language-tagged value') return {}
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( print('EX: ' +
'Invalid JSON-LD syntax; an element containing "@value" ' 'Invalid JSON-LD syntax; ' +
'and "@type" must have an absolute IRI for the value ' 'an element containing "@value" ' +
'of "@type".', 'jsonld.SyntaxError', {'element': rval}, 'and "@type" must have an absolute IRI for the value ' +
code='invalid typed value') 'of "@type". ' + str(rval))
return {}
# convert @type to an array # convert @type to an array
elif '@type' in rval and not _is_array(rval['@type']): elif '@type' in rval and not _is_array(rval['@type']):
rval['@type'] = [rval['@type']] rval['@type'] = [rval['@type']]
# handle @set and @list # handle @set and @list
elif '@set' in rval or '@list' in rval: elif '@set' in rval or '@list' in rval:
if count > 1 and not (count == 2 and '@index' in rval): if count > 1 and not (count == 2 and '@index' in rval):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; if an element has the ' 'Invalid JSON-LD syntax; if an element has the ' +
'property "@set" or "@list", then it can have at most ' 'property "@set" or "@list", then it can have at most ' +
'one other property, which is "@index".', 'one other property, which is "@index". ' + str(rval))
'jsonld.SyntaxError', {'element': rval}, return {}
code='invalid set or list object')
# optimize away @set # optimize away @set
if '@set' in rval: if '@set' in rval:
rval = rval['@set'] rval = rval['@set']
@ -2340,9 +2340,9 @@ class JsonLdProcessor(object):
if 'format' in options: if 'format' in options:
if options['format'] == 'application/nquads': if options['format'] == 'application/nquads':
return ''.join(normalized) return ''.join(normalized)
raise JsonLdError( print('EX: ' +
'Unknown output format.', 'Unknown output format. ' + str(options['format']))
'jsonld.UnknownFormat', {'format': options['format']}) return {}
# return parsed RDF dataset # return parsed RDF dataset
return JsonLdProcessor.parse_nquads(''.join(normalized)) return JsonLdProcessor.parse_nquads(''.join(normalized))
@ -2525,10 +2525,10 @@ class JsonLdProcessor(object):
# context must be an object now, all URLs retrieved prior to call # context must be an object now, all URLs retrieved prior to call
if not _is_object(ctx): if not _is_object(ctx):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; @context must be an object.', 'Invalid JSON-LD syntax; @context must be an object. ' +
'jsonld.SyntaxError', {'context': ctx}, str(ctx))
code='invalid local context') return {}
# get context from src.cache if available # get context from src.cache if available
if _cache.get('activeCtx') is not None: if _cache.get('activeCtx') is not None:
@ -2550,17 +2550,18 @@ class JsonLdProcessor(object):
if base is None: if base is None:
base = None base = None
elif not _is_string(base): elif not _is_string(base):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; the value of "@base" in a ' 'Invalid JSON-LD syntax; the value of ' +
'@context must be a string or null.', '"@base" in a @context must be a string or null. ' +
'jsonld.SyntaxError', {'context': ctx}, str(ctx))
code='invalid base IRI') return {}
elif base != '' and not _is_absolute_iri(base): elif base != '' and not _is_absolute_iri(base):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; the value of "@base" in a ' 'Invalid JSON-LD syntax; ' +
'@context must be an absolute IRI or the empty ' 'the value of "@base" in a ' +
'string.', 'jsonld.SyntaxError', {'context': ctx}, '@context must be an absolute IRI or the empty ' +
code='invalid base IRI') 'string. ' + str(ctx))
return {}
rval['@base'] = base rval['@base'] = base
defined['@base'] = True defined['@base'] = True
@ -2570,17 +2571,18 @@ class JsonLdProcessor(object):
if value is None: if value is None:
del rval['@vocab'] del rval['@vocab']
elif not _is_string(value): elif not _is_string(value):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; the value of "@vocab" in a ' 'Invalid JSON-LD syntax; ' +
'@context must be a string or null.', 'the value of "@vocab" in a ' +
'jsonld.SyntaxError', {'context': ctx}, '@context must be a string or null. ' + str(ctx))
code='invalid vocab mapping') return {}
elif not _is_absolute_iri(value): elif not _is_absolute_iri(value):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; the value of "@vocab" in a ' 'Invalid JSON-LD syntax; ' +
'@context must be an absolute IRI.', 'the value of "@vocab" in a '
'jsonld.SyntaxError', {'context': ctx}, '@context must be an absolute IRI. ' +
code='invalid vocab mapping') str(ctx))
return {}
else: else:
rval['@vocab'] = value rval['@vocab'] = value
defined['@vocab'] = True defined['@vocab'] = True
@ -2591,11 +2593,12 @@ class JsonLdProcessor(object):
if value is None: if value is None:
del rval['@language'] del rval['@language']
elif not _is_string(value): elif not _is_string(value):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; the value of "@language" in ' 'Invalid JSON-LD syntax; ' +
'a @context must be a string or null.', 'the value of "@language" in ' +
'jsonld.SyntaxError', {'context': ctx}, 'a @context must be a string or null. ' +
code='invalid default language') str(ctx))
return {}
else: else:
rval['@language'] = value.lower() rval['@language'] = value.lower()
defined['@language'] = True defined['@language'] = True
@ -2623,11 +2626,11 @@ class JsonLdProcessor(object):
values = JsonLdProcessor.arrayify(values) values = JsonLdProcessor.arrayify(values)
for item in values: for item in values:
if not _is_string(item): if not _is_string(item):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; language map values must be ' 'Invalid JSON-LD syntax; ' +
'strings.', 'jsonld.SyntaxError', 'language map values must be strings. ' +
{'languageMap': language_map}, str(language_map))
code='invalid language map value') return {}
rval.append({'@value': item, '@language': key.lower()}) rval.append({'@value': item, '@language': key.lower()})
return rval return rval
@ -2946,10 +2949,11 @@ class JsonLdProcessor(object):
if property == '@index' and '@index' in subject \ if property == '@index' and '@index' in subject \
and (input_['@index'] != subject['@index'] or and (input_['@index'] != subject['@index'] or
input_['@index']['@id'] != subject['@index']['@id']): input_['@index']['@id'] != subject['@index']['@id']):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; conflicting @index property ' 'Invalid JSON-LD syntax; ' +
' detected.', 'jsonld.SyntaxError', 'conflicting @index property detected. ' +
{'subject': subject}, code='conflicting indexes') str(subject))
return {}
subject[property] = input_[property] subject[property] = input_[property]
continue continue
@ -3205,9 +3209,11 @@ class JsonLdProcessor(object):
""" """
if (not _is_array(frame) or len(frame) != 1 or if (not _is_array(frame) or len(frame) != 1 or
not _is_object(frame[0])): not _is_object(frame[0])):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; a JSON-LD frame must be a single ' 'Invalid JSON-LD syntax; ' +
'object.', 'jsonld.SyntaxError', {'frame': frame}) 'a JSON-LD frame must be a single object. ' +
str(frame))
return {}
def _filter_subjects(self, state, subjects, frame, flags): def _filter_subjects(self, state, subjects, frame, flags):
""" """
@ -3867,27 +3873,26 @@ class JsonLdProcessor(object):
if defined[term]: if defined[term]:
return return
# cycle detected # cycle detected
raise JsonLdError( print('EX: Cyclical context definition detected. ' +
'Cyclical context definition detected.', 'context: ' + str(local_ctx) + ' ' +
'jsonld.CyclicalContext', { 'term: ' + str(term))
'context': local_ctx, return {}
'term': term
}, code='cyclic IRI mapping')
# now defining term # now defining term
defined[term] = False defined[term] = False
if _is_keyword(term): if _is_keyword(term):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; keywords cannot be overridden.', 'Invalid JSON-LD syntax; keywords cannot be overridden. ' +
'jsonld.SyntaxError', {'context': local_ctx, 'term': term}, 'context: ' + str(local_ctx) + ' ' +
code='keyword redefinition') 'term: ' + str(term))
return {}
if term == '': if term == '':
raise JsonLdError( print('EX: Invalid JSON-LD syntax; ' +
'Invalid JSON-LD syntax; a term cannot be an empty string.', 'a term cannot be an empty string. ' +
'jsonld.SyntaxError', {'context': local_ctx}, 'context: ' + str(local_ctx))
code='invalid term definition') return {}
# remove old mapping # remove old mapping
if term in active_ctx['mappings']: if term in active_ctx['mappings']:
@ -3908,10 +3913,12 @@ class JsonLdProcessor(object):
value = {'@id': value} value = {'@id': value}
if not _is_object(value): if not _is_object(value):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; @context property values must be ' 'Invalid JSON-LD syntax; ' +
'strings or objects.', 'jsonld.SyntaxError', '@context property values must be ' +
{'context': local_ctx}, code='invalid term definition') 'strings or objects. context: ' +
str(local_ctx))
return
# create new mapping # create new mapping
mapping = active_ctx['mappings'][term] = {'reverse': False} mapping = active_ctx['mappings'][term] = {'reverse': False}
@ -3919,21 +3926,22 @@ class JsonLdProcessor(object):
if '@id' in value: if '@id' in value:
id_ = value['@id'] id_ = value['@id']
if not _is_string(id_): if not _is_string(id_):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; @context @id value must be a ' 'Invalid JSON-LD syntax; @context @id value must be a ' +
'string.', 'jsonld.SyntaxError', 'string. context: ' + str(local_ctx))
{'context': local_ctx}, code='invalid IRI mapping') return
if id_ != term: if id_ != term:
# add @id to mapping # add @id to mapping
id_ = self._expand_iri( id_ = self._expand_iri(
active_ctx, id_, vocab=True, base=False, active_ctx, id_, vocab=True, base=False,
local_ctx=local_ctx, defined=defined) local_ctx=local_ctx, defined=defined)
if not _is_absolute_iri(id_) and not _is_keyword(id_): if not _is_absolute_iri(id_) and not _is_keyword(id_):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; @context @id value must be ' 'Invalid JSON-LD syntax; ' +
'an absolute IRI, a blank node identifier, or a ' '@context @id value must be an absolute IRI, ' +
'keyword.', 'jsonld.SyntaxError', 'a blank node identifier, or a keyword. ' +
{'context': local_ctx}, code='invalid IRI mapping') 'context: ' + str(local_ctx))
return
mapping['@id'] = id_ mapping['@id'] = id_
if '@id' not in mapping: if '@id' not in mapping:
# see if the term has a prefix # see if the term has a prefix
@ -3956,12 +3964,13 @@ class JsonLdProcessor(object):
else: else:
# non-IRIs MUST define @ids if @vocab not available # non-IRIs MUST define @ids if @vocab not available
if '@vocab' not in active_ctx: if '@vocab' not in active_ctx:
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; @context terms must define ' 'Invalid JSON-LD syntax; ' +
'an @id.', 'jsonld.SyntaxError', { '@context terms must define ' +
'context': local_ctx, 'an @id.', 'jsonld.SyntaxError. ' +
'term': term 'context: ' + str(local_ctx) + ' ' +
}, code='invalid IRI mapping') 'term: ' + str(term))
return
# prepend vocab to term # prepend vocab to term
mapping['@id'] = active_ctx['@vocab'] + term mapping['@id'] = active_ctx['@vocab'] + term
@ -3971,37 +3980,39 @@ class JsonLdProcessor(object):
if '@type' in value: if '@type' in value:
type_ = value['@type'] type_ = value['@type']
if not _is_string(type_): if not _is_string(type_):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; @context @type value must be ' 'Invalid JSON-LD syntax; @context @type value must be ' +
'a string.', 'jsonld.SyntaxError', 'a string. context: ' + str(local_ctx))
{'context': local_ctx}, code='invalid type mapping') return
if type_ != '@id' and type_ != '@vocab': if type_ != '@id' and type_ != '@vocab':
# expand @type to full IRI # expand @type to full IRI
type_ = self._expand_iri( type_ = self._expand_iri(
active_ctx, type_, vocab=True, active_ctx, type_, vocab=True,
local_ctx=local_ctx, defined=defined) local_ctx=local_ctx, defined=defined)
if not _is_absolute_iri(type_): if not _is_absolute_iri(type_):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; an @context @type value must ' 'Invalid JSON-LD syntax; ' +
'be an absolute IRI.', 'jsonld.SyntaxError', 'an @context @type value must ' +
{'context': local_ctx}, code='invalid type mapping') 'be an absolute IRI. context: ' + str(local_ctx))
return
if type_.startswith('_:'): if type_.startswith('_:'):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; an @context @type values ' 'Invalid JSON-LD syntax; an @context @type values ' +
'must be an IRI, not a blank node identifier.', 'must be an IRI, not a blank node identifier. ' +
'jsonld.SyntaxError', {'context': local_ctx}, 'context: ' + str(local_ctx))
code='invalid type mapping') return
# add @type to mapping # add @type to mapping
mapping['@type'] = type_ mapping['@type'] = type_
if '@container' in value: if '@container' in value:
container = value['@container'] container = value['@container']
if container not in ['@list', '@set', '@index', '@language']: if container not in ['@list', '@set', '@index', '@language']:
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; @context @container value ' 'Invalid JSON-LD syntax; @context @container value ' +
'must be one of the following: @list, @set, @index, or ' 'must be one of the following: ' +
'@language.', 'jsonld.SyntaxError', '@list, @set, @index, or @language. context: ' +
{'context': local_ctx}, code='invalid container mapping') str(local_ctx))
return
# add @container to mapping # add @container to mapping
mapping['@container'] = container mapping['@container'] = container
@ -4009,10 +4020,11 @@ class JsonLdProcessor(object):
if '@language' in value and '@type' not in value: if '@language' in value and '@type' not in value:
language = value['@language'] language = value['@language']
if not (language is None or _is_string(language)): if not (language is None or _is_string(language)):
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; @context @language value must be ' 'Invalid JSON-LD syntax; ' +
'a string or null.', 'jsonld.SyntaxError', '@context @language value must be a string or null. ' +
{'context': local_ctx}, code='invalid language mapping') 'context: ' + str(local_ctx))
return
# add @language to mapping # add @language to mapping
if language is not None: if language is not None:
language = language.lower() language = language.lower()
@ -4021,10 +4033,11 @@ class JsonLdProcessor(object):
# disallow aliasing @context and @preserve # disallow aliasing @context and @preserve
id_ = mapping['@id'] id_ = mapping['@id']
if id_ == '@context' or id_ == '@preserve': if id_ == '@context' or id_ == '@preserve':
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; @context and @preserve ' 'Invalid JSON-LD syntax; @context and @preserve ' +
'cannot be aliased.', 'jsonld.SyntaxError', 'cannot be aliased. context: ' +
{'context': local_ctx}, code='invalid keyword alias') str(local_ctx))
return
def _expand_iri( def _expand_iri(
self, active_ctx, value, base=False, vocab=False, self, active_ctx, value, base=False, vocab=False,
@ -4160,10 +4173,10 @@ class JsonLdProcessor(object):
:return: the result. :return: the result.
""" """
if len(cycles) > MAX_CONTEXT_URLS: if len(cycles) > MAX_CONTEXT_URLS:
raise JsonLdError( print('EX: ' +
'Maximum number of @context URLs exceeded.', 'Maximum number of @context URLs exceeded. ' +
'jsonld.ContextUrlError', {'max': MAX_CONTEXT_URLS}, str(MAX_CONTEXT_URLS))
code='loading remote context failed') return {}
# for tracking URLs to retrieve # for tracking URLs to retrieve
urls = {} urls = {}
@ -4181,10 +4194,8 @@ class JsonLdProcessor(object):
for url in queue: for url in queue:
# check for context URL cycle # check for context URL cycle
if url in cycles: if url in cycles:
raise JsonLdError( print('EX: Cyclical @context URLs detected. ' + str(url))
'Cyclical @context URLs detected.', return {}
'jsonld.ContextUrlError', {'url': url},
code='recursive context inclusion')
cycles_ = copy.deepcopy(cycles) cycles_ = copy.deepcopy(cycles)
cycles_[url] = True cycles_[url] = True
@ -4193,29 +4204,25 @@ class JsonLdProcessor(object):
remote_doc = load_document(url) remote_doc = load_document(url)
ctx = remote_doc['document'] ctx = remote_doc['document']
except BaseException as cause: except BaseException as cause:
raise JsonLdError( print('EX: Dereferencing a URL did not result ' +
'Dereferencing a URL did not result in a valid JSON-LD ' 'in a valid JSON-LD context. ' + str(url) + ' ' +
'context.', str(cause))
'jsonld.ContextUrlError', {'url': url}, return {}
code='loading remote context failed', cause=cause)
# parse string context as JSON # parse string context as JSON
if _is_string(ctx): if _is_string(ctx):
try: try:
ctx = json.loads(ctx) ctx = json.loads(ctx)
except BaseException as cause: except BaseException as cause:
raise JsonLdError( print('EX: Could not parse JSON from URL. ' + str(url) +
'Could not parse JSON from URL.', ' ' + str(cause))
'jsonld.ParseError', {'url': url}, return {}
code='loading remote context failed', cause=cause)
# ensure ctx is an object # ensure ctx is an object
if not _is_object(ctx): if not _is_object(ctx):
raise JsonLdError( print('EX: Dereferencing a URL did not result ' +
'Dereferencing a URL did not result in a valid JSON-LD ' 'in a valid JSON-LD object. ' + str(url))
'object.', return {}
'jsonld.InvalidUrl', {'url': url},
code='invalid remote context')
# use empty context if no @context key is present # use empty context if no @context key is present
if '@context' not in ctx: if '@context' not in ctx:
@ -4446,7 +4453,8 @@ def permutations(elements):
# no more permutations # no more permutations
if k is None: if k is None:
raise StopIteration print('EX: permutations StopIteration')
break
# swap k and the element it is looking at # swap k and the element it is looking at
swap = pos - 1 if left[k] else pos + 1 swap = pos - 1 if left[k] else pos + 1
@ -4551,10 +4559,11 @@ def _validate_type_value(v):
break break
if not is_valid: if not is_valid:
raise JsonLdError( print('EX: ' +
'Invalid JSON-LD syntax; "@type" value must a string, an array of ' 'Invalid JSON-LD syntax; ' +
'strings, or an empty object.', '"@type" value must a string, an array of '
'jsonld.SyntaxError', {'value': v}, code='invalid type value') 'strings, or an empty object. ' + str(v))
return
def _is_bool(v): def _is_bool(v):