Repository: scikit-hep/uproot5

Issue:
XRootD version detection doesn't work for versions before 4.11.1
There are two independent places where the XRootD version is detected:

https://github.com/scikit-hep/uproot4/blob/9607057b07b5936d6f2925e33ad6386a7dfc7705/src/uproot/extras.py#L121 and https://github.com/scikit-hep/uproot4/blob/9607057b07b5936d6f2925e33ad6386a7dfc7705/src/uproot/reading.py#L170

These both rely on `pkg_resources.get_distribution("XRootD")`, but the name of the Python module [changed from `pyxrootd` to `xrootd`](https://github.com/xrootd/xrootd/commit/dfa0806f02775dc04e7835e8fc871b81a2bd786f) in [v4.11.1](https://github.com/xrootd/xrootd/blob/v4.11.1/docs/ReleaseNotes.txt#L26). Critically, this means that with XRootD v4.11.0 and earlier, the workaround here (for the deadlock condition described in https://github.com/scikit-hep/uproot3/issues/504):

https://github.com/scikit-hep/uproot4/blob/9607057b07b5936d6f2925e33ad6386a7dfc7705/src/uproot/extras.py#L87-L107

doesn't get applied, and you don't get the warning in:

https://github.com/scikit-hep/uproot4/blob/9607057b07b5936d6f2925e33ad6386a7dfc7705/src/uproot/reading.py#L169-L178


Discussion:
Is the `xrootd` package actually `pyxrootd` for the versions before 4.11.1 ([see list](https://pypi.org/project/xrootd/#history))? Uproot never imports `pyxrootd`; it (now) always uses the name `xrootd`.

If you have `xrootd < 5.2.0`, then you'll get the fix and the warning; if you have a newer `xrootd`, you won't, and if you don't have a package named `xrootd`—perhaps you have a package named `pyxrootd`, but we don't look at that—then you just won't be able to use `root://` URLs, right?
That would be logical, but yeah, this is where things get weird:

```python
>>> import XRootD
>>> XRootD.client
<module 'XRootD.client' from '/home/mproffit/miniconda3/envs/xrootd_test/lib/python3.8/site-packages/XRootD/client/__init__.py'>

>>> import pkg_resources
>>> pkg_resources.get_distribution('XRootD')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/mproffit/miniconda3/envs/xrootd_test/lib/python3.8/site-packages/pkg_resources/__init__.py", line 466, in get_distribution
    dist = get_provider(dist)
  File "/home/mproffit/miniconda3/envs/xrootd_test/lib/python3.8/site-packages/pkg_resources/__init__.py", line 342, in get_provider
    return working_set.find(moduleOrReq) or require(str(moduleOrReq))[0]
  File "/home/mproffit/miniconda3/envs/xrootd_test/lib/python3.8/site-packages/pkg_resources/__init__.py", line 886, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/home/mproffit/miniconda3/envs/xrootd_test/lib/python3.8/site-packages/pkg_resources/__init__.py", line 772, in resolve
    raise DistributionNotFound(req, requirers)
pkg_resources.DistributionNotFound: The 'XRootD' distribution was not found and is required by the application

>>> pkg_resources.get_distribution('pyxrootd')
pyxrootd 4.11.0 (/home/mproffit/miniconda3/envs/xrootd_test/lib/python3.8/site-packages)

>>> import uproot
>>> uproot.__version__
'4.1.5'
>>> uproot.open("root://eospublic.cern.ch//eos/root-eos/benchmark/Run2012B_SingleMu.root").keys()
['Events;1']
```

This is with `conda install -c conda-forge xrootd==4.11.0`.
So for this version of the package, `pkg_resources.get_distribution('XRootD')` raises an exception, `pkg_resources.get_distribution('pyxrootd')` returns a value, and `import XRootD` works? I don't know how that's possible; I would have thought that the `pkg_resources` name would have to be the `import` name.

It could be acceptable to stop supporting XRootD < 5.2.0 (there seems to be some confusion above as to whether it's 5.1.0 or 5.2.0). What do you think? Do you know of any groups of users who might be stuck on an old XRootD for some reason? (E.g. glued to a collaboration's software distribution version or something?)
Yeah, I just checked the latest ATLAS AnalsisBase image and it has 4.12.2. Right now, I'm dealing with old versions of XRootD because that's what's in the ServiceX Uproot transformer image. It's currently using 4.11.0, and updating up through 5.1.1 seems to work fine, but updating to v5.2.0 or higher looks like it's going to require updating `conda` and bring a lot of new dependency conflicts.

My inclination would be to just keep the limited support in but to add a `try` for `pkg_resources.get_distribution('pyxrootd')` after `try`ing `'XRootD'` so that earlier versions still get detected and have the workaround applied and show the warning.
That sounds good. If you add the check for both "pyxrootd" and "XRootD" in a PR, I'll review it and release a new version of Uproot quickly.

Resolving patch:
diff --git a/src/uproot/extras.py b/src/uproot/extras.py
--- a/src/uproot/extras.py
+++ b/src/uproot/extras.py
@@ -117,17 +117,31 @@ def older_xrootd(min_version):
     return False: that is, they're assumed to be new, so that no warnings
     are raised.
     """
-    try:
-        dist = pkg_resources.get_distribution("XRootD")
-    except pkg_resources.DistributionNotFound:
+    version = xrootd_version()
+    if version is None:
         return False
     else:
         try:
-            return LooseVersion(dist.version) < LooseVersion(min_version)
+            return LooseVersion(version) < LooseVersion(min_version)
         except TypeError:
             return False
 
 
+def xrootd_version():
+    """
+    Gets the XRootD version if installed, otherwise returns None.
+    """
+    try:
+        version = pkg_resources.get_distribution("XRootD").version
+    except pkg_resources.DistributionNotFound:
+        try:
+            # Versions before 4.11.1 used pyxrootd as the package name
+            version = pkg_resources.get_distribution("pyxrootd").version
+        except pkg_resources.DistributionNotFound:
+            version = None
+    return version
+
+
 def lzma():
     """
     Imports and returns ``lzma`` (which is part of the Python 3 standard
diff --git a/src/uproot/reading.py b/src/uproot/reading.py
--- a/src/uproot/reading.py
+++ b/src/uproot/reading.py
@@ -15,8 +15,6 @@
 import uuid
 import warnings
 
-import pkg_resources
-
 try:
     from collections.abc import Mapping, MutableMapping
 except ImportError:
@@ -167,9 +165,10 @@ def __getitem__(self, where):
         if where == "xrootd_handler" and where not in self:
             # See https://github.com/scikit-hep/uproot4/issues/294
             if uproot.extras.older_xrootd("5.2.0"):
-                dist = pkg_resources.get_distribution("XRootD")
                 message = (
-                    "XRootD {0} is not fully supported; ".format(dist.version)
+                    "XRootD {0} is not fully supported; ".format(
+                        uproot.extras.xrootd_version()
+                    )
                     + """either upgrade to 5.2.0+ or set
 
     open.defaults["xrootd_handler"] = uproot.MultithreadedXRootDSource


Test patch: