opencloning 0.2.8.2__py3-none-any.whl → 0.3.0__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.
- opencloning/_version.py +7 -0
- opencloning/assembly2.py +11 -0
- opencloning/batch_cloning/pombe/__init__.py +0 -6
- opencloning/batch_cloning/ziqiang_et_al2024/ziqiang_et_al2024.json +39 -46
- opencloning/bug_fixing/README.md +138 -0
- opencloning/bug_fixing/__init__.py +0 -0
- opencloning/bug_fixing/backend_v0_3.py +117 -0
- opencloning/cre_lox.py +58 -0
- opencloning/endpoints/assembly.py +12 -3
- opencloning/endpoints/external_import.py +3 -3
- opencloning/endpoints/other.py +49 -7
- opencloning/endpoints/primer_design.py +5 -6
- opencloning/gateway.py +5 -4
- opencloning/pydantic_models.py +119 -25
- opencloning/utils.py +0 -12
- {opencloning-0.2.8.2.dist-info → opencloning-0.3.0.dist-info}/METADATA +11 -4
- {opencloning-0.2.8.2.dist-info → opencloning-0.3.0.dist-info}/RECORD +19 -15
- {opencloning-0.2.8.2.dist-info → opencloning-0.3.0.dist-info}/LICENSE +0 -0
- {opencloning-0.2.8.2.dist-info → opencloning-0.3.0.dist-info}/WHEEL +0 -0
opencloning/pydantic_models.py
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
from pydantic import BaseModel, Field, model_validator
|
|
1
|
+
from pydantic import BaseModel, Field, model_validator, field_validator
|
|
2
2
|
from typing import Optional, List
|
|
3
|
+
from pydantic_core import core_schema
|
|
4
|
+
from ._version import __version__
|
|
3
5
|
|
|
4
6
|
from Bio.SeqFeature import (
|
|
5
7
|
SeqFeature,
|
|
6
8
|
Location,
|
|
7
|
-
SimpleLocation
|
|
9
|
+
SimpleLocation,
|
|
8
10
|
FeatureLocation as BioFeatureLocation,
|
|
11
|
+
LocationParserError,
|
|
9
12
|
)
|
|
10
13
|
from Bio.SeqIO.InsdcIO import _insdc_location_string as format_feature_location
|
|
11
14
|
from Bio.Restriction.Restriction import RestrictionType, RestrictionBatch
|
|
@@ -31,7 +34,6 @@ from opencloning_linkml.datamodel import (
|
|
|
31
34
|
CRISPRSource as _CRISPRSource,
|
|
32
35
|
Primer as _Primer,
|
|
33
36
|
AssemblyFragment as _AssemblyFragment,
|
|
34
|
-
SimpleSequenceLocation as _SimpleSequenceLocation,
|
|
35
37
|
AddgeneIdSource as _AddgeneIdSource,
|
|
36
38
|
WekWikGeneIdSource as _WekWikGeneIdSource,
|
|
37
39
|
BenchlingUrlSource as _BenchlingUrlSource,
|
|
@@ -48,8 +50,11 @@ from opencloning_linkml.datamodel import (
|
|
|
48
50
|
CreLoxRecombinationSource as _CreLoxRecombinationSource,
|
|
49
51
|
InVivoAssemblySource as _InVivoAssemblySource,
|
|
50
52
|
)
|
|
51
|
-
from
|
|
52
|
-
|
|
53
|
+
from .assembly2 import (
|
|
54
|
+
edge_representation2subfragment_representation,
|
|
55
|
+
subfragment_representation2edge_representation,
|
|
56
|
+
)
|
|
57
|
+
from pydna.utils import location_boundaries, shift_location
|
|
53
58
|
|
|
54
59
|
|
|
55
60
|
SequenceFileFormat = _SequenceFileFormat
|
|
@@ -110,7 +115,17 @@ class ManuallyTypedSource(SourceCommonClass, _ManuallyTypedSource):
|
|
|
110
115
|
|
|
111
116
|
|
|
112
117
|
class UploadedFileSource(SourceCommonClass, _UploadedFileSource):
|
|
113
|
-
|
|
118
|
+
coordinates: Optional['SequenceLocationStr'] = Field(
|
|
119
|
+
default=None,
|
|
120
|
+
description="""If provided, coordinates within the sequence of the file to extract a subsequence""",
|
|
121
|
+
json_schema_extra={'linkml_meta': {'alias': 'coordinates', 'domain_of': ['UploadedFileSource']}},
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
@field_validator('coordinates', mode='before')
|
|
125
|
+
def parse_coordinates(cls, v):
|
|
126
|
+
if v is None:
|
|
127
|
+
return None
|
|
128
|
+
return SequenceLocationStr.field_validator(v)
|
|
114
129
|
|
|
115
130
|
|
|
116
131
|
class RepositoryIdSource(SourceCommonClass, _RepositoryIdSource):
|
|
@@ -218,36 +233,91 @@ class RestrictionEnzymeDigestionSource(SourceCommonClass, _RestrictionEnzymeDige
|
|
|
218
233
|
return sorted(list(set(out)), key=out.index)
|
|
219
234
|
|
|
220
235
|
|
|
221
|
-
class
|
|
236
|
+
class SequenceLocationStr(str):
|
|
237
|
+
"""A string representation of a sequence location, genbank-like."""
|
|
238
|
+
|
|
222
239
|
# TODO: this should handle origin-spanning simple locations (splitted)
|
|
223
240
|
@classmethod
|
|
224
|
-
def
|
|
225
|
-
return cls(
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
241
|
+
def from_biopython_location(cls, location: Location):
|
|
242
|
+
return cls(format_feature_location(location, None))
|
|
243
|
+
|
|
244
|
+
@classmethod
|
|
245
|
+
def from_start_and_end(cls, start: int, end: int, seq_len: int | None = None, strand: int | None = 1):
|
|
246
|
+
if end >= start:
|
|
247
|
+
return cls.from_biopython_location(SimpleLocation(start, end, strand=strand))
|
|
248
|
+
else:
|
|
249
|
+
if seq_len is None:
|
|
250
|
+
raise ValueError('Sequence length is required to handle origin-spanning simple locations')
|
|
251
|
+
unwrapped_location = SimpleLocation(start, end + seq_len, strand=strand)
|
|
252
|
+
wrapped_location = shift_location(unwrapped_location, 0, seq_len)
|
|
253
|
+
return cls.from_biopython_location(wrapped_location)
|
|
254
|
+
|
|
255
|
+
def to_biopython_location(self) -> BioFeatureLocation:
|
|
256
|
+
return Location.fromstring(self)
|
|
257
|
+
|
|
258
|
+
@classmethod
|
|
259
|
+
def field_validator(cls, v):
|
|
260
|
+
if isinstance(v, str):
|
|
261
|
+
value = cls(v)
|
|
262
|
+
try:
|
|
263
|
+
value.to_biopython_location()
|
|
264
|
+
except LocationParserError:
|
|
265
|
+
raise ValueError(f'Location "{v}" is not a valid location')
|
|
266
|
+
return value
|
|
267
|
+
raise ValueError(f'Location must be a string or a {cls.__name__}')
|
|
268
|
+
|
|
269
|
+
@property
|
|
270
|
+
def start(self) -> int:
|
|
271
|
+
return location_boundaries(self.to_biopython_location())[0]
|
|
272
|
+
|
|
273
|
+
@property
|
|
274
|
+
def end(self) -> int:
|
|
275
|
+
return location_boundaries(self.to_biopython_location())[1]
|
|
276
|
+
|
|
277
|
+
@classmethod
|
|
278
|
+
def __get_pydantic_core_schema__(
|
|
279
|
+
cls,
|
|
280
|
+
source_type,
|
|
281
|
+
handler,
|
|
282
|
+
) -> core_schema.CoreSchema:
|
|
283
|
+
"""Generate Pydantic core schema for SequenceLocationStr."""
|
|
284
|
+
return core_schema.with_info_after_validator_function(
|
|
285
|
+
cls._validate,
|
|
286
|
+
core_schema.str_schema(),
|
|
229
287
|
)
|
|
230
288
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
return BioSimpleLocation(self.start, self.end, self.strand)
|
|
289
|
+
@classmethod
|
|
290
|
+
def _validate(cls, value: str, info):
|
|
291
|
+
"""Validate and create SequenceLocationStr instance."""
|
|
292
|
+
return cls.field_validator(value)
|
|
236
293
|
|
|
237
294
|
|
|
238
295
|
class AssemblyFragment(_AssemblyFragment):
|
|
239
|
-
left_location: Optional[
|
|
240
|
-
right_location: Optional[
|
|
296
|
+
left_location: Optional[SequenceLocationStr] = None
|
|
297
|
+
right_location: Optional[SequenceLocationStr] = None
|
|
241
298
|
|
|
242
|
-
def to_fragment_tuple(self, fragments) -> tuple[int,
|
|
299
|
+
def to_fragment_tuple(self, fragments) -> tuple[int, Location, Location]:
|
|
243
300
|
fragment_ids = [int(f.id) for f in fragments]
|
|
301
|
+
# By convention, these have no strand
|
|
302
|
+
left_loc = None if self.left_location is None else self.left_location.to_biopython_location()
|
|
303
|
+
right_loc = None if self.right_location is None else self.right_location.to_biopython_location()
|
|
304
|
+
if left_loc is not None:
|
|
305
|
+
left_loc.strand = None
|
|
306
|
+
if right_loc is not None:
|
|
307
|
+
right_loc.strand = None
|
|
244
308
|
|
|
245
309
|
return (
|
|
246
310
|
(fragment_ids.index(self.sequence) + 1) * (-1 if self.reverse_complemented else 1),
|
|
247
|
-
|
|
248
|
-
|
|
311
|
+
left_loc,
|
|
312
|
+
right_loc,
|
|
249
313
|
)
|
|
250
314
|
|
|
315
|
+
@field_validator('left_location', 'right_location', mode='before')
|
|
316
|
+
def parse_location(cls, v):
|
|
317
|
+
if v is None:
|
|
318
|
+
return None
|
|
319
|
+
return SequenceLocationStr.field_validator(v)
|
|
320
|
+
|
|
251
321
|
|
|
252
322
|
class AssemblySourceCommonClass(SourceCommonClass):
|
|
253
323
|
# TODO: This is different in the LinkML model, because there it is not required,
|
|
@@ -290,8 +360,8 @@ class AssemblySourceCommonClass(SourceCommonClass):
|
|
|
290
360
|
assembly_fragments = [
|
|
291
361
|
AssemblyFragment(
|
|
292
362
|
sequence=fragment_ids[abs(pos) - 1],
|
|
293
|
-
left_location=None if left_loc is None else
|
|
294
|
-
right_location=None if right_loc is None else
|
|
363
|
+
left_location=None if left_loc is None else SequenceLocationStr.from_biopython_location(left_loc),
|
|
364
|
+
right_location=None if right_loc is None else SequenceLocationStr.from_biopython_location(right_loc),
|
|
295
365
|
reverse_complemented=pos < 0,
|
|
296
366
|
)
|
|
297
367
|
for pos, left_loc, right_loc in fragment_assembly_positions
|
|
@@ -410,6 +480,11 @@ class BaseCloningStrategy(_CloningStrategy):
|
|
|
410
480
|
description="""The primers that are used in the cloning strategy""",
|
|
411
481
|
json_schema_extra={'linkml_meta': {'alias': 'primers', 'domain_of': ['CloningStrategy']}},
|
|
412
482
|
)
|
|
483
|
+
backend_version: Optional[str] = Field(
|
|
484
|
+
default=__version__,
|
|
485
|
+
description="""The version of the backend that was used to generate this cloning strategy""",
|
|
486
|
+
json_schema_extra={'linkml_meta': {'alias': 'backend_version', 'domain_of': ['CloningStrategy']}},
|
|
487
|
+
)
|
|
413
488
|
|
|
414
489
|
def next_primer_id(self):
|
|
415
490
|
return max([p.id for p in self.primers], default=0) + 1
|
|
@@ -436,8 +511,27 @@ class BaseCloningStrategy(_CloningStrategy):
|
|
|
436
511
|
self.sequences.append(sequence)
|
|
437
512
|
source.output = sequence.id
|
|
438
513
|
|
|
514
|
+
def all_children_source_ids(self, source_id: int, source_children: list | None = None) -> list[int]:
|
|
515
|
+
"""Returns the ids of all source children ids of a source"""
|
|
516
|
+
source = next(s for s in self.sources if s.id == source_id)
|
|
517
|
+
if source_children is None:
|
|
518
|
+
source_children = []
|
|
519
|
+
|
|
520
|
+
sources_that_take_output_as_input = [s for s in self.sources if source.output in s.input]
|
|
521
|
+
new_source_ids = [s.id for s in sources_that_take_output_as_input]
|
|
522
|
+
|
|
523
|
+
source_children.extend(new_source_ids)
|
|
524
|
+
for new_source_id in new_source_ids:
|
|
525
|
+
self.all_children_source_ids(new_source_id, source_children)
|
|
526
|
+
return source_children
|
|
527
|
+
|
|
439
528
|
|
|
440
529
|
class PrimerDesignQuery(BaseModel):
|
|
530
|
+
model_config = {'arbitrary_types_allowed': True}
|
|
441
531
|
sequence: TextFileSequence
|
|
442
|
-
location:
|
|
532
|
+
location: SequenceLocationStr
|
|
443
533
|
forward_orientation: bool = True
|
|
534
|
+
|
|
535
|
+
@field_validator('location', mode='before')
|
|
536
|
+
def parse_location(cls, v):
|
|
537
|
+
return SequenceLocationStr.field_validator(v)
|
opencloning/utils.py
CHANGED
|
@@ -43,15 +43,3 @@ class TemporaryFolderOverride:
|
|
|
43
43
|
if self.target_folder_exists:
|
|
44
44
|
os.mkdir(self.target_folder)
|
|
45
45
|
move_all_contents(self.backup_folder, self.target_folder)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
def api_version() -> dict[str, str | None]:
|
|
49
|
-
version = None
|
|
50
|
-
commit_sha = None
|
|
51
|
-
if os.path.exists('version.txt'):
|
|
52
|
-
with open('version.txt', 'r') as f:
|
|
53
|
-
version = f.read().strip()
|
|
54
|
-
if os.path.exists('commit_sha.txt'):
|
|
55
|
-
with open('commit_sha.txt', 'r') as f:
|
|
56
|
-
commit_sha = f.read().strip()
|
|
57
|
-
return {'version': version, 'commit_sha': commit_sha}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: opencloning
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Backend of OpenCloning, a web application to generate molecular cloning strategies in json format, and share them with others.
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: Manuel Lera-Ramirez
|
|
@@ -15,10 +15,11 @@ Requires-Dist: beautifulsoup4 (>=4.11.1,<5.0.0)
|
|
|
15
15
|
Requires-Dist: biopython (==1.84)
|
|
16
16
|
Requires-Dist: fastapi
|
|
17
17
|
Requires-Dist: httpx (>=0.25.0,<0.26.0)
|
|
18
|
-
Requires-Dist: opencloning-linkml (==0.
|
|
18
|
+
Requires-Dist: opencloning-linkml (==0.3.0a0)
|
|
19
19
|
Requires-Dist: openpyxl (>=3.1.5,<4.0.0)
|
|
20
|
+
Requires-Dist: packaging (>=25.0,<26.0)
|
|
20
21
|
Requires-Dist: pandas (>=2.2.3,<3.0.0)
|
|
21
|
-
Requires-Dist: primer3-py (
|
|
22
|
+
Requires-Dist: primer3-py (==2.0.3)
|
|
22
23
|
Requires-Dist: pydantic (>=2.7.1,<3.0.0)
|
|
23
24
|
Requires-Dist: pydna (==5.5.0)
|
|
24
25
|
Requires-Dist: python-multipart
|
|
@@ -48,6 +49,12 @@ This API provides a series of entry points. The API documentation can be accesse
|
|
|
48
49
|
|
|
49
50
|
The API functions can also be used to write python scripts to automate cloning. See the [scripting examples](examples/scripting) for more information.
|
|
50
51
|
|
|
52
|
+
## Migrating between model versions and fixing model bugs
|
|
53
|
+
|
|
54
|
+
* The data model changes, so the json files you created may not be compatible with the newest version of the library, which uses the latest data mode. You can easily fix this using `python -m opencloning_linkml.migrations.migrate file.json
|
|
55
|
+
` see [full documentation](https://github.com/OpenCloning/OpenCloning_LinkML?tab=readme-ov-file#migration-from-previous-versions-of-the-schema).
|
|
56
|
+
* Before version 0.3, there was a bug for assembly fields that included locations spanning the origin. See the details and how to fix it in the documentation of [this file](./src/opencloning/bug_fixing/README.md).
|
|
57
|
+
|
|
51
58
|
## Getting started
|
|
52
59
|
|
|
53
60
|
If you want to quickly set up a local instance of the frontend and backend of the application, check [getting started in 5 minutes](https://github.com/manulera/OpenCloning#timer_clock-getting-started-in-5-minutes) in the main repository.
|
|
@@ -61,7 +68,7 @@ You can install this as a python package:
|
|
|
61
68
|
python -m venv .venv
|
|
62
69
|
# Activate the virtual environment
|
|
63
70
|
source .venv/bin/activate
|
|
64
|
-
# Install the package from
|
|
71
|
+
# Install the package from pypi
|
|
65
72
|
pip install opencloning
|
|
66
73
|
# Run the API (uvicorn should be installed in the virtual environment)
|
|
67
74
|
uvicorn opencloning.main:app
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
opencloning/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
opencloning/_version.py,sha256=6QbWXLSZypjtWL_CwJFHH4dzMRK3AUH4B0YudzvGz9s,200
|
|
2
3
|
opencloning/api_config_utils.py,sha256=inAXPGYNDz-DuEoSqitImj0Vv5TpQSbMZH9D3dQb5P0,4319
|
|
3
4
|
opencloning/app_settings.py,sha256=x5ddkaoyWE76fa4CdwIv-aDfg1eyZr6qTQwfKJB4mCo,1785
|
|
4
|
-
opencloning/assembly2.py,sha256=
|
|
5
|
+
opencloning/assembly2.py,sha256=_UdQCnjc2wmWoeVT9NKwXcYUAEBrBT0OSBNMbGYAIL8,57041
|
|
5
6
|
opencloning/batch_cloning/EBIC/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
7
|
opencloning/batch_cloning/EBIC/barcode.gb,sha256=G6kP6MuY23S-n3xg16LQaTasFtYFqik5eEgcooZ9ATM,815
|
|
7
8
|
opencloning/batch_cloning/EBIC/common_plasmid.gb,sha256=At1HJjqJ2MsLMEx6W3MihJy7tgdtDu3fhwF4YGuw8Dk,13068
|
|
@@ -9,7 +10,7 @@ opencloning/batch_cloning/EBIC/example.py,sha256=FWjROXWsgM-gz2oYnKiywUVKa9uoEe9
|
|
|
9
10
|
opencloning/batch_cloning/EBIC/primer_design_settings.py,sha256=MVML1r1ciJYMFUJoqZVcGLoPM-f28oBN1wSDzlD0y64,1896
|
|
10
11
|
opencloning/batch_cloning/__init__.py,sha256=uDxAa45g30_S6dJScNMlIxubQXlLRUsWoLX4S4y-l88,244
|
|
11
12
|
opencloning/batch_cloning/index.html,sha256=HDqPHrJxrrKfGmy_dwYHhOsdUgZHHIch7Z0ey8qyvZI,1332
|
|
12
|
-
opencloning/batch_cloning/pombe/__init__.py,sha256=
|
|
13
|
+
opencloning/batch_cloning/pombe/__init__.py,sha256=Fq7SroO0Fer5CtFBRWdduIvzp1_dTUZwBb8IjBtRQO0,3332
|
|
13
14
|
opencloning/batch_cloning/pombe/index.html,sha256=3YchoKGpcKDfvTOW1Rdih4PkbZIkMjKIQ0PaVXfV3e8,8348
|
|
14
15
|
opencloning/batch_cloning/pombe/pombe_all.sh,sha256=0yvDdBaIdt2RsIrvnjgn5L3KtYBToq3Rl8-X8RFHibE,364
|
|
15
16
|
opencloning/batch_cloning/pombe/pombe_clone.py,sha256=OY6yOlBK-9OAmHu3HUhP50mIXvyR0HJg1_2OjBFifV8,8123
|
|
@@ -18,29 +19,32 @@ opencloning/batch_cloning/pombe/pombe_get_primers.py,sha256=1RbR_8YGhSrmeIVDOpUp
|
|
|
18
19
|
opencloning/batch_cloning/pombe/pombe_summary.py,sha256=W9DLpnCuwK7w2DhHLu60N7L6jquuYubD3ZRFwdhNPVw,4033
|
|
19
20
|
opencloning/batch_cloning/ziqiang_et_al2024/__init__.py,sha256=zZUbj3uMzd9rKMXi5s9LQ1yUg7sccdS0f_4kpw7SQlk,7584
|
|
20
21
|
opencloning/batch_cloning/ziqiang_et_al2024/index.html,sha256=EDncANDhhQkhi5FjnnAP6liHkG5srf4_Y46IrnMUG5g,4607
|
|
21
|
-
opencloning/batch_cloning/ziqiang_et_al2024/ziqiang_et_al2024.json,sha256=
|
|
22
|
-
opencloning/
|
|
22
|
+
opencloning/batch_cloning/ziqiang_et_al2024/ziqiang_et_al2024.json,sha256=d-7oXbxoKhMKLz4FJ2OGDdedWTisoaRqLAh1NZnScBg,157189
|
|
23
|
+
opencloning/bug_fixing/README.md,sha256=9EMhP_ibl_HDt745dz1Cw_Pl2kTMVrNJQW5ysCBcJoE,4231
|
|
24
|
+
opencloning/bug_fixing/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
|
+
opencloning/bug_fixing/backend_v0_3.py,sha256=ubfDN-IEwj-dW1Qgy3ozrkXcUIXwXvZcxJHrVanR_Ws,4213
|
|
26
|
+
opencloning/cre_lox.py,sha256=x_OVYzfaLJH5eVyp05_I9YNycT606UL683AswhQ-gjU,4294
|
|
23
27
|
opencloning/dna_functions.py,sha256=ivepJM2wRTIW0ArSiQ5s-XuqBd69giEQijaWXXGT64E,16536
|
|
24
28
|
opencloning/dna_utils.py,sha256=uv97aO04dbk3NnqbN6GlnwOu0MOpK88rl2np2QcEQ4Y,6301
|
|
25
29
|
opencloning/ebic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
26
30
|
opencloning/ebic/primer_design.py,sha256=gPZTF9w5SV7WGgnefp_HBM831y0z73M1Kb0QUPnbfIM,2270
|
|
27
31
|
opencloning/ebic/primer_design_settings.py,sha256=OnFsuh0QCvplUEPXLZouzRo9R7rm4nLbcd2LkDCiIDM,1896
|
|
28
32
|
opencloning/endpoints/annotation.py,sha256=3rlIXeNQzoqPD9lJUEBGLGxvlhUCTcfkqno814A8P0U,2283
|
|
29
|
-
opencloning/endpoints/assembly.py,sha256=
|
|
30
|
-
opencloning/endpoints/external_import.py,sha256=
|
|
33
|
+
opencloning/endpoints/assembly.py,sha256=MMwvlyM2NHnT04Pp7LdKQRvahq0itdqTtZx3OQhOswc,20980
|
|
34
|
+
opencloning/endpoints/external_import.py,sha256=xU-ZL503pJW1M08gxXTULaLgp9jHc_dBVrcyMRjNmow,18178
|
|
31
35
|
opencloning/endpoints/no_assembly.py,sha256=NY6rhEDCNoZVn6Xk81cen2n-FkMr7ierfxM8G0npbQs,4722
|
|
32
36
|
opencloning/endpoints/no_input.py,sha256=DuqKD3Ph3a44ZxPMEzZv1nwD5xlxYsN7YyxXcfjSUFc,3844
|
|
33
|
-
opencloning/endpoints/other.py,sha256=
|
|
34
|
-
opencloning/endpoints/primer_design.py,sha256=
|
|
35
|
-
opencloning/gateway.py,sha256=
|
|
37
|
+
opencloning/endpoints/other.py,sha256=7YBXU5UrVCjEjOjdYWw-0sASXn3MhWVZYwDYSZD4C9E,3452
|
|
38
|
+
opencloning/endpoints/primer_design.py,sha256=3eiQ7MwgeLoAuXFUMNF-DzjzwH_eJGCjd4s32CjxIic,12717
|
|
39
|
+
opencloning/gateway.py,sha256=pFB3gsCQL715kOFOP1NQOOsQqrkWuQe5qXk4IunF5SA,8486
|
|
36
40
|
opencloning/get_router.py,sha256=l2DXaTbeL2tDqlnVMlcewutzt1sjaHlxku1X9HVUwJk,252
|
|
37
41
|
opencloning/main.py,sha256=l9PrPBMtGMEWxAPiPWR15Qv2oDNnRoNd8H8E3bZW6Do,3750
|
|
38
42
|
opencloning/ncbi_requests.py,sha256=JrFc-Ugr1r1F4LqsdpJZEiERj7ZemvZSgiIltl2Chx8,5547
|
|
39
43
|
opencloning/primer_design.py,sha256=nqCmYIZ7UvU4CQwVGJwX7T5LTHwt3-51_ZcTZZAgT_Y,9175
|
|
40
|
-
opencloning/pydantic_models.py,sha256=
|
|
44
|
+
opencloning/pydantic_models.py,sha256=lMO78M4MwDgzTEGz9qzsaADwAFXagWK4qGsF1K1hLZw,18865
|
|
41
45
|
opencloning/request_examples.py,sha256=QAsJxVaq5tHwlPB404IiJ9WC6SA7iNY7XnJm63BWT_E,2944
|
|
42
|
-
opencloning/utils.py,sha256=
|
|
43
|
-
opencloning-0.
|
|
44
|
-
opencloning-0.
|
|
45
|
-
opencloning-0.
|
|
46
|
-
opencloning-0.
|
|
46
|
+
opencloning/utils.py,sha256=0Lvw1h1AsUJTK2b9mNzYVi_DBeWmWCFA5dIPl_gERcI,1479
|
|
47
|
+
opencloning-0.3.0.dist-info/LICENSE,sha256=VSdVE1f8axjIh6gvo9ZZygJdTVkRFMcwCW_hvjOHC_w,1058
|
|
48
|
+
opencloning-0.3.0.dist-info/METADATA,sha256=fqz_qzNi4Q4eHOzzx4B6iMUMf7WMLFOu5EY4x0vthek,9083
|
|
49
|
+
opencloning-0.3.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
50
|
+
opencloning-0.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|