Coverage for python/lsst/ctrl/execute/findPackageFile.py: 24%
19 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-10-14 02:01 -0700
« prev ^ index » next coverage.py v7.10.6, created at 2025-10-14 02:01 -0700
1#!/usr/bin/env python
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
27import lsst.utils
28from lsst.resources import ResourcePath
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.
34 Parameters
35 ----------
36 filename : `str`
37 The unqualified name of a file to locate.
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.
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.
47 Returns
48 -------
49 `lsst.resources.ResourcePath`
51 Raises
52 ------
53 FileNotFoundError
54 If a requested file object cannot be located in the candidate hierarchy
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
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
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