diff options
-rw-r--r-- | jsonschema/_format.py | 39 | ||||
-rw-r--r-- | jsonschema/_legacy_validators.py | 5 | ||||
-rw-r--r-- | jsonschema/_reflect.py | 10 | ||||
-rw-r--r-- | jsonschema/_types.py | 5 | ||||
-rw-r--r-- | jsonschema/_utils.py | 6 | ||||
-rw-r--r-- | jsonschema/_validators.py | 9 | ||||
-rw-r--r-- | jsonschema/cli.py | 2 | ||||
-rw-r--r-- | jsonschema/compat.py | 60 | ||||
-rw-r--r-- | jsonschema/exceptions.py | 37 | ||||
-rw-r--r-- | jsonschema/tests/_helpers.py | 7 | ||||
-rw-r--r-- | jsonschema/tests/_suite.py | 7 | ||||
-rw-r--r-- | jsonschema/tests/test_cli.py | 17 | ||||
-rw-r--r-- | jsonschema/tests/test_exceptions.py | 19 | ||||
-rw-r--r-- | jsonschema/tests/test_validators.py | 6 | ||||
-rw-r--r-- | jsonschema/validators.py | 26 |
15 files changed, 70 insertions, 185 deletions
diff --git a/jsonschema/_format.py b/jsonschema/_format.py index aa5dd6e..3c1e6fe 100644 --- a/jsonschema/_format.py +++ b/jsonschema/_format.py @@ -3,7 +3,6 @@ import re import socket import struct -from jsonschema.compat import str_types from jsonschema.exceptions import FormatError @@ -179,7 +178,7 @@ def _checks_drafts( @_checks_drafts(name="idn-email") @_checks_drafts(name="email") def is_email(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return "@" in instance @@ -191,7 +190,7 @@ _ipv4_re = re.compile(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$") draft3="ip-address", draft4="ipv4", draft6="ipv4", draft7="ipv4", ) def is_ipv4(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True if not _ipv4_re.match(instance): return False @@ -205,7 +204,7 @@ if hasattr(socket, "inet_pton"): name="ipv6", raises=(socket.error, struct.error, ValueError), ) def is_ipv6(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return socket.inet_pton(socket.AF_INET6, instance) @@ -220,7 +219,7 @@ _host_name_re = re.compile(r"^[A-Za-z0-9][A-Za-z0-9\.\-]{1,255}$") draft7="hostname", ) def is_host_name(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True if not _host_name_re.match(instance): return False @@ -242,7 +241,7 @@ else: raises=(idna.IDNAError, UnicodeError), ) def is_idn_host_name(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True idna.encode(instance) return True @@ -258,7 +257,7 @@ except ImportError: else: @_checks_drafts(name="uri") def is_uri(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return validate_rfc3986(instance, rule="URI") @@ -268,26 +267,26 @@ except ImportError: raises=ValueError, ) def is_uri_reference(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return validate_rfc3986(instance, rule="URI_reference") else: @_checks_drafts(draft7="iri", raises=ValueError) def is_iri(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return rfc3987.parse(instance, rule="IRI") @_checks_drafts(draft7="iri-reference", raises=ValueError) def is_iri_reference(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return rfc3987.parse(instance, rule="IRI_reference") @_checks_drafts(name="uri", raises=ValueError) def is_uri(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return rfc3987.parse(instance, rule="URI") @@ -297,7 +296,7 @@ else: raises=ValueError, ) def is_uri_reference(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return rfc3987.parse(instance, rule="URI_reference") @@ -313,34 +312,34 @@ except ImportError: if validate_rfc3339: @_checks_drafts(name="date-time") def is_datetime(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return validate_rfc3339(instance) @_checks_drafts(draft7="time") def is_time(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return is_datetime("1970-01-01T" + instance) @_checks_drafts(name="regex", raises=re.error) def is_regex(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return re.compile(instance) @_checks_drafts(draft3="date", draft7="date", raises=ValueError) def is_date(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return datetime.datetime.strptime(instance, "%Y-%m-%d") @_checks_drafts(draft3="time", raises=ValueError) def is_draft3_time(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return datetime.datetime.strptime(instance, "%H:%M:%S") @@ -361,7 +360,7 @@ else: @_checks_drafts(draft3="color", raises=(ValueError, TypeError)) def is_css21_color(instance): if ( - not isinstance(instance, str_types) or + not isinstance(instance, str) or instance.lower() in CSS21_NAMES_TO_HEX ): return True @@ -384,7 +383,7 @@ else: raises=jsonpointer.JsonPointerException, ) def is_json_pointer(instance): - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True return jsonpointer.JsonPointer(instance) @@ -399,7 +398,7 @@ else: def is_relative_json_pointer(instance): # Definition taken from: # https://tools.ietf.org/html/draft-handrews-relative-json-pointer-01#section-3 - if not isinstance(instance, str_types): + if not isinstance(instance, str): return True non_negative_integer, rest = [], "" for i, character in enumerate(instance): diff --git a/jsonschema/_legacy_validators.py b/jsonschema/_legacy_validators.py index 264ff7d..80f798b 100644 --- a/jsonschema/_legacy_validators.py +++ b/jsonschema/_legacy_validators.py @@ -1,5 +1,4 @@ from jsonschema import _utils -from jsonschema.compat import iteritems from jsonschema.exceptions import ValidationError @@ -7,7 +6,7 @@ def dependencies_draft3(validator, dependencies, instance, schema): if not validator.is_type(instance, "object"): return - for property, dependency in iteritems(dependencies): + for property, dependency in dependencies.items(): if property not in instance: continue @@ -100,7 +99,7 @@ def properties_draft3(validator, properties, instance, schema): if not validator.is_type(instance, "object"): return - for property, subschema in iteritems(properties): + for property, subschema in properties.items(): if property in instance: for error in validator.descend( instance[property], diff --git a/jsonschema/_reflect.py b/jsonschema/_reflect.py index d09e38f..39ee7a6 100644 --- a/jsonschema/_reflect.py +++ b/jsonschema/_reflect.py @@ -9,8 +9,6 @@ with Python's reflection capabilities. import sys -from jsonschema.compat import PY3 - class _NoModuleFound(Exception): """ @@ -42,12 +40,8 @@ class ObjectNotFound(InvalidName): -if PY3: - def reraise(exception, traceback): - raise exception.with_traceback(traceback) -else: - exec("""def reraise(exception, traceback): - raise exception.__class__, exception, traceback""") +def reraise(exception, traceback): + raise exception.with_traceback(traceback) reraise.__doc__ = """ Re-raise an exception, with an optional traceback, in a way that is compatible diff --git a/jsonschema/_types.py b/jsonschema/_types.py index 9957d02..50bcf99 100644 --- a/jsonschema/_types.py +++ b/jsonschema/_types.py @@ -3,7 +3,6 @@ import numbers from pyrsistent import pmap import attr -from jsonschema.compat import int_types, str_types from jsonschema.exceptions import UndefinedTypeCheck @@ -19,7 +18,7 @@ def is_integer(checker, instance): # bool inherits from int, so ensure bools aren't reported as ints if isinstance(instance, bool): return False - return isinstance(instance, int_types) + return isinstance(instance, int) def is_null(checker, instance): @@ -38,7 +37,7 @@ def is_object(checker, instance): def is_string(checker, instance): - return isinstance(instance, str_types) + return isinstance(instance, str) def is_any(checker, instance): diff --git a/jsonschema/_utils.py b/jsonschema/_utils.py index ceb8801..780a22d 100644 --- a/jsonschema/_utils.py +++ b/jsonschema/_utils.py @@ -1,10 +1,10 @@ +from collections.abc import MutableMapping +from urllib.parse import urlsplit import itertools import json import pkgutil import re -from jsonschema.compat import MutableMapping, str_types, urlsplit - class URIDict(MutableMapping): """ @@ -160,7 +160,7 @@ def ensure_list(thing): Otherwise, return it unchanged. """ - if isinstance(thing, str_types): + if isinstance(thing, str): return [thing] return thing diff --git a/jsonschema/_validators.py b/jsonschema/_validators.py index 179fec0..d7097ff 100644 --- a/jsonschema/_validators.py +++ b/jsonschema/_validators.py @@ -10,15 +10,14 @@ from jsonschema._utils import ( uniq, ) from jsonschema.exceptions import FormatError, ValidationError -from jsonschema.compat import iteritems def patternProperties(validator, patternProperties, instance, schema): if not validator.is_type(instance, "object"): return - for pattern, subschema in iteritems(patternProperties): - for k, v in iteritems(instance): + for pattern, subschema in patternProperties.items(): + for k, v in instance.items(): if re.search(pattern, k): for error in validator.descend( v, subschema, path=k, schema_path=pattern, @@ -224,7 +223,7 @@ def dependencies(validator, dependencies, instance, schema): if not validator.is_type(instance, "object"): return - for property, dependency in iteritems(dependencies): + for property, dependency in dependencies.items(): if property not in instance: continue @@ -277,7 +276,7 @@ def properties(validator, properties, instance, schema): if not validator.is_type(instance, "object"): return - for property, subschema in iteritems(properties): + for property, subschema in properties.items(): if property in instance: for error in validator.descend( instance[property], diff --git a/jsonschema/cli.py b/jsonschema/cli.py index 7a32917..4c2bb4f 100644 --- a/jsonschema/cli.py +++ b/jsonschema/cli.py @@ -2,6 +2,7 @@ The ``jsonschema`` command line. """ +from json import JSONDecodeError from textwrap import dedent import argparse import errno @@ -13,7 +14,6 @@ import attr from jsonschema import __version__ from jsonschema._reflect import namedAny -from jsonschema.compat import JSONDecodeError from jsonschema.exceptions import SchemaError from jsonschema.validators import validator_for diff --git a/jsonschema/compat.py b/jsonschema/compat.py deleted file mode 100644 index 623b666..0000000 --- a/jsonschema/compat.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -Python 2/3 compatibility helpers. - -Note: This module is *not* public API. -""" -import contextlib -import operator -import sys - - -try: - from collections.abc import MutableMapping, Sequence # noqa -except ImportError: - from collections import MutableMapping, Sequence # noqa - -try: - from json import JSONDecodeError -except ImportError: - JSONDecodeError = ValueError - -PY3 = sys.version_info[0] >= 3 - -if PY3: - zip = zip - from functools import lru_cache - from io import StringIO as NativeIO - from urllib.parse import ( - unquote, urljoin, urlunsplit, SplitResult, urlsplit - ) - from urllib.request import pathname2url, urlopen - str_types = str, - int_types = int, - iteritems = operator.methodcaller("items") -else: - from itertools import izip as zip # noqa - from io import BytesIO as NativeIO - from urlparse import urljoin, urlunsplit, SplitResult, urlsplit - from urllib import pathname2url, unquote # noqa - import urllib2 # noqa - def urlopen(*args, **kwargs): - return contextlib.closing(urllib2.urlopen(*args, **kwargs)) - - str_types = basestring - int_types = int, long - iteritems = operator.methodcaller("iteritems") - - from functools32 import lru_cache - - -def urldefrag(url): - if "#" in url: - s, n, p, q, frag = urlsplit(url) - defrag = urlunsplit((s, n, p, q, "")) - else: - defrag = url - frag = "" - return defrag, frag - - -# flake8: noqa diff --git a/jsonschema/exceptions.py b/jsonschema/exceptions.py index 4f2f3e7..2c2ce4d 100644 --- a/jsonschema/exceptions.py +++ b/jsonschema/exceptions.py @@ -9,7 +9,6 @@ import textwrap import attr from jsonschema import _utils -from jsonschema.compat import PY3, iteritems WEAK_MATCHES = frozenset(["anyOf", "oneOf"]) @@ -61,7 +60,7 @@ class _Error(Exception): def __repr__(self): return "<%s: %r>" % (self.__class__.__name__, self.message) - def __unicode__(self): + def __str__(self): essential_for_verbose = ( self.validator, self.validator_value, self.instance, self.schema, ) @@ -88,12 +87,6 @@ class _Error(Exception): _utils.indent(pinstance), ) - if PY3: - __str__ = __unicode__ - else: - def __str__(self): - return unicode(self).encode("utf-8") - @classmethod def create_from(cls, other): return cls(**other._contents()) @@ -129,7 +122,7 @@ class _Error(Exception): return path def _set(self, **kwargs): - for k, v in iteritems(kwargs): + for k, v in kwargs.items(): if getattr(self, k) is _unset: setattr(self, k, v) @@ -179,15 +172,9 @@ class UndefinedTypeCheck(Exception): def __init__(self, type): self.type = type - def __unicode__(self): + def __str__(self): return "Type %r is unknown to this type checker" % self.type - if PY3: - __str__ = __unicode__ - else: - def __str__(self): - return unicode(self).encode("utf-8") - class UnknownType(Exception): """ @@ -199,7 +186,7 @@ class UnknownType(Exception): self.instance = instance self.schema = schema - def __unicode__(self): + def __str__(self): pschema = pprint.pformat(self.schema, width=72) pinstance = pprint.pformat(self.instance, width=72) return textwrap.dedent(""" @@ -211,12 +198,6 @@ class UnknownType(Exception): """.rstrip() ) % (self.type, _utils.indent(pschema), _utils.indent(pinstance)) - if PY3: - __str__ = __unicode__ - else: - def __str__(self): - return unicode(self).encode("utf-8") - class FormatError(Exception): """ @@ -228,15 +209,9 @@ class FormatError(Exception): self.message = message self.cause = self.__cause__ = cause - def __unicode__(self): + def __str__(self): return self.message - if PY3: - __str__ = __unicode__ - else: - def __str__(self): - return self.message.encode("utf-8") - class ErrorTree(object): """ @@ -306,7 +281,7 @@ class ErrorTree(object): The total number of errors in the entire tree, including children. """ - child_errors = sum(len(tree) for _, tree in iteritems(self._contents)) + child_errors = sum(len(tree) for _, tree in self._contents.items()) return len(self.errors) + child_errors diff --git a/jsonschema/tests/_helpers.py b/jsonschema/tests/_helpers.py index e35084c..761b404 100644 --- a/jsonschema/tests/_helpers.py +++ b/jsonschema/tests/_helpers.py @@ -1,7 +1,6 @@ -import sys +from io import StringIO from contextlib import contextmanager - -from jsonschema.compat import NativeIO +import sys def bug(issue=None): @@ -13,7 +12,7 @@ def bug(issue=None): @contextmanager def captured_output(): - new_out, new_err = NativeIO(), NativeIO() + new_out, new_err = StringIO(), StringIO() old_out, old_err = sys.stdout, sys.stderr try: sys.stdout, sys.stderr = new_out, new_err diff --git a/jsonschema/tests/_suite.py b/jsonschema/tests/_suite.py index bedf09b..cba4f87 100644 --- a/jsonschema/tests/_suite.py +++ b/jsonschema/tests/_suite.py @@ -17,7 +17,6 @@ except ImportError: import attr -from jsonschema.compat import PY3 from jsonschema.validators import validators import jsonschema @@ -188,16 +187,12 @@ class _Test(object): @property def method_name(self): delimiters = r"[\W\- ]+" - name = "test_%s_%s_%s" % ( + return "test_%s_%s_%s" % ( re.sub(delimiters, "_", self.subject), re.sub(delimiters, "_", self.case_description), re.sub(delimiters, "_", self.description), ) - if not PY3: # pragma: no cover - name = name.encode("utf-8") - return name - def to_unittest_method(self, skip=lambda test: None, **kwargs): if self.valid: def fn(this): diff --git a/jsonschema/tests/test_cli.py b/jsonschema/tests/test_cli.py index c4affaf..c473e58 100644 --- a/jsonschema/tests/test_cli.py +++ b/jsonschema/tests/test_cli.py @@ -1,3 +1,5 @@ +from io import StringIO +from json import JSONDecodeError from textwrap import dedent from unittest import TestCase import errno @@ -7,7 +9,6 @@ import subprocess import sys from jsonschema import Draft4Validator, cli, __version__ -from jsonschema.compat import JSONDecodeError, NativeIO from jsonschema.exceptions import SchemaError, ValidationError from jsonschema.tests._helpers import captured_output from jsonschema.validators import _LATEST_VERSION, validate @@ -37,7 +38,7 @@ def fake_open(all_contents): contents = all_contents.get(path) if contents is None: raise OSError(errno.ENOENT, os.strerror(errno.ENOENT), path) - return NativeIO(contents) + return StringIO(contents) return open @@ -52,7 +53,7 @@ def _message_for(non_json): class TestCLI(TestCase): def run_cli( - self, argv, files={}, stdin=NativeIO(), exit_code=0, **override + self, argv, files={}, stdin=StringIO(), exit_code=0, **override ): arguments = cli.parse_args(argv) arguments.update(override) @@ -60,7 +61,7 @@ class TestCLI(TestCase): self.assertFalse(hasattr(cli, "open")) cli.open = fake_open(files) try: - stdout, stderr = NativeIO(), NativeIO() + stdout, stderr = StringIO(), StringIO() actual_exit_code = cli.run( arguments, stdin=stdin, @@ -466,7 +467,7 @@ class TestCLI(TestCase): self.assertOutputs( files=dict(some_schema="{}"), - stdin=NativeIO(instance), + stdin=StringIO(instance), argv=["some_schema"], @@ -479,7 +480,7 @@ class TestCLI(TestCase): def test_instance_is_invalid_JSON_on_stdin_pretty_output(self): stdout, stderr = self.run_cli( files=dict(some_schema="{}"), - stdin=NativeIO("not valid JSON!"), + stdin=StringIO("not valid JSON!"), argv=["--output", "pretty", "some_schema"], @@ -651,7 +652,7 @@ class TestCLI(TestCase): def test_successful_validation_of_stdin(self): self.assertOutputs( files=dict(some_schema="{}"), - stdin=NativeIO("{}"), + stdin=StringIO("{}"), argv=["some_schema"], stdout="", stderr="", @@ -660,7 +661,7 @@ class TestCLI(TestCase): def test_successful_validation_of_stdin_pretty_output(self): self.assertOutputs( files=dict(some_schema="{}"), - stdin=NativeIO("{}"), + stdin=StringIO("{}"), argv=["--output", "pretty", "some_schema"], stdout="===[SUCCESS]===(<stdin>)===\n", stderr="", diff --git a/jsonschema/tests/test_exceptions.py b/jsonschema/tests/test_exceptions.py index eae00d7..a285550 100644 --- a/jsonschema/tests/test_exceptions.py +++ b/jsonschema/tests/test_exceptions.py @@ -2,7 +2,6 @@ from unittest import TestCase import textwrap from jsonschema import Draft4Validator, exceptions -from jsonschema.compat import PY3 class TestBestMatch(TestCase): @@ -299,8 +298,6 @@ class TestErrorInitReprStr(TestCase): return exceptions.ValidationError(**defaults) def assertShows(self, expected, **kwargs): - if PY3: # pragma: no cover - expected = expected.replace("u'", "'") expected = textwrap.dedent(expected).rstrip("\n") error = self.make_error(**kwargs) @@ -338,8 +335,8 @@ class TestErrorInitReprStr(TestCase): def test_empty_paths(self): self.assertShows( """ - Failed validating u'type' in schema: - {u'type': u'string'} + Failed validating 'type' in schema: + {'type': 'string'} On instance: 5 @@ -351,8 +348,8 @@ class TestErrorInitReprStr(TestCase): def test_one_item_paths(self): self.assertShows( """ - Failed validating u'type' in schema: - {u'type': u'string'} + Failed validating 'type' in schema: + {'type': 'string'} On instance[0]: 5 @@ -364,10 +361,10 @@ class TestErrorInitReprStr(TestCase): def test_multiple_item_paths(self): self.assertShows( """ - Failed validating u'type' in schema[u'items'][0]: - {u'type': u'string'} + Failed validating 'type' in schema['items'][0]: + {'type': 'string'} - On instance[0][u'a']: + On instance[0]['a']: 5 """, path=[0, u"a"], @@ -377,7 +374,7 @@ class TestErrorInitReprStr(TestCase): def test_uses_pprint(self): self.assertShows( """ - Failed validating u'maxLength' in schema: + Failed validating 'maxLength' in schema: {0: 0, 1: 1, 2: 2, diff --git a/jsonschema/tests/test_validators.py b/jsonschema/tests/test_validators.py index ee1ab0c..fc6a355 100644 --- a/jsonschema/tests/test_validators.py +++ b/jsonschema/tests/test_validators.py @@ -3,6 +3,7 @@ from contextlib import contextmanager from decimal import Decimal from io import BytesIO from unittest import TestCase +from urllib.request import pathname2url import json import os import sys @@ -13,7 +14,6 @@ from twisted.trial.unittest import SynchronousTestCase import attr from jsonschema import FormatChecker, TypeChecker, exceptions, validators -from jsonschema.compat import PY3, pathname2url from jsonschema.tests._helpers import bug @@ -1218,10 +1218,6 @@ class ValidatorTestMixin(MetaSchemaTestsMixin, object): self.assertFalse(self.Validator({}).is_type(True, "integer")) self.assertFalse(self.Validator({}).is_type(True, "number")) - @unittest.skipIf(PY3, "In Python 3 json.load always produces unicode") - def test_string_a_bytestring_is_a_string(self): - self.Validator({"type": "string"}).validate(b"foo") - def test_patterns_can_be_native_strings(self): """ See https://github.com/Julian/jsonschema/issues/611. diff --git a/jsonschema/validators.py b/jsonschema/validators.py index 004c09b..2ea23ac 100644 --- a/jsonschema/validators.py +++ b/jsonschema/validators.py @@ -1,6 +1,10 @@ """ Creation and extension of validators, with implementations for existing drafts. """ +from collections.abc import Sequence +from functools import lru_cache +from urllib.parse import unquote, urldefrag, urljoin, urlsplit +from urllib.request import urlopen from warnings import warn import contextlib import json @@ -13,18 +17,6 @@ from jsonschema import ( _validators, exceptions, ) -from jsonschema.compat import ( - Sequence, - int_types, - iteritems, - lru_cache, - str_types, - unquote, - urldefrag, - urljoin, - urlopen, - urlsplit, -) # Sigh. https://gitlab.com/pycqa/flake8/issues/280 # https://github.com/pyga/ebb-lint/issues/7 @@ -78,7 +70,7 @@ def _generate_legacy_type_checks(types=()): return type_check definitions = {} - for typename, pytypes in iteritems(types): + for typename, pytypes in types.items(): definitions[typename] = gen_type_check(pytypes) return definitions @@ -87,11 +79,11 @@ def _generate_legacy_type_checks(types=()): _DEPRECATED_DEFAULT_TYPES = { u"array": list, u"boolean": bool, - u"integer": int_types, + u"integer": int, u"null": type(None), u"number": numbers.Number, u"object": dict, - u"string": str_types, + u"string": str, } _TYPE_CHECKER_FOR_DEPRECATED_DEFAULT_TYPES = _types.TypeChecker( type_checkers=_generate_legacy_type_checks(_DEPRECATED_DEFAULT_TYPES), @@ -312,7 +304,7 @@ def create( if ref is not None: validators = [(u"$ref", ref)] else: - validators = iteritems(_schema) + validators = _schema.items() for k, v in validators: validator = self.VALIDATORS.get(k) @@ -650,7 +642,7 @@ class RefResolver(object): self._scopes_stack = [base_uri] self.store = _utils.URIDict( (id, validator.META_SCHEMA) - for id, validator in iteritems(meta_schemas) + for id, validator in meta_schemas.items() ) self.store.update(store) self.store[base_uri] = referrer |