From 2b3f5a8c56c8fab2cd71f0e0af8986eaf79c757c Mon Sep 17 00:00:00 2001 From: Tim Van Campenhout Date: Mon, 24 Jun 2024 11:58:08 +0200 Subject: [PATCH 1/2] #107 upgrade --- .flake8 | 7 + .github/workflows/urireferencer.yaml | 42 +++ .pre-commit-config.yaml | 25 ++ .travis.yml | 13 - CHANGES.md | 54 ++++ CHANGES.rst | 49 ---- MANIFEST.in | 1 - README.md | 15 + README.rst | 18 -- pyproject.toml | 67 +++++ pyramid_urireferencer/__init__.py | 18 +- pyramid_urireferencer/models.py | 43 +-- pyramid_urireferencer/protected_resources.py | 108 ++++--- pyramid_urireferencer/referencer.py | 33 ++- pyramid_urireferencer/renderers.py | 81 +++--- pyramid_urireferencer/views.py | 18 +- requirements-dev.txt | 118 +++++++- requirements.txt | 39 ++- setup.cfg | 2 - setup.py | 42 --- tests/test_models.py | 162 +++++------ tests/test_protected_resources.py | 288 ++++++++++++------- tests/test_renderers.py | 92 +++--- tests/test_views.py | 52 ++-- tox.ini | 19 -- 25 files changed, 863 insertions(+), 543 deletions(-) create mode 100755 .flake8 create mode 100644 .github/workflows/urireferencer.yaml create mode 100644 .pre-commit-config.yaml delete mode 100644 .travis.yml create mode 100644 CHANGES.md delete mode 100644 CHANGES.rst delete mode 100644 MANIFEST.in create mode 100644 README.md delete mode 100644 README.rst create mode 100644 pyproject.toml delete mode 100644 setup.cfg delete mode 100644 setup.py delete mode 100644 tox.ini 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..ee419a0 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,6 +125,7 @@ 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) @@ -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..187d0af 100644 --- a/tests/test_protected_resources.py +++ b/tests/test_protected_resources.py @@ -1,161 +1,228 @@ -# -*- 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='*/*'): + def __init__(self, accepts="*/*"): self.request = testing.DummyRequest() self.request.accept = AcceptValidHeader(accepts) config = testing.setUp(request=self.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' + 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) @@ -163,77 +230,96 @@ def setUp(self): @pytest.fixture() def request(self): request = testing.DummyRequest() - request.accept = AcceptValidHeader('application/html') + request.accept = AcceptValidHeader("application/html") config = testing.setUp(request=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") return request def test_protected_operation(self, is_referenced_mock, request): is_referenced_mock.return_value = RegistryResponse( - 'https://id.erfgoed.net/resources/1', True, False, 0, []) + "https://id.erfgoed.net/resources/1", True, False, 0, [] + ) protected_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): 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) 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): 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) 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') + 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)]) + "https://id.erfgoed.net/resources/1", + False, + True, + 2, + [get_app(1), get_app(2)], + ) res = protected_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): 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) 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') + request.accept = AcceptValidHeader("application/json") 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()] + ) res = protected_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 From 26849f1abe70997658e874feb87538ce667c157e Mon Sep 17 00:00:00 2001 From: Tim Van Campenhout Date: Mon, 24 Jun 2024 12:02:09 +0200 Subject: [PATCH 2/2] #107 upgrade --- pyramid_urireferencer/protected_resources.py | 2 +- tests/test_protected_resources.py | 48 ++++++++++---------- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/pyramid_urireferencer/protected_resources.py b/pyramid_urireferencer/protected_resources.py index ee419a0..1443fb7 100644 --- a/pyramid_urireferencer/protected_resources.py +++ b/pyramid_urireferencer/protected_resources.py @@ -128,7 +128,7 @@ def protected_operation(fn): @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: diff --git a/tests/test_protected_resources.py b/tests/test_protected_resources.py index 187d0af..1e043bf 100644 --- a/tests/test_protected_resources.py +++ b/tests/test_protected_resources.py @@ -28,7 +28,7 @@ def get_app(nr): Item( uri="https://dev-besluiten.onroerenderfgoed.be/besluiten/154", title="Vaststelling van de inventaris van het " - "Bouwkundig Erfgoed op 28 november 2014", + "Bouwkundig Erfgoed op 28 november 2014", ) ) a = ApplicationResponse( @@ -57,9 +57,9 @@ def get_app_500(): class DummyParent(object): def __init__(self, accepts="*/*"): - self.request = testing.DummyRequest() - self.request.accept = AcceptValidHeader(accepts) - config = testing.setUp(request=self.request) + 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", @@ -215,7 +215,7 @@ def test_protected_operation_500_json(self, is_referenced_mock): @protected_operation_with_request -def protected_dummy(request): +def protected_dummy(dummy_request): return "dummy ok" @@ -228,26 +228,26 @@ 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", } config.include("pyramid_urireferencer") - return request + 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) + 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] - 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, @@ -256,11 +256,11 @@ def test_protected_operation_409(self, is_referenced_mock, request): [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] - 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, @@ -269,12 +269,12 @@ def test_protected_operation_409_2(self, is_referenced_mock, request): [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] - 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, @@ -282,7 +282,7 @@ def test_protected_operation_409_json(self, is_referenced_mock, request): 2, [get_app(1), get_app(2)], ) - res = protected_dummy(request) + res = protected_dummy(dummy_request) assert 409 == res.status_code msg = ( "The uri https://id.erfgoed.net/resources/1 is still in use by " @@ -294,21 +294,21 @@ def test_protected_operation_409_json(self, is_referenced_mock, request): is_referenced_call = is_referenced_mock.mock_calls[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()] ) 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] - 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) + res = protected_dummy(dummy_request) assert 500 == res.status_code msg = ( "Unable to verify the uri https://id.erfgoed.net/resources/1 "