Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Source and Selector Rules Fail on SpecificResource #221

Open
markpbaggett opened this issue Jan 3, 2025 · 1 comment
Open

Source and Selector Rules Fail on SpecificResource #221

markpbaggett opened this issue Jan 3, 2025 · 1 comment
Labels
bug Something isn't working

Comments

@markpbaggett
Copy link
Member

Recipes 0299-region and 0040-image-region-service use the SpecificResource class from IIIF Open/Web Annotation Extensions. The current generated schema doesn't allow for someone to implement either recipe.

The SpecificResource class is currently defined as:

class SpecificResource(Base):
    id: Optional[Id] = None
    type: constr(regex=r'^SpecificResource$') = 'SpecificResource'
    format: Optional[Format] = None
    accessibility: Optional[str] = None
    source: Union[Id, Class]
    selector: Union[Selector, List[Selector]]

Expected behaviour:

The generated schema should allow one to use a SpecificResouce with source and selector properties defined as in the example recipes without throwing an error (schema currently doesn't allow for the type to be namespaced as it is) and without dropping both properties.

Observed behaviour:

For source, if you try to use ResourceItem or just pass the info from the recipe as a dict, and then print SpecificResource, only id and type are kept:

id=Id(__root__=AnyUrl('https://iiif.io/api/cookbook/recipe/0299-region/body/b1', scheme='https', host='iiif.io', tld='io', host_type='domain', path='/api/cookbook/recipe/0299-region/body/b1')) type='SpecificResource' format=Format(__root__='image/jpeg') accessibility=None source=Class(id=Id(__root__=AnyUrl('https://iiif.io/api/image/3.0/example/reference/4ce82cef49fb16798f4c2440307c3d6f-newspaper-p2/full/max/0/default.jpg', scheme='https', host='iiif.io', tld='io', host_type='domain', path='/api/image/3.0/example/reference/4ce82cef49fb16798f4c2440307c3d6f-newspaper-p2/full/max/0/default.jpg')), type='Image', label=None) selector=Selector(__root__=SelectorItem3(type='ImageApiSelector', region='1768,2423,1768,2080', size=None, rotation=None, quality=None, format=None))

For selector, you MUST drop the namespace from iiif:ImageApiSelector to even get things to pass. That's quite clearly a result of:

class SelectorItem3(Base):
    type: constr(regex=r'^ImageApiSelector$') = 'ImageApiSelector'

Even after changing the type to not use the namespace, the @context property is dropped. According to 0040, "you must use a @context field in order to point to the ImageApiSelector definition for canonical rotation options".

Once SpecificResource is added as the value of the body property on the painting annotation, source and selector are both dropped:

id=Id(__root__=AnyUrl('https://iiif.io/api/cookbook/recipe/0299-region/page/p1/1', scheme='https', host='iiif.io', tld='io', host_type='domain', path='/api/cookbook/recipe/0299-region/page/p1/1')) type='AnnotationPage' label=None context=None rendering=None service=None thumbnail=None items=[Annotation(id=Id(__root__=AnyUrl('https://iiif.io/api/cookbook/recipe/0299-region/annotation/p0001-image', scheme='https', host='iiif.io', tld='io', host_type='domain', path='/api/cookbook/recipe/0299-region/annotation/p0001-image')), type='Annotation', label=None, service=None, rendering=None, thumbnail=None, motivation='painting', body=Resource(__root__=ResourceItem(id=Id(__root__=AnyUrl('https://iiif.io/api/cookbook/recipe/0299-region/body/b1', scheme='https', host='iiif.io', tld='io', host_type='domain', path='/api/cookbook/recipe/0299-region/body/b1')), type='SpecificResource', height=None, width=None, duration=None, language=None, rendering=None, service=None, format=Format(__root__='image/jpeg'), label=None, thumbnail=None, annotations=None)), target=AnnoTarget(__root__=AnyUrl('https://iiif.io/api/cookbook/recipe/0299-region/canvas/p1', scheme='https', host='iiif.io', tld='io', host_type='domain', path='/api/cookbook/recipe/0299-region/canvas/p1')))]

Potential bug location(s):

This one is complex.

Let's start with selector. Looking at the validator json, it seems to me that maybe the regex pattern is too strict and doesn't allow for the namespace to be present (even though both recipes currently pass with validation). Perhaps this be addressed first. Also, maybe the following should be added to the SelectorItem3 class:

class Config:
        extra = Extra.allow

As for source, I'm not sure where to begin or the ramifications of how to address this in the validator json.

There are definitely other things that need investigation and discussion beyond these two areas, but I'm getting a little out of my depths without talking about this more.

Any other comments:

In case it's useful, here is a bunch of sample code based on Recipe 0299 that can help illustrate the problems here:

from iiif_prezi3 import Manifest, ResourceItem, SelectorItem3, AnnotationPage, Annotation, config, SpecificResource

config.configs['helpers.auto_fields.AutoLang'].auto_lang = "en"
base_url = "https://iiif.io/api/cookbook/recipe/0299-region"

manifest = Manifest(
    id=f"{base_url}/manifest.json",
    label="Berliner Tageblatt article, 'Ein neuer Sicherungsplan?'"
)

anno_page = AnnotationPage(
    id=f"{base_url}/page/p1/1"
)
selector = SelectorItem3(
    type="ImageApiSelector"
)
image_source = ResourceItem(
    id="https://iiif.io/api/image/3.0/example/reference/4ce82cef49fb16798f4c2440307c3d6f-newspaper-p2/full/max/0/default.jpg",
    type="Image",
    format="image/jpeg",
    height=4999,
    width=3536,
)
image_source.make_service(
    id="https://iiif.io/api/image/3.0/example/reference/4ce82cef49fb16798f4c2440307c3d6f-newspaper-p2",
    type="ImageService3",
    profile="level1"
)
temp_source = {
                  "id": "https://iiif.io/api/image/3.0/example/reference/4ce82cef49fb16798f4c2440307c3d6f-newspaper-p2/full/max/0/default.jpg",
                  "type": "Image",
                  "format": "image/jpeg",
                  "height": 4999,
                  "width": 3536,
                  "service": [
                    {
                      "id": "https://iiif.io/api/image/3.0/example/reference/4ce82cef49fb16798f4c2440307c3d6f-newspaper-p2",
                      "profile": "level1",
                      "type": "ImageService3"
                    }
                  ]
                }
temp_selector = {
                  "@context": "http://iiif.io/api/annex/openannotation/context.json",
                  "type": "ImageApiSelector",
                  "region": "1768,2423,1768,2080"
                }
anno_body = SpecificResource(
    id=f"{base_url}/body/b1",
    type="SpecificResource",
    format="image/jpeg",
    source=image_source,
    selector=temp_selector,
)
# print(anno_body.json(indent=2))
canvas = manifest.make_canvas(
    id=f"{base_url}/canvas/p1",
)
anno = Annotation(
    id=f"{base_url}/annotation/p0001-image",
    motivation="painting",
    body=anno_body,
    target=canvas.id
)
anno_page.add_item(anno)
# print(anno_page.json(indent=2))
canvas.add_item(anno_page)

print(manifest.json(indent=2))
@markpbaggett markpbaggett added the bug Something isn't working label Jan 3, 2025
@markpbaggett
Copy link
Member Author

This isn't described above, but I also noticed that Recipe 0258: Tagging with an External Resource isn't solvable because the JSON schema in the presentaion-validator says that selector is a required property on SpecificResource and thus the schema here is wrong as well. This issue has been brought up here and here. I also took a stab at a pr that would hopefully resolve this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant