Skip to content

Commit 3323b9d

Browse files
committed
[_120,_801] misc changes
1 parent 5b0873a commit 3323b9d

3 files changed

Lines changed: 86 additions & 16 deletions

File tree

irods/models.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,10 +242,8 @@ class Ticket(Model):
242242
write_file_limit = Column(Integer, "TICKET_WRITE_FILE_LIMIT", 2212)
243243
write_byte_count = Column(Integer, "TICKET_WRITE_BYTE_COUNT", 2213)
244244
write_byte_limit = Column(Integer, "TICKET_WRITE_BYTE_LIMIT", 2214)
245-
246-
## For now, use of these columns raises CAT_SQL_ERR in both PRC and iquest: (irods/irods#5929)
247-
create_time = Column(DateTime, 'TICKET_CREATE_TIME', 2209)
248-
modify_time = Column(DateTime, 'TICKET_MODIFY_TIME', 2210)
245+
create_time = Column(DateTime, 'TICKET_CREATE_TIME', 2209, min_version=(4, 3, 0))
246+
modify_time = Column(DateTime, 'TICKET_MODIFY_TIME', 2210, min_version=(4, 3, 0))
249247

250248
class DataObject(Model):
251249
"""For queries of R_DATA_MAIN when joining to R_TICKET_MAIN.

irods/test/ticket_test.py

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,25 @@
11
#! /usr/bin/env python
22

3+
import calendar
4+
import datetime
5+
import logging
36
import os
47
import sys
5-
import unittest
68
import time
7-
import calendar
9+
import unittest
810

911
import irods.test.helpers as helpers
1012
import tempfile
1113
from irods.session import iRODSSession
1214
import irods.exception as ex
1315
import irods.keywords as kw
14-
from irods.ticket import Ticket
16+
from irods.ticket import list_tickets, Ticket
1517
from irods.models import TicketQuery, DataObject, Collection
1618

1719

20+
logger = logging.getLogger(__name__)
21+
22+
1823
# As with most of the modules in this test suite, session objects created via
1924
# make_session() are implicitly agents of a rodsadmin unless otherwise indicated.
2025
# Counterexamples within this module shall be obvious as they are instantiated by
@@ -29,6 +34,17 @@ def gmtime_to_timestamp(gmt_struct):
2934
)
3035

3136

37+
def delete_tickets(session, dry_run = False):
38+
for res in session.query(TicketQuery.Ticket):
39+
t = Ticket(session, result=res)
40+
if dry_run in (False, None):
41+
t.delete(**{kw.ADMIN_KW: ""})
42+
elif isinstance(dry_run, list):
43+
dry_run.append(t)
44+
else:
45+
logger.info('Found ticket: %s',t.string)
46+
47+
3248
def delete_my_tickets(session):
3349
my_userid = session.users.get(session.username).id
3450
my_tickets = session.query(TicketQuery.Ticket).filter(
@@ -358,6 +374,27 @@ def test_coll_read_ticket_between_rodsusers(self):
358374
os.unlink(file_.name)
359375
alice.cleanup()
360376

377+
def test_new_attributes_in_tickets__issue_801(self):
378+
379+
if (admin:=helpers.make_session()).server_version < (4, 3, 0):
380+
self.skipTest('"create_time" and "modify_time" not supported for Ticket')
381+
382+
try:
383+
with self.login(self.bob) as bob:
384+
bobs_ticket = Ticket(bob)
385+
bobs_ticket.issue('write', helpers.home_collection(bob))
386+
time.sleep(2)
387+
bobs_ticket.modify('add', 'user', admin.username)
388+
bobs_ticket = Ticket(bob, result=[], ticket=bobs_ticket.string)
389+
self.assertGreaterEqual(
390+
bobs_ticket.modify_time,
391+
bobs_ticket.create_time + datetime.timedelta(seconds=1)
392+
)
393+
394+
admin_ticket_for_bob = Ticket(admin, result=[], ticket=bobs_ticket.string)
395+
self.assertEqual(admin_ticket_for_bob.id, bobs_ticket.id)
396+
finally:
397+
admin_ticket_for_bob.delete(**{kw.ADMIN_KW:''})
361398

362399
class TestTicketOps(unittest.TestCase):
363400

@@ -456,6 +493,21 @@ def test_coll_ticket_write(self):
456493
self._ticket_write_helper(obj_type="coll")
457494

458495

496+
def test_list_tickets__issue_120(self):
497+
498+
ses = self.sess
499+
500+
# t first assigned as a "utility" Ticket object
501+
t = Ticket(ses).issue('read', helpers.home_collection(ses))
502+
self.assertGreater(len(t.string) , 5)
503+
504+
# This time, t receives attributes from the GenQuery row result
505+
t = Ticket(ses, result=[], ticket=t.string)
506+
507+
# Check an id attribute is present and listed in the results from list_tickets
508+
self.assertIn(t.id, (_.id for _ in list_tickets(ses)))
509+
510+
459511
if __name__ == "__main__":
460512
# let the tests find the parent irods lib
461513
sys.path.insert(0, os.path.abspath("../.."))

irods/ticket.py

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
from irods.api_number import api_number
22
from irods.message import iRODSMessage, TicketAdminRequest
33
from irods.models import TicketQuery
4+
from irods.column import Like
5+
from collections.abc import Mapping, Sequence
46

57
import random
68
import string
@@ -28,12 +30,13 @@ def get_epoch_seconds(utc_timestamp):
2830
raise # final try at conversion, so a failure is an error
2931

3032

31-
def list_tickets(session, all=True):
33+
def list_tickets(session, *, raw=False, all=True):
3234
"""
3335
Enumerates (via GenQuery1) all tickets visible by, or owned by, the current user.
3436
3537
Args:
3638
session: An iRODSSession object for use in the query.
39+
raw: True if only the queried rows are to be returned; False to construct Ticket objects for each row.
3740
all: True if a comprehensive list is desired; otherwise only those
3841
tickets owned by the calling user.
3942
@@ -45,32 +48,49 @@ def list_tickets(session, all=True):
4548
query = query.filter(
4649
TicketQuery.Ticket.user_id == session.users.get(session.username).id
4750
)
48-
yield from query
51+
if raw:
52+
yield from query
53+
else:
54+
yield from (Ticket(session, result=_) for _ in query)
4955

