Repository: sdss/sdss_access

Issue:
non-public dr needs to use the sdss5 user
When a public DR is not yet public, it needs to use the sdss5 user.  See the `is_sdss5` method, which currently checks only for IPL and work configs when public is False.  

Discussion:

Patch:
diff --git a/python/sdss_access/path/path.py b/python/sdss_access/path/path.py
index 3a60cc7..71cb4d7 100644
--- a/python/sdss_access/path/path.py
+++ b/python/sdss_access/path/path.py
@@ -10,6 +10,7 @@ import datetime
 from glob import glob
 from os.path import join, sep
 from random import choice, sample
+from tree import Tree
 from sdss_access import tree, log, config
 from sdss_access import is_posix
 
@@ -63,7 +64,19 @@ def check_public_release(release: str = None, public: bool = False) -> bool:
         when tree does not have a valid release date for a DR tree config
     """
     today = datetime.datetime.now().date()
-    release_date = getattr(tree, 'release_date', None)
+
+    # get the release date from the tree
+    if release and release != tree.release:
+        # grab the release date from a new tree
+        t = Tree(release.lower())
+        release_date = getattr(t, 'release_date', None)
+    else:
+        # use the release from global tree
+        release_date = getattr(tree, 'release_date', None)
+
+    # always return false if input is a work release
+    if release in ('WORK', 'sdsswork'):
+        return False
 
     # check if tree has a valid release date attr
     if release_date is None and "DR" in tree.release:
@@ -833,7 +846,7 @@ class BasePath(object):
 
     def is_sdss5(self) -> bool:
         """ Checks if the release is an SDSS-V work or ipl release """
-        return any(s5cfg for s5cfg in self._s5cfgs if self.release.startswith(s5cfg))
+        return any(s5cfg for s5cfg in self._s5cfgs if self.release.startswith(s5cfg)) or ('dr' in self.release and not self.public)
 
     def get_netloc(self, netloc=None, sdss=None, sdss5=None, dtn=None, svn=None, mirror=None):
         ''' Get a net url domain
@@ -1581,7 +1594,7 @@ class Path(BasePath):
 
         run2d = kwargs.get('run2d', None)
         coaddname = kwargs.get('coadd', None)
-        
+
         if (not run2d):
             return ''
         if (('v5' in run2d) or (str(run2d) in ['26','103','104']) or
@@ -1619,7 +1632,7 @@ class Path(BasePath):
             ('v6_0' in run2d) or ('v6_1' in run2d)):
             return ''
         return coaddname
-            
+
     def sptypefolder(self, filetype, **kwargs):
         ''' Returns the reorganized subfolder structure for the BOSS idlspec2d run2d version
 
@@ -1635,7 +1648,7 @@ class Path(BasePath):
         '''
 
         run2d = kwargs.get('run2d', None)
-        
+
         if (not run2d) or ('v5' in run2d) or (str(run2d) in ['26','103','104']):
             return ''
         if ('v6_0' in run2d) or ('v6_1' in run2d):
@@ -1658,10 +1671,10 @@ class Path(BasePath):
                                 'spallfield','spalllinefield']:
             return 'daily'
         return 'fields'
-                    
+
     def spcoaddobs(self, filetype, **kwargs):
         ''' Returns the formatted observatory flag for custom coadds for the BOSS idlspec2d
-        
+
         Parameters
         ----------
         filetype : str
@@ -1670,15 +1683,15 @@ class Path(BasePath):
             BOSS idlspec2d run2d version
         obs : str
             Observatory of observations: LCO, APO, ''(for merged)
-            
+
         Returns
         -------
         obs : str
         '''
-        
+
         obs = kwargs.get('obs', None)
         run2d = kwargs.get('run2d', None)
-        
+
         if not obs or obs == '':
             return ''
         if (('v5' in run2d) or (str(run2d) in ['26','103','104']) or
@@ -1687,28 +1700,28 @@ class Path(BasePath):
         if obs == '*':
             return obs
         return '_{}'.format(obs.lower())
-            
+
     def epochflag(self, filetype, **kwargs):
         ''' Returns the flag for epoch coadds for the BOSS idlspec2d
-        
+
         Parameters
         ----------
         filetype : str
             File type parameter
         run2d : str
             BOSS idlspec2d run2d version
-            
+
         Returns
         -------
         epochflag : str
         '''
-        
+
         run2d = kwargs.get('run2d', None)
         if (('v5' in run2d) or (str(run2d) in ['26','103','104']) or
             ('v6_0' in run2d) or ('v6_1' in run2d)):
             return ''
         return '-epoch'
-    
+
     def fieldgrp(self, filetype, **kwargs):
         ''' Returns the fieldid group for the BOSS idlspec2d run2d version
 


Test patch:
diff --git a/tests/path/test_path.py b/tests/path/test_path.py
index de1a0c2..6ae35c1 100644
--- a/tests/path/test_path.py
+++ b/tests/path/test_path.py
@@ -396,7 +396,8 @@ def monkeyoos(monkeypatch, mocker):
 def test_public_release():
     tree.replant_tree('dr15')
     assert check_public_release('DR15') is True
-    assert check_public_release('MPL10') is False
+    assert check_public_release('DR17') is True
+    assert check_public_release('IPL3') is False
     assert check_public_release('sdsswork') is False
 
 def test_bad_release_old_tree(monkeypatch):
@@ -404,3 +405,20 @@ def test_bad_release_old_tree(monkeypatch):
     monkeypatch.setattr(tree.__class__, "release_date", None)
     with pytest.raises(AttributeError, match='Cannot find a valid release date in the sdss-tree product.  Try upgrading to min. version 3.1.0.'):
         check_public_release('DR15')
+
+
+@pytest.mark.parametrize('release, exp',
+                         [('sdsswork', True),
+                          ('IPL3', True),
+                          ('DR15', False),
+                          ('DR17', False),
+                          ('DR19', False)],
+                         ids=['sdsswork', 'IPL3', 'DR15', 'DR17', 'DR19'])
+def test_is_sdss5(release, exp):
+    ''' test which releases are correctly sdss5 '''
+    p = Path(release)
+
+    # this hack is to test when a DR release is not yet public, it should be sdss5
+    exp = True if 'DR' in release and p.public is False else exp
+
+    assert p.is_sdss5() is exp