Skip to content

Commit

Permalink
Merge branch 'release/0.6'
Browse files Browse the repository at this point in the history
  • Loading branch information
rlskoeser committed Aug 12, 2024
2 parents 203a065 + 6ecf0af commit a663ab3
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 47 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Change & Version Information

## 0.6.0

* HTTP request method `get_iiif_url` is now a class method on
`piffle.presentation.IIIFPresentation`, which can be extended when request
customization is needed
* Manifests now supports attr-dict style access to `@id` in `seeAlso` list entries

## 0.5.1

* Add explicit support and testing for python 3.12
Expand Down
2 changes: 1 addition & 1 deletion piffle/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.5.1"
__version__ = "0.6.0"
101 changes: 55 additions & 46 deletions piffle/presentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,69 @@ class IIIFException(Exception):
"""Custom exception for IIIF errors"""


def get_iiif_url(url):
"""Wrapper around :meth:`requests.get` to support conditionally
adding an auth tokens or other parameters."""
request_options = {}
# TODO: need some way of configuring hooks for e.g. setting auth tokens
return requests.get(url, **request_options)
class AtDict(addict.Dict):
"""Base attrdict class with handling for fields like @type, @id, etc"""

at_fields = ["type", "id", "context"]

def _key(self, key):
# convert key to @key if in the list of fields that requires it
if key in self.at_fields:
key = "@%s" % key
return key

def __missing__(self, key):
raise KeyError(self._key(key))

def __getattr__(self, key):
try:
# addict getattr just calls getitem
return super().__getattr__(self._key(key))
except KeyError:
# python hasattr checks for attribute error
# translate key error to attribute error,
# since in an attr dict it's kind of both
raise AttributeError

def __getitem__(self, key):
"""
Access a value associated with a key.
"""
val = super().__getitem__(self._key(key))

if key == "seeAlso" and isinstance(val, list) and isinstance(val[0], dict):
return [AtDict(entry) for entry in val]
return val

def __setitem__(self, key, value):
"""
Add a key-value pair to the instance.
"""
return super().__setitem__(self._key(key), value)

def __delitem__(self, key):
"""
Delete a key-value pair
"""
super().__delitem__(self._key(key))


class IIIFPresentation(addict.Dict):
class IIIFPresentation(AtDict):
""":class:`addict.Dict` subclass for read access to IIIF Presentation
content"""

# TODO: document sample use, e.g. @ fields

at_fields = ["type", "id", "context"]

@classmethod
def get_iiif_url(cls, url):
"""Wrapper around :meth:`requests.get` to support conditionally
adding an auth tokens or other parameters."""
request_options = {}
# TODO: need some way of configuring hooks for e.g. setting auth tokens
return requests.get(url, **request_options)

@classmethod
def from_file(cls, path):
"""Initialize :class:`IIIFPresentation` from a file."""
Expand All @@ -41,7 +88,7 @@ def from_url(cls, uri):
:raises: :class:`IIIFException` if URL is not retrieved successfully,
if the response is not JSON content, or if the JSON cannot be parsed.
"""
response = get_iiif_url(uri)
response = cls.get_iiif_url(uri)
if response.status_code == requests.codes.ok:
try:
return cls(response.json())
Expand Down Expand Up @@ -91,44 +138,6 @@ def short_id(cls, uri):
# split on slashes and return the last portion
return uri.split("/")[-1]

def __missing__(self, key):
raise KeyError(self._key(key))

def _key(self, key):
# convert key to @key if in the list of fields that requires it
if key in self.at_fields:
key = "@%s" % key
return key

def __getattr__(self, key):
try:
# addict getattr just calls getitem
return super().__getattr__(self._key(key))
except KeyError:
# python hasattr checks for attribute error
# translate key error to attribute error,
# since in an attr dict it's kind of both
raise AttributeError

def __getitem__(self, key):
"""
Access a value associated with a key.
"""
val = super().__getitem__(self._key(key))
return val

def __setitem__(self, key, value):
"""
Add a key-value pair to the instance.
"""
return super().__setitem__(self._key(key), value)

def __delitem__(self, key):
"""
Delete a key-value pair
"""
super().__delitem__(self._key(key))

@property
def first_label(self):
# label can be a string or list of strings
Expand Down

0 comments on commit a663ab3

Please sign in to comment.