5056

5157
class Ticket:
5258
def __init__(self, session, ticket="", result=None, allow_punctuation=False):
5359
self._session = session
5460
try:
55-
if hasattr(result,'__getitem__') and result.get(TicketQuery.Ticket.string,''):
56-
pass
57-
elif ticket and hasattr(result,'__iter__'):
58-
result = [_ for _ in result if _[TicketQuery.Ticket.string] == ticket][0]
61+
if isinstance(result, Mapping):
62+
if (single_string:=result.get(TicketQuery.Ticket.string, '')):
63+
if ticket and (ticket != single_string):
64+
raise RuntimeError(
65+
f"The specified result contained a ticket string mismatched to the provided identifier ({ticket = })"
66+
)
67+
68+
# Allow limited query for the purpose of populating id and other attributes
69+
if result == [] and ticket:
70+
result[:] = list(session.query(TicketQuery.Ticket).filter(TicketQuery.Ticket.string == ticket))
71+
72+
if isinstance(result, Sequence):
73+
if ticket:
74+
result = [_ for _ in result if _[TicketQuery.Ticket.string] == ticket][:1]
75+
76+
if not result:
77+
result = None
78+
else:
79+
result = result[0]
80+
5981
if result:
6082
ticket = result[TicketQuery.Ticket.string]
6183
for attr, value in TicketQuery.Ticket.__dict__.items():
6284
if value is TicketQuery.Ticket.string: continue
63-
#print ('copying',attr)
6485
if not attr.startswith("_"):
6586
try:
6687
setattr(self, attr, result[value])
6788
except KeyError:
6889
# backward compatibility with older schema versions
6990
pass
7091
except TypeError:
71-
7292
raise RuntimeError(
73-
"If specified, 'result' parameter must be a TicketQuery.Ticket search result"
93+
"If specified, 'result' parameter must be a TicketQuery.Ticket search result or iterable of same"
7494
)
7595
except IndexError:
7696
raise RuntimeError(

0 commit comments

Comments
 (0)