Skip to content

Commit

Permalink
Tidy layout_nnnn_tuple_tree
Browse files Browse the repository at this point in the history
  • Loading branch information
zimeon committed Dec 12, 2024
1 parent b4dc92d commit 64c9c3c
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 29 deletions.
24 changes: 24 additions & 0 deletions ocfl/layout_0003_hash_and_id_n_tuple.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ def check_digest_algorithm(self, value):
Type: string
Constraints: Must not be empty
Default: sha256
Argument:
value (str): digest algorithm name
Raises:
LayoutException: if the digest algorithm is not supported
Sets the digest_algorithm property of this object as a side effect.
"""
if value is None:
raise LayoutException("digestAlgorithm parameter must be specified")
Expand All @@ -91,6 +99,14 @@ def check_tuple_size(self, value):
Type: number
Constraints: An integer between 0 and 32 inclusive
Default: 3
Argument:
value (int): integer value for tuple size in characters
Raises:
LayoutException: if the tuple size is not allowed
Sets the tuple_size property of this object as a side effect.
"""
if value is None:
raise LayoutException("tupleSize parameter must be specified")
Expand All @@ -107,6 +123,14 @@ def check_number_of_tuples(self, value):
Type: number
Constraints: An integer between 0 and 32 inclusive
Default: 3
Argument:
value (int): integer value for number of tuples
Raises:
LayoutException: if the number of tuples is not allowed
Sets the number_of_tuples property of this object as a side effect.
"""
if value is None:
raise LayoutException("numberOfTuples parameter must be specified")
Expand Down
50 changes: 44 additions & 6 deletions ocfl/layout_nnnn_tuple_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,16 @@ def check_tuple_size(self, value):
Description: Indicates the size of the segments (in characters)
that the digest is split into
Type: number
Constraints: An integer between 0 and 32 inclusive
Default: 3
Constraints: An integer between 2 and 6 inclusive
Default: 2
Argument:
value (int): integer value for tuple size in characters
Raises:
LayoutException: if the tuple size is not allowed
Sets the tuple_size property of this object as a side effect.
"""
if value is None:
raise LayoutException("tupleSize parameter must be specified")
Expand All @@ -54,15 +62,45 @@ def check_tuple_size(self, value):
self.tuple_size = value

def encode(self, identifier):
"""Pairtree encode identifier."""
"""Pairtree encode identifier.
Argument:
identifier (str): object identifier to encode
Returns:
str: encoded identifier
"""
return id_encode(identifier)

def decode(self, identifier):
"""Pairtree decode identifier."""
"""Pairtree decode identifier.
Argument:
identifier (str): object identifier to decode
Returns:
str: decoded identifier
"""
return id_decode(identifier)

def identifier_to_path(self, identifier):
"""Convert identifier to path relative to root."""
"""Convert identifier to path relative to root.
Argument:
identifier (str): object identifier
Returns:
str: object path for this layout
Raises:
LayoutException: if the identifier cannot be converted to a valid
object path. Currently just a check for blank
Uses Layout.encode() to generate a safe directory name from any
identifier.
"""
if identifier == "":
raise LayoutException("Identifier '%s' unsafe for %s layout" % (identifier, self.NAME))
identifier = self.encode(identifier)
id_remains = identifier
segments = []
Expand All @@ -72,4 +110,4 @@ def identifier_to_path(self, identifier):
segments.append(id_remains) # the statement means that segments will always have at least one element
# Use full identifier to encapsulate
segments.append(identifier)
return os.path.join(*segments) # pylint: disable=no-value-for-parameter
return os.path.join(*segments)
1 change: 0 additions & 1 deletion tests/test_layout_0003-hash-and-id-n-tuple.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,6 @@ def test_check_full_config(self):
"numberOfTuples": 9},
require_extension_name=False)


