Coverage for python/lsst/ctrl/execute/findPackageFile.py: 24%

19 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-10-11 01:45 -0700

1#!/usr/bin/env python 

2 

3# 

4# LSST Data Management System 

5# Copyright 2008-2016 LSST Corporation. 

6# 

7# This product includes software developed by the 

8# LSST Project (http://www.lsst.org/). 

9# 

10# This program is free software: you can redistribute it and/or modify 

11# it under the terms of the GNU General Public License as published by 

12# the Free Software Foundation, either version 3 of the License, or 

13# (at your option) any later version. 

14# 

15# This program is distributed in the hope that it will be useful, 

16# but WITHOUT ANY WARRANTY; without even the implied warranty of 

17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

18# GNU General Public License for more details. 

19# 

20# You should have received a copy of the LSST License Statement and 

21# the GNU General Public License along with this program. If not, 

22# see <http://www.lsstcorp.org/LegalNotices/>. 

23# 

24import os 

25import sys 

26 

27import lsst.utils 

28from lsst.resources import ResourcePath 

29 

30 

31def find_package_file(filename: str, kind: str = "config", platform: str | None = None) -> ResourcePath: 

32 """Find a package file from a set of candidate locations. 

33 

34 Parameters 

35 ---------- 

36 filename : `str` 

37 The unqualified name of a file to locate. 

38 

39 kind : `str` 

40 The name of a subdirectory in which to look for the file within a 

41 package location, relative to an ``etc/`` directory. 

42 

43 platform : `str` | `None` 

44 The name of a platform plugin in which to look for the file, or `None` 

45 if no platform plugin should be searched. 

46 

47 Returns 

48 ------- 

49 `lsst.resources.ResourcePath` 

50 

51 Raises 

52 ------ 

53 FileNotFoundError 

54 If a requested file object cannot be located in the candidate hierarchy 

55 

56 Notes 

57 ----- 

58 The candidate locations are, in descending order of preference: 

59 - An ``.lsst`` directory in the user's home directory. 

60 - An ``lsst`` directory in the user's ``$XDG_CONFIG_HOME`` directory 

61 - An ``etc/{kind}`` directory in the EUPS stack environment for the 

62 platform. 

63 - An ``etc/{kind}`` directory in the current Python environment/venv shared 

64 data directory. 

65 - An ``etc/{kind}`` directory in an installed ``lsst.ctrl.platform.*`` 

66 package. 

67 - An ``etc/{kind}`` directory in the ``lsst.ctrl.execute`` package. 

68 """ 

69 # If the path, after expansion, is absolute, we don't need to go looking 

70 # for it, it should be exactly where it is. 

71 if (_filename := ResourcePath(filename, forceAbsolute=False)).isabs(): 

72 return _filename 

73 

74 home_dir = os.getenv("HOME", "~") 

75 xdg_config_home = os.getenv("XDG_CONFIG_HOME", "~/.config") 

76 try: 

77 platform_pkg_dir = lsst.utils.getPackageDir(f"ctrl_platform_{platform}") 

78 except (LookupError, ValueError): 

79 platform_pkg_dir = None 

80 

81 file_candidates = [ 

82 ResourcePath(home_dir).join(".lsst").join(_filename), 

83 ResourcePath(xdg_config_home).join("lsst").join(_filename), 

84 (ResourcePath(platform_pkg_dir).join("etc").join(kind).join(_filename) if platform_pkg_dir else None), 

85 ResourcePath(sys.exec_prefix).join("etc").join(kind).join(_filename), 

86 ( 

87 ResourcePath(f"resource://lsst.ctrl.platform.{platform}/etc/{kind}/{_filename}") 

88 if platform 

89 else None 

90 ), 

91 ResourcePath(f"resource://lsst.ctrl.execute/etc/{kind}/{_filename}"), 

92 ] 

93 try: 

94 found_file: ResourcePath = [c for c in file_candidates if c is not None and c.exists()][0] 

95 except IndexError: 

96 raise FileNotFoundError(f"No file {filename} found in package file lookup") 

97 return found_file