Skip to content

Commit

Permalink
Merge pull request #1 from open-contracting/dev
Browse files Browse the repository at this point in the history
  • Loading branch information
jpmckinney committed Jun 12, 2018
2 parents 4c88f0e + 50aabe0 commit 3f8d5a3
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 16 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,3 +1,4 @@
/.cache
/.coverage
/dist
/*.egg-info
12 changes: 12 additions & 0 deletions CHANGELOG.md
@@ -0,0 +1,12 @@
# Changelog

## 0.0.2 (2018-06-12)

* Make `ExtensionRegistry` iterable.
* Remove `all()` method from `ExtensionRegistry`.
* Add `get(**kwargs)` method to `ExtensionRegistry`.
* Add package-specific exceptions.

## 0.0.1 (2018-06-11)

First release.
38 changes: 31 additions & 7 deletions ocdsextensionregistry/__init__.py
Expand Up @@ -6,6 +6,18 @@
import requests


class OCDSExtensionRegistryError(Exception):
"""Base class for exceptions from within this package"""


class DoesNotExist(OCDSExtensionRegistryError):
"""Raised if an object wasn't found for the given parameters"""


class MissingExtensionMetadata(OCDSExtensionRegistryError):
"""Raised if a method call requires extensions metadata, with which the extension registry was not initialized"""


class ExtensionRegistry:
def __init__(self, extension_versions_data, extensions_data=None):
"""
Expand Down Expand Up @@ -37,16 +49,22 @@ def filter(self, **kwargs):
try:
return list(filter(lambda ver: all(getattr(ver, k) == v for k, v in kwargs.items()), self.versions))
except AttributeError as e:
if "'category'" in str(e.args) or "'core'" in str(e.args):
raise Exception('You must initialize ExtensionRegistry with two arguments.') from e
else:
raise
self._handle_attribute_error(e)

def all(self):
def get(self, **kwargs):
"""
Returns all the extension versions in the registry.
Returns the first extension version in the registry that matches the keyword arguments.
"""
return self.versions
try:
return next(ver for ver in self.versions if all(getattr(ver, k) == v for k, v in kwargs.items()))
except StopIteration:
raise DoesNotExist('Extension version matching {} does not exist.'.format(repr(kwargs)))
except AttributeError as e:
self._handle_attribute_error(e)

def __iter__(self):
for version in self.versions:
yield version

def _resolve(self, data_or_url):
parsed = urlparse(data_or_url)
Expand All @@ -55,6 +73,12 @@ def _resolve(self, data_or_url):
else:
return data_or_url

def _handle_attribute_error(self, e):
if "'category'" in str(e.args) or "'core'" in str(e.args):
raise MissingExtensionMetadata('ExtensionRegistry must be initialized with extensions data.') from e
else:
raise


class Extension:
def __init__(self, data):
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Expand Up @@ -5,7 +5,7 @@

setup(
name='ocdsextensionregistry',
version='0.0.0',
version='0.0.2',
author='James McKinney',
author_email='james@slashpoundbang.com',
url='https://github.com/open-contracting/extension_registry.py',
Expand Down
65 changes: 57 additions & 8 deletions tests/test_extension_registry.py
@@ -1,6 +1,6 @@
import pytest

from ocdsextensionregistry import ExtensionRegistry
from ocdsextensionregistry import ExtensionRegistry, DoesNotExist, MissingExtensionMetadata

extensions_url = 'https://raw.githubusercontent.com/open-contracting/extension_registry/master/extensions.csv'
extension_versions_url = 'https://raw.githubusercontent.com/open-contracting/extension_registry/master/extension_versions.csv' # noqa
Expand Down Expand Up @@ -34,6 +34,7 @@ def test_init_with_url():
obj = ExtensionRegistry(extension_versions_url, extensions_url)

assert len(obj.versions) > 50
# Skip testing data, as the data changes over time.


def test_init_with_data():
Expand All @@ -49,6 +50,7 @@ def test_init_with_data():
'category': 'ppp',
'core': False,
}
# Assume intermediate data is correctly parsed.
assert obj.versions[-1].__dict__ == {
'id': 'lots',
'date': '2018-01-30',
Expand All @@ -71,6 +73,7 @@ def test_init_with_versions_only():
'base_url': 'https://raw.githubusercontent.com/open-contracting/ocds_charges_extension/master/',
'download_url': 'https://github.com/open-contracting/ocds_charges_extension/archive/master.zip',
}
# Assume intermediate data is correctly parsed.
assert obj.versions[-1].__dict__ == {
'id': 'lots',
'date': '2018-01-30',
Expand All @@ -85,20 +88,66 @@ def test_filter():
result = obj.filter(core=True, version='v1.1.3', category='tender')

assert len(result) == 2
assert result[0].id == 'enquiries'
assert result[1].id == 'lots'
assert result[0].__dict__ == {
'id': 'enquiries',
'date': '2018-02-01',
'version': 'v1.1.3',
'base_url': 'https://raw.githubusercontent.com/open-contracting/ocds_enquiry_extension/v1.1.3/',
'download_url': 'https://api.github.com/repos/open-contracting/ocds_enquiry_extension/zipball/v1.1.3',
'category': 'tender',
'core': True,
}
assert result[1].__dict__ == {
'id': 'lots',
'date': '2018-01-30',
'version': 'v1.1.3',
'base_url': 'https://raw.githubusercontent.com/open-contracting/ocds_lots_extension/v1.1.3/',
'download_url': 'https://api.github.com/repos/open-contracting/ocds_lots_extension/zipball/v1.1.3',
'category': 'tender',
'core': True,
}


def test_filter_without_extensions():
obj = ExtensionRegistry(extension_versions_data)
with pytest.raises(Exception) as excinfo:
with pytest.raises(MissingExtensionMetadata) as excinfo:
obj.filter(category='tender')

assert str(excinfo.value) == 'You must initialize ExtensionRegistry with two arguments.'
assert str(excinfo.value) == 'ExtensionRegistry must be initialized with extensions data.'


def test_get():
obj = ExtensionRegistry(extension_versions_data)
result = obj.get(id='lots', version='v1.1.3')

assert result.__dict__ == {
'id': 'lots',
'date': '2018-01-30',
'version': 'v1.1.3',
'base_url': 'https://raw.githubusercontent.com/open-contracting/ocds_lots_extension/v1.1.3/',
'download_url': 'https://api.github.com/repos/open-contracting/ocds_lots_extension/zipball/v1.1.3',
}


def test_get_no_match():
obj = ExtensionRegistry(extension_versions_data)
with pytest.raises(DoesNotExist) as excinfo:
obj.get(id='nonexistent')

assert str(excinfo.value) == "Extension version matching {'id': 'nonexistent'} does not exist."


def test_get_without_extensions():
obj = ExtensionRegistry(extension_versions_data)
with pytest.raises(MissingExtensionMetadata) as excinfo:
obj.get(category='tender')

assert str(excinfo.value) == 'ExtensionRegistry must be initialized with extensions data.'


def test_all():
def test_iter():
obj = ExtensionRegistry(extension_versions_data)
result = obj.all()
for i, version in enumerate(obj, 1):
pass

assert len(result) == 14
assert i == 14

0 comments on commit 3f8d5a3

Please sign in to comment.