seqtree 1.3.1__tar.gz → 1.3.2__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 (53) hide show
  1. {seqtree-1.3.1 → seqtree-1.3.2}/PKG-INFO +1 -1
  2. {seqtree-1.3.1 → seqtree-1.3.2}/pyproject.toml +1 -1
  3. {seqtree-1.3.1 → seqtree-1.3.2}/python/seqtree/control.py +46 -17
  4. {seqtree-1.3.1 → seqtree-1.3.2}/.gitattributes +0 -0
  5. {seqtree-1.3.1 → seqtree-1.3.2}/.gitignore +0 -0
  6. {seqtree-1.3.1 → seqtree-1.3.2}/CHANGELOG.md +0 -0
  7. {seqtree-1.3.1 → seqtree-1.3.2}/CMakeLists.txt +0 -0
  8. {seqtree-1.3.1 → seqtree-1.3.2}/LICENSE +0 -0
  9. {seqtree-1.3.1 → seqtree-1.3.2}/README.md +0 -0
  10. {seqtree-1.3.1 → seqtree-1.3.2}/RELEASE_AUDIT.md +0 -0
  11. {seqtree-1.3.1 → seqtree-1.3.2}/include/seqtree/kmer_index.hpp +0 -0
  12. {seqtree-1.3.1 → seqtree-1.3.2}/include/seqtree/parallel.hpp +0 -0
  13. {seqtree-1.3.1 → seqtree-1.3.2}/include/seqtree/seqtree.hpp +0 -0
  14. {seqtree-1.3.1 → seqtree-1.3.2}/include/seqtree/text_index.hpp +0 -0
  15. {seqtree-1.3.1 → seqtree-1.3.2}/include/seqtree/types.hpp +0 -0
  16. {seqtree-1.3.1 → seqtree-1.3.2}/python/seqtree/__init__.py +0 -0
  17. {seqtree-1.3.1 → seqtree-1.3.2}/python/seqtree/data/control_human_trb_aa.txt.gz +0 -0
  18. {seqtree-1.3.1 → seqtree-1.3.2}/python/seqtree/distance.py +0 -0
  19. {seqtree-1.3.1 → seqtree-1.3.2}/python/seqtree/evalue.py +0 -0
  20. {seqtree-1.3.1 → seqtree-1.3.2}/python/seqtree/gapblock.py +0 -0
  21. {seqtree-1.3.1 → seqtree-1.3.2}/python/seqtree/layout.py +0 -0
  22. {seqtree-1.3.1 → seqtree-1.3.2}/python/seqtree/pairwise.py +0 -0
  23. {seqtree-1.3.1 → seqtree-1.3.2}/python/seqtree/pmhc.py +0 -0
  24. {seqtree-1.3.1 → seqtree-1.3.2}/python/seqtree/pmhc_evalue.py +0 -0
  25. {seqtree-1.3.1 → seqtree-1.3.2}/python/seqtree/py.typed +0 -0
  26. {seqtree-1.3.1 → seqtree-1.3.2}/python/seqtree/seeds.py +0 -0
  27. {seqtree-1.3.1 → seqtree-1.3.2}/python/seqtree/text_evalue.py +0 -0
  28. {seqtree-1.3.1 → seqtree-1.3.2}/src/_bindings.cpp +0 -0
  29. {seqtree-1.3.1 → seqtree-1.3.2}/src/alignment_max.cpp +0 -0
  30. {seqtree-1.3.1 → seqtree-1.3.2}/src/atomic_write.hpp +0 -0
  31. {seqtree-1.3.1 → seqtree-1.3.2}/src/blosum45.inc +0 -0
  32. {seqtree-1.3.1 → seqtree-1.3.2}/src/blosum62.inc +0 -0
  33. {seqtree-1.3.1 → seqtree-1.3.2}/src/blosum80.inc +0 -0
  34. {seqtree-1.3.1 → seqtree-1.3.2}/src/codec.cpp +0 -0
  35. {seqtree-1.3.1 → seqtree-1.3.2}/src/count_unit.hpp +0 -0
  36. {seqtree-1.3.1 → seqtree-1.3.2}/src/distance.cpp +0 -0
  37. {seqtree-1.3.1 → seqtree-1.3.2}/src/engine_seqtm.cpp +0 -0
  38. {seqtree-1.3.1 → seqtree-1.3.2}/src/engine_seqtrie.cpp +0 -0
  39. {seqtree-1.3.1 → seqtree-1.3.2}/src/engines.hpp +0 -0
  40. {seqtree-1.3.1 → seqtree-1.3.2}/src/gapblock.cpp +0 -0
  41. {seqtree-1.3.1 → seqtree-1.3.2}/src/index.cpp +0 -0
  42. {seqtree-1.3.1 → seqtree-1.3.2}/src/kmer_index.cpp +0 -0
  43. {seqtree-1.3.1 → seqtree-1.3.2}/src/pairwise.cpp +0 -0
  44. {seqtree-1.3.1 → seqtree-1.3.2}/src/pairwise_detail.hpp +0 -0
  45. {seqtree-1.3.1 → seqtree-1.3.2}/src/pam100.inc +0 -0
  46. {seqtree-1.3.1 → seqtree-1.3.2}/src/pam250.inc +0 -0
  47. {seqtree-1.3.1 → seqtree-1.3.2}/src/positional_matrix.cpp +0 -0
  48. {seqtree-1.3.1 → seqtree-1.3.2}/src/searcher.cpp +0 -0
  49. {seqtree-1.3.1 → seqtree-1.3.2}/src/structural.inc +0 -0
  50. {seqtree-1.3.1 → seqtree-1.3.2}/src/substitution_matrix.cpp +0 -0
  51. {seqtree-1.3.1 → seqtree-1.3.2}/src/text_index.cpp +0 -0
  52. {seqtree-1.3.1 → seqtree-1.3.2}/src/trie.cpp +0 -0
  53. {seqtree-1.3.1 → seqtree-1.3.2}/src/trie.hpp +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: seqtree
