summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIwan Aucamp <aucampia@gmail.com>2023-04-12 22:10:43 +0200
committerGitHub <noreply@github.com>2023-04-12 22:10:43 +0200
commit7df77cd3fa0381ae2b309981230eaa0d42e90b79 (patch)
tree0d02cc4f882e68ae7b3341b805c2338691a6853e
parent81d13d432b7e49b557b5de11691bdeaed31a9b06 (diff)
downloadrdflib-7df77cd3fa0381ae2b309981230eaa0d42e90b79.tar.gz
fix: correct imports and `__all__` (#2340)
Disable [`implicit_reexport`](https://mypy.readthedocs.io/en/stable/config_file.html#confval-implicit_reexport) and eliminate all errors reported by mypy after this. This helps ensure that import statements import from the right module and that the `__all__` variable is correct.
-rw-r--r--docs/conf.py50
-rw-r--r--docs/rdf_terms.rst2
-rw-r--r--pyproject.toml1
-rw-r--r--rdflib/namespace/_GEO.py26
-rw-r--r--rdflib/namespace/__init__.py28
-rw-r--r--rdflib/plugins/stores/sparqlconnector.py3
-rw-r--r--rdflib/plugins/stores/sparqlstore.py3
-rw-r--r--test/jsonld/runner.py6
-rw-r--r--test/jsonld/test_api.py4
-rw-r--r--test/jsonld/test_compaction.py3
-rw-r--r--test/jsonld/test_context.py3
-rw-r--r--test/jsonld/test_named_graphs.py3
-rw-r--r--test/test_dataset/test_dataset.py6
-rw-r--r--test/test_graph/test_graph.py4
-rw-r--r--test/test_graph/test_graph_context.py3
-rw-r--r--test/test_graph/test_graph_http.py8
-rw-r--r--test/test_namespace/test_namespace.py4
-rw-r--r--test/test_roundtrip.py9
-rw-r--r--test/test_sparql/test_service.py7
-rw-r--r--test/test_store/test_store_sparqlstore.py9
-rw-r--r--test/test_store/test_store_sparqlstore_query.py7
-rw-r--r--test/test_store/test_store_sparqlstore_sparqlconnector.py7
-rw-r--r--test/test_store/test_store_sparqlupdatestore_mock.py7
-rw-r--r--test/utils/httpfileserver.py3
-rw-r--r--test/utils/test/test_httpservermock.py9
25 files changed, 143 insertions, 72 deletions
diff --git a/docs/conf.py b/docs/conf.py
index 785c6fc6..1e2b7ef4 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -16,8 +16,10 @@ import logging
import os
import re
import sys
+from typing import Any, Dict
import sphinx
+import sphinx.application
import rdflib
@@ -47,6 +49,7 @@ extensions = [
"sphinx.ext.autosectionlabel",
]
+# https://github.com/sphinx-contrib/apidoc/blob/master/README.rst#configuration
apidoc_module_dir = "../rdflib"
apidoc_output_dir = "apidocs"
@@ -328,3 +331,50 @@ if sys.version_info < (3, 9):
if sys.version_info < (3, 8):
nitpick_ignore.extend([("py:class", "importlib_metadata.EntryPoint")])
+
+
+def autodoc_skip_member_handler(
+ app: sphinx.application.Sphinx,
+ what: str,
+ name: str,
+ obj: Any,
+ skip: bool,
+ options: Dict[str, Any],
+):
+ """
+ This function will be called by Sphinx when it is deciding whether to skip a
+ member of a class or module.
+ """
+ # https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#event-autodoc-skip-member
+ if (
+ app.env.docname == "apidocs/rdflib"
+ and what == "module"
+ and type(obj).__name__.endswith("DefinedNamespaceMeta")
+ ):
+ # Don't document namespaces in the `rdflib` module, they will be
+ # documented in the `rdflib.namespace` module instead and Sphinx does
+ # not like when these are documented in two places.
+ #
+ # An example of the WARNINGS that occur without this is:
+ #
+ # "WARNING: duplicate object description of rdflib.namespace._SDO.SDO,
+ # other instance in apidocs/rdflib, use :noindex: for one of them"
+ logging.info(
+ "Skipping %s %s in %s, it will be documented in ",
+ what,
+ name,
+ app.env.docname,
+ )
+ return True
+ return None
+
+
+# https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#skipping-members
+def setup(app: sphinx.application.Sphinx) -> None:
+ """
+ Setup the Sphinx application.
+ """
+
+ # Register a autodoc-skip-member handler so that certain members can be
+ # skipped.
+ app.connect("autodoc-skip-member", autodoc_skip_member_handler)
diff --git a/docs/rdf_terms.rst b/docs/rdf_terms.rst
index 66abd183..b44b0a58 100644
--- a/docs/rdf_terms.rst
+++ b/docs/rdf_terms.rst
@@ -150,7 +150,7 @@ Common XSD datatypes
^^^^^^^^^^^^^^^^^^^^
Most simple literals such as *string* or *integer* have XML Schema (XSD) datatypes defined for them, see the figure
-below. Additionally, these XSD datatypes are listed in the :class:`XSD Namespace class <rdflib.XSD>` that
+below. Additionally, these XSD datatypes are listed in the :class:`XSD Namespace class <rdflib.namespace.XSD>` that
ships with RDFLib, so many Python code editors will prompt you with autocomplete for them when using it.
Remember, you don't *have* to use XSD datatypes and can always make up your own, as GeoSPARQL does, as described above.
diff --git a/pyproject.toml b/pyproject.toml
index 87bc3cf7..5dee7655 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -211,6 +211,7 @@ disallow_subclassing_any = false
warn_unreachable = true
warn_unused_ignores = true
no_implicit_optional = false
+implicit_reexport = false
[[tool.mypy.overrides]]
module = "pyparsing.*"
diff --git a/rdflib/namespace/_GEO.py b/rdflib/namespace/_GEO.py
index 7f316fcb..c890973c 100644
--- a/rdflib/namespace/_GEO.py
+++ b/rdflib/namespace/_GEO.py
@@ -9,18 +9,20 @@ class GEO(DefinedNamespace):
Generated from: http://schemas.opengis.net/geosparql/1.0/geosparql_vocab_all.rdf
Date: 2021-12-27 17:38:15.101187
- <http://www.opengis.net/ont/geosparql> dc:creator "Open Geospatial Consortium"^^xsd:string
- dc:date "2012-04-30"^^xsd:date
- dc:source <http://www.opengis.net/doc/IS/geosparql/1.0>
- "OGC GeoSPARQL – A Geographic Query Language for RDF Data OGC 11-052r5"^^xsd:string
- rdfs:seeAlso <http://www.opengis.net/def/function/ogc-geosparql/1.0>
- <http://www.opengis.net/def/rule/ogc-geosparql/1.0>
- <http://www.opengis.net/doc/IS/geosparql/1.0>
- owl:imports dc:
- <http://www.opengis.net/ont/gml>
- <http://www.opengis.net/ont/sf>
- <http://www.w3.org/2004/02/skos/core>
- owl:versionInfo "OGC GeoSPARQL 1.0"^^xsd:string
+ .. code-block:: Turtle
+
+ <http://www.opengis.net/ont/geosparql> dc:creator "Open Geospatial Consortium"^^xsd:string
+ dc:date "2012-04-30"^^xsd:date
+ dc:source <http://www.opengis.net/doc/IS/geosparql/1.0>
+ "OGC GeoSPARQL – A Geographic Query Language for RDF Data OGC 11-052r5"^^xsd:string
+ rdfs:seeAlso <http://www.opengis.net/def/function/ogc-geosparql/1.0>
+ <http://www.opengis.net/def/rule/ogc-geosparql/1.0>
+ <http://www.opengis.net/doc/IS/geosparql/1.0>
+ owl:imports dc:
+ <http://www.opengis.net/ont/gml>
+ <http://www.opengis.net/ont/sf>
+ <http://www.w3.org/2004/02/skos/core>
+ owl:versionInfo "OGC GeoSPARQL 1.0"^^xsd:string
"""
# http://www.w3.org/2000/01/rdf-schema#Datatype
diff --git a/rdflib/namespace/__init__.py b/rdflib/namespace/__init__.py
index 618cab78..d96c21f3 100644
--- a/rdflib/namespace/__init__.py
+++ b/rdflib/namespace/__init__.py
@@ -91,6 +91,34 @@ __all__ = [
"ClosedNamespace",
"DefinedNamespace",
"NamespaceManager",
+ "BRICK",
+ "CSVW",
+ "DC",
+ "DCAM",
+ "DCAT",
+ "DCMITYPE",
+ "DCTERMS",
+ "DOAP",
+ "FOAF",
+ "GEO",
+ "ODRL2",
+ "ORG",
+ "OWL",
+ "PROF",
+ "PROV",
+ "QB",
+ "RDF",
+ "RDFS",
+ "SDO",
+ "SH",
+ "SKOS",
+ "SOSA",
+ "SSN",
+ "TIME",
+ "VANN",
+ "VOID",
+ "WGS",
+ "XSD",
]
logger = logging.getLogger(__name__)
diff --git a/rdflib/plugins/stores/sparqlconnector.py b/rdflib/plugins/stores/sparqlconnector.py
index faf57538..cbf7bd92 100644
--- a/rdflib/plugins/stores/sparqlconnector.py
+++ b/rdflib/plugins/stores/sparqlconnector.py
@@ -185,3 +185,6 @@ class SPARQLConnector:
self.update_endpoint + qsa, data=query.encode(), headers=args["headers"]
)
)
+
+
+__all__ = ["SPARQLConnector", "SPARQLConnectorException"]
diff --git a/rdflib/plugins/stores/sparqlstore.py b/rdflib/plugins/stores/sparqlstore.py
index 47bb57f9..cfffbd76 100644
--- a/rdflib/plugins/stores/sparqlstore.py
+++ b/rdflib/plugins/stores/sparqlstore.py
@@ -1011,3 +1011,6 @@ class SPARQLUpdateStore(SPARQLStore):
"""A generator of (predicate, object) tuples for the given subject"""
for t, c in self.triples((subject, None, None)):
yield t[1], t[2]
+
+
+__all__ = ["SPARQLUpdateStore", "SPARQLStore"]
diff --git a/test/jsonld/runner.py b/test/jsonld/runner.py
index 13afc085..77a80ed4 100644
--- a/test/jsonld/runner.py
+++ b/test/jsonld/runner.py
@@ -1,13 +1,13 @@
# -*- coding: UTF-8 -*-
import json
-from rdflib import ConjunctiveGraph
+from rdflib import BNode, ConjunctiveGraph
from rdflib.compare import isomorphic
from rdflib.parser import InputSource
from rdflib.plugins.parsers.jsonld import JsonLDParser, to_rdf
# monkey-patch N-Quads parser via it's underlying W3CNTriplesParser to keep source bnode id:s ..
-from rdflib.plugins.parsers.ntriples import W3CNTriplesParser, bNode, r_nodeid
+from rdflib.plugins.parsers.ntriples import W3CNTriplesParser, r_nodeid
from rdflib.plugins.serializers.jsonld import from_rdf
from rdflib.plugins.shared.jsonld.keys import CONTEXT, GRAPH
@@ -15,7 +15,7 @@ from rdflib.plugins.shared.jsonld.keys import CONTEXT, GRAPH
def _preserving_nodeid(self, bnode_context=None):
if not self.peek("_"):
return False
- return bNode(self.eat(r_nodeid).group(1))
+ return BNode(self.eat(r_nodeid).group(1))
DEFAULT_PARSER_VERSION = 1.0
diff --git a/test/jsonld/test_api.py b/test/jsonld/test_api.py
index 265c9fd5..7879bfda 100644
--- a/test/jsonld/test_api.py
+++ b/test/jsonld/test_api.py
@@ -1,5 +1,7 @@
# -*- coding: UTF-8 -*-
-from rdflib.plugin import Parser, Serializer, register
+from rdflib.parser import Parser
+from rdflib.plugin import register
+from rdflib.serializer import Serializer
register("json-ld", Parser, "rdflib.plugins.parsers.jsonld", "JsonLDParser")
register("json-ld", Serializer, "rdflib.plugins.serializers.jsonld", "JsonLDSerializer")
diff --git a/test/jsonld/test_compaction.py b/test/jsonld/test_compaction.py
index 88bcce87..e76de558 100644
--- a/test/jsonld/test_compaction.py
+++ b/test/jsonld/test_compaction.py
@@ -7,7 +7,8 @@ import re
import pytest
from rdflib import Graph
-from rdflib.plugin import Serializer, register
+from rdflib.plugin import register
+from rdflib.serializer import Serializer
register("json-ld", Serializer, "rdflib.plugins.serializers.jsonld", "JsonLDSerializer")
diff --git a/test/jsonld/test_context.py b/test/jsonld/test_context.py
index 034936d2..c26fcb0c 100644
--- a/test/jsonld/test_context.py
+++ b/test/jsonld/test_context.py
@@ -134,7 +134,8 @@ def test_prefix_like_vocab():
# Mock external sources loading
SOURCES: Dict[str, Dict[str, Any]] = {}
-_source_to_json = context.source_to_json
+# type error: Module "rdflib.plugins.shared.jsonld.context" does not explicitly export attribute "source_to_json"
+_source_to_json = context.source_to_json # type: ignore[attr-defined]
def _mock_source_loader(f):
diff --git a/test/jsonld/test_named_graphs.py b/test/jsonld/test_named_graphs.py
index 4c544621..ca25b795 100644
--- a/test/jsonld/test_named_graphs.py
+++ b/test/jsonld/test_named_graphs.py
@@ -1,6 +1,7 @@
# -*- coding: UTF-8 -*-
from rdflib import *
-from rdflib.plugin import Parser, register
+from rdflib.parser import Parser
+from rdflib.plugin import register
register("json-ld", Parser, "rdflib.plugins.parsers.jsonld", "JsonLDParser")
register("application/ld+json", Parser, "rdflib.plugins.parsers.jsonld", "JsonLDParser")
diff --git a/test/test_dataset/test_dataset.py b/test/test_dataset/test_dataset.py
index 3733a556..373383f7 100644
--- a/test/test_dataset/test_dataset.py
+++ b/test/test_dataset/test_dataset.py
@@ -7,7 +7,9 @@ from test.data import context1, likes, pizza, tarek
import pytest
from rdflib import URIRef, plugin
-from rdflib.graph import DATASET_DEFAULT_GRAPH_ID, Dataset, Graph, Namespace
+from rdflib.graph import DATASET_DEFAULT_GRAPH_ID, Dataset, Graph
+from rdflib.namespace import Namespace
+from rdflib.store import Store
# Will also run SPARQLUpdateStore tests against local SPARQL1.1 endpoint if
# available. This assumes SPARQL1.1 query/update endpoints running locally at
@@ -26,7 +28,7 @@ DB = "/db/"
pluginstores = []
-for s in plugin.plugins(None, plugin.Store):
+for s in plugin.plugins(None, Store):
if s.name in ("Memory", "Auditable", "Concurrent", "SPARQLStore"):
continue # these are tested by default
diff --git a/test/test_graph/test_graph.py b/test/test_graph/test_graph.py
index 33898d97..b133c2b5 100644
--- a/test/test_graph/test_graph.py
+++ b/test/test_graph/test_graph.py
@@ -10,7 +10,7 @@ from urllib.error import HTTPError, URLError
import pytest
-from rdflib import Graph, URIRef, plugin
+from rdflib import Graph, URIRef
from rdflib.exceptions import ParserError
from rdflib.namespace import Namespace, NamespaceManager
from rdflib.plugin import PluginException
@@ -62,7 +62,7 @@ def test_property_namespace_manager() -> None:
def get_store_names() -> Set[Optional[str]]:
- names: Set[Optional[str]] = {*get_unique_plugin_names(plugin.Store)}
+ names: Set[Optional[str]] = {*get_unique_plugin_names(Store)}
names.difference_update(
{
"default",
diff --git a/test/test_graph/test_graph_context.py b/test/test_graph/test_graph_context.py
index 9e0b712a..f6ef5c3e 100644
--- a/test/test_graph/test_graph_context.py
+++ b/test/test_graph/test_graph_context.py
@@ -7,6 +7,7 @@ from tempfile import mkdtemp, mkstemp
import pytest
from rdflib import BNode, ConjunctiveGraph, Graph, URIRef, plugin
+from rdflib.store import Store
class ContextTestCase(unittest.TestCase):
@@ -367,7 +368,7 @@ if __name__ == "__main__":
pluginname = sys.argv[1]
tests = 0
-for s in plugin.plugins(pluginname, plugin.Store):
+for s in plugin.plugins(pluginname, Store):
if s.name in (
"default",
"Memory",
diff --git a/test/test_graph/test_graph_http.py b/test/test_graph/test_graph_http.py
index 97c64c3a..4d5ed09e 100644
--- a/test/test_graph/test_graph_http.py
+++ b/test/test_graph/test_graph_http.py
@@ -6,14 +6,12 @@ from test.utils import GraphHelper
from test.utils.graph import cached_graph
from test.utils.http import (
MOCK_HTTP_REQUEST_WILDCARD,
- MockHTTPRequest,
- ctx_http_handler,
-)
-from test.utils.httpservermock import (
MethodName,
+ MockHTTPRequest,
MockHTTPResponse,
- ServedBaseHTTPServerMock,
+ ctx_http_handler,
)
+from test.utils.httpservermock import ServedBaseHTTPServerMock
from test.utils.wildcard import URL_PARSE_RESULT_WILDCARD
from urllib.error import HTTPError
diff --git a/test/test_namespace/test_namespace.py b/test/test_namespace/test_namespace.py
index db06b51f..cb3f26f5 100644
--- a/test/test_namespace/test_namespace.py
+++ b/test/test_namespace/test_namespace.py
@@ -5,7 +5,7 @@ from warnings import warn
import pytest
from rdflib import DCTERMS
-from rdflib.graph import BNode, Graph, Literal
+from rdflib.graph import Graph
from rdflib.namespace import (
FOAF,
OWL,
@@ -17,7 +17,7 @@ from rdflib.namespace import (
Namespace,
URIPattern,
)
-from rdflib.term import URIRef
+from rdflib.term import BNode, Literal, URIRef
class TestNamespace:
diff --git a/test/test_roundtrip.py b/test/test_roundtrip.py
index f06db6b8..5f233ea5 100644
--- a/test/test_roundtrip.py
+++ b/test/test_roundtrip.py
@@ -14,8 +14,9 @@ import rdflib
import rdflib.compare
from rdflib.graph import ConjunctiveGraph, Graph
from rdflib.namespace import XSD
-from rdflib.parser import create_input_source
+from rdflib.parser import Parser, create_input_source
from rdflib.plugins.parsers.notation3 import BadSyntax
+from rdflib.serializer import Serializer
from rdflib.util import guess_format
logger = logging.getLogger(__name__)
@@ -302,10 +303,8 @@ _formats: Optional[Set[str]] = None
def get_formats() -> Set[str]:
global _formats
if not _formats:
- serializers = set(
- x.name for x in rdflib.plugin.plugins(None, rdflib.plugin.Serializer)
- )
- parsers = set(x.name for x in rdflib.plugin.plugins(None, rdflib.plugin.Parser))
+ serializers = set(x.name for x in rdflib.plugin.plugins(None, Serializer))
+ parsers = set(x.name for x in rdflib.plugin.plugins(None, Parser))
_formats = {
format for format in parsers.intersection(serializers) if "/" not in format
}
diff --git a/test/test_sparql/test_service.py b/test/test_sparql/test_service.py
index 3a827054..61c317ac 100644
--- a/test/test_sparql/test_service.py
+++ b/test/test_sparql/test_service.py
@@ -1,11 +1,8 @@
import json
from contextlib import ExitStack
from test.utils import helper
-from test.utils.httpservermock import (
- MethodName,
- MockHTTPResponse,
- ServedBaseHTTPServerMock,
-)
+from test.utils.http import MethodName, MockHTTPResponse
+from test.utils.httpservermock import ServedBaseHTTPServerMock
from typing import (
Dict,
FrozenSet,
diff --git a/test/test_store/test_store_sparqlstore.py b/test/test_store/test_store_sparqlstore.py
index 62542047..5d862935 100644
--- a/test/test_store/test_store_sparqlstore.py
+++ b/test/test_store/test_store_sparqlstore.py
@@ -3,11 +3,8 @@ import re
import socket
from http.server import BaseHTTPRequestHandler, HTTPServer
from test.utils import helper
-from test.utils.httpservermock import (
- MethodName,
- MockHTTPResponse,
- ServedBaseHTTPServerMock,
-)
+from test.utils.http import MethodName, MockHTTPResponse
+from test.utils.httpservermock import ServedBaseHTTPServerMock
from threading import Thread
from typing import Callable, ClassVar, Type
from unittest.mock import patch
@@ -16,7 +13,7 @@ import pytest
from rdflib import Graph, Literal, URIRef
from rdflib.namespace import FOAF, RDF, RDFS, XMLNS, XSD
-from rdflib.plugins.stores.sparqlstore import SPARQLConnector
+from rdflib.plugins.stores.sparqlconnector import SPARQLConnector
class TestSPARQLStoreGraph:
diff --git a/test/test_store/test_store_sparqlstore_query.py b/test/test_store/test_store_sparqlstore_query.py
index da59f544..b2258592 100644
--- a/test/test_store/test_store_sparqlstore_query.py
+++ b/test/test_store/test_store_sparqlstore_query.py
@@ -3,11 +3,8 @@ from __future__ import annotations
import itertools
import logging
from test.utils import GraphHelper
-from test.utils.httpservermock import (
- MethodName,
- MockHTTPResponse,
- ServedBaseHTTPServerMock,
-)
+from test.utils.http import MethodName, MockHTTPResponse
+from test.utils.httpservermock import ServedBaseHTTPServerMock
from typing import Dict, Iterable, List, Optional, Set, Tuple
import pytest
diff --git a/test/test_store/test_store_sparqlstore_sparqlconnector.py b/test/test_store/test_store_sparqlstore_sparqlconnector.py
index b0bba9b7..992ef2b0 100644
--- a/test/test_store/test_store_sparqlstore_sparqlconnector.py
+++ b/test/test_store/test_store_sparqlstore_sparqlconnector.py
@@ -2,11 +2,8 @@ from __future__ import annotations
import json
import logging
-from test.utils.httpservermock import (
- MethodName,
- MockHTTPResponse,
- ServedBaseHTTPServerMock,
-)
+from test.utils.http import MethodName, MockHTTPResponse
+from test.utils.httpservermock import ServedBaseHTTPServerMock
from typing import Optional
import pytest
diff --git a/test/test_store/test_store_sparqlupdatestore_mock.py b/test/test_store/test_store_sparqlupdatestore_mock.py
index 1e8246be..16af8774 100644
--- a/test/test_store/test_store_sparqlupdatestore_mock.py
+++ b/test/test_store/test_store_sparqlupdatestore_mock.py
@@ -1,8 +1,5 @@
-from test.utils.httpservermock import (
- MethodName,
- MockHTTPResponse,
- ServedBaseHTTPServerMock,
-)
+from test.utils.http import MethodName, MockHTTPResponse
+from test.utils.httpservermock import ServedBaseHTTPServerMock
from typing import ClassVar
from rdflib import Namespace
diff --git a/test/utils/httpfileserver.py b/test/utils/httpfileserver.py
index c9a9dc5a..1989070a 100644
--- a/test/utils/httpfileserver.py
+++ b/test/utils/httpfileserver.py
@@ -7,8 +7,7 @@ from dataclasses import dataclass, field
from functools import lru_cache
from http.server import BaseHTTPRequestHandler, HTTPServer
from pathlib import Path
-from test.utils.http import HeadersT, MethodName, apply_headers_to
-from test.utils.httpservermock import MockHTTPRequest
+from test.utils.http import HeadersT, MethodName, MockHTTPRequest, apply_headers_to
from typing import Dict, List, Optional, Sequence, Type
from urllib.parse import parse_qs, urljoin, urlparse
from uuid import uuid4
diff --git a/test/utils/test/test_httpservermock.py b/test/utils/test/test_httpservermock.py
index e7d6e291..fe147c9e 100644
--- a/test/utils/test/test_httpservermock.py
+++ b/test/utils/test/test_httpservermock.py
@@ -1,10 +1,5 @@
-from test.utils.http import ctx_http_handler
-from test.utils.httpservermock import (
- BaseHTTPServerMock,
- MethodName,
- MockHTTPResponse,
- ServedBaseHTTPServerMock,
-)
+from test.utils.http import MethodName, MockHTTPResponse, ctx_http_handler
+from test.utils.httpservermock import BaseHTTPServerMock, ServedBaseHTTPServerMock
from urllib.error import HTTPError
from urllib.request import Request, urlopen