sqlmesh.dbt.package
1from __future__ import annotations 2 3import typing as t 4from pathlib import Path 5 6from sqlmesh.dbt.common import ( 7 PROJECT_FILENAME, 8 BaseConfig, 9 DbtContext, 10 SqlStr, 11 load_yaml, 12) 13from sqlmesh.dbt.model import ModelConfig 14from sqlmesh.dbt.seed import SeedConfig 15from sqlmesh.dbt.source import SourceConfig 16from sqlmesh.utils.errors import ConfigError 17from sqlmesh.utils.jinja import MacroExtractor, MacroInfo 18from sqlmesh.utils.pydantic import PydanticModel 19 20if t.TYPE_CHECKING: 21 C = t.TypeVar("C", bound=BaseConfig) 22 23Scope = t.Union[t.Tuple[()], t.Tuple[str, ...]] 24ScopedSources = t.Dict[Scope, SourceConfig] 25ScopedSeeds = t.Dict[Scope, SeedConfig] 26ScopedModels = t.Dict[Scope, ModelConfig] 27 28 29class ProjectConfig(PydanticModel): 30 """Class to contain configuration from dbt_project.yml""" 31 32 source_config: ScopedSources = {(): SourceConfig()} 33 seed_config: ScopedSeeds = {(): SeedConfig()} 34 model_config: ScopedModels = {(): ModelConfig()} 35 36 37class Package(PydanticModel): 38 """Class to contain package configuration""" 39 40 sources: t.Dict[str, SourceConfig] 41 seeds: t.Dict[str, SeedConfig] 42 models: t.Dict[str, ModelConfig] 43 variables: t.Dict[str, t.Any] 44 macros: t.Dict[str, MacroInfo] 45 files: t.Set[Path] 46 47 48class PackageLoader: 49 """Loader for DBT packages""" 50 51 def __init__(self, context: DbtContext, overrides: ProjectConfig): 52 self._context = context.copy() 53 self._overrides = overrides 54 self._config_paths: t.Set[Path] = set() 55 self.project_config = ProjectConfig() 56 57 def load(self) -> Package: 58 """ 59 Loads the specified package. 60 61 Returns: 62 Package containing the configuration found within this package 63 """ 64 project_file_path = Path(self._context.project_root, PROJECT_FILENAME) 65 if not project_file_path.exists(): 66 raise ConfigError(f"Could not find {PROJECT_FILENAME} in {self._context.project_root}") 67 68 self._config_paths.add(project_file_path) 69 project_yaml = load_yaml(project_file_path) 70 71 self._package_name = self._context.render(project_yaml.get("name", "")) 72 73 # Only include globally-scoped variables (i.e. filter out the package-scoped ones) 74 self._context.variables = { 75 var: value 76 for var, value in project_yaml.get("vars", {}).items() 77 if not isinstance(value, dict) 78 } 79 80 self._load_project_config(project_yaml) 81 82 models_dirs = [ 83 Path(self._context.project_root, self._context.render(dir)) 84 for dir in project_yaml.get("model-paths") or ["models"] 85 ] 86 models, sources = self._load_models(models_dirs) 87 88 seeds_dirs = [ 89 Path(self._context.project_root, self._context.render(dir)) 90 for dir in project_yaml.get("seed-paths") or ["seeds"] 91 ] 92 seeds = self._load_seeds(seeds_dirs) 93 94 macros_dirs = [ 95 Path(self._context.project_root, self._context.render(dir)) 96 for dir in project_yaml.get("macro-paths") or ["macros"] 97 ] 98 macros = self._load_macros(macros_dirs) 99 100 return Package( 101 models=models, 102 sources=sources, 103 seeds=seeds, 104 variables=self._context.variables, 105 macros=macros, 106 files=self._config_paths, 107 ) 108 109 def _load_project_config(self, yaml: t.Dict[str, t.Any]) -> None: 110 def load_config( 111 data: t.Dict[str, t.Any], 112 parent: C, 113 scope: Scope, 114 scoped_configs: t.Optional[t.Dict[Scope, C]] = None, 115 ) -> t.Dict[Scope, C]: 116 """Recursively loads config and nested configs in the provided yaml""" 117 scoped_configs = scoped_configs or {} 118 119 config_fields = parent.all_fields() 120 121 nested_config = {} 122 fields = {} 123 for key, value in data.items(): 124 if key.startswith("+") or key in config_fields or not isinstance(value, dict): 125 fields[key[1:]] = value 126 else: 127 nested_config[key] = value 128 129 config = parent.update_with(fields) 130 scoped_configs[scope] = config 131 for key, value in nested_config.items(): 132 nested_scope = (*scope, key) 133 load_config(value, config, nested_scope, scoped_configs) 134 135 return scoped_configs 136 137 scope = () 138 self.project_config.source_config = load_config( 139 yaml.get("sources", {}), SourceConfig(), scope 140 ) 141 self.project_config.seed_config = load_config( 142 yaml.get("seeds", {}), 143 SeedConfig(target_schema=self._context.target.schema_), 144 scope, 145 ) 146 self.project_config.model_config = load_config( 147 yaml.get("models", {}), 148 ModelConfig(target_schema=self._context.target.schema_), 149 scope, 150 ) 151 152 def _load_models( 153 self, models_dirs: t.List[Path] 154 ) -> t.Tuple[t.Dict[str, ModelConfig], t.Dict[str, SourceConfig]]: 155 """ 156 Loads the configuration of all models within the DBT project. 157 158 Args: 159 models_dirs: List of dirs containing models 160 161 Returns: 162 Tuple containing Dicts of model configs, source configs, and list of config files 163 used by them 164 """ 165 models: t.Dict[str, ModelConfig] = {} 166 sources: t.Dict[str, SourceConfig] = {} 167 168 for root in models_dirs: 169 # Layer on configs in properties files 170 for path in root.glob("**/*.yml"): 171 self._config_paths.add(path) 172 173 scope = self._scope_from_path(path, root) 174 properties_yaml = load_yaml(path) 175 176 self._load_config_section_from_properties( 177 properties_yaml, "models", scope, self.project_config.model_config 178 ) 179 180 source_configs_in_file = self._load_sources_config_from_properties( 181 properties_yaml, scope, self.project_config.source_config 182 ) 183 sources.update(source_configs_in_file) 184 185 # Layer on configs from the model file and create model configs 186 for path in root.glob("**/*.sql"): 187 self._config_paths.add(path) 188 189 scope = self._scope_from_path(path, root) 190 model_config = self._load_model_config_from_model(path, scope) 191 model_config.update_with(self._overridden_model_fields(scope)) 192 if model_config.enabled and model_config.table_name: 193 models[model_config.table_name] = model_config 194 195 return (models, sources) 196 197 def _load_seeds( 198 self, 199 seeds_dirs: t.List[Path], 200 ) -> t.Dict[str, SeedConfig]: 201 """ 202 Loads the configuration of all seeds within the DBT project. 203 204 Args: 205 seeds_dirs: List of dirs containing seeds 206 207 Returns: 208 Tuple containing Dicts of seed configs and list of config files used by them 209 """ 210 seeds: t.Dict[str, SeedConfig] = {} 211 212 for root in seeds_dirs: 213 # Layer on configs in properties files 214 for path in root.glob("**/*.yml"): 215 self._config_paths.add(path) 216 217 scope = self._scope_from_path(path, root) 218 properties_yaml = load_yaml(path) 219 220 self._load_config_section_from_properties( 221 properties_yaml, "seeds", scope, self.project_config.seed_config 222 ) 223 224 # Layer on configs from the model file and create seed configs 225 for path in root.glob("**/*.csv"): 226 self._config_paths.add(path) 227 228 scope = self._scope_from_path(path, root) 229 seed_config = self._config_for_scope(scope, self.project_config.seed_config).copy() 230 seed_config.update_with(self._overridden_seed_fields(scope)) 231 seed_config.path = path 232 if seed_config.enabled: 233 seeds[path.stem] = seed_config 234 235 return seeds 236 237 def _load_macros(self, macros_dirs: t.List[Path]) -> t.Dict[str, MacroInfo]: 238 macros: t.Dict[str, MacroInfo] = {} 239 240 for root in macros_dirs: 241 for path in root.glob("**/*.sql"): 242 macros.update(self._load_macro_file(path)) 243 244 return macros 245 246 def _load_macro_file(self, path: Path) -> t.Dict[str, MacroInfo]: 247 self._config_paths.add(path) 248 with open(path, mode="r", encoding="utf8") as file: 249 return MacroExtractor().extract(file.read()) 250 251 def _load_config_section_from_properties( 252 self, 253 yaml: t.Dict[str, t.Any], 254 section_name: str, 255 scope: Scope, 256 scoped_configs: t.Dict[Scope, C], 257 ) -> None: 258 section_yaml = yaml.get(section_name) 259 if not section_yaml: 260 return 261 262 for value in section_yaml: 263 fields = value.get("config") 264 if not fields: 265 continue 266 267 model_scope = (*scope, value["name"]) 268 scoped_configs[model_scope] = self._config_for_scope(scope, scoped_configs).update_with( 269 fields 270 ) 271 272 def _load_sources_config_from_properties( 273 self, 274 properties_yaml: t.Dict[str, t.Any], 275 scope: Scope, 276 scoped_configs: t.Dict[Scope, SourceConfig], 277 ) -> t.Dict[str, SourceConfig]: 278 sources_yaml = properties_yaml.get("sources") 279 if not sources_yaml: 280 return {} 281 282 configs = {} 283 284 for source in sources_yaml: 285 source_name = source["name"] 286 source_config = self._config_for_scope((*scope, source_name), scoped_configs) 287 288 source_config.schema_ = source_name 289 config_fields = source.get("config") 290 if config_fields: 291 source_config = source_config.update_with(config_fields) 292 293 for table in source["tables"]: 294 table_name = table["name"] 295 table_config = source_config.copy() 296 297 table_config.identifier = table_name 298 config_fields = source.get("config") 299 if config_fields: 300 table_config = table_config.update_with(config_fields) 301 302 table_config.config_name = f"{source_name}.{table_name}" 303 if table_config.enabled: 304 configs[table_config.config_name] = table_config 305 306 return configs 307 308 def _load_model_config_from_model(self, filepath: Path, scope: Scope) -> ModelConfig: 309 with filepath.open(encoding="utf-8") as file: 310 sql = file.read() 311 312 model_config = self._config_for_scope(scope, self.project_config.model_config).copy( 313 update={"path": filepath} 314 ) 315 model_config.sql = SqlStr(sql) 316 317 return model_config 318 319 def _overridden_source_fields(self, scope: Scope) -> t.Dict[str, t.Any]: 320 return self._overridden_fields(scope, self._overrides.source_config) 321 322 def _overridden_model_fields(self, scope: Scope) -> t.Dict[str, t.Any]: 323 return self._overridden_fields(scope, self._overrides.model_config) 324 325 def _overridden_seed_fields(self, scope: Scope) -> t.Dict[str, t.Any]: 326 return self._overridden_fields(scope, self._overrides.seed_config) 327 328 def _overridden_fields(self, scope: Scope, config: t.Dict[Scope, C]) -> t.Dict[str, t.Any]: 329 return self._config_for_scope(scope, config).dict(exclude_defaults=True, exclude_none=True) 330 331 def _scope_from_path(self, path: Path, root_path: Path) -> Scope: 332 """ 333 DBT rolls-up configuration based o the directory structure. Scope mimics this structure, 334 building a tuple containing the project name and directories from project root to the file, 335 omitting the "models" directory and filename if a properties file. 336 """ 337 path_from_root = path.relative_to(root_path) 338 scope = (self._package_name, *path_from_root.parts[:-1]) 339 if path.match("*.sql") or path.match("*.csv"): 340 scope = (*scope, path_from_root.stem) 341 return scope 342 343 def _config_for_scope(self, scope: Scope, configs: t.Dict[Scope, C]) -> C: 344 return configs.get(scope) or self._config_for_scope(scope[0:-1], configs)
30class ProjectConfig(PydanticModel): 31 """Class to contain configuration from dbt_project.yml""" 32 33 source_config: ScopedSources = {(): SourceConfig()} 34 seed_config: ScopedSeeds = {(): SeedConfig()} 35 model_config: ScopedModels = {(): ModelConfig()}
Class to contain configuration from dbt_project.yml
Inherited Members
- pydantic.main.BaseModel
- BaseModel
- parse_obj
- parse_raw
- parse_file
- from_orm
- construct
- copy
- schema
- schema_json
- validate
- update_forward_refs
38class Package(PydanticModel): 39 """Class to contain package configuration""" 40 41 sources: t.Dict[str, SourceConfig] 42 seeds: t.Dict[str, SeedConfig] 43 models: t.Dict[str, ModelConfig] 44 variables: t.Dict[str, t.Any] 45 macros: t.Dict[str, MacroInfo] 46 files: t.Set[Path]
Class to contain package configuration
Inherited Members
- pydantic.main.BaseModel
- BaseModel
- parse_obj
- parse_raw
- parse_file
- from_orm
- construct
- copy
- schema
- schema_json
- validate
- update_forward_refs
class
PackageLoader:
49class PackageLoader: 50 """Loader for DBT packages""" 51 52 def __init__(self, context: DbtContext, overrides: ProjectConfig): 53 self._context = context.copy() 54 self._overrides = overrides 55 self._config_paths: t.Set[Path] = set() 56 self.project_config = ProjectConfig() 57 58 def load(self) -> Package: 59 """ 60 Loads the specified package. 61 62 Returns: 63 Package containing the configuration found within this package 64 """ 65 project_file_path = Path(self._context.project_root, PROJECT_FILENAME) 66 if not project_file_path.exists(): 67 raise ConfigError(f"Could not find {PROJECT_FILENAME} in {self._context.project_root}") 68 69 self._config_paths.add(project_file_path) 70 project_yaml = load_yaml(project_file_path) 71 72 self._package_name = self._context.render(project_yaml.get("name", "")) 73 74 # Only include globally-scoped variables (i.e. filter out the package-scoped ones) 75 self._context.variables = { 76 var: value 77 for var, value in project_yaml.get("vars", {}).items() 78 if not isinstance(value, dict) 79 } 80 81 self._load_project_config(project_yaml) 82 83 models_dirs = [ 84 Path(self._context.project_root, self._context.render(dir)) 85 for dir in project_yaml.get("model-paths") or ["models"] 86 ] 87 models, sources = self._load_models(models_dirs) 88 89 seeds_dirs = [ 90 Path(self._context.project_root, self._context.render(dir)) 91 for dir in project_yaml.get("seed-paths") or ["seeds"] 92 ] 93 seeds = self._load_seeds(seeds_dirs) 94 95 macros_dirs = [ 96 Path(self._context.project_root, self._context.render(dir)) 97 for dir in project_yaml.get("macro-paths") or ["macros"] 98 ] 99 macros = self._load_macros(macros_dirs) 100 101 return Package( 102 models=models, 103 sources=sources, 104 seeds=seeds, 105 variables=self._context.variables, 106 macros=macros, 107 files=self._config_paths, 108 ) 109 110 def _load_project_config(self, yaml: t.Dict[str, t.Any]) -> None: 111 def load_config( 112 data: t.Dict[str, t.Any], 113 parent: C, 114 scope: Scope, 115 scoped_configs: t.Optional[t.Dict[Scope, C]] = None, 116 ) -> t.Dict[Scope, C]: 117 """Recursively loads config and nested configs in the provided yaml""" 118 scoped_configs = scoped_configs or {} 119 120 config_fields = parent.all_fields() 121 122 nested_config = {} 123 fields = {} 124 for key, value in data.items(): 125 if key.startswith("+") or key in config_fields or not isinstance(value, dict): 126 fields[key[1:]] = value 127 else: 128 nested_config[key] = value 129 130 config = parent.update_with(fields) 131 scoped_configs[scope] = config 132 for key, value in nested_config.items(): 133 nested_scope = (*scope, key) 134 load_config(value, config, nested_scope, scoped_configs) 135 136 return scoped_configs 137 138 scope = () 139 self.project_config.source_config = load_config( 140 yaml.get("sources", {}), SourceConfig(), scope 141 ) 142 self.project_config.seed_config = load_config( 143 yaml.get("seeds", {}), 144 SeedConfig(target_schema=self._context.target.schema_), 145 scope, 146 ) 147 self.project_config.model_config = load_config( 148 yaml.get("models", {}), 149 ModelConfig(target_schema=self._context.target.schema_), 150 scope, 151 ) 152 153 def _load_models( 154 self, models_dirs: t.List[Path] 155 ) -> t.Tuple[t.Dict[str, ModelConfig], t.Dict[str, SourceConfig]]: 156 """ 157 Loads the configuration of all models within the DBT project. 158 159 Args: 160 models_dirs: List of dirs containing models 161 162 Returns: 163 Tuple containing Dicts of model configs, source configs, and list of config files 164 used by them 165 """ 166 models: t.Dict[str, ModelConfig] = {} 167 sources: t.Dict[str, SourceConfig] = {} 168 169 for root in models_dirs: 170 # Layer on configs in properties files 171 for path in root.glob("**/*.yml"): 172 self._config_paths.add(path) 173 174 scope = self._scope_from_path(path, root) 175 properties_yaml = load_yaml(path) 176 177 self._load_config_section_from_properties( 178 properties_yaml, "models", scope, self.project_config.model_config 179 ) 180 181 source_configs_in_file = self._load_sources_config_from_properties( 182 properties_yaml, scope, self.project_config.source_config 183 ) 184 sources.update(source_configs_in_file) 185 186 # Layer on configs from the model file and create model configs 187 for path in root.glob("**/*.sql"): 188 self._config_paths.add(path) 189 190 scope = self._scope_from_path(path, root) 191 model_config = self._load_model_config_from_model(path, scope) 192 model_config.update_with(self._overridden_model_fields(scope)) 193 if model_config.enabled and model_config.table_name: 194 models[model_config.table_name] = model_config 195 196 return (models, sources) 197 198 def _load_seeds( 199 self, 200 seeds_dirs: t.List[Path], 201 ) -> t.Dict[str, SeedConfig]: 202 """ 203 Loads the configuration of all seeds within the DBT project. 204 205 Args: 206 seeds_dirs: List of dirs containing seeds 207 208 Returns: 209 Tuple containing Dicts of seed configs and list of config files used by them 210 """ 211 seeds: t.Dict[str, SeedConfig] = {} 212 213 for root in seeds_dirs: 214 # Layer on configs in properties files 215 for path in root.glob("**/*.yml"): 216 self._config_paths.add(path) 217 218 scope = self._scope_from_path(path, root) 219 properties_yaml = load_yaml(path) 220 221 self._load_config_section_from_properties( 222 properties_yaml, "seeds", scope, self.project_config.seed_config 223 ) 224 225 # Layer on configs from the model file and create seed configs 226 for path in root.glob("**/*.csv"): 227 self._config_paths.add(path) 228 229 scope = self._scope_from_path(path, root) 230 seed_config = self._config_for_scope(scope, self.project_config.seed_config).copy() 231 seed_config.update_with(self._overridden_seed_fields(scope)) 232 seed_config.path = path 233 if seed_config.enabled: 234 seeds[path.stem] = seed_config 235 236 return seeds 237 238 def _load_macros(self, macros_dirs: t.List[Path]) -> t.Dict[str, MacroInfo]: 239 macros: t.Dict[str, MacroInfo] = {} 240 241 for root in macros_dirs: 242 for path in root.glob("**/*.sql"): 243 macros.update(self._load_macro_file(path)) 244 245 return macros 246 247 def _load_macro_file(self, path: Path) -> t.Dict[str, MacroInfo]: 248 self._config_paths.add(path) 249 with open(path, mode="r", encoding="utf8") as file: 250 return MacroExtractor().extract(file.read()) 251 252 def _load_config_section_from_properties( 253 self, 254 yaml: t.Dict[str, t.Any], 255 section_name: str, 256 scope: Scope, 257 scoped_configs: t.Dict[Scope, C], 258 ) -> None: 259 section_yaml = yaml.get(section_name) 260 if not section_yaml: 261 return 262 263 for value in section_yaml: 264 fields = value.get("config") 265 if not fields: 266 continue 267 268 model_scope = (*scope, value["name"]) 269 scoped_configs[model_scope] = self._config_for_scope(scope, scoped_configs).update_with( 270 fields 271 ) 272 273 def _load_sources_config_from_properties( 274 self, 275 properties_yaml: t.Dict[str, t.Any], 276 scope: Scope, 277 scoped_configs: t.Dict[Scope, SourceConfig], 278 ) -> t.Dict[str, SourceConfig]: 279 sources_yaml = properties_yaml.get("sources") 280 if not sources_yaml: 281 return {} 282 283 configs = {} 284 285 for source in sources_yaml: 286 source_name = source["name"] 287 source_config = self._config_for_scope((*scope, source_name), scoped_configs) 288 289 source_config.schema_ = source_name 290 config_fields = source.get("config") 291 if config_fields: 292 source_config = source_config.update_with(config_fields) 293 294 for table in source["tables"]: 295 table_name = table["name"] 296 table_config = source_config.copy() 297 298 table_config.identifier = table_name 299 config_fields = source.get("config") 300 if config_fields: 301 table_config = table_config.update_with(config_fields) 302 303 table_config.config_name = f"{source_name}.{table_name}" 304 if table_config.enabled: 305 configs[table_config.config_name] = table_config 306 307 return configs 308 309 def _load_model_config_from_model(self, filepath: Path, scope: Scope) -> ModelConfig: 310 with filepath.open(encoding="utf-8") as file: 311 sql = file.read() 312 313 model_config = self._config_for_scope(scope, self.project_config.model_config).copy( 314 update={"path": filepath} 315 ) 316 model_config.sql = SqlStr(sql) 317 318 return model_config 319 320 def _overridden_source_fields(self, scope: Scope) -> t.Dict[str, t.Any]: 321 return self._overridden_fields(scope, self._overrides.source_config) 322 323 def _overridden_model_fields(self, scope: Scope) -> t.Dict[str, t.Any]: 324 return self._overridden_fields(scope, self._overrides.model_config) 325 326 def _overridden_seed_fields(self, scope: Scope) -> t.Dict[str, t.Any]: 327 return self._overridden_fields(scope, self._overrides.seed_config) 328 329 def _overridden_fields(self, scope: Scope, config: t.Dict[Scope, C]) -> t.Dict[str, t.Any]: 330 return self._config_for_scope(scope, config).dict(exclude_defaults=True, exclude_none=True) 331 332 def _scope_from_path(self, path: Path, root_path: Path) -> Scope: 333 """ 334 DBT rolls-up configuration based o the directory structure. Scope mimics this structure, 335 building a tuple containing the project name and directories from project root to the file, 336 omitting the "models" directory and filename if a properties file. 337 """ 338 path_from_root = path.relative_to(root_path) 339 scope = (self._package_name, *path_from_root.parts[:-1]) 340 if path.match("*.sql") or path.match("*.csv"): 341 scope = (*scope, path_from_root.stem) 342 return scope 343 344 def _config_for_scope(self, scope: Scope, configs: t.Dict[Scope, C]) -> C: 345 return configs.get(scope) or self._config_for_scope(scope[0:-1], configs)
Loader for DBT packages
PackageLoader( context: sqlmesh.dbt.common.DbtContext, overrides: sqlmesh.dbt.package.ProjectConfig)
58 def load(self) -> Package: 59 """ 60 Loads the specified package. 61 62 Returns: 63 Package containing the configuration found within this package 64 """ 65 project_file_path = Path(self._context.project_root, PROJECT_FILENAME) 66 if not project_file_path.exists(): 67 raise ConfigError(f"Could not find {PROJECT_FILENAME} in {self._context.project_root}") 68 69 self._config_paths.add(project_file_path) 70 project_yaml = load_yaml(project_file_path) 71 72 self._package_name = self._context.render(project_yaml.get("name", "")) 73 74 # Only include globally-scoped variables (i.e. filter out the package-scoped ones) 75 self._context.variables = { 76 var: value 77 for var, value in project_yaml.get("vars", {}).items() 78 if not isinstance(value, dict) 79 } 80 81 self._load_project_config(project_yaml) 82 83 models_dirs = [ 84 Path(self._context.project_root, self._context.render(dir)) 85 for dir in project_yaml.get("model-paths") or ["models"] 86 ] 87 models, sources = self._load_models(models_dirs) 88 89 seeds_dirs = [ 90 Path(self._context.project_root, self._context.render(dir)) 91 for dir in project_yaml.get("seed-paths") or ["seeds"] 92 ] 93 seeds = self._load_seeds(seeds_dirs) 94 95 macros_dirs = [ 96 Path(self._context.project_root, self._context.render(dir)) 97 for dir in project_yaml.get("macro-paths") or ["macros"] 98 ] 99 macros = self._load_macros(macros_dirs) 100 101 return Package( 102 models=models, 103 sources=sources, 104 seeds=seeds, 105 variables=self._context.variables, 106 macros=macros, 107 files=self._config_paths, 108 )
Loads the specified package.
Returns:
Package containing the configuration found within this package