Skip to content

Commit

Permalink
Documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
zimeon committed Oct 14, 2024
1 parent 575a118 commit 8e8f0be
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 19 deletions.
31 changes: 27 additions & 4 deletions ocfl/object.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,17 @@ def parse_version_directory(dirname):


class Object():
"""Class for handling OCFL Object data and operations."""
"""Class for handling OCFL Object data and operations.
Example use:
>>> import ocfl
>>> object = ocfl.Object(path="fixtures/1.1/good-objects/spec-ex-full")
>>> passed, validator = object.validate()
>>> passed
True
>>> validator.spec_version
'1.1'
"""

def __init__(self, identifier=None, content_directory='content',
digest_algorithm='sha512', filepath_normalization='uri',
Expand All @@ -44,7 +54,7 @@ def __init__(self, identifier=None, content_directory='content',
obj_fs=None, path=None, create=False):
"""Initialize OCFL object.
Parameters relevant to building an object:
Arguments relevant to building an object:
identifier - id for this object
content_directory - allow override of the default 'content'
digest_algorithm - allow override of the default 'sha512'
Expand Down Expand Up @@ -85,7 +95,18 @@ def __init__(self, identifier=None, content_directory='content',
self.open_fs(path, create=create)

def open_fs(self, objdir, create=False):
"""Open an fs filesystem for this object."""
"""Open an fs filesystem for this object.
Arguments:
objdir: path string to either regular filesystem directory or else
to a fs filesystem string (e.g. may be "zip://.../zipfile.zip"
or "mem://")
create: True to create path/filesystem as needed, defaults to False.
Sets obj_fs attribute.
Raises ObjectException on failure to open filesystem.
"""
try:
self.obj_fs = open_fs(fs_url=objdir, create=create)
except (fs.opener.errors.OpenerError, fs.errors.CreateFailed) as e:
Expand Down Expand Up @@ -529,7 +550,7 @@ def _show_indent(level, last=False, last_v=False):
tree += _show_indent(1, last, (nn == len(v_notes))) + v_note + "\n"
return tree

def validate(self, objdir, show_warnings=True, show_errors=True, check_digests=True):
def validate(self, objdir=None, show_warnings=True, show_errors=True, check_digests=True):
"""Validate OCFL object at objdir.
Returns tuple (passed, validator) where:
Expand All @@ -541,6 +562,8 @@ def validate(self, objdir, show_warnings=True, show_errors=True, check_digests=T
show_errors=show_errors,
check_digests=check_digests,
lax_digests=self.lax_digests)
if objdir is None:
objdir = self.obj_fs
passed = validator.validate_object(objdir)
return passed, validator

Expand Down
43 changes: 38 additions & 5 deletions ocfl/validation_logger.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
"""OCFL Validation Logger.
Handle logging of validation errors and warnings.
Handle logging of validation errors and warnings. All the error and
warning messages are stored in a separate JSON file that is keyed
by the anchors ("E001", "W001") that are used in the specification.
The format of the `validation-codes.json` files is as follows:
```
{
"E001a": {
"params": ["file"],
"description": {
"en": "OCFL Object root contains unexpected file: %s"
}
},
"E001b": {
"params": ["dir"],
"description": {
"en": "OCFL Object root contains unexpected directory: %s"
}
},
...
}
```
"""
import json
import os
Expand All @@ -23,7 +44,6 @@ def __init__(self, show_warnings=False, show_errors=True,
self.messages = []
self.num_errors = 0
self.num_warnings = 0
self.info = 0
self.spec = 'https://ocfl.io/1.0/spec/'
if validation_codes is not None:
self.validation_codes = validation_codes
Expand All @@ -32,7 +52,20 @@ def __init__(self, show_warnings=False, show_errors=True,
self.validation_codes = json.load(fh)

def error_or_warning(self, code, severity='error', **args):
"""Add error or warning to self.codes."""
"""Add error or warning to self.codes.
Arguments:
code: string for the error code (starts with `E` or `W`).
severity: string for severity, `error` (default) or `warning`.
**args: additional arguments that correspond with named arguments
in the error messages.
Adds or updates the `codes` attribute with the last message for the given
code.
Adds to the log of all messages in the `messages` atttibute depending on
severity and the values of the `show_warnings` and `show_errors` attributes.
"""
if code in self.validation_codes and 'description' in self.validation_codes[code]:
desc = self.validation_codes[code]['description']
lang_desc = None
Expand Down Expand Up @@ -67,12 +100,12 @@ def error_or_warning(self, code, severity='error', **args):
self.messages.append(message)

def error(self, code, **args):
"""Add error code to self.codes."""
"""Log an error."""
self.error_or_warning(code, severity='error', **args)
self.num_errors += 1

def warning(self, code, **args):
"""Add warning code to self.codes."""
"""Log a warning."""
self.error_or_warning(code, severity='warning', **args)
self.num_warnings += 1

Expand Down
48 changes: 38 additions & 10 deletions ocfl/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,42 @@ class ValidatorAbortException(Exception):
class Validator():
"""Class for OCFL Object Validator."""

def __init__(self, log=None, show_warnings=False, show_errors=True,
def __init__(self, show_warnings=False, show_errors=True,
check_digests=True, lax_digests=False,
force_spec_version=None, default_spec_version='1.1', lang='en'):
"""Initialize OCFL validator."""
self.log = log
force_spec_version=None, default_spec_version='1.1',
log=None, lang='en'):
"""Initialize OCFL Object validator object.
Arguments:
show_warnings: True to record warnings during validation
(default: False)
show_errors: True to record errors during validation
(default: True)
check_digests: True to check digests of files within the objects
lax_digests: default is False. Set True to allow digests beyond
those included in the specification for fixity and to allow
non-preferred digest algorithms for content references in the
object.
force_spec_version: string of specification version to force
validation at, else None (default) to not force a specific
version. If force_spec_version is set then a declaration within
the object that doesn't match will be reported as an error.
default_spec_version: string of default specification version to
assume where not specified (default '1.1')
log: None (default) to create new ValidationLogger instance, or
else an instance to use.
lang: language string (default 'en') to pass to the validation
logger.
"""
self.check_digests = check_digests
self.lax_digests = lax_digests
self.force_spec_version = force_spec_version
self.default_spec_version = default_spec_version
self.log = log
if self.log is None:
self.log = ValidationLogger(show_warnings=show_warnings, show_errors=show_errors, lang=lang)
self.log = ValidationLogger(show_warnings=show_warnings,
show_errors=show_errors,
lang=lang)
self.registered_extensions = [
'0001-digest-algorithms', '0002-flat-direct-storage-layout',
'0003-hash-and-id-n-tuple-storage-layout', '0004-hashed-n-tuple-storage-layout',
Expand Down Expand Up @@ -152,11 +177,14 @@ def validate_inventory(self, inv_file, where='root', force_spec_version=None):
of object content. Does not look at anything else in the
object itself.
where - used for reporting messages of where inventory is in object, will
be either 'root' or the version directory
force_spec_version - if set None will attempt to take spec_version from the
inventory itself instead of using the spec version provided
Arguments:
inv_file: file name of inventory within self.obj_fs
where: string (default 'root') used for reporting messages of
where inventory is in object, will be either 'root' or the
version directory
force_spec_version: if None (default) will attempt to take
spec_version from the inventory itself instead of using the
spec version provided
"""
try:
with self.obj_fs.openbin(inv_file, 'r') as fh:
Expand Down

0 comments on commit 8e8f0be

Please sign in to comment.