Coverage for python/lsst/daf/butler/registry/_config.py: 53%

32 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-08-05 01:26 +0000

1# This file is part of daf_butler. 

2# 

3# Developed for the LSST Data Management System. 

4# This product includes software developed by the LSST Project 

5# (http://www.lsst.org). 

6# See the COPYRIGHT file at the top-level directory of this distribution 

7# for details of code ownership. 

8# 

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

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

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

12# (at your option) any later version. 

13# 

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

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

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

17# GNU General Public License for more details. 

18# 

19# You should have received a copy of the GNU General Public License 

20# along with this program. If not, see <http://www.gnu.org/licenses/>. 

21 

22from __future__ import annotations 

23 

24__all__ = ("RegistryConfig",) 

25 

26from typing import TYPE_CHECKING 

27 

28from lsst.utils import doImportType 

29 

30from ..core import ConfigSubset 

31from ..core.repoRelocation import replaceRoot 

32from .connectionString import ConnectionStringFactory 

33from .interfaces import Database 

34 

35if TYPE_CHECKING: 

36 import sqlalchemy 

37 from lsst.resources import ResourcePathExpression 

38 

39 

40class RegistryConfig(ConfigSubset): 

41 """Configuration specific to a butler Registry.""" 

42 

43 component = "registry" 

44 requiredKeys = ("db",) 

45 defaultConfigFile = "registry.yaml" 

46 

47 def getDialect(self) -> str: 

48 """Parse the `db` key of the config and returns the database dialect. 

49 

50 Returns 

51 ------- 

52 dialect : `str` 

53 Dialect found in the connection string. 

54 """ 

55 conStr = ConnectionStringFactory.fromConfig(self) 

56 return conStr.get_backend_name() 

57 

58 def getDatabaseClass(self) -> type[Database]: 

59 """Return the `Database` class targeted by configuration values. 

60 

61 The appropriate class is determined by parsing the `db` key to extract 

62 the dialect, and then looking that up under the `engines` key of the 

63 registry config. 

64 """ 

65 dialect = self.getDialect() 

66 if dialect not in self["engines"]: 

67 raise ValueError(f"Connection string dialect has no known aliases. Received: {dialect}") 

68 databaseClassName = self["engines", dialect] 

69 databaseClass = doImportType(databaseClassName) 

70 if not issubclass(databaseClass, Database): 

71 raise TypeError(f"Imported database class {databaseClassName} is not a Database") 

72 return databaseClass 

73 

74 def makeDefaultDatabaseUri(self, root: str) -> str | None: 

75 """Return a default 'db' URI for the registry configured here that is 

76 appropriate for a new empty repository with the given root. 

77 

78 Parameters 

79 ---------- 

80 root : `str` 

81 Filesystem path to the root of the data repository. 

82 

83 Returns 

84 ------- 

85 uri : `str` 

86 URI usable as the 'db' string in a `RegistryConfig`. 

87 """ 

88 DatabaseClass = self.getDatabaseClass() 

89 return DatabaseClass.makeDefaultUri(root) 

90 

91 def replaceRoot(self, root: ResourcePathExpression | None) -> None: 

92 """Replace any occurrences of `BUTLER_ROOT_TAG` in the connection 

93 with the given root directory. 

94 

95 Parameters 

96 ---------- 

97 root : `lsst.resources.ResourcePathExpression`, or `None` 

98 String to substitute for `BUTLER_ROOT_TAG`. Passing `None` here is 

99 allowed only as a convenient way to raise an exception 

100 (`ValueError`). 

101 

102 Raises 

103 ------ 

104 ValueError 

105 Raised if ``root`` is not set but a value is required. 

106 """ 

107 self["db"] = replaceRoot(self["db"], root) 

108 

109 @property 

110 def connectionString(self) -> sqlalchemy.engine.url.URL: 

111 """Return the connection string to the underlying database 

112 (`sqlalchemy.engine.url.URL`). 

113 """ 

114 return ConnectionStringFactory.fromConfig(self)