Coverage for src/python/ensembl/io/genomio/database/dbconnection_lite.py: 96%
39 statements
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-21 15:37 +0000
« prev ^ index » next coverage.py v7.6.12, created at 2025-02-21 15:37 +0000
1# See the NOTICE file distributed with this work for additional information
2# regarding copyright ownership.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15"""Simplified Database interface to an Ensembl database, to make access to metadata easier and faster."""
17__all__ = ["DBConnectionLite"]
19import logging
20import re
21from typing import Any, Dict, List, Optional
23from sqlalchemy import select
24from sqlalchemy.orm import Session
26from ensembl.core.models import Meta
27from ensembl.utils.database import DBConnection, StrURL
29_DB_PATTERN_RELEASE = re.compile(r".+_(?:core|otherfeatures|variation)_(?P<release>\d+)_\d+_\d+")
32class DBConnectionLite(DBConnection):
33 """Extension to get metadata directly from a database, assuming it has a metadata table."""
35 def __init__(self, url: StrURL, reflect: bool = False, **kwargs: Any) -> None:
36 super().__init__(url, reflect, **kwargs)
37 self._metadata: Dict[str, List] = {}
39 def get_metadata(self) -> Dict[str, List]:
40 """Retrieves all metadata from the `meta` table in the database.
42 Returns:
43 A dict of with key meta_key, and value=List of meta_value.
45 """
46 self._load_metadata()
47 return self._metadata
49 def _load_metadata(self) -> None:
50 """Caches the metadata values."""
52 if self._metadata: 52 ↛ 53line 52 didn't jump to line 53 because the condition on line 52 was never true
53 return
55 with Session(self._engine) as session:
56 meta_stmt = select(Meta)
58 for meta_row in session.scalars(meta_stmt).unique().all():
59 meta_key = meta_row.meta_key
60 meta_value = meta_row.meta_value
61 if meta_key in self._metadata:
62 self._metadata[meta_key].append(meta_value)
63 else:
64 self._metadata[meta_key] = [meta_value]
66 def get_meta_value(self, meta_key: str) -> Optional[str]:
67 """Returns the first meta_value for a given meta_key."""
69 self._load_metadata()
70 try:
71 return self._metadata[meta_key][0]
72 except KeyError:
73 logging.debug(f"No meta_key {meta_key}")
74 return None
76 def get_project_release(self) -> str:
77 """Returns the project release number from the database name. Returns empty string if not found."""
79 match = re.search(_DB_PATTERN_RELEASE, self.db_name)
80 if match:
81 return match.group(1)
82 return ""