3
- Version: 1.3.1
3
+ Version: 1.3.2
4
4
  Summary: Fast fuzzy search over biological sequences (C++ core, Python bindings)
5
5
  Keywords: sequence-search,fuzzy-matching,CDR3,immunology,bioinformatics,trie
6
6
  Author-Email: ISALGO laboratory <mikhail.shugay@gmail.com>
@@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"
4
4
 
5
5
  [project]
6
6
  name = "seqtree"
7
- version = "1.3.1"
7
+ version = "1.3.2"
8
8
  description = "Fast fuzzy search over biological sequences (C++ core, Python bindings)"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -122,24 +122,53 @@ def _prune_superseded(cache_dir, name, size, keep):
122
122
  pass
123
123
 
124
124
 
125
- def _build_lock(cache):
126
- """An inter-process lock around build-and-save, if ``filelock`` happens to be installed.
127
-
128
- This is an *optimisation*, not the fix. ``Index.save`` writes to a temporary and renames it
129
- into place, so a reader can never observe a half-written index whether or not this lock is
130
- taken. What the lock buys is work: without it, a cold-cache fan-out of N workers has every
131
- worker build the same 250k-clonotype index (seconds of CPU, 45 MB written) and N-1 of those
132
- are thrown away. With it, one builds and the rest wait and load.
133
-
134
- seqtree has no runtime dependencies, so ``filelock`` is used only if something else already
135
- put it there -- ``huggingface_hub`` pulls it in, and that is installed whenever a control is
136
- downloaded rather than read from the bundled asset.
125
+ @contextlib.contextmanager
126
+ def _build_lock(cache, timeout=600):
127
+ """Serialize cold builds without optional dependencies; process death releases the lock.
128
+
129
+ Keep the guard file: deleting it could let waiters lock different inodes.
137
130
  """
138
- try:
139
- from filelock import FileLock
140
- except ImportError:
141
- return contextlib.nullcontext()
142
- return FileLock(cache + ".lock", timeout=600)
131
+ import errno
132
+ import time
133
+
134
+ with open(cache + ".lock", "a+b") as handle:
135
+ if os.name == "nt":
136
+ import msvcrt
137
+ if handle.seek(0, 2) == 0:
138
+ handle.write(b"\0")
139
+ handle.flush()
140
+
141
+ def acquire():
142
+ handle.seek(0)
143
+ msvcrt.locking(handle.fileno(), msvcrt.LK_NBLCK, 1)
144
+
145
+ def release():
146
+ handle.seek(0)
147
+ msvcrt.locking(handle.fileno(), msvcrt.LK_UNLCK, 1)
148
+ else:
149
+ import fcntl
150
+
151
+ def acquire():
152
+ fcntl.flock(handle.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
153
+
154
+ def release():
155
+ fcntl.flock(handle.fileno(), fcntl.LOCK_UN)
156
+
157
+ deadline = time.monotonic() + timeout
158
+ while True:
159
+ try:
160
+ acquire()
161
+ break
162
+ except OSError as exc:
163
+ if exc.errno not in (errno.EACCES, errno.EAGAIN, errno.EDEADLK):
164
+ raise
165
+ if time.monotonic() >= deadline:
166
+ raise TimeoutError(f"Another control build owns {cache}.lock after {timeout:g}s") from exc
167
+ time.sleep(0.05)
168
+ try:
169
+ yield
170
+ finally:
171
+ release()
143
172
 
144
173
 
145
174
  def _load_cached(cache):
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes