cool-seq-tool 0.4.0.dev1__tar.gz → 0.4.0.dev2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. {cool_seq_tool-0.4.0.dev1/src/cool_seq_tool.egg-info → cool_seq_tool-0.4.0.dev2}/PKG-INFO +7 -6
  2. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/README.md +3 -3
  3. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/pyproject.toml +53 -12
  4. cool_seq_tool-0.4.0.dev2/src/cool_seq_tool/data/__init__.py +2 -0
  5. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/data/data_downloads.py +19 -13
  6. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/handlers/seqrepo_access.py +2 -4
  7. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/mappers/exon_genomic_coords.py +25 -26
  8. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/mappers/mane_transcript.py +112 -106
  9. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/routers/default.py +7 -9
  10. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/routers/mane.py +2 -2
  11. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/schemas.py +30 -21
  12. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/sources/mane_transcript_mappings.py +1 -1
  13. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/sources/transcript_mappings.py +13 -16
  14. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/sources/uta_database.py +134 -153
  15. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/utils.py +5 -2
  16. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/version.py +1 -1
  17. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2/src/cool_seq_tool.egg-info}/PKG-INFO +7 -6
  18. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool.egg-info/requires.txt +3 -2
  19. cool_seq_tool-0.4.0.dev1/src/cool_seq_tool/data/__init__.py +0 -2
  20. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/LICENSE +0 -0
  21. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/setup.cfg +0 -0
  22. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/__init__.py +0 -0
  23. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/api.py +0 -0
  24. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/app.py +0 -0
  25. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/data/transcript_mapping.tsv +0 -0
  26. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/handlers/__init__.py +0 -0
  27. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/mappers/__init__.py +0 -0
  28. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/mappers/alignment.py +0 -0
  29. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/paths.py +0 -0
  30. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/routers/__init__.py +0 -0
  31. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/routers/mappings.py +0 -0
  32. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool/sources/__init__.py +0 -0
  33. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool.egg-info/SOURCES.txt +0 -0
  34. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool.egg-info/dependency_links.txt +0 -0
  35. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/src/cool_seq_tool.egg-info/top_level.txt +0 -0
  36. {cool_seq_tool-0.4.0.dev1 → cool_seq_tool-0.4.0.dev2}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cool_seq_tool
3
- Version: 0.4.0.dev1
3
+ Version: 0.4.0.dev2
4
4
  Summary: Common Operation on Lots of Sequences Tool
5
5
  Author: Kori Kuzma, James Stevenson, Katie Stahl, Alex Wagner
6
6
  License: MIT License
@@ -49,7 +49,7 @@ License-File: LICENSE
49
49
  Requires-Dist: asyncpg
50
50
  Requires-Dist: aiofiles
51
51
  Requires-Dist: boto3
52
- Requires-Dist: pyliftover
52
+ Requires-Dist: agct>=0.1.0-dev1
53
53
  Requires-Dist: polars
54
54
  Requires-Dist: hgvs
55
55
  Requires-Dist: biocommons.seqrepo
@@ -62,7 +62,7 @@ Requires-Dist: pre-commit; extra == "dev"
62
62
  Requires-Dist: ipython; extra == "dev"
63
63
  Requires-Dist: ipykernel; extra == "dev"
64
64
  Requires-Dist: psycopg2-binary; extra == "dev"
65
- Requires-Dist: ruff; extra == "dev"
65
+ Requires-Dist: ruff>=0.1.14; extra == "dev"
66
66
  Provides-Extra: tests
67
67
  Requires-Dist: pytest; extra == "tests"
68
68
  Requires-Dist: pytest-cov; extra == "tests"
@@ -75,12 +75,13 @@ Requires-Dist: sphinx-autobuild==2021.3.14; extra == "docs"
75
75
  Requires-Dist: sphinx-copybutton==0.5.2; extra == "docs"
76
76
  Requires-Dist: sphinxext-opengraph==0.8.2; extra == "docs"
