internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: rucio/rucio

Issue:
conveyor submitter crashes on python3
Motivation
----------
The submitter crashed when run with python3 with the following message. This doesn't happen in python2.


```
CRITICAL        Thread [0/73] :  Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/rucio/daemons/conveyor/submitter.py", line 170, in submitter
    retry_other_fts=retry_other_fts)
  File "/usr/local/lib/python3.6/site-packages/rucio/daemons/conveyor/submitter.py", line 337, in __get_transfers
    failover_schemes=failover_schemes)
  File "/usr/local/lib/python3.6/site-packages/rucio/db/sqla/session.py", line 377, in new_funct
    result = function(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/rucio/core/transfer.py", line 723, in get_transfer_requests_and_source_replicas
    session=session)
  File "/usr/local/lib/python3.6/site-packages/rucio/db/sqla/session.py", line 393, in new_funct
    result = function(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/rucio/core/transfer.py", line 582, in get_hops
    scheme=limit_dest_schemes if out_v == dest_rse_id and limit_dest_schemes else None)
  File "/usr/local/lib/python3.6/site-packages/rucio/rse/rsemanager.py", line 712, in find_matching_scheme
    dest_candidates = sorted(dest_candidates, key=lambda k: k['domains'][domain][operation_dest])
TypeError: '<' not supported between instances of 'NoneType' and 'int'
```





Discussion:

Resolving patch:
diff --git a/lib/rucio/rse/rsemanager.py b/lib/rucio/rse/rsemanager.py
--- a/lib/rucio/rse/rsemanager.py
+++ b/lib/rucio/rse/rsemanager.py
@@ -17,7 +17,7 @@
 # - Ralph Vigne <ralph.vigne@cern.ch>, 2012-2015
 # - Vincent Garonne <vincent.garonne@cern.ch>, 2012-2018
 # - Mario Lassnig <mario.lassnig@cern.ch>, 2012-2020
-# - Cedric Serfon <cedric.serfon@cern.ch>, 2012-2019
+# - Cedric Serfon <cedric.serfon@cern.ch>, 2012-2020
 # - Yun-Pin Sun <winter0128@gmail.com>, 2013
 # - Wen Guan <wen.guan@cern.ch>, 2014-2017
 # - Martin Barisits <martin.barisits@cern.ch>, 2017-2020
