Skip to content

Commit

Permalink
implement xml_mode() in a new irods.helpers module
Browse files Browse the repository at this point in the history
  • Loading branch information
d-w-moore committed Jul 21, 2024
1 parent 34c931c commit 530f97e
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 1 deletion.
50 changes: 50 additions & 0 deletions irods/helpers/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import functools
import inspect
import types
import contextlib
from ..test.helpers import make_session as make_test_session
from irods.message import (ET, XML_Parser_Type)


# See https://stackoverflow.com/questions/67028108/overriding-function-signature-in-help-when-using-functools-wraps
def update_func(f, func_name='', update_kwargs: dict = None):
"""Based on http://stackoverflow.com/a/6528148/190597 (Glenn Maynard)"""
g = types.FunctionType(
code=f.__code__,
globals=f.__globals__.copy(),
name=f.__name__,
argdefs=f.__defaults__,
closure=f.__closure__
)

g = functools.update_wrapper(g, f)
g.__signature__ = inspect.signature(g)
g.__kwdefaults__ = (f.__kwdefaults__ or {}).copy()

# Adjust your arguments
for key, value in (update_kwargs or {}).items():
g.__kwdefaults__[key] = value
g.__signature__.parameters[key]._default = value

g.__name__ = func_name or g.__name__
return g


make_session = update_func(make_test_session,
update_kwargs = dict(test_server_version = False))


@contextlib.contextmanager
def xml_mode(s):
try:
if isinstance(s,str):
ET(getattr(XML_Parser_Type,s)) # e.g. xml_mode("QUASI_XML")
elif isinstance(s,(int,XML_Parser_Type)):
ET(s) # e.g. xml_mode(2) or xml_mode(XML_Parser_Type.QUASI_XML)
else:
msg = "xml_mode argument must be a string (e.g. 'QUASI_XML'), XML_Parser_Type enum, or int."
raise ValueError(msg)
yield
finally:
ET(None)

5 changes: 4 additions & 1 deletion irods/message/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def __repr__(self):
XML_Parser_Type.__members__ = {k:v for k,v in XML_Parser_Type.__dict__.items()
if isinstance(v,XML_Parser_Type)}

PARSER_TYPE_STRINGS = {v:k for k,v in XML_Parser_Type.__members__.items() if v.value != 0}
PARSER_TYPE_STRINGS = {v:k for k,v in XML_Parser_Type.__members__.items() if v.value != 0}

# We maintain values on a per-thread basis of:
# - the server version with which we're communicating
Expand Down Expand Up @@ -111,6 +111,9 @@ def default_XML_parser(get_module = False):
d = _default_XML
return d if not get_module else _XML_parsers[d]

def string_for_XML_parser(parser_enum):
return PARSER_TYPE_STRINGS[parser_enum]

_XML_parsers = {
XML_Parser_Type.STANDARD_XML : ET_xml,
XML_Parser_Type.QUASI_XML : ET_quasi_xml,
Expand Down
12 changes: 12 additions & 0 deletions irods/test/data_obj_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -1847,6 +1847,18 @@ def test_access_through_resc_hierarchy__243(self):
finally:
s.resources.remove('parent')

def test_temporary_xml_mode_change__issue_586(self): #dwm
from irods.message import (XML_Parser_Type, current_XML_parser, string_for_XML_parser)
from concurrent.futures import ThreadPoolExecutor
active_xml_for_thread = lambda : string_for_XML_parser(current_XML_parser())
from irods.helpers import xml_mode
self.assertEqual( active_xml_for_thread(), 'STANDARD_XML')
with xml_mode('QUASI_XML'):
# Test that this thread is the only one affected, and that in it we get 'QUASI_XML' when we call
# current_XML_parser(), i.e. the function used internally by ET() to retrieve the current parser module].
self.assertEqual( 'QUASI_XML',active_xml_for_thread())
self.assertEqual( 'STANDARD_XML',ThreadPoolExecutor(max_workers = 1).submit(active_xml_for_thread).result())

def test_register_with_xml_special_chars(self):
test_dir = helpers.irods_shared_tmp_dir()
loc_server = self.sess.host in ('localhost', socket.gethostname())
Expand Down
12 changes: 12 additions & 0 deletions irods/test/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,18 @@ def recast(k):
# Create a connection for test, based on ~/.irods environment by default.

def make_session(test_server_version = True, **kwargs):
'''
Connect to an active iRODS server as determined by any client environment
file present at a standard location, and by any keyword arguments given.
Arguments:
test_server_version (True or False). Raises iRODS_Server_Too_Recent if
the server connected to is more recent than the current python iRODS
client's advertised level of compatibility.
**kwargs: keyword arguments. Fed directly to the iRODSSession constructor.
'''
try:
env_file = kwargs.pop('irods_env_file')
except KeyError:
Expand Down

0 comments on commit 530f97e

Please sign in to comment.