77
77
  Requires-Dist: furo==2023.3.27; extra == "docs"
78
+ Requires-Dist: sphinx-github-changelog==1.2.1; extra == "docs"
78
79
 
79
80
  <h1 align="center">
80
81
  CoolSeqTool
81
82
  </h1>
82
83
 
83
- **[Documentation](https://coolseqtool.readthedocs.io/en/latest/)** · [Installation](https://coolseqtool.readthedocs.io/en/latest/install.html) · [Usage](https://coolseqtool.readthedocs.io/en/latest/usage.html) · [API reference](https://coolseqtool.readthedocs.io/en/latest/reference/index.html)
84
+ **[Documentation](https://coolseqtool.readthedocs.io/latest/)** · [Installation](https://coolseqtool.readthedocs.io/latest/install.html) · [Usage](https://coolseqtool.readthedocs.io/latest/usage.html) · [API reference](https://coolseqtool.readthedocs.io/latest/reference/index.html)
84
85
 
85
86
  ## Overview
86
87
 
@@ -102,7 +103,7 @@ CoolSeqTool is available on [PyPI](https://pypi.org/project/cool-seq-tool)
102
103
  python3 -m pip install cool-seq-tool
103
104
  ```
104
105
 
105
- See the [installation instructions](https://coolseqtool.readthedocs.io/en/latest/install.html) in the documentation for a description of dependency setup requirements.
106
+ See the [installation instructions](https://coolseqtool.readthedocs.io/latest/install.html) in the documentation for a description of dependency setup requirements.
106
107
 
107
108
  ---
108
109
 
@@ -127,4 +128,4 @@ All CoolSeqTool resources can be initialized by way of a top-level class instanc
127
128
 
128
129
  ## Feedback and contributing
129
130
 
130
- We welcome bug reports, feature requests, and code contributions from users and interested collaborators. The [documentation](https://coolseqtool.readthedocs.io/en/latest/contributing.html) contains guidance for submitting feedback and contributing new code.
131
+ We welcome bug reports, feature requests, and code contributions from users and interested collaborators. The [documentation](https://coolseqtool.readthedocs.io/latest/contributing.html) contains guidance for submitting feedback and contributing new code.
@@ -2,7 +2,7 @@
2
2
  CoolSeqTool
3
3
  </h1>
4
4
 
5
- **[Documentation](https://coolseqtool.readthedocs.io/en/latest/)** · [Installation](https://coolseqtool.readthedocs.io/en/latest/install.html) · [Usage](https://coolseqtool.readthedocs.io/en/latest/usage.html) · [API reference](https://coolseqtool.readthedocs.io/en/latest/reference/index.html)
5
+ **[Documentation](https://coolseqtool.readthedocs.io/latest/)** · [Installation](https://coolseqtool.readthedocs.io/latest/install.html) · [Usage](https://coolseqtool.readthedocs.io/latest/usage.html) · [API reference](https://coolseqtool.readthedocs.io/latest/reference/index.html)
6
6
 
7
7
  ## Overview
8
8
 
@@ -24,7 +24,7 @@ CoolSeqTool is available on [PyPI](https://pypi.org/project/cool-seq-tool)
24
24
  python3 -m pip install cool-seq-tool
25
25
  ```
26
26
 
27
- See the [installation instructions](https://coolseqtool.readthedocs.io/en/latest/install.html) in the documentation for a description of dependency setup requirements.
27
+ See the [installation instructions](https://coolseqtool.readthedocs.io/latest/install.html) in the documentation for a description of dependency setup requirements.
28
28
 
29
29
  ---
30
30
 
@@ -49,4 +49,4 @@ All CoolSeqTool resources can be initialized by way of a top-level class instanc
49
49
 
50
50
  ## Feedback and contributing
51
51
 
52
- We welcome bug reports, feature requests, and code contributions from users and interested collaborators. The [documentation](https://coolseqtool.readthedocs.io/en/latest/contributing.html) contains guidance for submitting feedback and contributing new code.
52
+ We welcome bug reports, feature requests, and code contributions from users and interested collaborators. The [documentation](https://coolseqtool.readthedocs.io/latest/contributing.html) contains guidance for submitting feedback and contributing new code.
@@ -29,7 +29,7 @@ dependencies = [
29
29
  "asyncpg",
30
30
  "aiofiles",
31
31
  "boto3",
32
- "pyliftover",
32
+ "agct >= 0.1.0-dev1",
33
33
  "polars",
34
34
  "hgvs",
35
35
  "biocommons.seqrepo",
@@ -41,7 +41,7 @@ dependencies = [
41
41
  dynamic = ["version"]
42
42
 
43
43
  [project.optional-dependencies]
44
- dev = ["pre-commit", "ipython", "ipykernel", "psycopg2-binary", "ruff"]
44
+ dev = ["pre-commit", "ipython", "ipykernel", "psycopg2-binary", "ruff>=0.1.14"]
45
45
  tests = ["pytest", "pytest-cov", "pytest-asyncio==0.18.3", "mock"]
46
46
  docs = [
47
47
  "sphinx==6.1.3",
@@ -50,6 +50,7 @@ docs = [
50
50
  "sphinx-copybutton==0.5.2",
51
51
  "sphinxext-opengraph==0.8.2",
52
52
  "furo==2023.3.27",
53
+ "sphinx-github-changelog==1.2.1"
53
54
  ]
54
55
 
55
56
  [project.urls]
@@ -86,14 +87,49 @@ branch = true
86
87
  [tool.ruff]
87
88
  src = ["src"]
88
89
  exclude = ["docs/source/conf.py"]
89
- # pycodestyle (E, W)
90
- # Pyflakes (F)
91
- # flake8-annotations (ANN)
92
- # pydocstyle (D)
93
- # pep8-naming (N)
94
- # isort (I)
95
- select = ["E", "W", "F", "ANN", "D", "N", "I"]
96
- fixable = ["I", "F401"]
90
+ select = [
91
+ "F", # https://docs.astral.sh/ruff/rules/#pyflakes-f
92
+ "E", "W", # https://docs.astral.sh/ruff/rules/#pycodestyle-e-w
93
+ "I", # https://docs.astral.sh/ruff/rules/#isort-i
94
+ "N", # https://docs.astral.sh/ruff/rules/#pep8-naming-n
95
+ "D", # https://docs.astral.sh/ruff/rules/#pydocstyle-d
96
+ "UP", # https://docs.astral.sh/ruff/rules/#pyupgrade-up
97
+ "ANN", # https://docs.astral.sh/ruff/rules/#flake8-annotations-ann
98
+ "ASYNC", # https://docs.astral.sh/ruff/rules/#flake8-async-async
99
+ "S", # https://docs.astral.sh/ruff/rules/#flake8-bandit-s
100
+ "B", # https://docs.astral.sh/ruff/rules/#flake8-bugbear-b
101
+ "A", # https://docs.astral.sh/ruff/rules/#flake8-builtins-a
102
+ "C4", # https://docs.astral.sh/ruff/rules/#flake8-comprehensions-c4
103
+ "DTZ", # https://docs.astral.sh/ruff/rules/#flake8-datetimez-dtz
104
+ "T10", # https://docs.astral.sh/ruff/rules/#flake8-datetimez-dtz
105
+ "EM", # https://docs.astral.sh/ruff/rules/#flake8-errmsg-em
106
+ "G", # https://docs.astral.sh/ruff/rules/#flake8-logging-format-g
107
+ "PIE", # https://docs.astral.sh/ruff/rules/#flake8-pie-pie
108
+ "T20", # https://docs.astral.sh/ruff/rules/#flake8-print-t20
109
+ "PT", # https://docs.astral.sh/ruff/rules/#flake8-pytest-style-pt
110
+ "Q", # https://docs.astral.sh/ruff/rules/#flake8-quotes-q
111
+ "RSE", # https://docs.astral.sh/ruff/rules/#flake8-raise-rse
112
+ "RET", # https://docs.astral.sh/ruff/rules/#flake8-return-ret
113
+ "SIM", # https://docs.astral.sh/ruff/rules/#flake8-simplify-sim
114
+ "PTH", # https://docs.astral.sh/ruff/rules/#flake8-use-pathlib-pth
115
+ "PGH", # https://docs.astral.sh/ruff/rules/#pygrep-hooks-pgh
116
+ "RUF", # https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf
117
+ ]
118
+ fixable = [
119
+ "I",
120
+ "F401",
121
+ "D",
122
+ "UP",
123
+ "ANN",
124
+ "B",
125
+ "C4",
126
+ "G",
127
+ "PIE",
128
+ "PT",
129
+ "RSE",
130
+ "SIM",
131
+ "RUF"
132
+ ]
97
133
 
98
134
  # ANN101 - missing-type-self
99
135
  # ANN003 - missing-type-kwargs
@@ -109,12 +145,14 @@ fixable = ["I", "F401"]
109
145
  # E117 - over-indented*
110
146
  # E501 - line-too-long*
111
147
  # W191 - tab-indentation*
148
+ # S321 - suspicious-ftp-lib-usage
112
149
  # *ignored for compatibility with formatter
113
150
  ignore = [
114
151
  "ANN101", "ANN003",
115
152
  "D203", "D205", "D206", "D213", "D300", "D400", "D415",
116
153
  "E111", "E114", "E117", "E501",
117
- "W191"
154
+ "W191",
155
+ "S321",
118
156
  ]
119
157
 
120
158
  [tool.ruff.per-file-ignores]
@@ -124,6 +162,9 @@ ignore = [
124
162
  # N805 - invalid-first-argument-name-for-method
125
163
  # F821 - undefined-name
126
164
  # F401 - unused-import
127
- "tests/*" = ["ANN001", "ANN2", "ANN102"]
165
+ "tests/*" = ["ANN001", "ANN2", "ANN102", "S101"]
128
166
  "*__init__.py" = ["F401"]
129
167
  "src/cool_seq_tool/schemas.py" = ["ANN201", "N805", "ANN001"]
168
+
169
+ [tool.ruff.lint.flake8-bugbear]
170
+ extend-immutable-calls = ["fastapi.Query"]
@@ -0,0 +1,2 @@
1
+ """Module for data"""
2
+ from .data_downloads import DataDownload
@@ -4,7 +4,6 @@ import gzip
4
4
  import logging
5
5
  import shutil
6
6
  from ftplib import FTP
7
- from os import remove
8
7
  from pathlib import Path
9
8
 
10
9
  from dateutil import parser
@@ -38,18 +37,20 @@ class DataDownload:
38
37
  files = ftp.nlst()
39
38
  mane_summary_file = [f for f in files if f.endswith(".summary.txt.gz")]
40
39
  if not mane_summary_file:
41
- raise Exception("Unable to download MANE summary data")
40
+ msg = "Unable to download MANE summary data"
41
+ raise Exception(msg)
42
42
  mane_summary_file = mane_summary_file[0]
43
43
  self._mane_summary_path = self._data_dir / mane_summary_file[:-3]
44
44
  mane_data_path = self._data_dir / mane_summary_file
45
45
  if not self._mane_summary_path.exists():
46
46
  logger.info("Downloading MANE summary file from NCBI.")
47
- with open(mane_data_path, "wb") as fp:
47
+ with mane_data_path.open("wb") as fp:
48
48
  ftp.retrbinary(f"RETR {mane_summary_file}", fp.write)
49
- with gzip.open(mane_data_path, "rb") as f_in:
50
- with open(self._mane_summary_path, "wb") as f_out:
51
- shutil.copyfileobj(f_in, f_out)
52
- remove(mane_data_path)
49
+ with gzip.open(
50
+ mane_data_path, "rb"
51
+ ) as f_in, self._mane_summary_path.open("wb") as f_out:
52
+ shutil.copyfileobj(f_in, f_out)
53
+ mane_data_path.unlink()
53
54
  logger.info("MANE summary file download complete.")
54
55
  return self._mane_summary_path
55
56
 
@@ -66,18 +67,23 @@ class DataDownload:
66
67
  ftp_file_path = f"{ftp_dir_path}{lrg_refseqgene_file}"
67
68
  timestamp = ftp.voidcmd(f"MDTM {ftp_file_path}")[4:].strip()
68
69
  date = str(parser.parse(timestamp)).split()[0]
69
- version = datetime.datetime.strptime(date, "%Y-%m-%d").strftime("%Y%m%d")
70
+ version = (
71
+ datetime.datetime.strptime(date, "%Y-%m-%d")
72
+ .astimezone(tz=datetime.timezone.utc)
73
+ .strftime("%Y%m%d")
74
+ )
70
75
  fn_versioned = f"{lrg_refseqgene_file}_{version}"
71
76
  lrg_refseqgene_path = self._data_dir / lrg_refseqgene_file
72
77
  self._lrg_refseqgene_path = self._data_dir / fn_versioned
73
78
  if not self._lrg_refseqgene_path.exists():
74
79
  logger.info("Downloading LRG RefSeq data from NCBI.")
75
80
  ftp.cwd(ftp_dir_path)
76
- with open(lrg_refseqgene_path, "wb") as fp:
81
+ with lrg_refseqgene_path.open("wb") as fp:
77
82
  ftp.retrbinary(f"RETR {lrg_refseqgene_file}", fp.write)
78
- with open(lrg_refseqgene_path, "rb") as f_in:
79
- with open(self._lrg_refseqgene_path, "wb") as f_out:
80
- shutil.copyfileobj(f_in, f_out)
81
- remove(lrg_refseqgene_path)
83
+ with lrg_refseqgene_path.open(
84
+ "rb"
85
+ ) as f_in, self._lrg_refseqgene_path.open("wb") as f_out:
86
+ shutil.copyfileobj(f_in, f_out)
87
+ lrg_refseqgene_path.unlink()
82
88
  logger.info("LRG RefSeq data download complete.")
83
89
  return self._lrg_refseqgene_path
@@ -152,8 +152,7 @@ class SeqRepoAccess(SeqRepoDataProxy):
152
152
  acs.append(ac.split("refseq:")[-1])
153
153
  if acs:
154
154
  return acs, None
155
- else:
156
- return None, f"{chromosome} is not a valid chromosome"
155
+ return None, f"{chromosome} is not a valid chromosome"
157
156
 
158
157
  def ac_to_chromosome(self, ac: str) -> Tuple[Optional[str], Optional[str]]:
159
158
  """Get chromosome for accession.
@@ -172,8 +171,7 @@ class SeqRepoAccess(SeqRepoDataProxy):
172
171
  )[0]
173
172
  if aliases is None:
174
173
  return None, f"Unable to get chromosome for {ac}"
175
- else:
176
- return aliases, None
174
+ return aliases, None
177
175
 
178
176
  def get_fasta_file(self, sequence_id: str, outfile_path: Path) -> None:
179
177
  """Retrieve FASTA file containing sequence for requested sequence ID.
@@ -112,8 +112,7 @@ class ExonGenomicCoordsMapper:
112
112
  # Ensure valid inputs
113
113
  if not transcript:
114
114
  return self._return_warnings(resp, "Must provide `transcript`")
115
- else:
116
- transcript = transcript.strip()
115
+ transcript = transcript.strip()
117
116
 
118
117
  exon_start_exists, exon_end_exists = False, False
119
118
  if exon_start is not None:
@@ -130,12 +129,11 @@ class ExonGenomicCoordsMapper:
130
129
  return self._return_warnings(
131
130
  resp, "Must provide either `exon_start` or `exon_end`"
132
131
  )
133
- elif exon_start_exists and exon_end_exists:
134
- if exon_start > exon_end:
135
- return self._return_warnings(
136
- resp,
137
- f"Start exon {exon_start} is greater than end exon {exon_end}",
138
- )
132
+ if exon_start_exists and exon_end_exists and (exon_start > exon_end):
133
+ return self._return_warnings(
134
+ resp,
135
+ f"Start exon {exon_start} is greater than end exon {exon_end}",
136
+ )
139
137
 
140
138
  # Get all exons and associated start/end coordinates for transcript
141
139
  tx_exons, warning = await self.uta_db.get_tx_exons(transcript)
@@ -266,7 +264,7 @@ class ExonGenomicCoordsMapper:
266
264
  if start is None and end is None:
267
265
  return self._return_warnings(resp, "Must provide either `start` or `end`")
268
266
 
269
- params = {key: None for key in GenomicData.model_fields.keys()}
267
+ params = {key: None for key in GenomicData.model_fields}
270
268
  if gene is not None:
271
269
  gene = gene.upper().strip()
272
270
 
@@ -312,13 +310,12 @@ class ExonGenomicCoordsMapper:
312
310
 
313
311
  for field in ["transcript", "gene", "chr", "strand"]:
314
312
  if start_data:
315
- if end_data:
316
- if start_data[field] != end_data[field]:
317
- msg = (
318
- f"Start `{field}`, {start_data[field]}, does "
319
- f"not match End `{field}`, {end_data[field]}"
320
- )
321
- return self._return_warnings(resp, msg)
313
+ if end_data and (start_data[field] != end_data[field]):
314
+ msg = (
315
+ f"Start `{field}`, {start_data[field]}, does "
316
+ f"not match End `{field}`, {end_data[field]}"
317
+ )
318
+ return self._return_warnings(resp, msg)
322
319
  params[field] = start_data[field]
323
320
  else:
324
321
  params[field] = end_data[field]
@@ -440,7 +437,10 @@ class ExonGenomicCoordsMapper:
440
437
  else:
441
438
  error = "Strand does not match"
442
439
  logger.warning(
443
- f"{error}: {alt_ac_data['start'][i]} != {alt_ac_data['end'][i]}"
440
+ "%s: %s != %s",
441
+ error,
442
+ alt_ac_data["start"][i],
443
+ alt_ac_data["end"][i],
444
444
  )
445
445
  return None, error
446
446
  return tuple(alt_ac_data_values), None
@@ -482,7 +482,7 @@ class ExonGenomicCoordsMapper:
482
482
  resp, "Must provide either `gene` or `transcript`"
483
483
  )
484
484
 
485
- params = {key: None for key in TranscriptExonData.model_fields.keys()}
485
+ params = {key: None for key in TranscriptExonData.model_fields}
486
486
 
487
487
  if alt_ac:
488
488
  # Check if valid accession is given
@@ -550,7 +550,7 @@ class ExonGenomicCoordsMapper:
550
550
  len_alt_acs = len(alt_acs)
551
551
  if len_alt_acs > 1:
552
552
  return None, f"Found more than one accessions: {alt_acs}"
553
- elif len_alt_acs == 0:
553
+ if len_alt_acs == 0:
554
554
  return None, "No genomic accessions found"
555
555
  alt_ac = next(iter(alt_acs))
556
556
 
@@ -565,13 +565,12 @@ class ExonGenomicCoordsMapper:
565
565
  elif len_genes == 0:
566
566
  return None, "No genes found"
567
567
 
568
- if input_gene is not None:
569
- if output_gene != input_gene.upper():
570
- return (
571
- None,
572
- f"Input gene, {input_gene}, does not match "
573
- f"expected output gene, {output_gene}",
574
- )
568
+ if input_gene is not None and output_gene != input_gene.upper():
569
+ return (
570
+ None,
571
+ f"Input gene, {input_gene}, does not match "
572
+ f"expected output gene, {output_gene}",
573
+ )
575
574
 
576
575
  gene = output_gene if output_gene else input_gene
577
576
  return (gene, alt_ac), None