allelix 2.2.2__py3-none-any.whl → 2.2.3__py3-none-any.whl

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.
@@ -247,34 +247,29 @@ class GnomadAnnotator(Annotator):
247
247
  return {}
248
248
  conn = self._connection()
249
249
  result: dict[tuple[str, int], list[tuple[str, str, str]]] = {}
250
- # GH #134: issue a single combined SQL statement per chunk
251
- # using SQLite's row-value ``(chrom, pos) IN ((?, ?), ...)``
252
- # form instead of grouping by chromosome and issuing one
253
- # statement per (chrom, chunk) pair. On WGS input each batch
254
- # touches all ~24 chromosomes; the per-chrom shape was a 24x
255
- # query multiplier the new ``idx_gnomad_position`` index could
256
- # not amortize away. The row-value IN form keeps the same
257
- # carrier-rule contract — both ``chrom`` and ``pos`` must
258
- # match the input pair simultaneously — and the
259
- # ``idx_gnomad_position`` covering index on (chrom, pos)
260
- # serves the lookup directly. ``_BULK_BATCH_SIZE`` here
261
- # refers to (chrom, pos) PAIRS not single ints, so each
262
- # chunk binds 2 * batch_size parameters.
250
+ # Issue a single combined SQL statement per chunk using SQLite's
251
+ # row-value ``(chrom, pos) IN ((?, ?), ...)`` form instead of
252
+ # grouping by chromosome and issuing one statement per
253
+ # (chrom, chunk) pair. On WGS input each batch touches all ~24
254
+ # chromosomes; the per-chrom shape was a 24x query multiplier
255
+ # the ``idx_gnomad_position`` index could not amortize away. The
256
+ # row-value IN form keeps the same carrier-rule contract — both
257
+ # ``chrom`` and ``pos`` must match the input pair simultaneously
258
+ # — and the ``idx_gnomad_position`` covering index on
259
+ # ``(chrom, pos)`` serves the lookup directly.
263
260
  #
264
- # SQLite parameter-limit awareness: 2 * _BULK_BATCH_SIZE =
265
- # 1800 bind parameters per chunk. The historical SQLite
266
- # ``SQLITE_MAX_VARIABLE_NUMBER`` default was 999, raised to
267
- # 32766 in SQLite 3.32 (2020-05-22). Every Python version
268
- # Allelix supports (>= 3.11) ships with SQLite >= 3.34, so
269
- # the 1800-param chunk is well within the modern limit. If a
270
- # future change bumps ``_BULK_BATCH_SIZE`` toward 16000 or
271
- # the project drops Python's bundled SQLite for a system
272
- # ``libsqlite3`` of unknown vintage, re-check this against
273
- # the runtime ``sqlite3.sqlite_version`` before assuming
274
- # capacity.
261
+ # Each input pair binds 2 SQLite parameters (chrom + pos), so
262
+ # the chunk size is ``_BULK_BATCH_SIZE // 2`` to stay inside the
263
+ # 999-param convention every other annotator and gnomAD's own
264
+ # multi-param queries respect (``bulk_lookup_by_alt`` does the
265
+ # same 2-param shape with the same ``// 2``;
266
+ # ``bulk_lookup_by_position`` uses ``// 4`` for its 4-param
267
+ # shape, same convention scaled). Net effective batch size:
268
+ # 450 pairs x 2 = 900 params per chunk.
269
+ chunk_pairs = _BULK_BATCH_SIZE // 2
275
270
  position_list = list(positions)
276
- for i in range(0, len(position_list), _BULK_BATCH_SIZE):
277
- batch = position_list[i : i + _BULK_BATCH_SIZE]
271
+ for i in range(0, len(position_list), chunk_pairs):
272
+ batch = position_list[i : i + chunk_pairs]
278
273
  placeholders = ",".join("(?, ?)" for _ in batch)
279
274
  params: list[str | int] = []
280
275
  for chrom, pos in batch:
@@ -42,7 +42,26 @@ if TYPE_CHECKING:
42
42
 
43
43
  logger = logging.getLogger(__name__)
44
44
 
45
- _CANONICAL_PREFIX = "# This data file generated by 23andMe"
45
+ # Known canonical first-line banner variants 23andMe wraps raw exports in.
46
+ # The original v2/v3/v4-era exports used the verbatim ``generated by`` form;
47
+ # the June 2026 v5 export prose was edited to ``is generated by`` (with a
48
+ # trailing period in some samples). Match either; future vendor banner
49
+ # edits get a new entry here.
50
+ #
51
+ # Why a tuple of exact prefixes instead of a loose ``"23andMe" in line``
52
+ # substring match: a bare substring check false-positives on transcoded
53
+ # fixtures and third-party tool output. Files that strip the canonical
54
+ # banner entirely (WGSExtract output, Genetic Lifehacks converter output,
55
+ # privacy-conscious users who delete the comment block) are out of scope
56
+ # for this parser by design — they are handled by ``GenericTsvParser`` at
57
+ # the end of the dispatch chain (planned, see GH #146 / GH #127). That
58
+ # two-layer design keeps banner-bearing 23andMe files attributed to
59
+ # "23andMe" and banner-less 23andMe-shape files attributed to "generic-tsv"
60
+ # without guessing a vendor.
61
+ _CANONICAL_PREFIXES: tuple[str, ...] = (
62
+ "# This data file generated by 23andMe",
63
+ "# This data file is generated by 23andMe",
64
+ )
46
65
  SNIFF_LINE_LIMIT = 50
47
66
  EXPECTED_COLUMNS = 4
48
67
 
@@ -58,10 +77,13 @@ class TwentyThreeAndMeParser(GenotypeParser):
58
77
  def can_parse(self, file_path: Path) -> bool:
59
78
  """Recognize a real 23andMe export by its canonical first-line header.
60
79
 
61
- Real exports start with ``# This data file generated by 23andMe at: ...``.
80
+ Real exports start with one of the variants in ``_CANONICAL_PREFIXES``:
81
+ the historical ``# This data file generated by 23andMe at: ...`` form
82
+ or the June 2026 v5 ``# This data file is generated by 23andMe.`` form.
62
83
  Some files have user-prepended comments before the canonical line; the
63
- fallback loop scans up to ``SNIFF_LINE_LIMIT`` comment lines. A bare
64
- "23andMe" mention without the canonical prefix is rejected.
84
+ scan loop reads up to ``SNIFF_LINE_LIMIT`` comment lines. A bare
85
+ "23andMe" substring mention without one of the canonical prefixes is
86
+ rejected (see ``_CANONICAL_PREFIXES`` rationale).
65
87
  """
66
88
  try:
67
89
  with file_path.open("r", encoding="utf-8") as fh:
@@ -71,7 +93,7 @@ class TwentyThreeAndMeParser(GenotypeParser):
71
93
  return False
72
94
  if not line.startswith("#"):
73
95
  return False
74
- if line.startswith(_CANONICAL_PREFIX):
96
+ if any(line.startswith(p) for p in _CANONICAL_PREFIXES):
75
97
  return True
76
98
  except (OSError, UnicodeDecodeError):
77
99
  return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: allelix
3
- Version: 2.2.2
3
+ Version: 2.2.3
4
4
  Summary: Open-source genotype analysis toolkit. Format-agnostic ingestion, database-agnostic annotation, offline-first.
5
5
  Author: Allelix
6
6
  Maintainer-email: dial481 <dial481@users.noreply.github.com>
@@ -190,8 +190,10 @@ disease findings. Wherever you write them via `--output <path>`,
190
190
  that's where they sit until you delete them. Allelix doesn't
191
191
  auto-clean and won't warn you when you write to `/tmp/` or any
192
192
  other shared location. Treat the files as personal data: read them,
193
- move them somewhere you control, or delete when you're done. A
194
- data-lifecycle subcommand is planned for v2.1.
193
+ move them somewhere you control, or delete when you're done.
194
+ `allelix db clean` (shipped in v2.2.0) handles the cache side of
195
+ the lifecycle; output reports are still the user's responsibility
196
+ to manage.
195
197
 
196
198
  ## Configuration
197
199
 
@@ -8,7 +8,7 @@ allelix/annotators/alphamissense.py,sha256=GT5y35jQ97oZW3X9SqJgTcmqYn-GgK2_WbSvl
8
8
  allelix/annotators/base.py,sha256=emwF6-zs8I7v_m24bC_ocsUeppp2gP9vtGCfMyQQOTo,7994
9
9
  allelix/annotators/cadd.py,sha256=BT7JqbHabdEhz9PiQ7nzPJjv25lu3tMDMuoMYQfsUf4,11065
10
10
  allelix/annotators/clinvar.py,sha256=VUyDDf3L5VT_MRrTHVXZZKl9Z6RFln3TvRAky9itxv4,35894
11
- allelix/annotators/gnomad.py,sha256=aJUvHFGAgh3M5lo6NK0eDL30xjSuAbbcnJlxHAsyIIQ,15013
11
+ allelix/annotators/gnomad.py,sha256=A4HGEvZT-x-OWxJwXQ8LYs5T3XGYwlwcP7ZAUkRudLI,14725
12
12
  allelix/annotators/gwas.py,sha256=ZsZokbb65HDdJON_oMlIprny0LexrHvWDQPNjClxc5M,18786
13
13
  allelix/annotators/pharmgkb.py,sha256=1knBbMtDoZd4ZdH3gIeAfr63tZsfMOaOkImrKE3KxHQ,21008
14
14
  allelix/annotators/snpedia.py,sha256=WI0eaSKkr4qoQChpayyqkPLGE5XX_l8L4ZWIhu1zDmY,13844
@@ -48,7 +48,7 @@ allelix/parsers/ftdna_illumina.py,sha256=ZbejAa6vWT8wdwkdpCzsXA7g_1WoltbUEpO2K5t
48
48
  allelix/parsers/livingdna.py,sha256=18-3Vjc3L7fVR3gHGjrVnPPEqC0Ype2nOb4Ltz1VzRc,5368
49
49
  allelix/parsers/myhappygenes.py,sha256=3i8yKMA1WBs6vBPFNkIm7q5hVqNJBu_CZUmlyDMp-QE,4911
50
50
  allelix/parsers/myheritage.py,sha256=N6aCdj9SD0tiW8S_yylNlVZy8CrUGazdQvTpr7rT29Y,4311
51
- allelix/parsers/twentythreeandme.py,sha256=cdTj8YjFff8nYB4V5z_SwtV2l6FAmhyRiVzOytbsSHc,5608
51
+ allelix/parsers/twentythreeandme.py,sha256=757nA1mw7aEsG4nOdOFbHdKbwIIz0p05oaSzI90x268,6932
52
52
  allelix/parsers/vcf.py,sha256=6KhqEyb29pL58ZniaC7zm87QELudEJG_R_VwLZeENNM,28105
53
53
  allelix/reports/__init__.py,sha256=9WK8hR03DV1dP2bM7AloJfzSOTVQoFd6AOnaKjQyScs,1408
54
54
  allelix/reports/_pipeline.py,sha256=SkT2WqnakB2I60Z-BCox6SIrmQCSFNCK_Na8Kxuggrs,40925
@@ -61,9 +61,9 @@ allelix/reports/terminal.py,sha256=cPdG3mwUsmty26WIdfbkLtgPF6CTr91ZMk7o2siTumQ,1
61
61
  allelix/utils/__init__.py,sha256=ALRku0gzoAbTA6gipnMr0aEFYRyI2DUaTB25DHkXXLw,138
62
62
  allelix/utils/allele.py,sha256=d7cT1b-XxcD6jID9bLDhvVCOxoK_2Ga4-nXcHRN-h4Q,9620
63
63
  allelix/utils/build_detect.py,sha256=Sxlg0OXyL9vDuJAl04pQZQ8oizSVeUV4Gte9tVEvKu0,8718
64
- allelix-2.2.2.dist-info/licenses/LICENSE,sha256=QWRhgdtPnw-Xay85rhILM_cxYofYh91NfTOWwI_AOQI,34841
65
- allelix-2.2.2.dist-info/METADATA,sha256=rVzYuKPpBDujZaFbuNjvwirGF3QmwAvExzhIvw26Epk,31707
66
- allelix-2.2.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
67
- allelix-2.2.2.dist-info/entry_points.txt,sha256=n75_TahJixgNPt1Xhk2V1wDR3RNCiKq4xAKa4_skYNI,45
68
- allelix-2.2.2.dist-info/top_level.txt,sha256=2SoebaRt4WWVq8Ynk-5uNN1ATE_dJtOqsgj39oCHVbk,8
69
- allelix-2.2.2.dist-info/RECORD,,
64
+ allelix-2.2.3.dist-info/licenses/LICENSE,sha256=QWRhgdtPnw-Xay85rhILM_cxYofYh91NfTOWwI_AOQI,34841
65
+ allelix-2.2.3.dist-info/METADATA,sha256=9KMuC0LRIevmywag657PaoUeuCCOU3tMbPEyTohkh10,31800
66
+ allelix-2.2.3.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
67
+ allelix-2.2.3.dist-info/entry_points.txt,sha256=n75_TahJixgNPt1Xhk2V1wDR3RNCiKq4xAKa4_skYNI,45
68
+ allelix-2.2.3.dist-info/top_level.txt,sha256=2SoebaRt4WWVq8Ynk-5uNN1ATE_dJtOqsgj39oCHVbk,8
69
+ allelix-2.2.3.dist-info/RECORD,,