Skip to content

Commit 65843a7

Browse files
committed
[_688] impl raw _server_version
1 parent e561032 commit 65843a7

5 files changed

Lines changed: 90 additions & 3 deletions

File tree

irods/connection.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ def __init__(self, pool, account):
8383
self._disconnected = False
8484

8585
scheme = self.account._original_authentication_scheme
86+
if self.pool and not self.pool._need_auth:
87+
return
8688

8789
# These variables are just useful diagnostics. The login_XYZ() methods should fail by
8890
# raising exceptions if they encounter authentication errors.

irods/helpers/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,13 @@ def xml_mode(s):
3636
yield
3737
finally:
3838
ET(None)
39+
40+
41+
@contextlib.contextmanager
42+
def attr_changed(obj, attrname, value):
43+
old = getattr(obj, attrname, None)
44+
try:
45+
setattr(obj, attrname, value)
46+
yield
47+
finally:
48+
setattr(obj, attrname, old)

irods/pool.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import contextlib
12
import datetime
23
import logging
34
import threading
@@ -57,6 +58,7 @@ def __init__(
5758
or application_name
5859
or DEFAULT_APPLICATION_NAME
5960
)
61+
self._need_auth = True
6062

6163
if connection_refresh_time > 0:
6264
self.refresh_connection = True
@@ -65,6 +67,15 @@ def __init__(
6567
self.refresh_connection = False
6668
self.connection_refresh_time = None
6769

70+
@contextlib.contextmanager
71+
def no_auto_authenticate(self):
72+
import irods.helpers
73+
with irods.helpers.attr_changed(self, '_need_auth', False):
74+
yield self
75+
76+
def set_session_ref(self, session):
77+
self.session_ref = weakref.ref(session) if session is not None else lambda: None
78+
6879
@property
6980
def _conn(self):
7081
return getattr(self._thread_local, "_conn", None)

irods/session.py

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import ast
22
import atexit
3+
import contextlib
34
import copy
45
import errno
56
import json
@@ -69,6 +70,16 @@ class NonAnonymousLoginWithoutPassword(RuntimeError):
6970
pass
7071

7172

73+
@contextlib.contextmanager
74+
def attr_changed(obj, attrname, value):
75+
old = getattr(obj, attrname, None)
76+
try:
77+
setattr(obj, attrname, value)
78+
yield
79+
finally:
80+
setattr(obj, attrname, old)
81+
82+
7283
class iRODSSession:
7384

7485
def library_features(self):
@@ -354,11 +365,36 @@ def port(self):
354365
return self.pool.account.port
355366

356367
@property
357-
def server_version(self):
368+
def server_version(self): return self._server_version()
369+
370+
def raw_server_version(self):
371+
"""Returns the same version tuple as iRODSSession's server_version property, but
372+
does not require successful authentication.
373+
"""
374+
import irods.connection
375+
with self.clone().pool.no_auto_authenticate() as pool:
376+
return irods.connection.Connection(
377+
pool, pool.account
378+
).server_version
379+
380+
RAW_SERVER_VERSION = staticmethod(lambda s:s.raw_server_version())
381+
382+
def _server_version(self, version_func = None):
383+
"""The server version can be retrieved by the usage
384+
session._server_version()
385+
with conditional substitution by another version by use of the environment variable:
386+
PYTHON_IRODSCLIENT_REPORTED_SERVER_VERSION.
387+
388+
Also: if iRODSServer.RAW_SERVER_VERSION is passed in version_func, the true server
389+
version can be accessed without first going through authentication.
390+
Example:
391+
ses = irods.helpers.make_session()
392+
vsn = ses._server_version( ses.RAW_SERVER_VERSION )
393+
"""
358394
reported_vsn = os.environ.get("PYTHON_IRODSCLIENT_REPORTED_SERVER_VERSION", "")
359395
if reported_vsn:
360396
return tuple(ast.literal_eval(reported_vsn))
361-
return self.__server_version()
397+
return self.__server_version() if version_func is None else version_func(self)
362398

363399
def __server_version(self):
364400
try:

irods/test/connection_test.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
#! /usr/bin/env python
22

3+
import numbers
34
import os
45
import sys
56
import tempfile
67
import unittest
7-
from irods.exception import NetworkException
88
from irods import MAXIMUM_CONNECTION_TIMEOUT
9+
from irods.exception import (
10+
NetworkException,
11+
CAT_INVALID_AUTHENTICATION
12+
)
13+
import irods.session
914
import irods.test.helpers as helpers
1015
from irods.test.helpers import (
1116
server_side_sleep,
@@ -34,6 +39,29 @@ def test_connection_destructor(self):
3439
self.assertTrue(conn._disconnected)
3540
conn.release(destroy=True)
3641

42+
def test_server_version_without_authentication__issue_688 (self):
43+
sess = self.sess
44+
45+
# Make a session object that cannot authenticate.
46+
non_authenticating_session = irods.session.iRODSSession(
47+
host = sess.host,
48+
port = sess.port,
49+
user = sess.username,
50+
zone = sess.zone,
51+
# No password.
52+
)
53+
54+
# Test raw_server_version method returns a value.
55+
version_tup = non_authenticating_session.raw_server_version()
56+
57+
# Test returned value is non-empty "version" tuple, i.e. holds only integer values.
58+
self.assertTrue(len(version_tup) > 0)
59+
self.assertFalse(any(not isinstance(_, numbers.Integral) for _ in version_tup))
60+
61+
# Test that the older server_version property fails for the unauthorized session object.
62+
with self.assertRaises(CAT_INVALID_AUTHENTICATION):
63+
non_authenticating_session.server_version
64+
3765
def test_failed_connection(self):
3866
# Make sure no connections are cached in self.sess.pool.idle to be grabbed by get_connection().
3967
# (Necessary after #418 fix; make_session() can probe server_version, which then leaves an idle conn.)

0 commit comments

Comments
 (0)