Skip to content

Commit be92b5b

Browse files
d-w-moorealanking
authored andcommitted
[#386][#389] only load timestamps when requested
1 parent 8556671 commit be92b5b

4 files changed

Lines changed: 82 additions & 17 deletions

File tree

README.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,12 @@ or even:
432432

433433
>>> album.metadata(admin = True)[meta.name] = meta
434434

435+
In v1.1.5, the "timestamps" keyword is provided to enable the loading of create and modify timestamps
436+
for every AVU returned from the server:
437+
438+
>>> avus = album.metadata(timestamps = True).items()
439+
>>> avus[0].create_time
440+
datetime.datetime(2022, 9, 19, 15, 26, 7)
435441

436442
Atomic operations on metadata
437443
-----------------------------

irods/manager/metadata_manager.py

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,24 @@ class InvalidAtomicAVURequest(Exception): pass
2121

2222
class MetadataManager(Manager):
2323

24+
@property
25+
def use_timestamps(self):
26+
return getattr(self,'_use_ts',False)
27+
2428
__kw = {} # default (empty) keywords
2529

2630
def _updated_keywords(self,opts):
2731
kw_ = self.__kw.copy()
2832
kw_.update(opts)
2933
return kw_
3034

31-
def __call__(self, admin = False, **irods_kw_opt):
32-
x = copy.copy(self)
33-
irods_kw_opt.update([() if not admin else (kw.ADMIN_KW,"")])
34-
x.__kw = irods_kw_opt
35-
return x
35+
def __call__(self, admin = False, timestamps = False, **irods_kw_opt):
36+
if admin:
37+
irods_kw_opt.update([(kw.ADMIN_KW,"")])
38+
new_self = copy.copy(self)
39+
new_self._use_ts = timestamps
40+
new_self.__kw = irods_kw_opt
41+
return new_self
3642

3743
@staticmethod
3844
def _model_class_to_resource_type(model_cls):
@@ -69,17 +75,24 @@ def get(self, model_cls, path):
6975
'R': [Resource.name == path],
7076
'u': [User.name == path]
7177
}[resource_type]
72-
results = self.sess.query(model.id, model.name, model.value, model.units, model.create_time, model.modify_time)\
73-
.filter(*conditions).all()
78+
79+
columns = (model.id, model.name, model.value, model.units)
80+
if self.use_timestamps:
81+
columns += (model.create_time, model.modify_time)
82+
results = self.sess.query(*columns).filter(*conditions).all()
83+
84+
def meta_opts(row):
85+
opts = {'avu_id': row[model.id]}
86+
if self.use_timestamps:
87+
opts.update(create_time = row[model.create_time], modify_time=row[model.modify_time])
88+
return opts
89+
7490
return [iRODSMeta(
75-
row[model.name],
76-
row[model.value],
77-
row[model.units],
78-
avu_id=row[model.id],
79-
create_time=row[model.create_time],
80-
modify_time=row[model.modify_time],
81-
82-
) for row in results]
91+
row[model.name],
92+
row[model.value],
93+
row[model.units],
94+
**meta_opts(row))
95+
for row in results]
8396

8497
def add(self, model_cls, path, meta, **opts):
8598
# Avoid sending request with empty argument(s)

irods/meta.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,10 @@ def __init__(self, operation, avu, **kw):
7676

7777
class iRODSMetaCollection(object):
7878

79-
def __call__(self, admin = False, **opts):
79+
def __call__(self, admin = False, timestamps = False, **opts):
8080
x = copy.copy(self)
81-
x._manager = (x._manager)(admin, **opts)
81+
x._manager = (x._manager)(admin, timestamps, **opts)
82+
x._reset_metadata()
8283
return x
8384

8485
def __init__(self, manager, model_cls, path):

irods/test/meta_test.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from __future__ import absolute_import
44
import os
55
import sys
6+
import time
7+
import datetime
68
import unittest
79
from irods.meta import (iRODSMeta, AVUOperation, BadAVUOperationValue, BadAVUOperationKeyword)
810
from irods.manager.metadata_manager import InvalidAtomicAVURequest
@@ -393,6 +395,49 @@ def test_irodsmetacollection_data_obj(self):
393395
test_obj.unlink(force=True)
394396

395397

398+
@staticmethod
399+
def check_timestamps(metadata_accessor, key):
400+
avu = metadata_accessor[key]
401+
create = getattr(avu,'create_time',None)
402+
modify = getattr(avu,'modify_time',None)
403+
return (create,modify)
404+
405+
406+
def test_timestamp_access_386(self):
407+
with helpers.make_session() as session:
408+
def units():
409+
return str(time.time())
410+
d = None
411+
try:
412+
d = session.data_objects.create('/tempZone/home/rods/issue_386')
413+
414+
# Test metadata access without timestamps
415+
416+
meta = d.metadata
417+
avu = iRODSMeta('no_ts','val',units())
418+
meta.set(avu)
419+
self.assertEqual((None, None), # Assert no timestamps are stored.
420+
self.check_timestamps(meta, key = avu.name))
421+
422+
# -- Test metadata access with timestamps
423+
424+
meta_ts = meta(timestamps = True)
425+
avu_use_ts = iRODSMeta('use_ts','val',units())
426+
meta_ts.set(avu_use_ts)
427+
time.sleep(1.5)
428+
now = datetime.datetime.utcnow()
429+
time.sleep(1.5)
430+
avu_use_ts.units = units()
431+
meta_ts.set(avu_use_ts) # Set an AVU with modified units.
432+
433+
(create, modify) = self.check_timestamps(meta_ts, key = avu_use_ts.name)
434+
435+
self.assertLess(create, now) # Ensure timestamps are in proper order.
436+
self.assertLess(now, modify)
437+
finally:
438+
if d: d.unlink(force = True)
439+
helpers.remove_unused_metadata(session)
440+
396441
if __name__ == '__main__':
397442
# let the tests find the parent irods lib
398443
sys.path.insert(0, os.path.abspath('../..'))

0 commit comments

Comments
 (0)