diff --git a/.flake8 b/.flake8 new file mode 100755 index 0000000..b70ee9f --- /dev/null +++ b/.flake8 @@ -0,0 +1,7 @@ +[flake8] +application_import_names = pyramid_urireferencer, tests +exclude = .venv, + __pycache__, +import-order-style = pycharm +max-line-length = 90 +ignore = E402, E405, W503, F403, F405 \ No newline at end of file diff --git a/.github/workflows/urireferencer.yaml b/.github/workflows/urireferencer.yaml new file mode 100644 index 0000000..21fae48 --- /dev/null +++ b/.github/workflows/urireferencer.yaml @@ -0,0 +1,42 @@ +name: Urireferencer backend tests + +on: + workflow_dispatch: + + pull_request: + paths: + - pyramid_urireferencer/** + - .github/workflows/pyramid_urireferencer.yaml + - scripts/** + - pyproject.toml + - requirements*.txt + - tests/** + + push: + branches: + - main +env: + PYTHON_VERSION: '3.11' + +jobs: + test: + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - uses: actions/checkout@v3 + + - uses: actions/setup-python@v4 + with: + python-version: ${{ env.PYTHON_VERSION }} + - name: Install python requirements + env: + HATCH_BUILD_NO_HOOKS: true + working-directory: ./ + run: | + pip --version + pip install pip-tools + pip-sync requirements-dev.txt + pip install -e . + + - name: Python tests + run: pytest tests --exitfirst --capture=no -vvv --full-trace diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..f08a0e2 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,25 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + types: [python] + - id: trailing-whitespace + types: [python] +- repo: https://github.com/psf/black + rev: 24.3.0 + hooks: + - id: black + types: [python] + args: [--preview] + exclude: docs, tests +- repo: https://github.com/PyCQA/flake8 + rev: 7.0.0 + hooks: + - id: flake8 + additional_dependencies: + - flake8-import-order==0.18.2 + - flake8-bugbear==24.2.6 + types: [python] + exclude: docs diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 3852c9d..0000000 --- a/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: python -python: - - "2.7" - - "3.6" -env: - - LC_ALL=en_US.utf-8 -install: - - pip install -r requirements-dev.txt #fix versions - - python setup.py develop -script: - - py.test --cov pyramid_urireferencer --cov-report term-missing tests -after_success: - - coveralls diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000..1c7853b --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,54 @@ +0.7.0 (29-01-2019) +================== + +- Better matching on Accept headers (\#18) +- Nieuwe protected decorator toevoegen die de request niet uit de + parent haalt maar rechtstreeks (\#50) + +0.6.0 (2017-06-08) +================== + +- Add some extra logging. (\#13) +- Add required function [get\_uri]{.title-ref} to the + [AbstractReferencer]{.title-ref} to determine the uri of the current + request (\#7 and \#8) + +0.5.0 (2016-09-28) +================== + +- Add support for python 3.5 +- Some minor doc fixes +- Changed an edge case where [items]{.title-ref} or + [applications]{.title-ref} response attributes could be + [None]{.title-ref} so that they are now always empty lists. (\#6) +- Updated error message and added JSON error message when a backend + application can\'t be reached (\#9) and when a resource can\'t be + deleted (\#10) + +0.4.0 (2015-07-10) +================== + +- Added module [protected\_resources]{.title-ref} containing a + [protected\_operation]{.title-ref} decorator function. + +0.3.0 (2015-06-25) +================== + +- Added uri and request to references parameters +- Included renderer in request config +- Removed exception in get\_references view +- Fixed ApplicationResponse title from json + +0.2.0 (2015-06-07) +================== + +- Changed ApplicationResponse.url to service\_url. +- Cleaned up some documentation. +- Added an AbstractReferencer that has no implementation whatsoever. +- Added Python Wheel support +- Make sure that the uri parameter is properly urlencoded. + +0.1.0 (2015-05-21) +================== + +- Initial version diff --git a/CHANGES.rst b/CHANGES.rst deleted file mode 100644 index 512dfb5..0000000 --- a/CHANGES.rst +++ /dev/null @@ -1,49 +0,0 @@ -0.7.0 (29-01-2019) ------------------- - -- Better matching on Accept headers (#18) -- Nieuwe protected decorator toevoegen die de request niet uit de parent haalt maar rechtstreeks (#50) - -0.6.0 (2017-06-08) ------------------- - -- Add some extra logging. (#13) -- Add required function `get_uri` to the `AbstractReferencer` to determine the uri of the current request (#7 and #8) - - -0.5.0 (2016-09-28) ------------------- - -- Add support for python 3.5 -- Some minor doc fixes -- Changed an edge case where `items` or `applications` response attributes could - be `None` so that they are now always empty lists. (#6) -- Updated error message and added JSON error message when a backend application can't be reached (#9) and when a resource can't be deleted (#10) - -0.4.0 (2015-07-10) ------------------- - -- Added module `protected_resources` containing a `protected_operation` decorator function. - -0.3.0 (2015-06-25) ------------------- - -- Added uri and request to references parameters -- Included renderer in request config -- Removed exception in get_references view -- Fixed ApplicationResponse title from json - -0.2.0 (2015-06-07) ------------------- - -- Changed ApplicationResponse.url to service_url. -- Cleaned up some documentation. -- Added an AbstractReferencer that has no implementation whatsoever. -- Added Python Wheel support -- Make sure that the uri parameter is properly urlencoded. - - -0.1.0 (2015-05-21) ------------------- - -- Initial version diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 9b9030a..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ -include *.txt *.ini *.cfg *.rst diff --git a/README.md b/README.md new file mode 100644 index 0000000..f390065 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +pyramid\_urireferencer +====================== + +This plugin for pyramid helps in handling references to resources in +other applications by allowing querying on references to certain URI\'s. + +[![image](https://travis-ci.org/OnroerendErfgoed/pyramid_urireferencer.png?branch=master)](https://travis-ci.org/OnroerendErfgoed/pyramid_urireferencer) + +[![image](https://coveralls.io/repos/OnroerendErfgoed/pyramid_urireferencer/badge.png?branch=master)](https://coveralls.io/r/OnroerendErfgoed/pyramid_urireferencer) + +[![image](https://badge.fury.io/py/pyramid_urireferencer.png)](http://badge.fury.io/py/pyramid_urireferencer) + +Please consult the documentatation for +[UriRegistry](http://uriregistry.readthedocs.org/en/latest/) for more +information on how to use this library. diff --git a/README.rst b/README.rst deleted file mode 100644 index 7e34011..0000000 --- a/README.rst +++ /dev/null @@ -1,18 +0,0 @@ -pyramid_urireferencer -===================== - -This plugin for pyramid helps in handling references to resources in other -applications by allowing querying on references to certain URI's. - - -.. image:: https://travis-ci.org/OnroerendErfgoed/pyramid_urireferencer.png?branch=master - :target: https://travis-ci.org/OnroerendErfgoed/pyramid_urireferencer -.. image:: https://coveralls.io/repos/OnroerendErfgoed/pyramid_urireferencer/badge.png?branch=master - :target: https://coveralls.io/r/OnroerendErfgoed/pyramid_urireferencer - -.. image:: https://badge.fury.io/py/pyramid_urireferencer.png - :target: http://badge.fury.io/py/pyramid_urireferencer - -Please consult the documentatation for `UriRegistry -`_ for more information on how -to use this library. diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..53b4e9b --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,67 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +version = "1.2.0" +name = "pyramid_urireferencer" +dynamic = ["readme"] +authors = [ + { name = "Flanders Heritage Agency", email = "ict@onroerenderfgoed.be" }, +] +description = "A pyramid plugin to handle referencing external URIs." +requires-python = ">=3.10,<3.13" +keywords = ["web", "wsgi", "pyramid", "SKOS", "thesaurus", "vocabulary"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Programming Language :: Python", + "Framework :: Pyramid", + "Topic :: Internet :: WWW/HTTP", + "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] +dependencies = [ + "pyramid==2.0.2", + "requests==2.32.3", + "six==1.16.0" +] + +[project.urls] +History = "https://github.com/OnroerendErfgoed/pyramid_urireferencer/blob/master/CHANGES.md" +Tracker = "https://github.com/OnroerendErfgoed/pyramid_urireferencer/issues" +Source = "https://github.com/OnroerendErfgoed/pyramid_urireferencer" +Documentation = "https://pyramid_urireferencer.readthedocs.io/en/latest/" + +[project.optional-dependencies] +dev = [ + "black==24.4.2", + "coveralls==4.0.1", + "flake8-import-order==0.18.2", + "flake8==7.1.0", + "httpretty==1.1.4", + "mock==5.1.0", + "pre-commit==3.7.1", + "pytest-cov==5.0.0", + "pytest==8.2.2", + "uv==0.2.13", + "webtest==3.0.0" +] + +[project.entry-points."paste.app_factory"] +main = "pyramid_urireferencer:main" + +## +# Build tool specific +## +[tool.hatch.build.targets.wheel] +# In the wheel we want to have pyramid_urireferencer in the root as python module. +only-include = [ + "/pyramid_urireferencer", +] + +[tool.hatch.metadata] +# This allows us to use github links as dependencies +allow-direct-references = true + diff --git a/pyramid_urireferencer/__init__.py b/pyramid_urireferencer/__init__.py index ec68237..fb2f957 100644 --- a/pyramid_urireferencer/__init__.py +++ b/pyramid_urireferencer/__init__.py @@ -1,12 +1,8 @@ -# -*- coding: utf-8 -*- - -from pyramid.path import ( - DottedNameResolver -) +from pyramid.path import DottedNameResolver from zope.interface import Interface from pyramid_urireferencer import protected_resources -from .referencer import Referencer +from .referencer import Referencer # NoQa from .renderers import json_renderer @@ -16,10 +12,10 @@ class IReferencer(Interface): def includeme(config): """this function adds some configuration for the application""" - config.add_route('references', '/references') + config.add_route("references", "/references") _add_referencer(config.registry) config.add_view_deriver(protected_resources.protected_view) - config.add_renderer('json_item', json_renderer) + config.add_renderer("json_item", json_renderer) config.scan() @@ -30,8 +26,8 @@ def _add_referencer(registry): referencer = registry.queryUtility(IReferencer) if referencer is not None: return referencer - ref = registry.settings['urireferencer.referencer'] - url = registry.settings['urireferencer.registry_url'] + ref = registry.settings["urireferencer.referencer"] + url = registry.settings["urireferencer.registry_url"] r = DottedNameResolver() registry.registerUtility(r.resolve(ref)(url), IReferencer) return registry.queryUtility(IReferencer) @@ -44,7 +40,7 @@ def get_referencer(registry): :rtype: pyramid_urireferencer.referencer.AbstractReferencer """ # Argument might be a config or request - regis = getattr(registry, 'registry', None) + regis = getattr(registry, "registry", None) if regis is None: regis = registry return regis.queryUtility(IReferencer) diff --git a/pyramid_urireferencer/models.py b/pyramid_urireferencer/models.py index cbbc231..f725ff9 100644 --- a/pyramid_urireferencer/models.py +++ b/pyramid_urireferencer/models.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import json @@ -30,12 +28,17 @@ def load_from_json(data): """ if isinstance(data, str): data = json.loads(data) - applications = [ - ApplicationResponse.load_from_json(a) for a in data['applications'] - ] if data['applications'] is not None else [] + applications = ( + [ApplicationResponse.load_from_json(a) for a in data["applications"]] + if data["applications"] is not None + else [] + ) return RegistryResponse( - data['query_uri'], data['success'], - data['has_references'], data['count'], applications + data["query_uri"], + data["success"], + data["has_references"], + data["count"], + applications, ) def to_json(self): @@ -44,7 +47,7 @@ def to_json(self): "success": self.success, "has_references": self.has_references, "count": self.count, - "applications": [app.to_json() for app in self.applications] + "applications": [app.to_json() for app in self.applications], } @@ -80,10 +83,19 @@ def load_from_json(data): """ if isinstance(data, str): data = json.loads(data) - items = [Item.load_from_json(a) for a in data['items']] if data['items'] is not None else [] + items = ( + [Item.load_from_json(a) for a in data["items"]] + if data["items"] is not None + else [] + ) return ApplicationResponse( - data['title'], data['uri'], data['service_url'], - data['success'], data['has_references'], data['count'], items + data["title"], + data["uri"], + data["service_url"], + data["success"], + data["has_references"], + data["count"], + items, ) def to_json(self): @@ -94,7 +106,7 @@ def to_json(self): "success": self.success, "has_references": self.has_references, "count": self.count, - "items": [item.to_json() for item in self.items] if self.items else [] + "items": [item.to_json() for item in self.items] if self.items else [], } @@ -118,10 +130,7 @@ def load_from_json(data): """ if isinstance(data, str): data = json.loads(data) - return Item(data['title'], data['uri']) + return Item(data["title"], data["uri"]) def to_json(self): - return { - "title": self.title, - "uri": self.uri - } + return {"title": self.title, "uri": self.uri} diff --git a/pyramid_urireferencer/protected_resources.py b/pyramid_urireferencer/protected_resources.py index 52aa7bf..1443fb7 100644 --- a/pyramid_urireferencer/protected_resources.py +++ b/pyramid_urireferencer/protected_resources.py @@ -1,15 +1,14 @@ -# -*- coding: utf-8 -*- """ Thids module is used when blocking operations on a certain uri that might be used in external applications. .. versionadded:: 0.4.0 """ + import functools import logging -from pyramid.httpexceptions import ( - HTTPInternalServerError, - HTTPConflict) +from pyramid.httpexceptions import HTTPConflict +from pyramid.httpexceptions import HTTPInternalServerError from webob import Response import pyramid_urireferencer @@ -22,62 +21,96 @@ def _advice(request): uri = referencer.get_uri(request) registery_response = referencer.is_referenced(uri) if registery_response.has_references: - if 'application/json' in request.accept: + if "application/json" in request.accept: response = Response() response.status_code = 409 response_json = { "message": "The uri {0} is still in use by other applications. " - "A total of {1} references have been found.".format(uri, registery_response.count), + "A total of {1} references have been found.".format( + uri, registery_response.count + ), "errors": [], - "registry_response": registery_response.to_json() + "registry_response": registery_response.to_json(), } for app_response in registery_response.applications: if app_response.has_references: - error_string = "{0}: {1} references found, such as {2}" \ - .format(app_response.uri, - app_response.count, - ', '.join([i.uri for i in app_response.items])) + error_string = "{0}: {1} references found, such as {2}".format( + app_response.uri, + app_response.count, + ", ".join([i.uri for i in app_response.items]), + ) response_json["errors"].append(error_string) response.json_body = response_json - response.content_type = 'application/json' + response.content_type = "application/json" return response else: raise HTTPConflict( - detail="Urireferencer: The uri {0} is still in use by other applications. " - "A total of {1} references have been found " - "in the following applications: {2}".format(uri, registery_response.count, - ', '.join([app_response.title for app_response in - registery_response.applications - if app_response.has_references]))) + detail="Urireferencer: The uri {0} is still in " + "use by other applications. " + "A total of {1} references have been found " + "in the following applications: {2}".format( + uri, + registery_response.count, + ", ".join( + [ + app_response.title + for app_response in registery_response.applications + if app_response.has_references + ] + ), + ) + ) elif not registery_response.success: - if 'application/json' in request.accept: + if "application/json" in request.accept: response = Response() response.status_code = 500 response_json = { - "message": "Unable to verify the uri {0} is no longer being used.".format(uri), + "message": "Unable to verify the uri {0} is no longer being used.".format( + uri + ), "errors": [], - "registry_response": registery_response.to_json() + "registry_response": registery_response.to_json(), } for app_response in registery_response.applications: if not app_response.success: response_json["errors"].append( - "{}: Could not verify the uri is no longer being used.".format(app_response.uri)) + "{}: Could not verify the uri is no longer being used.".format( + app_response.uri + ) + ) response.json_body = response_json - response.content_type = 'application/json' + response.content_type = "application/json" return response else: - log.error("Urireferencer: Unable to verify the uri {0} is no longer being used. " - "Could not verify with {1}".format(uri, ', ' - .join(["{0} ({1})".format(app_response.uri, - app_response.service_url) - for app_response - in registery_response.applications if - not app_response.success]))) + log.error( + "Urireferencer: Unable to verify the uri {0} is no longer being used. " + "Could not verify with {1}".format( + uri, + ", ".join( + [ + "{0} ({1})".format( + app_response.uri, app_response.service_url + ) + for app_response in registery_response.applications + if not app_response.success + ] + ), + ) + ) raise HTTPInternalServerError( - detail="Urireferencer: Unable to verify the uri {0} is no longer being used. " - "Could not verify with {1}".format(uri, ', '.join([app_response.uri for app_response - in registery_response.applications if - not app_response.success]))) + detail="Urireferencer: Unable to verify the uri {0} " + "is no longer being used. " + "Could not verify with {1}".format( + uri, + ", ".join( + [ + app_response.uri + for app_response in registery_response.applications + if not app_response.success + ] + ), + ) + ) def protected_operation(fn): @@ -92,9 +125,10 @@ def protected_operation(fn): :raises pyramid.httpexceptions.HTTPInternalServerError: Raised when we were unable to check that the URI is no longer being used. """ + @functools.wraps(fn) def advice(parent_object, *args, **kw): - response = _advice(parent_object.request) + response = _advice(parent_object.dummy_request) if response is not None: return response else: @@ -128,15 +162,17 @@ def wrapped(request, *args, **kwargs): def protected_view(view, info): """allows adding `protected=True` to a view_config`""" - if info.options.get('protected'): + if info.options.get("protected"): + def wrapper_view(context, request): response = _advice(request) if response is not None: return response else: return view(context, request) + return wrapper_view return view -protected_view.options = ('protected',) +protected_view.options = ("protected",) diff --git a/pyramid_urireferencer/referencer.py b/pyramid_urireferencer/referencer.py index 0e3336f..fd4861f 100644 --- a/pyramid_urireferencer/referencer.py +++ b/pyramid_urireferencer/referencer.py @@ -1,10 +1,9 @@ -# -*- coding: utf-8 -*- - import abc -import six +import logging + import requests +import six -import logging from .models import RegistryResponse log = logging.getLogger(__name__) @@ -16,20 +15,24 @@ class AbstractReferencer: This is an abstract class that defines what a Referencer needs to be able to handle. It does two things: - + * Check if a uri is being used in this application and report on this. * Check if a certain uri is being used in another application by query a central registry. - * this requires a function :meth:`get_uri` to determine the uri of the current request + * this requires a function :meth:`get_uri` to determine + the uri of the current request """ @abc.abstractmethod def get_uri(self, request): """ - This method extracts a uri from the request. This is the uri that needs to be checked. + This method extracts a uri from the request. + This is the uri that needs to be checked. - :param request: :class:`pyramid.request.Request` with useful configuration information and connections - of the application (registry, route_url, session) to determine the references + :param request: :class:`pyramid.request.Request` with useful + configuration information and connections + of the application (registry, route_url, session) + to determine the references :rtype: string uri: URI of the resource we need to check for """ @@ -40,8 +43,9 @@ def references(self, uri, request): resource within this application. :param string uri: URI of the resource we need to check for - :param request: :class:`pyramid.request.Request` with useful configuration information and connections - of the application (registry, route_url, session) to determine the references + :param request: :class:`pyramid.request.Request` with useful configuration + information and connections + of the application (registry, route_url, session) to determine the references :rtype: :class:`pyramid_urireferencer.models.ApplicationResponse` """ @@ -60,7 +64,8 @@ def is_referenced(self, uri): class Referencer(AbstractReferencer): """ This is an implementation of the :class:`AbstractReferencer` that adds a - generic :meth:`is_referenced` method and plain methods: :meth:`references` and :meth:`get_uri` + generic :meth:`is_referenced` method and plain + methods: :meth:`references` and :meth:`get_uri` """ def __init__(self, registry_url, **kwargs): @@ -79,8 +84,8 @@ def is_referenced(self, uri): :rtype: :class:`pyramid_urireferencer.models.RegistryResponse` """ try: - url = '{0}/references'.format(self.registry_url) - r = requests.get(url, params={'uri': uri}) + url = "{0}/references".format(self.registry_url) + r = requests.get(url, params={"uri": uri}) return RegistryResponse.load_from_json(r.json()) except Exception as e: log.error(e) diff --git a/pyramid_urireferencer/renderers.py b/pyramid_urireferencer/renderers.py index 469dc79..34e8247 100644 --- a/pyramid_urireferencer/renderers.py +++ b/pyramid_urireferencer/renderers.py @@ -1,61 +1,68 @@ -# -*- coding: utf-8 -*- - - from pyramid.renderers import JSON -from pyramid_urireferencer.models import ( - RegistryResponse, - ApplicationResponse -) +from pyramid_urireferencer.models import ApplicationResponse +from pyramid_urireferencer.models import RegistryResponse json_renderer = JSON() def registry_adapter(obj, request): """ - Adapter for rendering a :class:`pyramid_urireferencer.models.RegistryResponse` to json. + Adapter for rendering a :class:`RegistryResponse` to json. - :param pyramid_urireferencer.models.RegistryResponse obj: The response to be rendered. + :param pyramid_urireferencer.models.RegistryResponse obj: + The response to be rendered. :rtype: :class:`dict` """ return { - 'query_uri': obj.query_uri, - 'success': obj.success, - 'has_references': obj.has_references, - 'count': obj.count, - 'applications': [{ - 'title': a.title, - 'uri': a.uri, - 'service_url': a.service_url, - 'success': a.success, - 'has_references': a.has_references, - 'count': a.count, - 'items': [{ - 'uri': i.uri, - 'title': i.title - } for i in a.items] if a.items is not None else None - } for a in obj.applications] if obj.applications is not None else None + "query_uri": obj.query_uri, + "success": obj.success, + "has_references": obj.has_references, + "count": obj.count, + "applications": ( + [ + { + "title": a.title, + "uri": a.uri, + "service_url": a.service_url, + "success": a.success, + "has_references": a.has_references, + "count": a.count, + "items": ( + [{"uri": i.uri, "title": i.title} for i in a.items] + if a.items is not None + else None + ), + } + for a in obj.applications + ] + if obj.applications is not None + else None + ), } def application_adapter(obj, request): """ - Adapter for rendering a :class:`pyramid_urireferencer.models.ApplicationResponse` to json. + Adapter for rendering a + :class:`pyramid_urireferencer.models.ApplicationResponse` to json. - :param pyramid_urireferencer.models.ApplicationResponse obj: The response to be rendered. + :param pyramid_urireferencer.models.ApplicationResponse obj: + The response to be rendered. :rtype: :class:`dict` """ return { - 'title': obj.title, - 'uri': obj.uri, - 'service_url': obj.service_url, - 'success': obj.success, - 'has_references': obj.has_references, - 'count': obj.count, - 'items': [{ - 'uri': i.uri, - 'title': i.title - } for i in obj.items] if obj.items is not None else None + "title": obj.title, + "uri": obj.uri, + "service_url": obj.service_url, + "success": obj.success, + "has_references": obj.has_references, + "count": obj.count, + "items": ( + [{"uri": i.uri, "title": i.title} for i in obj.items] + if obj.items is not None + else None + ), } diff --git a/pyramid_urireferencer/views.py b/pyramid_urireferencer/views.py index b7f5670..4f4cbd1 100644 --- a/pyramid_urireferencer/views.py +++ b/pyramid_urireferencer/views.py @@ -1,9 +1,9 @@ -# -*- coding: utf-8 -*- +import logging + from pyramid.httpexceptions import HTTPBadRequest from pyramid.view import view_config -from pyramid_urireferencer import get_referencer -import logging +from pyramid_urireferencer import get_referencer log = logging.getLogger(__name__) @@ -18,8 +18,12 @@ class RestView(ApplicatieView): class ReferencesPluginView(RestView): - @view_config(route_name='references', renderer='json_item', accept='application/json') + @view_config( + route_name="references", renderer="json_item", accept="application/json" + ) def get_references(self): - if not self.request.params.get('uri'): - raise HTTPBadRequest('Uri is required.') - return get_referencer(self.request.registry).references(self.request.params.get('uri'), self.request) + if not self.request.params.get("uri"): + raise HTTPBadRequest("Uri is required.") + return get_referencer(self.request.registry).references( + self.request.params.get("uri"), self.request + ) diff --git a/requirements-dev.txt b/requirements-dev.txt index 0742359..868adc8 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,14 +1,104 @@ -# Runtime requirements ---requirement requirements.txt - -#testing -pytest==4.6.11 -pytest-cov==2.5.1 -webtest==2.0.29 -httpretty==0.8.14 -coveralls==1.3.0 -mock==2.0.0 - - -#wheel -wheel==0.30.0 +beautifulsoup4==4.12.3 + # via webtest +black==24.4.2 +certifi==2024.6.2 + # via requests +cfgv==3.4.0 + # via pre-commit +charset-normalizer==3.3.2 + # via requests +click==8.1.7 + # via black +coverage==7.5.4 + # via + # coveralls + # pytest-cov +coveralls==4.0.1 +distlib==0.3.8 + # via virtualenv +docopt==0.6.2 + # via coveralls +filelock==3.15.4 + # via virtualenv +flake8==7.1.0 +flake8-import-order==0.18.2 +httpretty==1.1.4 +hupper==1.12.1 + # via pyramid +identify==2.5.36 + # via pre-commit +idna==3.7 + # via requests +iniconfig==2.0.0 + # via pytest +mccabe==0.7.0 + # via flake8 +mock==5.1.0 +mypy-extensions==1.0.0 + # via black +nodeenv==1.9.1 + # via pre-commit +packaging==24.1 + # via + # black + # pytest +pastedeploy==3.1.0 + # via plaster-pastedeploy +pathspec==0.12.1 + # via black +plaster==1.1.2 + # via + # plaster-pastedeploy + # pyramid +plaster-pastedeploy==1.0.1 + # via pyramid +platformdirs==4.2.2 + # via + # black + # virtualenv +pluggy==1.5.0 + # via pytest +pre-commit==3.7.1 +pycodestyle==2.12.0 + # via + # flake8 + # flake8-import-order +pyflakes==3.2.0 + # via flake8 +pyramid==2.0.2 +pytest==8.2.2 + # via pytest-cov +pytest-cov==5.0.0 +pyyaml==6.0.1 + # via pre-commit +requests==2.32.3 + # via coveralls +setuptools==70.1.0 + # via + # flake8-import-order + # pyramid + # zope-deprecation + # zope-interface +six==1.16.0 +soupsieve==2.5 + # via beautifulsoup4 +translationstring==1.4 + # via pyramid +urllib3==2.2.2 + # via requests +uv==0.2.13 +venusian==3.1.0 + # via pyramid +virtualenv==20.26.3 + # via pre-commit +waitress==3.0.0 + # via webtest +webob==1.8.7 + # via + # pyramid + # webtest +webtest==3.0.0 +zope-deprecation==5.0 + # via pyramid +zope-interface==6.4.post2 + # via pyramid diff --git a/requirements.txt b/requirements.txt index 52e0b58..edb7eaa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,36 @@ -requests==2.21.0 -pyramid==1.10.1 -six==1.12.0 \ No newline at end of file +certifi==2024.6.2 + # via requests +charset-normalizer==3.3.2 + # via requests +hupper==1.12.1 + # via pyramid +idna==3.7 + # via requests +pastedeploy==3.1.0 + # via plaster-pastedeploy +plaster==1.1.2 + # via + # plaster-pastedeploy + # pyramid +plaster-pastedeploy==1.0.1 + # via pyramid +pyramid==2.0.2 +requests==2.32.3 +setuptools==70.1.0 + # via + # pyramid + # zope-deprecation + # zope-interface +six==1.16.0 +translationstring==1.4 + # via pyramid +urllib3==2.2.2 + # via requests +venusian==3.1.0 + # via pyramid +webob==1.8.7 + # via pyramid +zope-deprecation==5.0 + # via pyramid +zope-interface==6.4.post2 + # via pyramid diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 2a9acf1..0000000 --- a/setup.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[bdist_wheel] -universal = 1 diff --git a/setup.py b/setup.py deleted file mode 100644 index 9e1aded..0000000 --- a/setup.py +++ /dev/null @@ -1,42 +0,0 @@ -import os - -from setuptools import setup, find_packages - -requires = [ - 'pyramid', - 'requests', - 'six' - ] - -here = os.path.abspath(os.path.dirname(__file__)) -with open(os.path.join(here, 'README.rst')) as f: - README = f.read() -with open(os.path.join(here, 'CHANGES.rst')) as f: - CHANGES = f.read() - -setup(name='pyramid_urireferencer', - version='0.7.0', - description='A pyramid plugin to handle referencing external URIs.', - long_description=README + '\n\n' + CHANGES, - classifiers=[ - "License :: OSI Approved :: MIT License", - "Intended Audience :: Developers", - "Framework :: Pyramid", - "Topic :: Internet :: WWW/HTTP", - "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", - "Programming Language :: Python", - "Programming Language :: Python :: 2.7", - "Programming Language :: Python :: 3.3", - "Programming Language :: Python :: 3.4", - "Programming Language :: Python :: 3.5" - ], - author='Flanders Heritage Agency', - author_email='ict@onroerenderfgoed.be', - url='https://github.com/OnroerendErfgoed/pyramid_urireferencer', - keywords='web wsgi pyramid uri REST references', - packages=find_packages(), - include_package_data=True, - zip_safe=False, - test_suite='pyramid_urireferencer', - install_requires=requires, - ) diff --git a/tests/test_models.py b/tests/test_models.py index 324a53d..1ccb00f 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -1,34 +1,31 @@ -# -*- coding: utf-8 -*- - import json -from pyramid_urireferencer.models import ( - RegistryResponse, - ApplicationResponse, - Item -) +from pyramid_urireferencer.models import ApplicationResponse +from pyramid_urireferencer.models import Item +from pyramid_urireferencer.models import RegistryResponse + class TestRegistryResponse: def test_init(self): rr = RegistryResponse( - 'http://id.example.org/me', + "http://id.example.org/me", True, True, 1, [ ApplicationResponse( - 'Zotskapp', - 'http://zotskapp.be/', - 'http://zotskap.be/references', + "Zotskapp", + "http://zotskapp.be/", + "http://zotskap.be/references", True, True, 1, - [Item('Red with dots.', 'http://zotskapp.be/redwithdots')] + [Item("Red with dots.", "http://zotskapp.be/redwithdots")], ) - ] + ], ) - assert rr.query_uri == 'http://id.example.org/me' + assert rr.query_uri == "http://id.example.org/me" assert rr.success assert rr.has_references assert rr.count == 1 @@ -36,14 +33,14 @@ def test_init(self): def test_load_from_json(self): data = { - 'query_uri': 'http://id.example.org/me', - 'success': True, - 'has_references': False, - 'count': 0, - 'applications': [] + "query_uri": "http://id.example.org/me", + "success": True, + "has_references": False, + "count": 0, + "applications": [], } rr = RegistryResponse.load_from_json(data) - assert rr.query_uri == 'http://id.example.org/me' + assert rr.query_uri == "http://id.example.org/me" assert rr.success assert not rr.has_references assert rr.count == 0 @@ -51,15 +48,15 @@ def test_load_from_json(self): def test_load_from_json_string(self): data = { - 'query_uri': 'http://id.example.org/me', - 'success': True, - 'has_references': False, - 'count': 0, - 'applications': [] + "query_uri": "http://id.example.org/me", + "success": True, + "has_references": False, + "count": 0, + "applications": [], } data = json.dumps(data) rr = RegistryResponse.load_from_json(data) - assert rr.query_uri == 'http://id.example.org/me' + assert rr.query_uri == "http://id.example.org/me" assert rr.success assert not rr.has_references assert rr.count == 0 @@ -67,15 +64,15 @@ def test_load_from_json_string(self): def test_load_from_json_string_applications_none(self): data = { - 'query_uri': 'http://id.example.org/me', - 'success': True, - 'has_references': False, - 'count': 0, - 'applications': None + "query_uri": "http://id.example.org/me", + "success": True, + "has_references": False, + "count": 0, + "applications": None, } data = json.dumps(data) rr = RegistryResponse.load_from_json(data) - assert rr.query_uri == 'http://id.example.org/me' + assert rr.query_uri == "http://id.example.org/me" assert rr.success assert not rr.has_references assert rr.count == 0 @@ -86,16 +83,16 @@ class TestApplicationResponse: def test_init(self): ar = ApplicationResponse( - 'Zotskapp', - 'http://zotskapp.be', - 'http://zotskapp.be/references', + "Zotskapp", + "http://zotskapp.be", + "http://zotskapp.be/references", True, True, 1, - [Item('Red with dots.', 'http://zotskapp.be/redwithdots')] + [Item("Red with dots.", "http://zotskapp.be/redwithdots")], ) - assert ar.uri == 'http://zotskapp.be' - assert ar.service_url == 'http://zotskapp.be/references' + assert ar.uri == "http://zotskapp.be" + assert ar.service_url == "http://zotskapp.be/references" assert ar.success assert ar.has_references assert ar.count == 1 @@ -103,21 +100,20 @@ def test_init(self): def test_load_from_json(self): data = { - 'title': 'Zotskapp', - 'uri': 'http://zotskapp.be', - 'service_url': 'http://zotskapp.be/references', - 'success': True, - 'has_references': True, - 'count': 1, - 'items': [{ - 'uri': 'http://zotskapp.be/redwithdots', - 'title': 'Red with dots.' - }] + "title": "Zotskapp", + "uri": "http://zotskapp.be", + "service_url": "http://zotskapp.be/references", + "success": True, + "has_references": True, + "count": 1, + "items": [ + {"uri": "http://zotskapp.be/redwithdots", "title": "Red with dots."} + ], } ar = ApplicationResponse.load_from_json(data) assert isinstance(ar, ApplicationResponse) - assert ar.uri == 'http://zotskapp.be' - assert ar.service_url == 'http://zotskapp.be/references' + assert ar.uri == "http://zotskapp.be" + assert ar.service_url == "http://zotskapp.be/references" assert ar.success assert ar.has_references assert ar.count == 1 @@ -125,22 +121,21 @@ def test_load_from_json(self): def test_load_from_json_string(self): data = { - 'title': 'Zotskapp', - 'uri': 'http://zotskapp.be', - 'service_url': 'http://zotskapp.be/references', - 'success': True, - 'has_references': True, - 'count': 1, - 'items': [{ - 'uri': 'http://zotskapp.be/redwithdots', - 'title': 'Red with dots.' - }] + "title": "Zotskapp", + "uri": "http://zotskapp.be", + "service_url": "http://zotskapp.be/references", + "success": True, + "has_references": True, + "count": 1, + "items": [ + {"uri": "http://zotskapp.be/redwithdots", "title": "Red with dots."} + ], } data = json.dumps(data) ar = ApplicationResponse.load_from_json(data) assert isinstance(ar, ApplicationResponse) - assert ar.uri == 'http://zotskapp.be' - assert ar.service_url == 'http://zotskapp.be/references' + assert ar.uri == "http://zotskapp.be" + assert ar.service_url == "http://zotskapp.be/references" assert ar.success assert ar.has_references assert ar.count == 1 @@ -148,48 +143,43 @@ def test_load_from_json_string(self): def test_load_from_json_string_no_items(self): data = { - 'title': 'Zotskapp', - 'uri': 'http://zotskapp.be', - 'service_url': 'http://zotskapp.be/references', - 'success': True, - 'has_references': False, - 'count': 0, - 'items': [] + "title": "Zotskapp", + "uri": "http://zotskapp.be", + "service_url": "http://zotskapp.be/references", + "success": True, + "has_references": False, + "count": 0, + "items": [], } data = json.dumps(data) ar = ApplicationResponse.load_from_json(data) assert isinstance(ar, ApplicationResponse) - assert ar.uri == 'http://zotskapp.be' - assert ar.service_url == 'http://zotskapp.be/references' + assert ar.uri == "http://zotskapp.be" + assert ar.service_url == "http://zotskapp.be/references" assert ar.success assert not ar.has_references assert ar.count == 0 assert len(ar.items) == 0 + class TestItem: def test_init(self): - i = Item('Red with dots.', 'http://zotskapp.be/redwithdots') - assert i.title == 'Red with dots.' - assert i.uri == 'http://zotskapp.be/redwithdots' + i = Item("Red with dots.", "http://zotskapp.be/redwithdots") + assert i.title == "Red with dots." + assert i.uri == "http://zotskapp.be/redwithdots" def test_load_from_json(self): - data = { - 'uri': 'http://zotskapp.be/redwithdots', - 'title': 'Red with dots.' - } + data = {"uri": "http://zotskapp.be/redwithdots", "title": "Red with dots."} i = Item.load_from_json(data) assert isinstance(i, Item) - assert i.title == 'Red with dots.' - assert i.uri == 'http://zotskapp.be/redwithdots' + assert i.title == "Red with dots." + assert i.uri == "http://zotskapp.be/redwithdots" def test_load_from_json_string(self): - data = { - 'uri': 'http://zotskapp.be/redwithdots', - 'title': 'Red with dots.' - } + data = {"uri": "http://zotskapp.be/redwithdots", "title": "Red with dots."} data = json.dumps(data) i = Item.load_from_json(data) assert isinstance(i, Item) - assert i.title == 'Red with dots.' - assert i.uri == 'http://zotskapp.be/redwithdots' + assert i.title == "Red with dots." + assert i.uri == "http://zotskapp.be/redwithdots" diff --git a/tests/test_protected_resources.py b/tests/test_protected_resources.py index 8e8814d..1e043bf 100644 --- a/tests/test_protected_resources.py +++ b/tests/test_protected_resources.py @@ -1,239 +1,325 @@ -# -*- coding: utf-8 -*- import logging import unittest +from unittest.mock import patch import pytest from pyramid import testing +from pyramid.httpexceptions import HTTPConflict +from pyramid.httpexceptions import HTTPInternalServerError from webob.acceptparse import AcceptValidHeader +from pyramid_urireferencer.models import ApplicationResponse +from pyramid_urireferencer.models import Item +from pyramid_urireferencer.models import RegistryResponse from pyramid_urireferencer.protected_resources import protected_operation -from pyramid_urireferencer.protected_resources \ - import protected_operation_with_request -from pyramid_urireferencer.models import RegistryResponse, Item, ApplicationResponse -from pyramid.httpexceptions import HTTPConflict, HTTPInternalServerError - -try: - from unittest.mock import Mock, patch -except ImportError: - from mock import Mock, patch # pragma: no cover +from pyramid_urireferencer.protected_resources import protected_operation_with_request def get_app(nr): items = [] if nr == 1: - items.append(Item(uri="https://dev-besluiten.onroerenderfgoed.be/besluiten/152", title="Mijn besluit")) - items.append(Item(uri="https://dev-besluiten.onroerenderfgoed.be/besluiten/154", - title="Vaststelling van de inventaris van het Bouwkundig Erfgoed op 28 november 2014")) + items.append( + Item( + uri="https://dev-besluiten.onroerenderfgoed.be/besluiten/152", + title="Mijn besluit", + ) + ) + items.append( + Item( + uri="https://dev-besluiten.onroerenderfgoed.be/besluiten/154", + title="Vaststelling van de inventaris van het " + "Bouwkundig Erfgoed op 28 november 2014", + ) + ) a = ApplicationResponse( - title='App {0}'.format(nr), - uri="https://dev-app-{0}.onroerenderfgoed.be/".format(nr), - service_url="https://dev-app-{0}.onroerenderfgoed.be/references".format(nr), - success=True, - has_references=True if nr == 1 else False, - count=2 if nr == 1 else 0, - items=items + title="App {0}".format(nr), + uri="https://dev-app-{0}.onroerenderfgoed.be/".format(nr), + service_url="https://dev-app-{0}.onroerenderfgoed.be/references".format(nr), + success=True, + has_references=True if nr == 1 else False, + count=2 if nr == 1 else 0, + items=items, ) return a def get_app_500(): return ApplicationResponse( - title='App', + title="App", uri="https://dev-app.onroerenderfgoed.be/", service_url="https://dev-app.onroerenderfgoed.be/references", success=False, has_references=None, count=None, - items=None + items=None, ) class DummyParent(object): - def __init__(self, accepts='*/*'): - self.request = testing.DummyRequest() - self.request.accept = AcceptValidHeader(accepts) - config = testing.setUp(request=self.request) + def __init__(self, accepts="*/*"): + self.dummy_request = testing.DummyRequest() + self.dummy_request.accept = AcceptValidHeader(accepts) + config = testing.setUp(request=self.dummy_request) config.registry.settings = { - 'urireferencer.referencer': 'test_views.TestReferencer', - 'urireferencer.registry_url': 'http://my.registry.org' + "urireferencer.referencer": "test_views.TestReferencer", + "urireferencer.registry_url": "http://my.registry.org", } - config.include('pyramid_urireferencer') + config.include("pyramid_urireferencer") @protected_operation def protected_dummy(self): - return 'dummy ok' + return "dummy ok" class ProtectedTests(unittest.TestCase): def setUp(self): logging.basicConfig(level=logging.WARN) - @patch('pyramid_urireferencer.protected_resources.pyramid_urireferencer.Referencer.is_referenced') + @patch( + "pyramid_urireferencer.protected_resources" + ".pyramid_urireferencer.Referencer.is_referenced" + ) def test_protected_operation(self, is_referenced_mock): - dummy = DummyParent('application/html') - is_referenced_mock.return_value = RegistryResponse('https://id.erfgoed.net/resources/1', True, False, 0, []) + dummy = DummyParent("application/html") + is_referenced_mock.return_value = RegistryResponse( + "https://id.erfgoed.net/resources/1", True, False, 0, [] + ) dummy.protected_dummy() is_referenced_call = is_referenced_mock.mock_calls[0] - self.assertEqual('https://id.erfgoed.net/resources/1', is_referenced_call[1][0]) + self.assertEqual("https://id.erfgoed.net/resources/1", is_referenced_call[1][0]) - @patch('pyramid_urireferencer.protected_resources.pyramid_urireferencer.Referencer.is_referenced') + @patch( + "pyramid_urireferencer.protected_resources" + ".pyramid_urireferencer.Referencer.is_referenced" + ) def test_protected_operation_409(self, is_referenced_mock): - dummy = DummyParent(accepts='application/html') - is_referenced_mock.return_value = RegistryResponse('https://id.erfgoed.net/resources/1', True, True, 10, - [get_app(1), get_app(2)]) + dummy = DummyParent(accepts="application/html") + is_referenced_mock.return_value = RegistryResponse( + "https://id.erfgoed.net/resources/1", + True, + True, + 10, + [get_app(1), get_app(2)], + ) self.assertRaises(HTTPConflict, dummy.protected_dummy) is_referenced_call = is_referenced_mock.mock_calls[0] - self.assertEqual('https://id.erfgoed.net/resources/1', is_referenced_call[1][0]) + self.assertEqual("https://id.erfgoed.net/resources/1", is_referenced_call[1][0]) - @patch('pyramid_urireferencer.protected_resources.pyramid_urireferencer.Referencer.is_referenced') + @patch( + "pyramid_urireferencer.protected_resources" + ".pyramid_urireferencer.Referencer.is_referenced" + ) def test_protected_operation_409_2(self, is_referenced_mock): - dummy = DummyParent(accepts='application/html') - is_referenced_mock.return_value = RegistryResponse('https://id.erfgoed.net/resources/1', False, True, 10, - [get_app(1), get_app(2)]) + dummy = DummyParent(accepts="application/html") + is_referenced_mock.return_value = RegistryResponse( + "https://id.erfgoed.net/resources/1", + False, + True, + 10, + [get_app(1), get_app(2)], + ) self.assertRaises(HTTPConflict, dummy.protected_dummy) is_referenced_call = is_referenced_mock.mock_calls[0] - self.assertEqual('https://id.erfgoed.net/resources/1', is_referenced_call[1][0]) + self.assertEqual("https://id.erfgoed.net/resources/1", is_referenced_call[1][0]) - @patch('pyramid_urireferencer.protected_resources.pyramid_urireferencer.Referencer.is_referenced') + @patch( + "pyramid_urireferencer.protected_resources" + ".pyramid_urireferencer.Referencer.is_referenced" + ) def test_protected_operation_409_json(self, is_referenced_mock): - dummy = DummyParent('application/json') - is_referenced_mock.return_value = RegistryResponse('https://id.erfgoed.net/resources/1', False, True, 2, - [get_app(1), get_app(2)]) + dummy = DummyParent("application/json") + is_referenced_mock.return_value = RegistryResponse( + "https://id.erfgoed.net/resources/1", + False, + True, + 2, + [get_app(1), get_app(2)], + ) res = dummy.protected_dummy() self.assertEqual(409, res.status_code) - self.assertEqual(res.json_body["message"], - "The uri https://id.erfgoed.net/resources/1 is still in use by other applications. A total of 2 references have been found.") + self.assertEqual( + res.json_body["message"], + "The uri https://id.erfgoed.net/resources/1 is still in " + "use by other applications. A total of 2 references have been found.", + ) self.assertEqual("application/json", res.content_type) is_referenced_call = is_referenced_mock.mock_calls[0] - self.assertEqual('https://id.erfgoed.net/resources/1', is_referenced_call[1][0]) + self.assertEqual("https://id.erfgoed.net/resources/1", is_referenced_call[1][0]) - @patch('pyramid_urireferencer.protected_resources.pyramid_urireferencer.Referencer.is_referenced') + @patch( + "pyramid_urireferencer.protected_resources" + ".pyramid_urireferencer.Referencer.is_referenced" + ) def test_protected_operation_409_json_multiple(self, is_referenced_mock): - dummy = DummyParent('application/json, application/html') + dummy = DummyParent("application/json, application/html") is_referenced_mock.return_value = RegistryResponse( - 'https://id.erfgoed.net/resources/1', False, True, 2, - [get_app(1), get_app(2)]) + "https://id.erfgoed.net/resources/1", + False, + True, + 2, + [get_app(1), get_app(2)], + ) res = dummy.protected_dummy() self.assertEqual(409, res.status_code) - self.assertEqual(res.json_body["message"], - "The uri https://id.erfgoed.net/resources/1 is still in use by other applications. A total of 2 references have been found.") + self.assertEqual( + res.json_body["message"], + "The uri https://id.erfgoed.net/resources/1 is still in " + "use by other applications. A total of 2 references have been found.", + ) self.assertEqual("application/json", res.content_type) is_referenced_call = is_referenced_mock.mock_calls[0] - self.assertEqual('https://id.erfgoed.net/resources/1', is_referenced_call[1][0]) + self.assertEqual("https://id.erfgoed.net/resources/1", is_referenced_call[1][0]) - @patch('pyramid_urireferencer.protected_resources.pyramid_urireferencer.Referencer.is_referenced') + @patch( + "pyramid_urireferencer.protected_resources" + ".pyramid_urireferencer.Referencer.is_referenced" + ) def test_protected_operation_500(self, is_referenced_mock): - dummy = DummyParent('application/html') - is_referenced_mock.return_value = RegistryResponse('https://id.erfgoed.net/resources/1', False, None, None, - [get_app_500()]) + dummy = DummyParent("application/html") + is_referenced_mock.return_value = RegistryResponse( + "https://id.erfgoed.net/resources/1", False, None, None, [get_app_500()] + ) self.assertRaises(HTTPInternalServerError, dummy.protected_dummy) is_referenced_call = is_referenced_mock.mock_calls[0] - self.assertEqual('https://id.erfgoed.net/resources/1', is_referenced_call[1][0]) + self.assertEqual("https://id.erfgoed.net/resources/1", is_referenced_call[1][0]) - @patch('pyramid_urireferencer.protected_resources.pyramid_urireferencer.Referencer.is_referenced') + @patch( + "pyramid_urireferencer.protected_resources" + ".pyramid_urireferencer.Referencer.is_referenced" + ) def test_protected_operation_500_json(self, is_referenced_mock): - dummy = DummyParent('application/json') - is_referenced_mock.return_value = RegistryResponse('https://id.erfgoed.net/resources/1', False, None, None, - [get_app_500()]) + dummy = DummyParent("application/json") + is_referenced_mock.return_value = RegistryResponse( + "https://id.erfgoed.net/resources/1", False, None, None, [get_app_500()] + ) res = dummy.protected_dummy() self.assertEqual(500, res.status_code) - self.assertEqual(res.json_body["message"], - "Unable to verify the uri https://id.erfgoed.net/resources/1 is no longer being used.") - self.assertListEqual(res.json_body["errors"], - ["https://dev-app.onroerenderfgoed.be/: Could not verify the uri is no longer being used."]) + self.assertEqual( + res.json_body["message"], + "Unable to verify the uri " + "https://id.erfgoed.net/resources/1 is no longer being used.", + ) + self.assertListEqual( + res.json_body["errors"], + [ + "https://dev-app.onroerenderfgoed.be/: " + "Could not verify the uri is no longer being used." + ], + ) self.assertEqual("application/json", res.content_type) is_referenced_call = is_referenced_mock.mock_calls[0] - self.assertEqual('https://id.erfgoed.net/resources/1', is_referenced_call[1][0]) + self.assertEqual("https://id.erfgoed.net/resources/1", is_referenced_call[1][0]) @protected_operation_with_request -def protected_dummy(request): - return 'dummy ok' +def protected_dummy(dummy_request): + return "dummy ok" -@patch('pyramid_urireferencer.protected_resources.pyramid_urireferencer' - '.Referencer.is_referenced') +@patch( + "pyramid_urireferencer.protected_resources.pyramid_urireferencer" + ".Referencer.is_referenced" +) class TestProtectedWithRequest(object): def setUp(self): logging.basicConfig(level=logging.WARN) @pytest.fixture() - def request(self): - request = testing.DummyRequest() - request.accept = AcceptValidHeader('application/html') - config = testing.setUp(request=request) + def dummy_request(self): + dummy_request = testing.DummyRequest() + dummy_request.accept = AcceptValidHeader("application/html") + config = testing.setUp(request=dummy_request) config.registry.settings = { - 'urireferencer.referencer': 'test_views.TestReferencer', - 'urireferencer.registry_url': 'http://my.registry.org' + "urireferencer.referencer": "test_views.TestReferencer", + "urireferencer.registry_url": "http://my.registry.org", } - config.include('pyramid_urireferencer') - return request + config.include("pyramid_urireferencer") + return dummy_request - def test_protected_operation(self, is_referenced_mock, request): + def test_protected_operation(self, is_referenced_mock, dummy_request): is_referenced_mock.return_value = RegistryResponse( - 'https://id.erfgoed.net/resources/1', True, False, 0, []) - protected_dummy(request) + "https://id.erfgoed.net/resources/1", True, False, 0, [] + ) + protected_dummy(dummy_request) is_referenced_call = is_referenced_mock.mock_calls[0] - assert 'https://id.erfgoed.net/resources/1' == is_referenced_call[1][0] + assert "https://id.erfgoed.net/resources/1" == is_referenced_call[1][0] - def test_protected_operation_409(self, is_referenced_mock, request): + def test_protected_operation_409(self, is_referenced_mock, dummy_request): is_referenced_mock.return_value = RegistryResponse( - 'https://id.erfgoed.net/resources/1', True, True, 10, - [get_app(1), get_app(2)]) + "https://id.erfgoed.net/resources/1", + True, + True, + 10, + [get_app(1), get_app(2)], + ) with pytest.raises(HTTPConflict): - protected_dummy(request) + protected_dummy(dummy_request) is_referenced_call = is_referenced_mock.mock_calls[0] - assert 'https://id.erfgoed.net/resources/1' == is_referenced_call[1][0] + assert "https://id.erfgoed.net/resources/1" == is_referenced_call[1][0] - def test_protected_operation_409_2(self, is_referenced_mock, request): + def test_protected_operation_409_2(self, is_referenced_mock, dummy_request): is_referenced_mock.return_value = RegistryResponse( - 'https://id.erfgoed.net/resources/1', False, True, 10, - [get_app(1), get_app(2)]) + "https://id.erfgoed.net/resources/1", + False, + True, + 10, + [get_app(1), get_app(2)], + ) with pytest.raises(HTTPConflict): - protected_dummy(request) + protected_dummy(dummy_request) is_referenced_call = is_referenced_mock.mock_calls[0] - assert 'https://id.erfgoed.net/resources/1' == is_referenced_call[1][0] + assert "https://id.erfgoed.net/resources/1" == is_referenced_call[1][0] - def test_protected_operation_409_json(self, is_referenced_mock, request): - request.accept = AcceptValidHeader('application/json') + def test_protected_operation_409_json(self, is_referenced_mock, dummy_request): + dummy_request.accept = AcceptValidHeader("application/json") is_referenced_mock.return_value = RegistryResponse( - 'https://id.erfgoed.net/resources/1', False, True, 2, - [get_app(1), get_app(2)]) - res = protected_dummy(request) + "https://id.erfgoed.net/resources/1", + False, + True, + 2, + [get_app(1), get_app(2)], + ) + res = protected_dummy(dummy_request) assert 409 == res.status_code - msg = ("The uri https://id.erfgoed.net/resources/1 is still in use by " - "other applications. A total of 2 references have been found.") + msg = ( + "The uri https://id.erfgoed.net/resources/1 is still in use by " + "other applications. A total of 2 references have been found." + ) assert res.json_body["message"] == msg assert "application/json" == res.content_type is_referenced_call = is_referenced_mock.mock_calls[0] - assert 'https://id.erfgoed.net/resources/1' == is_referenced_call[1][0] + assert "https://id.erfgoed.net/resources/1" == is_referenced_call[1][0] - def test_protected_operation_500(self, is_referenced_mock, request): + def test_protected_operation_500(self, is_referenced_mock, dummy_request): is_referenced_mock.return_value = RegistryResponse( - 'https://id.erfgoed.net/resources/1', False, None, None, - [get_app_500()]) + "https://id.erfgoed.net/resources/1", False, None, None, [get_app_500()] + ) with pytest.raises(HTTPInternalServerError): - protected_dummy(request) + protected_dummy(dummy_request) is_referenced_call = is_referenced_mock.mock_calls[0] - assert 'https://id.erfgoed.net/resources/1' == is_referenced_call[1][0] + assert "https://id.erfgoed.net/resources/1" == is_referenced_call[1][0] - def test_protected_operation_500_json(self, is_referenced_mock, request): - request.accept = AcceptValidHeader('application/json') + def test_protected_operation_500_json(self, is_referenced_mock, dummy_request): + dummy_request.accept = AcceptValidHeader("application/json") is_referenced_mock.return_value = RegistryResponse( - 'https://id.erfgoed.net/resources/1', False, None, None, - [get_app_500()]) - res = protected_dummy(request) + "https://id.erfgoed.net/resources/1", False, None, None, [get_app_500()] + ) + res = protected_dummy(dummy_request) assert 500 == res.status_code - msg = ("Unable to verify the uri https://id.erfgoed.net/resources/1 " - "is no longer being used.") + msg = ( + "Unable to verify the uri https://id.erfgoed.net/resources/1 " + "is no longer being used." + ) assert res.json_body["message"] == msg - errors = ["https://dev-app.onroerenderfgoed.be/: Could not verify the " - "uri is no longer being used."] + errors = [ + "https://dev-app.onroerenderfgoed.be/: Could not verify the " + "uri is no longer being used." + ] assert res.json_body["errors"] == errors assert "application/json" == res.content_type is_referenced_call = is_referenced_mock.mock_calls[0] - assert 'https://id.erfgoed.net/resources/1' == is_referenced_call[1][0] + assert "https://id.erfgoed.net/resources/1" == is_referenced_call[1][0] diff --git a/tests/test_renderers.py b/tests/test_renderers.py index acd9838..eb4aa40 100644 --- a/tests/test_renderers.py +++ b/tests/test_renderers.py @@ -1,80 +1,80 @@ -# -*- coding: utf-8 -*- +from pyramid_urireferencer.models import ApplicationResponse +from pyramid_urireferencer.models import Item +from pyramid_urireferencer.models import RegistryResponse -from pyramid_urireferencer.models import ( - RegistryResponse, - ApplicationResponse, - Item -) class TestRenderers: def test_empty_registry_renderer(self): - rr = RegistryResponse('http://id.example.org/foo/1', True, False, 0, []) + rr = RegistryResponse("http://id.example.org/foo/1", True, False, 0, []) from pyramid_urireferencer.renderers import registry_adapter + r = registry_adapter(rr, {}) - assert r['query_uri'] == 'http://id.example.org/foo/1' - assert r['success'] - assert not r['has_references'] - assert r['count'] == 0 - assert len(r['applications']) == 0 + assert r["query_uri"] == "http://id.example.org/foo/1" + assert r["success"] + assert not r["has_references"] + assert r["count"] == 0 + assert len(r["applications"]) == 0 def test_registry_renderer_one_app_no_results(self): ar = ApplicationResponse( - 'My app', - 'http://something.example.org', - 'http://somethingelse.example.org', + "My app", + "http://something.example.org", + "http://somethingelse.example.org", True, False, 0, - [] + [], ) - rr = RegistryResponse('http://id.example.org/foo/1', True, False, 0, [ar]) + rr = RegistryResponse("http://id.example.org/foo/1", True, False, 0, [ar]) from pyramid_urireferencer.renderers import registry_adapter + r = registry_adapter(rr, {}) - assert r['query_uri'] == 'http://id.example.org/foo/1' - assert r['success'] - assert not r['has_references'] - assert r['count'] == 0 - assert len(r['applications']) == 1 - assert 'title' in r['applications'][0] + assert r["query_uri"] == "http://id.example.org/foo/1" + assert r["success"] + assert not r["has_references"] + assert r["count"] == 0 + assert len(r["applications"]) == 1 + assert "title" in r["applications"][0] def test_empty_application_renderer(self): ar = ApplicationResponse( - 'My app', - 'http://something.example.org', - 'http://somethingelse.example.org/references', + "My app", + "http://something.example.org", + "http://somethingelse.example.org/references", True, False, 0, - [] + [], ) from pyramid_urireferencer.renderers import application_adapter + r = application_adapter(ar, {}) - assert r['uri'] == 'http://something.example.org' - assert r['service_url'] == 'http://somethingelse.example.org/references' - assert r['success'] - assert not r['has_references'] - assert r['count'] == 0 - assert len(r['items']) == 0 + assert r["uri"] == "http://something.example.org" + assert r["service_url"] == "http://somethingelse.example.org/references" + assert r["success"] + assert not r["has_references"] + assert r["count"] == 0 + assert len(r["items"]) == 0 def test_application_renderer_one_item(self): ar = ApplicationResponse( - 'My app', - 'http://something.example.org', - 'http://somethingelse.example.org/references', + "My app", + "http://something.example.org", + "http://somethingelse.example.org/references", True, False, 0, - [Item('http://something.example.org/thingy/thing', 'My item')] + [Item("http://something.example.org/thingy/thing", "My item")], ) from pyramid_urireferencer.renderers import application_adapter - r = application_adapter(ar, {}) - assert r['uri'] == 'http://something.example.org' - assert r['service_url'] == 'http://somethingelse.example.org/references' - assert r['success'] - assert not r['has_references'] - assert r['count'] == 0 - assert len(r['items']) == 1 - assert 'title' in r['items'][0] - assert 'uri' in r['items'][0] + r = application_adapter(ar, {}) + assert r["uri"] == "http://something.example.org" + assert r["service_url"] == "http://somethingelse.example.org/references" + assert r["success"] + assert not r["has_references"] + assert r["count"] == 0 + assert len(r["items"]) == 1 + assert "title" in r["items"][0] + assert "uri" in r["items"][0] diff --git a/tests/test_views.py b/tests/test_views.py index b733809..c7b2bfc 100644 --- a/tests/test_views.py +++ b/tests/test_views.py @@ -1,7 +1,7 @@ -# -*- coding: utf-8 -*- - import json import unittest +from unittest.mock import Mock +from urllib.parse import urlencode import httpretty from pyramid import testing @@ -14,16 +14,6 @@ from pyramid_urireferencer.models import RegistryResponse from pyramid_urireferencer.views import ReferencesPluginView -try: - from urllib import urlencode -except ImportError: - from urllib.parse import urlencode - -try: - from unittest.mock import Mock, patch -except ImportError: - from mock import Mock, patch - class ViewTests(unittest.TestCase): def setUp(self): @@ -43,46 +33,54 @@ def test_add_get_referencer_without_config(self): self.assertRaises(KeyError, _add_referencer, registry) def test_add_referencer(self): - self.config.registry.settings['urireferencer.registry_url'] = 'http://my.registry.org' - self.config.registry.settings['urireferencer.referencer'] = 'test_views.TestReferencer' + self.config.registry.settings["urireferencer.registry_url"] = ( + "http://my.registry.org" + ) + self.config.registry.settings["urireferencer.referencer"] = ( + "test_views.TestReferencer" + ) ref = _add_referencer(self.config.registry) self.assertIsInstance(ref, TestReferencer) def test_is_referenced(self): - uri = 'http://id.erfgoed.net/foobar/2' - url = 'http://localhost:6543' + uri = "http://id.erfgoed.net/foobar/2" + url = "http://localhost:6543" from pyramid_urireferencer.renderers import registry_adapter - reg_response_success_ref1 = registry_adapter(RegistryResponse(uri, True, False, 0, []), {}) + + reg_response_success_ref1 = registry_adapter( + RegistryResponse(uri, True, False, 0, []), {} + ) referencer = TestReferencer(url) - self.assertIsNone(referencer.references(uri, 'test')) + self.assertIsNone(referencer.references(uri, "test")) response = referencer.is_referenced(uri) self.assertIsInstance(response, RegistryResponse) self.assertEqual(response.success, False) - - httpretty.enable() # enable HTTPretty so that it will monkey patch the socket module + # enable HTTPretty so that it will monkey patch the socket module + httpretty.enable() httpretty.register_uri( httpretty.GET, - '{0}/references?{1}'.format(url, urlencode({'uri': uri})), + "{0}/references?{1}".format(url, urlencode({"uri": uri})), body=json.dumps(reg_response_success_ref1), - content_type="application/json" + content_type="application/json", ) response = referencer.is_referenced(uri) self.assertIsInstance(response, RegistryResponse) self.assertTrue(response.success) - - httpretty.disable() # disable afterwards, so that you will have no problems in code that uses that socket module + # disable afterwards, so that you will have no problems + # in code that uses that socket module + httpretty.disable() httpretty.reset() def test_no_uri(self): - request = Mock(params={'uri': ''}) + request = Mock(params={"uri": ""}) view = ReferencesPluginView(request) with self.assertRaises(HTTPBadRequest): view.get_references() def test_uri_none(self): - request = Mock(params={'uri': None}) + request = Mock(params={"uri": None}) view = ReferencesPluginView(request) with self.assertRaises(HTTPBadRequest): view.get_references() @@ -93,4 +91,4 @@ def references(self, uri, request): return None def get_uri(self, request): - return 'https://id.erfgoed.net/resources/1' + return "https://id.erfgoed.net/resources/1" diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 0547669..0000000 --- a/tox.ini +++ /dev/null @@ -1,19 +0,0 @@ -[tox] -envlist = py27, py36, cover - -[testenv] -commands = - pip install -r requirements-dev.txt - python setup.py develop - py.test tests -setenv = - LC_ALL = en_US.utf-8 - - -[testenv:cover] -basepython = - python2.7 -commands = - pip install -r requirements-dev.txt - python setup.py develop - py.test --cov pyramid_urireferencer --cov-report term-missing tests