def test_config(self):
"""Test config property."""
layout = Layout_0003_Hash_And_Id_N_Tuple()
Expand Down
60 changes: 38 additions & 22 deletions tests/test_layout_nnnn_tuple_tree.py
Original file line number Diff line number Diff line change
@@ -1,34 +1,50 @@
"""Digest tests."""
"""Layout_NNNN_Tuple_Tree layout tests."""
import unittest
from ocfl.layout import LayoutException
from ocfl.layout_nnnn_tuple_tree import Layout_NNNN_Tuple_Tree


class TestAll(unittest.TestCase):
"""TestAll class to run tests."""

def test01_encode(self):
def test_encode(self):
"""Test encode."""
tt = Layout_NNNN_Tuple_Tree()
self.assertEqual(tt.encode(""), "")
self.assertEqual(tt.encode("a"), "a")
self.assertEqual(tt.encode("a/b:?"), "a=b+^3f")
layout = Layout_NNNN_Tuple_Tree()
self.assertEqual(layout.encode(""), "")
self.assertEqual(layout.encode("a"), "a")
self.assertEqual(layout.encode("a/b:?"), "a=b+^3f")

def test02_decode(self):
def test_decode(self):
"""Test decode."""
tt = Layout_NNNN_Tuple_Tree()
self.assertEqual(tt.decode(""), "")
self.assertEqual(tt.decode("a"), "a")
self.assertEqual(tt.decode("a=b+^3f"), "a/b:?")
layout = Layout_NNNN_Tuple_Tree()
self.assertEqual(layout.decode(""), "")
self.assertEqual(layout.decode("a"), "a")
self.assertEqual(layout.decode("a=b+^3f"), "a/b:?")

def test03_identifier_to_path(self):
def test_config(self):
"""Test config property."""
layout = Layout_NNNN_Tuple_Tree()
self.assertEqual(set(layout.config.keys()), set(("extensionName", "tupleSize")))

def test_check_tuple_size(self):
"""Test check_tuple_size method."""
layout = Layout_NNNN_Tuple_Tree()
self.assertRaises(LayoutException, layout.check_tuple_size, None)
self.assertRaises(LayoutException, layout.check_tuple_size, "string-not-num")
self.assertRaises(LayoutException, layout.check_tuple_size, 1)
self.assertRaises(LayoutException, layout.check_tuple_size, 7)
self.assertEqual(layout.check_tuple_size(4), None)
self.assertEqual(layout.tuple_size, 4)

def test_identifier_to_path(self):
"""Test path creation."""
tt = Layout_NNNN_Tuple_Tree(tuple_size=2)
self.assertEqual(tt.identifier_to_path(""), "")
self.assertEqual(tt.identifier_to_path("a"), "a/a")
self.assertEqual(tt.identifier_to_path("ab"), "ab/ab")
self.assertEqual(tt.identifier_to_path("abc"), "ab/c/abc")
self.assertEqual(tt.identifier_to_path("abcde"), "ab/cd/e/abcde")
tt = Layout_NNNN_Tuple_Tree(tuple_size=3)
self.assertEqual(tt.identifier_to_path("abcdefg"), "abc/def/g/abcdefg")
self.assertEqual(tt.identifier_to_path("abcdefgh"), "abc/def/gh/abcdefgh")
self.assertEqual(tt.identifier_to_path("abcdefghi"), "abc/def/ghi/abcdefghi")
layout = Layout_NNNN_Tuple_Tree(tuple_size=2)
self.assertRaises(LayoutException, layout.identifier_to_path, "")
self.assertEqual(layout.identifier_to_path("a"), "a/a")
self.assertEqual(layout.identifier_to_path("ab"), "ab/ab")
self.assertEqual(layout.identifier_to_path("abc"), "ab/c/abc")
self.assertEqual(layout.identifier_to_path("abcde"), "ab/cd/e/abcde")
layout = Layout_NNNN_Tuple_Tree(tuple_size=3)
self.assertEqual(layout.identifier_to_path("abcdefg"), "abc/def/g/abcdefg")
self.assertEqual(layout.identifier_to_path("abcdefgh"), "abc/def/gh/abcdefgh")
self.assertEqual(layout.identifier_to_path("abcdefghi"), "abc/def/ghi/abcdefghi")

0 comments on commit 64c9c3c

Please sign in to comment.