@@ -681,7 +681,8 @@ def find_matching_scheme(rse_settings_dest, rse_settings_src, operation_src, ope
             if protocol['scheme'] not in scheme:
                 tbr.append(protocol)
                 continue
-        if protocol['domains'].get(domain, {}).get(operation_src, 1) == 0:
+        prot = protocol['domains'].get(domain, {}).get(operation_src, 1)
+        if prot is None or prot == 0:
             tbr.append(protocol)
     for r in tbr:
         src_candidates.remove(r)
@@ -696,7 +697,8 @@ def find_matching_scheme(rse_settings_dest, rse_settings_src, operation_src, ope
             if protocol['scheme'] not in scheme:
                 tbr.append(protocol)
                 continue
-        if protocol['domains'].get(domain, {}).get(operation_dest, 1) == 0:
+        prot = protocol['domains'].get(domain, {}).get(operation_dest, 1)
+        if prot is None or prot == 0:
             tbr.append(protocol)
     for r in tbr:
         dest_candidates.remove(r)


Test patch:
Repository: rucio/rucio

Issue:
Fix wrong grouping for the rules in dirac add_files
Motivation
----------
Rule is has parameter `GROUPING` instead of `grouping`. Need to be fixed


Discussion:

Resolving patch:
diff --git a/lib/rucio/core/dirac.py b/lib/rucio/core/dirac.py
--- a/lib/rucio/core/dirac.py
+++ b/lib/rucio/core/dirac.py
@@ -97,7 +97,7 @@ def add_files(lfns, account, ignore_availability, session=None):
                     account=InternalAccount(account),
                     statuses=None,
                     meta=None,
-                    rules=[{'copies': 1, 'rse_expression': 'ANY=true', 'weight': None, 'account': InternalAccount(account), 'lifetime': None, 'GROUPING': 'NONE'}],
+                    rules=[{'copies': 1, 'rse_expression': 'ANY=true', 'weight': None, 'account': InternalAccount(account), 'lifetime': None, 'grouping': 'NONE'}],
                     lifetime=None,
                     dids=None,
                     rse_id=None,


Test patch:
Repository: rucio/rucio

Issue:
Clean URLs coming from AWS
Motivation
----------

Have to remove signature for successful registration replica matching:

https://github.com/rucio/rucio/blob/master/lib/rucio/common/utils.py#L668


Discussion:

Resolving patch:
diff --git a/lib/rucio/common/utils.py b/lib/rucio/common/utils.py
--- a/lib/rucio/common/utils.py
+++ b/lib/rucio/common/utils.py
@@ -670,6 +670,8 @@ def clean_surls(surls):
             surl = re.sub('/srm/managerv2\?SFN=', '', surl)  # NOQA: W605
         if surl.startswith('https://storage.googleapis.com'):
             surl = surl.split('?GoogleAccessId')[0]
+        if '?X-Amz' in surl:
+            surl = surl.split('?X-Amz')[0]
         res.append(surl)
     res.sort()
     return res


Test patch:
Repository: rucio/rucio

Issue:
1.24 Dependency upgrade
Motivation
----------
Upgrade dependencies for 1.24 package


Discussion:

Resolving patch:
diff --git a/setup_rucio.py b/setup_rucio.py
--- a/setup_rucio.py
+++ b/setup_rucio.py
@@ -162,8 +162,8 @@ def write_requirements():
         req_file.close()
 
 
-oracle_extras = ['cx_oracle==7.3']
-postgresql_extras = ['psycopg2-binary>=2.4.2,<2.8']
+oracle_extras = ['cx_oracle==8.0.1']
+postgresql_extras = ['psycopg2-binary==2.8.6']
 mysql_extras = ['PyMySQL']
 kerberos_extras = ['kerberos>=1.3.0', 'pykerberos>=1.2.1', 'requests-kerberos>=0.12.0']
 globus_extras = ['PyYAML==5.1.1', 'globus-sdk==1.8.0']


Test patch:
Repository: rucio/rucio

Issue:
Hardcoded atlas-adc-ddm-support eMail address for rule approval
Motivation
----------
Needs to be changed to something configurable.


Discussion:

Resolving patch:
diff --git a/lib/rucio/core/rule.py b/lib/rucio/core/rule.py
--- a/lib/rucio/core/rule.py
+++ b/lib/rucio/core/rule.py
@@ -3146,7 +3146,9 @@ def __create_recipents_list(rse_expression, filter=None, session=None):
 
     # DDMADMIN as default
     if not recipents:
-        recipents = [('atlas-adc-ddm-support@cern.ch', 'ddmadmin')]
+        default_mail_from = config_get('core', 'default_mail_from', raise_exception=False, default=None)
+        if default_mail_from:
+            recipents = [(default_mail_from, 'ddmadmin')]
 
     return list(set(recipents))
 


Test patch:
Repository: rucio/rucio

Issue:
Bug in Belle II permission for dirac
Motivation
----------

There's a bug in the belleii permission that prevent normal users to register files.




Discussion:

Resolving patch:
diff --git a/lib/rucio/core/permission/belleii.py b/lib/rucio/core/permission/belleii.py
--- a/lib/rucio/core/permission/belleii.py
+++ b/lib/rucio/core/permission/belleii.py
@@ -24,6 +24,7 @@
 #
 # PY3K COMPATIBLE
 
+from rucio.common.types import InternalScope
 from rucio.core.lifetime_exception import list_exceptions
 import rucio.core.scope
 from rucio.core.account import list_account_attributes, has_account_attribute
@@ -382,9 +383,12 @@ def perm_add_dids(issuer, kwargs):
     # Check the accounts of the issued rules
     if issuer != 'root' and not has_account_attribute(account=issuer, key='admin'):
         for did in kwargs['dids']:
+            if not rucio.core.scope.is_scope_owner(scope=InternalScope(did['scope']), account=issuer):
+                return False
             for rule in did.get('rules', []):
                 if rule['account'] != issuer:
                     return False
+        return True
 
     return _is_root(issuer) or has_account_attribute(account=issuer, key='admin')
 


Test patch:
Repository: rucio/rucio

Issue:
Conveyor wrongly force tranfers to use IPv4
Motivation
----------
Conveyor wrongly force tranfers to use IPv4





Discussion:

Resolving patch:
diff --git a/lib/rucio/core/transfer.py b/lib/rucio/core/transfer.py
--- a/lib/rucio/core/transfer.py
+++ b/lib/rucio/core/transfer.py
@@ -1069,7 +1069,8 @@ def get_transfer_requests_and_source_replicas(total_workers=0, worker_number=0,
                 # transfers[id]['src_urls'].append((source_rse_id, source_url))
                 transfers[req_id]['sources'].append((rse, source_url, source_rse_id, ranking, link_ranking))
                 # if one source has force IPv4, force IPv4 for the whole job
-                if rse_attrs[source_rse_id].get('use_ipv4', True):
+                use_ipv4 = rse_attrs[source_rse_id].get('use_ipv4', False)
+                if use_ipv4:
                     transfers[req_id]['use_ipv4'] = True
 
         except Exception:


Test patch:
Repository: rucio/rucio

Issue:
Add query hint to reaper2 replica state update query
Motivation
----------
Adding query hint due to unstable query plans on oracle.





Discussion:

Resolving patch:
diff --git a/lib/rucio/core/replica.py b/lib/rucio/core/replica.py
--- a/lib/rucio/core/replica.py
+++ b/lib/rucio/core/replica.py
@@ -1831,6 +1831,7 @@ def list_and_mark_unlocked_replicas(limit, bytes=None, rse_id=None, delay_second
                                            models.RSEFileAssociation.rse_id == rse_id))
     for chunk in chunks(replica_clause, 100):
         session.query(models.RSEFileAssociation).filter(or_(*chunk)).\
+            with_hint(models.RSEFileAssociation, text="INDEX(REPLICAS REPLICAS_PK)", dialect_name='oracle').\
             update({'updated_at': datetime.utcnow(), 'state': ReplicaState.BEING_DELETED}, synchronize_session=False)
 
     return rows


Test patch:
Repository: rucio/rucio

Issue:
PFNs that can’t be matched to an RSE remain in the BadPFNs table forever
Motivation
----------

For example:
```
$ rucio-admin replicas declare-bad --reason test srm://example.com/foo/bar/baz
Chunk 1/1 : 1 replicas successfully declared
--------------------------------
Summary
1 replicas successfully declared
```
The return values from [`get_pfn_to_rse()`](https://github.com/rucio/rucio/blob/420d5ee55f525c620bdc5decfef2f4a269dbf2e5/lib/rucio/daemons/badreplicas/minos.py#L138) are:
* `_ = 'srm'`
* `tmp_dict_rse = {}`
* `tmp_unknown_replicas = {'unknown': ['srm://example.com/foo/bar/baz']}`

However, the `for` loop that follows goes over the items in `tmp_dict_rse`. Since it’s empty, the PFNs are not processed.

Modification
------------

As far as I can tell, [line 143](https://github.com/rucio/rucio/blob/420d5ee55f525c620bdc5decfef2f4a269dbf2e5/lib/rucio/daemons/badreplicas/minos.py#L143) need to be moved out of that inner `for` loop.



Discussion:

Resolving patch:
diff --git a/lib/rucio/daemons/badreplicas/minos.py b/lib/rucio/daemons/badreplicas/minos.py
--- a/lib/rucio/daemons/badreplicas/minos.py
+++ b/lib/rucio/daemons/badreplicas/minos.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2018-2020 CERN
+# Copyright 2018-2021 CERN
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
 # - Patrick Austin <patrick.austin@stfc.ac.uk>, 2020
 # - Eli Chadwick <eli.chadwick@stfc.ac.uk>, 2020
 # - Benedikt Ziemons <benedikt.ziemons@cern.ch>, 2020
+# - Dimitrios Christidis <dimitrios.christidis@cern.ch>, 2021
 
 from __future__ import division
 
@@ -140,7 +141,7 @@ def minos(bulk=1000, once=False, sleep_time=60):
                             if rse_id not in dict_rse:
                                 dict_rse[rse_id] = []
                             dict_rse[rse_id].extend(tmp_dict_rse[rse_id])
-                            unknown_replicas.extend(tmp_unknown_replicas.get('unknown', []))
+                        unknown_replicas.extend(tmp_unknown_replicas.get('unknown', []))
                     # The replicas in unknown_replicas do not exist, so we flush them from bad_pfns
                     if unknown_replicas:
                         logging.info(prepend_str + 'The following replicas are unknown and will be removed : %s' % str(unknown_replicas))


Test patch:
Repository: rucio/rucio

Issue:
Belle II : Final version of the extract_scope method
Motivation
----------
Final version of the extract_scope method for Belle II before the migration






Discussion:

Resolving patch:
diff --git a/lib/rucio/common/utils.py b/lib/rucio/common/utils.py
--- a/lib/rucio/common/utils.py
+++ b/lib/rucio/common/utils.py
@@ -745,9 +745,9 @@ def extract_scope_belleii(did, scopes):
                 return 'user.%s' % split_did[3], did
         return 'user', did
     if did.startswith('/belle/group/'):
-        if len(split_did) > 3:
-            if 'group.%s' % (split_did[3]) in scopes:
-                return 'group.%s' % split_did[3], did
+        if len(split_did) > 4:
+            if 'group.%s' % (split_did[4]) in scopes:
+                return 'group.%s' % split_did[4], did
         return 'group', did
     if did.startswith('/belle/data/') or did.startswith('/belle/Data/'):
         if len(split_did) > 4:
@@ -769,8 +769,10 @@ def extract_scope_belleii(did, scopes):
                 if split_did[4].find('fab') > -1:  # /belle/Data/proc/fab* --> data_tmp
                     return 'data_tmp', did
         return 'data_tmp', did
-    if did.startswith('/belle/ddm/functional_tests/') or did.startswith('/belle/ddm/tests/'):
+    if did.startswith('/belle/ddm/functional_tests/') or did.startswith('/belle/ddm/tests/') or did.startswith('/belle/test/ddm_test'):
         return 'test', did
+    if did.startswith('/belle/BG/'):
+        return 'data', did
     return 'other', did
 
 


Test patch:
Repository: rucio/rucio

Issue:
RSEType not migrated to new enum in list_replicas
Motivation
----------

list_replicas() response comes back with `type:RSEType.DISK` instead of `type:DISK`.

This breaks the pilot which makes a strict check.



Discussion:

Resolving patch:
diff --git a/lib/rucio/core/replica.py b/lib/rucio/core/replica.py
--- a/lib/rucio/core/replica.py
+++ b/lib/rucio/core/replica.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2013-2020 CERN
+# Copyright 2013-2021 CERN
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@
 # - Cedric Serfon <cedric.serfon@cern.ch>, 2013-2020
 # - Ralph Vigne <ralph.vigne@cern.ch>, 2013-2014
 # - Martin Barisits <martin.barisits@cern.ch>, 2013-2020
-# - Mario Lassnig <mario.lassnig@cern.ch>, 2014-2020
+# - Mario Lassnig <mario.lassnig@cern.ch>, 2014-2021
 # - David Cameron <david.cameron@cern.ch>, 2014
 # - Thomas Beermann <thomas.beermann@cern.ch>, 2014-2020
 # - Wen Guan <wen.guan@cern.ch>, 2014-2015
@@ -1111,7 +1111,7 @@ def _list_replicas(dataset_clause, file_clause, state_clause, show_pfns,
                     for tmp_pfn in pfns:
                         file['pfns'][tmp_pfn[0]] = {'rse_id': tmp_pfn[4]['rse_id'] if tmp_pfn[1] == 'zip' else rse_id,
                                                     'rse': tmp_pfn[4]['rse'] if tmp_pfn[1] == 'zip' else rse,
-                                                    'type': tmp_pfn[4]['type'] if tmp_pfn[1] == 'zip' else str(rse_type),
+                                                    'type': tmp_pfn[4]['type'] if tmp_pfn[1] == 'zip' else str(rse_type.name),
                                                     'volatile': tmp_pfn[4]['volatile'] if tmp_pfn[1] == 'zip' else volatile,
                                                     'domain': tmp_pfn[1],
                                                     'priority': tmp_pfn[2],


Test patch:
Repository: rucio/rucio

Issue:
Messages created by core/transfer use the wrong type and state
Motivation
----------
Fallout from the ENUM patch. Need to properly address the request_type and request_state now, cannot just continue to use it as a string.


Discussion:

Resolving patch:
diff --git a/lib/rucio/core/request.py b/lib/rucio/core/request.py
--- a/lib/rucio/core/request.py
+++ b/lib/rucio/core/request.py
@@ -225,17 +225,18 @@ def temp_serializer(obj):
                                 'is_using': source['is_using']})
 
         if request['request_type']:
-            transfer_status = '%s-%s' % (request['request_type'], request['state'])
+            transfer_status = '%s-%s' % (request['request_type'].name, request['state'].name)
         else:
-            transfer_status = 'transfer-%s' % request['state']
+            transfer_status = 'transfer-%s' % request['state'].name
+        transfer_status = transfer_status.lower()
 
         payload = {'request-id': new_request['id'],
-                   'request-type': str(request['request_type']).lower(),
+                   'request-type': request['request_type'].name.lower(),
                    'scope': request['scope'].external,
                    'name': request['name'],
                    'dst-rse-id': request['dest_rse_id'],
                    'dst-rse': dest_rse_name,
-                   'state': str(request['state']),
+                   'state': request['state'].name.lower(),
                    'retry-count': request['retry_count'],
                    'rule-id': str(request['rule_id']),
                    'activity': request['attributes']['activity'],
@@ -245,7 +246,7 @@ def temp_serializer(obj):
                    'checksum-adler': request['attributes']['adler32'],
                    'queued_at': str(datetime.datetime.utcnow())}
 
-        messages.append({'event_type': transfer_status.lower(),
+        messages.append({'event_type': transfer_status,
                          'payload': json.dumps(payload)})
 
     for requests_chunk in chunks(new_requests, 1000):
@@ -1336,9 +1337,9 @@ def add_monitor_message(request, response, session=None):
     """
 
     if request['request_type']:
-        transfer_status = '%s-%s' % (request['request_type'], response['new_state'])
+        transfer_status = '%s-%s' % (request['request_type'].name, response['new_state'].name)
     else:
-        transfer_status = 'transfer-%s' % (response['new_state'])
+        transfer_status = 'transfer-%s' % (response['new_state'].name)
     transfer_status = transfer_status.lower()
 
     activity = response.get('activity', None)


Test patch:
Repository: rucio/rucio

Issue:
Rucio not able to correctly identify tape RSEs
Motivation
----------
During the migration to the newest SQLAlchemy version, a change with the ENUM settings was forgotten. 
https://github.com/rucio/rucio/blob/aa1a64af670de0d62fd8fc696c8bda696e5d9583/lib/rucio/core/rse.py#L1001
Due to that the `rse_type` string does not match anymore in the conveyor procedures, thus mis-identifiying all tape RSEs as DISKs. This leads to mixed disk/tape submissions as well as fts jobs without `bring_online` values, thus all tape jobs fail.


Discussion:

Resolving patch:
diff --git a/lib/rucio/core/rse.py b/lib/rucio/core/rse.py
--- a/lib/rucio/core/rse.py
+++ b/lib/rucio/core/rse.py
@@ -1,5 +1,5 @@
 # -*- coding: utf-8 -*-
-# Copyright 2012-2020 CERN
+# Copyright 2012-2021 CERN
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
 # Authors:
 # - Vincent Garonne <vincent.garonne@cern.ch>, 2012-2018
 # - Ralph Vigne <ralph.vigne@cern.ch>, 2012-2015
-# - Mario Lassnig <mario.lassnig@cern.ch>, 2012-2020
+# - Mario Lassnig <mario.lassnig@cern.ch>, 2012-2021
 # - Martin Barisits <martin.barisits@cern.ch>, 2013-2020
 # - Cedric Serfon <cedric.serfon@cern.ch>, 2013-2018
 # - Thomas Beermann <thomas.beermann@cern.ch>, 2014-2017
@@ -998,7 +998,7 @@ def get_rse_protocols(rse_id, schemes=None, session=None):
             'protocols': list(),
             'qos_class': _rse.qos_class,
             'rse': _rse.rse,
-            'rse_type': str(_rse.rse_type),
+            'rse_type': _rse.rse_type.name,
             'sign_url': sign_url[0] if sign_url else None,
             'staging_area': _rse.staging_area,
             'verify_checksum': verify_checksum[0] if verify_checksum else True,


Test patch:
Repository: rucio/rucio

Issue:
Cannot declare bad PFNs
Motivation
----------

We have identified another regression from the recent SQLAlchemy changes. In [this](https://github.com/rucio/rucio/blob/master/lib/rucio/core/permission/atlas.py#L1142) part of the code, `state` can be `BAD`, but `str(BadPFNStatus.BAD)` evaluates to `'BadPFNStatus.BAD'`.

Modification
------------

Use `BadPFNStatus.*.name` instead.



Discussion:

Resolving patch:
diff --git a/lib/rucio/core/permission/atlas.py b/lib/rucio/core/permission/atlas.py
--- a/lib/rucio/core/permission/atlas.py
+++ b/lib/rucio/core/permission/atlas.py
@@ -1139,10 +1139,10 @@ def perm_add_bad_pfns(issuer, kwargs):
     :param kwargs: List of arguments for the action.
     :returns: True if account is allowed, otherwise False
     """
-    if kwargs['state'] in [str(BadPFNStatus.BAD), str(BadPFNStatus.TEMPORARY_UNAVAILABLE)]:
+    if kwargs['state'] in [BadPFNStatus.BAD.name, BadPFNStatus.TEMPORARY_UNAVAILABLE.name]:
         is_cloud_admin = bool([acc_attr for acc_attr in list_account_attributes(account=issuer) if (acc_attr['key'].startswith('cloud-')) and (acc_attr['value'] == 'admin')])
         return _is_root(issuer) or has_account_attribute(account=issuer, key='admin') or is_cloud_admin
-    elif kwargs['state'] == str(BadPFNStatus.SUSPICIOUS):
+    elif kwargs['state'] == BadPFNStatus.SUSPICIOUS.name:
         return True
     return _is_root(issuer)
 


Test patch:
Repository: rucio/rucio

Issue:
Too restrictive RSE Expression regular expressions for RSE names
Motivation
----------
The default regular expression for RSE Expression RSE Names is too restrictive.
For example CMS uses lowercase characters in their RSE Names.


Discussion:

Resolving patch:
diff --git a/lib/rucio/core/rse_expression_parser.py b/lib/rucio/core/rse_expression_parser.py
--- a/lib/rucio/core/rse_expression_parser.py
+++ b/lib/rucio/core/rse_expression_parser.py
@@ -1,4 +1,5 @@
-# Copyright 2013-2018 CERN for the benefit of the ATLAS collaboration.
+# -*- coding: utf-8 -*-
+# Copyright 2013-2021 CERN
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -13,17 +14,16 @@
 # limitations under the License.
 #
 # Authors:
-# - Martin Barisits, <martin.barisits@cern.ch>, 2013-2019
-# - Vincent Garonne, <vincent.garonne@cern.ch>, 2013
-# - Mario Lassnig, <mario.lassnig@cern.ch>, 2013
-# - Cedric Serfon, <cedric.serfon@cern.ch>, 2014
-# - Hannes Hansen, <hannes.jakob.hansen@cern.ch>, 2018-2019
-# - Brandon White, <bjwhite@fnal.gov>, 2019
-# - Andrew Lister, <andrew.lister@stfc.ac.uk>, 2019
-# - Patrick Austin, <patrick.austin@stfc.ac.uk>, 2020
+# - Martin Barisits <martin.barisits@cern.ch>, 2013-2021
+# - Vincent Garonne <vincent.garonne@cern.ch>, 2013-2015
+# - Mario Lassnig <mario.lassnig@cern.ch>, 2013
+# - Cedric Serfon <cedric.serfon@cern.ch>, 2014-2019
+# - Hannes Hansen <hannes.jakob.hansen@cern.ch>, 2018-2019
+# - Brandon White <bjwhite@fnal.gov>, 2019
+# - Andrew Lister <andrew.lister@stfc.ac.uk>, 2019
+# - Patrick Austin <patrick.austin@stfc.ac.uk>, 2020
+# - James Perry <j.perry@epcc.ed.ac.uk>, 2020
 # - Eric Vaandering <ewv@fnal.gov>, 2020
-#
-# PY3K COMPATIBLE
 
 import abc
 import re
@@ -39,7 +39,7 @@
 from rucio.db.sqla.session import transactional_session
 
 
-DEFAULT_RSE_ATTRIBUTE = r'([A-Z0-9]+([_-][A-Z0-9]+)*)'
+DEFAULT_RSE_ATTRIBUTE = r'([A-Z0-9]+([_-][A-Za-z0-9]+)*)'
 RSE_ATTRIBUTE = r'([A-Za-z0-9\._-]+[=<>][A-Za-z0-9_-]+)'
 PRIMITIVE = r'(\(*(%s|%s|%s)\)*)' % (RSE_ATTRIBUTE, DEFAULT_RSE_ATTRIBUTE, r'\*')
 UNION = r'(\|%s)' % (PRIMITIVE)


Test patch: