Tidy and flesh out tests
This commit is contained in:
parent
065363e462
commit
518fd94e5c
@ -14,6 +14,22 @@ import collections.abc
|
|||||||
from .w3c_datetime import datetime_to_str
|
from .w3c_datetime import datetime_to_str
|
||||||
|
|
||||||
|
|
||||||
|
def _str_datetime_now(x='now'):
|
||||||
|
"""Return datetime string for use with time attributes.
|
||||||
|
|
||||||
|
Handling depends on input:
|
||||||
|
'now' - returns datetime for now
|
||||||
|
other string - no change, return same value
|
||||||
|
otherwise - assume datetime value, generate string
|
||||||
|
"""
|
||||||
|
if (x == 'now' or not isinstance(x, str)):
|
||||||
|
# Now, this is wht datetime_to_str() with no arg gives
|
||||||
|
return datetime_to_str(x)
|
||||||
|
else:
|
||||||
|
# Assume valid datetime string
|
||||||
|
return x
|
||||||
|
|
||||||
|
|
||||||
class ResourceContainer(object):
|
class ResourceContainer(object):
|
||||||
"""Class containing resource-like objects.
|
"""Class containing resource-like objects.
|
||||||
|
|
||||||
@ -26,6 +42,11 @@ class ResourceContainer(object):
|
|||||||
- uri is optional identifier of this container object
|
- uri is optional identifier of this container object
|
||||||
- capability_name - name of this capability
|
- capability_name - name of this capability
|
||||||
|
|
||||||
|
The properties md_from, md_at, md_until and md_completed are datetime
|
||||||
|
strings. The setters acceopt either a string value (not checked), the value
|
||||||
|
'now' to generate the current datetime, or otherwise an integer timestamp
|
||||||
|
value that is converted to a string.
|
||||||
|
|
||||||
Derived classes may add extra functionality such as len() etc..
|
Derived classes may add extra functionality such as len() etc..
|
||||||
However, any code designed to work with any ResourceContainer
|
However, any code designed to work with any ResourceContainer
|
||||||
should use only the core functionality.
|
should use only the core functionality.
|
||||||
@ -45,19 +66,16 @@ class ResourceContainer(object):
|
|||||||
|
|
||||||
Baseline implementation use iterator given by resources property.
|
Baseline implementation use iterator given by resources property.
|
||||||
"""
|
"""
|
||||||
return(iter(self.resources))
|
return iter(self.resources)
|
||||||
|
|
||||||
def __getitem__(self, index):
|
def __getitem__(self, index):
|
||||||
"""Feed through for __getitem__ of resources property."""
|
"""Feed through for __getitem__ of resources property."""
|
||||||
return(self.resources[index])
|
return self.resources[index]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def capability(self):
|
def capability(self):
|
||||||
"""Get/set the <rs:md capability="" .../> attribute."""
|
"""Get/set the <rs:md capability="" .../> attribute, None if not set."""
|
||||||
if ('capability' in self.md):
|
return self.md.get('capability')
|
||||||
return(self.md['capability'])
|
|
||||||
else:
|
|
||||||
return(None)
|
|
||||||
|
|
||||||
@capability.setter
|
@capability.setter
|
||||||
def capability(self, capability):
|
def capability(self, capability):
|
||||||
@ -65,65 +83,53 @@ class ResourceContainer(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def md_from(self):
|
def md_from(self):
|
||||||
"""Get/set the <rs:md from="" .../> attribute."""
|
"""Get/set the <rs:md from="" .../> attribute, None if not set."""
|
||||||
if ('md_from' in self.md):
|
return self.md.get('md_from')
|
||||||
return(self.md['md_from'])
|
|
||||||
else:
|
|
||||||
return(None)
|
|
||||||
|
|
||||||
@md_from.setter
|
@md_from.setter
|
||||||
def md_from(self, md_from):
|
def md_from(self, md_from):
|
||||||
self.md['md_from'] = self._str_datetime_now(md_from)
|
self.md['md_from'] = _str_datetime_now(md_from)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def md_until(self):
|
def md_until(self):
|
||||||
"""Get/set the <rs:md until="" .../> attribute."""
|
"""Get/set the <rs:md until="" .../> attribute, None if not set."""
|
||||||
if ('md_until' in self.md):
|
return self.md.get('md_until')
|
||||||
return(self.md['md_until'])
|
|
||||||
else:
|
|
||||||
return(None)
|
|
||||||
|
|
||||||
@md_until.setter
|
@md_until.setter
|
||||||
def md_until(self, md_until):
|
def md_until(self, md_until):
|
||||||
self.md['md_until'] = self._str_datetime_now(md_until)
|
self.md['md_until'] = _str_datetime_now(md_until)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def md_at(self):
|
def md_at(self):
|
||||||
"""Get/set the <rs:md at="" attribute."""
|
"""Get/set the <rs:md at="" attribute."""
|
||||||
if ('md_at' in self.md):
|
return self.md.get('md_at')
|
||||||
return(self.md['md_at'])
|
|
||||||
else:
|
|
||||||
return(None)
|
|
||||||
|
|
||||||
@md_at.setter
|
@md_at.setter
|
||||||
def md_at(self, md_at):
|
def md_at(self, md_at):
|
||||||
self.md['md_at'] = self._str_datetime_now(md_at)
|
self.md['md_at'] = _str_datetime_now(md_at)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def md_completed(self):
|
def md_completed(self):
|
||||||
"""Get/set the <rs:md completed="" .../> attribute."""
|
"""Get/set the <rs:md completed="" .../> attribute, None if not set."""
|
||||||
if ('md_completed' in self.md):
|
return self.md.get('md_completed')
|
||||||
return(self.md['md_completed'])
|
|
||||||
else:
|
|
||||||
return(None)
|
|
||||||
|
|
||||||
@md_completed.setter
|
@md_completed.setter
|
||||||
def md_completed(self, md_completed):
|
def md_completed(self, md_completed):
|
||||||
self.md['md_completed'] = self._str_datetime_now(md_completed)
|
self.md['md_completed'] = _str_datetime_now(md_completed)
|
||||||
|
|
||||||
def link(self, rel):
|
def link(self, rel):
|
||||||
"""Look for link with specified rel, return else None."""
|
"""Look for link with specified rel, return else None."""
|
||||||
for link in self.ln:
|
for link in self.ln:
|
||||||
if ('rel' in link and link['rel'] == rel):
|
if ('rel' in link and link['rel'] == rel):
|
||||||
return(link)
|
return link
|
||||||
return(None)
|
return None
|
||||||
|
|
||||||
def link_href(self, rel):
|
def link_href(self, rel):
|
||||||
"""Look for link with specified rel, return href from it or None."""
|
"""Look for link with specified rel, return href from it or None."""
|
||||||
link = self.link(rel)
|
link = self.link(rel)
|
||||||
if (link is not None):
|
if (link is not None):
|
||||||
link = link['href']
|
link = link['href']
|
||||||
return(link)
|
return link
|
||||||
|
|
||||||
def link_set(self, rel, href, **atts):
|
def link_set(self, rel, href, **atts):
|
||||||
"""Set/create link with specified rel, set href and any other attributes.
|
"""Set/create link with specified rel, set href and any other attributes.
|
||||||
@ -132,16 +138,16 @@ class ResourceContainer(object):
|
|||||||
also defines the type attributes and others are permitted also. See
|
also defines the type attributes and others are permitted also. See
|
||||||
description of allowed formats in
|
description of allowed formats in
|
||||||
|
|
||||||
http://www.openarchives.org/rs/resourcesync.html#DocumentFormats
|
http://www.openarchives.org/rs/resourcesync#DocumentFormats
|
||||||
"""
|
"""
|
||||||
link = self.link(rel)
|
link = self.link(rel)
|
||||||
if (link is not None):
|
if link is None:
|
||||||
# overwrite current value
|
|
||||||
link['href'] = href
|
|
||||||
else:
|
|
||||||
# create new link
|
# create new link
|
||||||
link = {'rel': rel, 'href': href}
|
link = {'rel': rel, 'href': href}
|
||||||
self.ln.append(link)
|
self.ln.append(link)
|
||||||
|
else:
|
||||||
|
# overwrite current value
|
||||||
|
link['href'] = href
|
||||||
for k in atts:
|
for k in atts:
|
||||||
link[k] = atts[k]
|
link[k] = atts[k]
|
||||||
|
|
||||||
@ -232,29 +238,3 @@ class ResourceContainer(object):
|
|||||||
pruned2.append(r)
|
pruned2.append(r)
|
||||||
self.resources = pruned2
|
self.resources = pruned2
|
||||||
return(n)
|
return(n)
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
"""Return string of all resources in order given by interator."""
|
|
||||||
s = ''
|
|
||||||
for resource in self:
|
|
||||||
s += str(resource) + "\n"
|
|
||||||
return(s)
|
|
||||||
|
|
||||||
def _str_datetime_now(self, x=None):
|
|
||||||
"""Return datetime string for use with time attributes.
|
|
||||||
|
|
||||||
Handling depends on input:
|
|
||||||
'now' - returns datetime for now
|
|
||||||
number - assume datetime values, generate string
|
|
||||||
other - no change, return same value
|
|
||||||
"""
|
|
||||||
if (x == 'now'):
|
|
||||||
# Now, this is wht datetime_to_str() with no arg gives
|
|
||||||
return(datetime_to_str())
|
|
||||||
try:
|
|
||||||
# Test for number
|
|
||||||
junk = x + 0.0
|
|
||||||
return datetime_to_str(x)
|
|
||||||
except TypeError:
|
|
||||||
# Didn't look like a number, treat as string
|
|
||||||
return x
|
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
|
"""Tests for resync.resource_container."""
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
from resync.resource import Resource
|
from resync.resource import Resource
|
||||||
from resync.resource_container import ResourceContainer
|
from resync.resource_container import ResourceContainer, _str_datetime_now
|
||||||
|
|
||||||
|
|
||||||
class TestResourceContainer(unittest.TestCase):
|
class TestResourceContainer(unittest.TestCase):
|
||||||
@ -8,9 +10,12 @@ class TestResourceContainer(unittest.TestCase):
|
|||||||
def test01_create_and_add(self):
|
def test01_create_and_add(self):
|
||||||
rc = ResourceContainer(resources=[])
|
rc = ResourceContainer(resources=[])
|
||||||
self.assertEqual(len(rc.resources), 0, "empty")
|
self.assertEqual(len(rc.resources), 0, "empty")
|
||||||
rc.resources.append(Resource('a', timestamp=1))
|
rc.add(Resource('a', timestamp=1))
|
||||||
rc.resources.append(Resource('b', timestamp=2))
|
rc.add(Resource('b', timestamp=2))
|
||||||
self.assertEqual(len(rc.resources), 2, "two resources")
|
self.assertEqual(len(rc.resources), 2, "two resources")
|
||||||
|
# Add two more
|
||||||
|
rc.add([Resource('c'), Resource('d')])
|
||||||
|
self.assertEqual(len(rc.resources), 4, "four resources")
|
||||||
|
|
||||||
def test02_iter(self):
|
def test02_iter(self):
|
||||||
rc = ResourceContainer(resources=[])
|
rc = ResourceContainer(resources=[])
|
||||||
@ -93,3 +98,37 @@ class TestResourceContainer(unittest.TestCase):
|
|||||||
self.assertEqual(rc.up, None)
|
self.assertEqual(rc.up, None)
|
||||||
rc.up = "up_uri"
|
rc.up = "up_uri"
|
||||||
self.assertEqual(rc.up, "up_uri")
|
self.assertEqual(rc.up, "up_uri")
|
||||||
|
|
||||||
|
def test09_capability(self):
|
||||||
|
"""Test capability property."""
|
||||||
|
rc = ResourceContainer()
|
||||||
|
self.assertEqual(rc.capability, None)
|
||||||
|
rc.capability = "fixit"
|
||||||
|
self.assertEqual(rc.capability, 'fixit')
|
||||||
|
|
||||||
|
def test10_link_set(self):
|
||||||
|
"""Test link_set method."""
|
||||||
|
rc = ResourceContainer()
|
||||||
|
self.assertEqual(rc.link('alink'), None) # non-spec rel should be supported
|
||||||
|
rc.link_set('alink', 'uri:l', extra1='one', extra2='two')
|
||||||
|
ln = rc.link('alink')
|
||||||
|
self.assertEqual(rc.link('alink'), {'rel': 'alink', 'href': 'uri:l',
|
||||||
|
'extra1': 'one', 'extra2': 'two'})
|
||||||
|
# Can update existing link
|
||||||
|
rc.link_set('alink', 'uri:new', extra1='1')
|
||||||
|
self.assertEqual(rc.link('alink'), {'rel': 'alink', 'href': 'uri:new',
|
||||||
|
'extra1': '1', 'extra2': 'two'})
|
||||||
|
|
||||||
|
def test11_index(self):
|
||||||
|
"""Test index property."""
|
||||||
|
rc = ResourceContainer()
|
||||||
|
self.assertEqual(rc.index, None)
|
||||||
|
rc.index = 'uri:i'
|
||||||
|
self.assertEqual(rc.index, 'uri:i')
|
||||||
|
|
||||||
|
def test12_str_datetime_now(self):
|
||||||
|
"""Test _str_datetime_now function."""
|
||||||
|
self.assertTrue(isinstance(_str_datetime_now(), str))
|
||||||
|
self.assertTrue(isinstance(_str_datetime_now('now'), str))
|
||||||
|
self.assertEqual(_str_datetime_now(0), '1970-01-01T00:00:00Z')
|
||||||
|
self.assertEqual(_str_datetime_now('2020-12-24T16:01:00Z'), '2020-12-24T16:01:00Z')
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user