pydna 5.5.2__py3-none-any.whl → 5.5.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.
pydna/cre_lox.py ADDED
@@ -0,0 +1,130 @@
1
+ # -*- coding: utf-8 -*-
2
+ from itertools import product
3
+ from pydna.dseqrecord import Dseqrecord
4
+ from Bio.Data.IUPACData import ambiguous_dna_values
5
+ from Bio.Seq import reverse_complement
6
+ from pydna.sequence_regex import compute_regex_site, dseqrecord_finditer
7
+ from Bio.SeqFeature import Location, SimpleLocation, SeqFeature
8
+ from pydna.utils import shift_location
9
+
10
+ # We create a dictionary to map ambiguous bases to their consensus base
11
+ # For example, ambigous_base_dict['ACGT'] -> 'N'
12
+ ambiguous_base_dict = {}
13
+ for ambiguous, bases in ambiguous_dna_values.items():
14
+ ambiguous_base_dict["".join(sorted(bases))] = ambiguous
15
+
16
+ # To handle N values
17
+ ambiguous_base_dict["N"] = "N"
18
+
19
+ # This is the original loxP sequence, here for reference
20
+ LOXP_SEQUENCE = "ATAACTTCGTATAGCATACATTATACGAAGTTAT"
21
+
22
+ loxP_sequences = [
23
+ # https://blog.addgene.org/plasmids-101-cre-lox
24
+ # loxP
25
+ "ATAACTTCGTATANNNTANNNTATACGAAGTTAT",
26
+ # PMID:12202778
27
+ # lox66
28
+ "ATAACTTCGTATANNNTANNNTATACGAACGGTA",
29
+ # lox71
30
+ "TACCGTTCGTATANNNTANNNTATACGAAGTTAT",
31
+ ]
32
+
33
+ loxP_consensus = ""
34
+
35
+ for pos in range(len(LOXP_SEQUENCE)):
36
+ all_letters = set(seq[pos] for seq in loxP_sequences)
37
+ key = "".join(sorted(all_letters))
38
+ loxP_consensus += ambiguous_base_dict[key]
39
+
40
+ # We compute the regex for the forward and reverse loxP sequences
41
+ loxP_regex = (
42
+ compute_regex_site(loxP_consensus),
43
+ compute_regex_site(reverse_complement(loxP_consensus)),
44
+ )
45
+
46
+
47
+ def cre_loxP_overlap(
48
+ x: Dseqrecord, y: Dseqrecord, _l: None = None
49
+ ) -> list[tuple[int, int, int]]:
50
+ """Find matching loxP sites between two sequences."""
51
+ out = list()
52
+ for pattern in loxP_regex:
53
+ matches_x = dseqrecord_finditer(pattern, x)
54
+ matches_y = dseqrecord_finditer(pattern, y)
55
+
56
+ for match_x, match_y in product(matches_x, matches_y):
57
+ value_x = match_x.group()
58
+ value_y = match_y.group()
59
+ if value_x[13:21] == value_y[13:21]:
60
+ out.append((match_x.start() + 13, match_y.start() + 13, 8))
61
+ # Unique values (keeping the order)
62
+ unique_out = []
63
+ for item in out:
64
+ if item not in unique_out:
65
+ unique_out.append(item)
66
+ return unique_out
67
+
68
+
69
+ loxP_dict = {
70
+ "loxP": "ATAACTTCGTATANNNTANNNTATACGAAGTTAT",
71
+ "lox66": "ATAACTTCGTATANNNTANNNTATACGAACGGTA",
72
+ "lox71": "TACCGTTCGTATANNNTANNNTATACGAAGTTAT",
73
+ "loxP_mutant": "TACCGTTCGTATANNNTANNNTATACGAACGGTA",
74
+ }
75
+
76
+
77
+ def get_regex_dict(original_dict: dict[str, str]) -> dict[str, str]:
78
+ """Get the regex dictionary for the original dictionary."""
79
+ out = dict()
80
+ for site in original_dict:
81
+ consensus_seq = original_dict[site]
82
+ is_palindromic = consensus_seq == reverse_complement(consensus_seq)
83
+ out[site] = {
84
+ "forward_regex": compute_regex_site(original_dict[site]),
85
+ "reverse_regex": (
86
+ None
87
+ if is_palindromic
88
+ else compute_regex_site(reverse_complement(original_dict[site]))
89
+ ),
90
+ }
91
+ return out
92
+
93
+
94
+ def find_loxP_sites(seq: Dseqrecord) -> dict[str, list[Location]]:
95
+ """Find all loxP sites in a sequence and return a dictionary with the name and positions of the sites."""
96
+
97
+ out = dict()
98
+ regex_dict = get_regex_dict(loxP_dict)
99
+ for site in loxP_dict:
100
+
101
+ for pattern in ["forward_regex", "reverse_regex"]:
102
+ # Palindromic sequences have no reverse complement
103
+ if regex_dict[site][pattern] is None:
104
+ continue
105
+ matches = list(dseqrecord_finditer(regex_dict[site][pattern], seq))
106
+ for match in matches:
107
+ if site not in out:
108
+ out[site] = []
109
+ strand = 1 if pattern == "forward_regex" else -1
110
+ loc = SimpleLocation(match.start(), match.end(), strand)
111
+ loc = shift_location(loc, 0, len(seq))
112
+ out[site].append(loc)
113
+ return out
114
+
115
+
116
+ def annotate_loxP_sites(seq: Dseqrecord) -> Dseqrecord:
117
+ sites = find_loxP_sites(seq)
118
+ for site in sites:
119
+ for loc in sites[site]:
120
+ # Don't add the same feature twice
121
+ if not any(
122
+ f.location == loc
123
+ and f.type == "protein_bind"
124
+ and f.qualifiers.get("label", []) == [site]
125
+ for f in seq.features
126
+ ):
127
+ seq.features.append(
128
+ SeqFeature(loc, type="protein_bind", qualifiers={"label": [site]})
129
+ )
130
+ return seq
pydna/gateway.py CHANGED
@@ -1,162 +1,164 @@
1
- #!/usr/bin/env python3
2
1
  # -*- coding: utf-8 -*-
3
- # Copyright 2013-2023 by Björn Johansson. All rights reserved.
4
- # This code is part of the Python-dna distribution and governed by its
5
- # license. Please see the LICENSE.txt file that should have been included
6
- # as part of this package.
7
-
8
- """Assembly of sequences by Gateway recombination.
9
-
10
- Given a list of sequences (Dseqrecords), all sequences are analyzed for
11
- presence of att(P|B|L|R)N where N is 1,2,3 or 4.
12
-
13
- A graph is constructed where the att sites form a nodes and
14
- sequences separating att sites form edges.
15
-
16
- The NetworkX package is used to trace linear and circular paths through the
17
- graph.
18
- """
19
- # from Bio.SeqFeature import ExactPosition as _ExactPosition
20
- # from Bio.SeqFeature import SimpleLocation as _SimpleLocation
21
- # from Bio.SeqFeature import CompoundLocation as _CompoundLocation
22
- # from pydna.utils import rc as _rc
23
-
24
- # from pydna._pretty import pretty_str as _pretty_str
25
- # from pydna.contig import Contig as _Contig
26
- # from pydna.common_sub_strings import common_sub_strings
27
- # from pydna.dseqrecord import Dseqrecord as _Dseqrecord
28
- # import networkx as _nx
29
- # from copy import deepcopy as _deepcopy
30
- # import itertools as _itertools
31
- # import logging as _logging
32
-
33
- # _module_logger = _logging.getLogger("pydna." + __name__)
34
-
35
- ambiguous_dna_regex = {
36
- "A": "T",
37
- "C": "G",
38
- "G": "C",
39
- "T": "A",
40
- "M": "[ACM]",
41
- "R": "[AGR]",
42
- "W": "[ATW]",
43
- "S": "[CGS]",
44
- "Y": "[CTY]",
45
- "K": "[GTK]",
46
- "V": "[ACGVMSR]",
47
- "H": "[ACTHMYW]",
48
- "D": "[AGTDRWK]",
49
- "B": "[CGTBSKY]",
50
- "X": "X",
51
- "N": "[ACGTBDHKMNRSVWY]",
2
+ from Bio.Seq import reverse_complement
3
+ from pydna.dseqrecord import Dseqrecord as _Dseqrecord
4
+ import re
5
+ import itertools as _itertools
6
+ from Bio.SeqFeature import SimpleLocation, SeqFeature
7
+ from pydna.utils import shift_location
8
+ from pydna.sequence_regex import compute_regex_site, dseqrecord_finditer
9
+
10
+
11
+ raw_gateway_common = {
12
+ "attB1": "CHWVTWTGTACAAAAAANNNG",
13
+ "attB2": "CHWVTWTGTACAAGAAANNNG",
14
+ "attB3": "CHWVTWTGTATAATAAANNNG",
15
+ "attB4": "CHWVTWTGTATAGAAAANNNG",
16
+ "attB5": "CHWVTWTGTATACAAAANNNG",
17
+ "attL1": "VAAWWAWKRWTTTWWTTYGACTGATAGTGACCTGTWCGTYGMAACAVATTGATRAGCAATKMTTTYYTATAWTGHCMASTWTGTACAAAAAANNNG",
18
+ "attL2": "VAAWWAWKRWTTTWWTTYGACTGATAGTGACCTGTWCGTYGMAACAVATTGATRAGCAATKMTTTYYTATAWTGHCMASTWTGTACAAGAAANNNG",
19
+ "attL3": "VAAWWAWKRWTTTWWTTYGACTGATAGTGACCTGTWCGTYGMAACAVATTGATRAGCAATKMTTTYYTATAWTGHCMASTWTGTATAATAAANNNG",
20
+ "attL4": "VAAWWAWKRWTTTWWTTYGACTGATAGTGACCTGTWCGTYGMAACAVATTGATRAGCAATKMTTTYYTATAWTGHCMASTWTGTATAGAAAANNNG",
21
+ "attL5": "VAAWWAWKRWTTTWWTTYGACTGATAGTGACCTGTWCGTYGMAACAVATTGATRAGCAATKMTTTYYTATAWTGHCMASTWTGTATACAAAANNNG",
22
+ "attR1": "CHWVTWTGTACAAAAAAGYWGARCGAGAARCGTAARRTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATRCTGTAARACACAACATATBCAGTCV",
23
+ "attR2": "CHWVTWTGTACAAGAAAGYWGARCGAGAARCGTAARRTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATRCTGTAARACACAACATATBCAGTCV",
24
+ "attR3": "CHWVTWTGTATAATAAAGYWGARCGAGAARCGTAARRTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATRCTGTAARACACAACATATBCAGTCV",
25
+ "attR4": "CHWVTWTGTATAGAAAAGYWGARCGAGAARCGTAARRTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATRCTGTAARACACAACATATBCAGTCV",
26
+ "attR5": "CHWVTWTGTATACAAAAGYWGARCGAGAARCGTAARRTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATRCTGTAARACACAACATATBCAGTCV",
27
+ "overlap_1": "twtGTACAAAaaa",
28
+ "overlap_2": "twtGTACAAGaaa",
29
+ "overlap_3": "twtGTATAATaaa",
30
+ "overlap_4": "twtGTATAGAaaa",
31
+ "overlap_5": "twtGTATACAaaa",
52
32
  }
53
33
 
54
- atts = """
55
- attP1 AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT GTACAAA AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG CMASTWT AAAGYWG
56
- attP2 AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT GTACAAG AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG CMASTWT AAAGYWG
57
- attP3 AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT GTATAAT AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG CMASTWT AAAGYWG
58
- attP4 AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT GTATAGA AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG CMASTWT AAAGYWG
59
- attP5 AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT GTATACA AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG CMASTWT AAAGYWG
60
-
61
- attB1 CMASTWT GTACAAA AAAGYWG AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG
62
- attB2 CMASTWT GTACAAG AAAGYWG AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG
63
- attB3 CMASTWT GTATAAT AAAGYWG AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG
64
- attB4 CMASTWT GTATAGA AAAGYWG AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG
65
- attB5 CMASTWT GTATACA AAAGYWG AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG
66
-
67
- attR1 CMASTWT GTACAAA AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT AAAGYWG
68
- attR2 CMASTWT GTACAAG AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT AAAGYWG
69
- attR3 CMASTWT GTATAAT AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT AAAGYWG
70
- attR4 CMASTWT GTATAGA AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT AAAGYWG
71
- attR5 CMASTWT GTATACA AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT AAAGYWG
72
-
73
- attL1 AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT GTACAAA AAAGYWG CMASTWT AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG
74
- attL2 AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT GTACAAG AAAGYWG CMASTWT AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG
75
- attL3 AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT GTATAAT AAAGYWG CMASTWT AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG
76
- attL4 AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT GTATAGA AAAGYWG CMASTWT AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG
77
- attL5 AAATAATGATTTTATTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATKMTTTYTTATAATGCCMASTTT GTATACA AAAGYWG CMASTWT AAAGYWGAACGAGAAACGTAAAATGATATAAATATCAATATATTAAATTAGATTTTGCATAAAAAACAGACTACATAATRCTGTAAAACACAACATATSCAGTCAYWWTG
78
- """
79
-
80
-
81
- retable = str.maketrans(ambiguous_dna_regex)
82
-
83
- for line in (line for line in atts.splitlines() if line.strip()):
84
- name, *parts = line.split()
85
- for part in parts:
86
- part.translate(retable)
87
-
88
-
89
- class Gateway(object):
90
- """Assembly of linear DNA fragments into linear or circular constructs.
91
-
92
- The Assembly is meant to replace the Assembly method as it
93
- is easier to use. Accepts a list of Dseqrecords (source fragments) to
94
- initiate an Assembly object. Several methods are available for analysis
95
- of overlapping sequences, graph construction and assembly.
96
-
97
- Parameters
98
- ----------
99
- fragments : list
100
- a list of Dseqrecord objects.
101
- """
102
-
103
- def __init__(self, molecules=None):
104
- self.molecules = molecules
105
-
106
-
107
- """
108
- Created on Sat Aug 21 15:41:42 2021
109
-
110
- @author: bjorn
111
-
112
-
113
- https://en.wikipedia.org/wiki/Cre-Lox_recombination
114
-
115
- 13bp 8bp 13bp
116
- ATAACTTCGTATA-NNNTANNN-TATACGAAGTTAT
117
-
118
-
119
- Name 13 bp 8 bp 13 bp
120
- Recognition Spacer Recognition
121
- Region Region Region
122
-
123
- Wild-Type ATAACTTCGTATA ATGTATGC TATACGAAGTTAT
124
- lox 511 ATAACTTCGTATA ATGTATaC TATACGAAGTTAT
125
- lox 5171 ATAACTTCGTATA ATGTgTaC TATACGAAGTTAT
126
- lox 2272 ATAACTTCGTATA AaGTATcC TATACGAAGTTAT
127
- M2 ATAACTTCGTATA AgaaAcca TATACGAAGTTAT
128
- M3 ATAACTTCGTATA taaTACCA TATACGAAGTTAT
129
- M7 ATAACTTCGTATA AgaTAGAA TATACGAAGTTAT
130
- M11 ATAACTTCGTATA cgaTAcca TATACGAAGTTAT
131
- lox 71 TACCGTTCGTATA NNNTANNN TATACGAAGTTAT
132
- lox 66 ATAACTTCGTATA NNNTANNN TATACGAACGGTA
133
34
 
134
- """
135
-
136
-
137
- """
138
-
139
- https://blog.addgene.org/plasmids-101-cre-lox
35
+ raw_gateway_sites_greedy = {
36
+ **raw_gateway_common,
37
+ "attP1": "VAAWWAWKRWTTTWWTTYGACTGATAGTGACCTGTWCGTYGMAACAVATTGATRAGCAATKMTTTYYTATAWTGHCMASTWTGTACAAAAAAGYWGARCGAGAARCGTAARRTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATRCTGTAARACACAACATATBCAGTCV",
38
+ "attP2": "VAAWWAWKRWTTTWWTTYGACTGATAGTGACCTGTWCGTYGMAACAVATTGATRAGCAATKMTTTYYTATAWTGHCMASTWTGTACAAGAAAGYWGARCGAGAARCGTAARRTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATRCTGTAARACACAACATATBCAGTCV",
39
+ "attP3": "VAAWWAWKRWTTTWWTTYGACTGATAGTGACCTGTWCGTYGMAACAVATTGATRAGCAATKMTTTYYTATAWTGHCMASTWTGTATAATAAAGYWGARCGAGAARCGTAARRTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATRCTGTAARACACAACATATBCAGTCV",
40
+ "attP4": "VAAWWAWKRWTTTWWTTYGACTGATAGTGACCTGTWCGTYGMAACAVATTGATRAGCAATKMTTTYYTATAWTGHCMASTWTGTATAGAAAAGYWGARCGAGAARCGTAARRTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATRCTGTAARACACAACATATBCAGTCV",
41
+ "attP5": "VAAWWAWKRWTTTWWTTYGACTGATAGTGACCTGTWCGTYGMAACAVATTGATRAGCAATKMTTTYYTATAWTGHCMASTWTGTATACAAAAGYWGARCGAGAARCGTAARRTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATRCTGTAARACACAACATATBCAGTCV",
42
+ }
140
43
 
141
- https://en.wikipedia.org/wiki/Cre-Lox_recombination
44
+ raw_gateway_sites_conservative = {
45
+ **raw_gateway_common,
46
+ "attP1": "AAAWWAWKRWTTTWWTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATGCTTTYTTATAATGCCMASTTTGTACAAAAAAGYWGAACGAGAARCGTAAARTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATACTGTAAAACACAACATATSCAGTCACTATGAAYCAACTACTTAGATGGTATTAGTGACCTGTA",
47
+ "attP2": "AAAWWAWKRWTTTWWTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATGCTTTYTTATAATGCCMASTTTGTACAAGAAAGYWGAACGAGAARCGTAAARTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATACTGTAAAACACAACATATSCAGTCACTATGAAYCAACTACTTAGATGGTATTAGTGACCTGTA",
48
+ "attP3": "AAAWWAWKRWTTTWWTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATGCTTTYTTATAATGCCMASTTTGTATAATAAAGYWGAACGAGAARCGTAAARTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATACTGTAAAACACAACATATSCAGTCACTATGAAYCAACTACTTAGATGGTATTAGTGACCTGTA",
49
+ "attP4": "AAAWWAWKRWTTTWWTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATGCTTTYTTATAATGCCMASTTTGTATAGAAAAGYWGAACGAGAARCGTAAARTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATACTGTAAAACACAACATATSCAGTCACTATGAAYCAACTACTTAGATGGTATTAGTGACCTGTA",
50
+ "attP5": "AAAWWAWKRWTTTWWTTTGACTGATAGTGACCTGTTCGTTGCAACAMATTGATRAGCAATGCTTTYTTATAATGCCMASTTTGTATACAAAAGYWGAACGAGAARCGTAAARTGATATAAATATCAATATATTAAATTAGAYTTTGCATAAAAAACAGACTACATAATACTGTAAAACACAACATATSCAGTCACTATGAAYCAACTACTTAGATGGTATTAGTGACCTGTA",
51
+ }
142
52
 
143
- 13bp 8bp 13bp
144
- ATAACTTCGTATA-NNNTANNN-TATACGAAGTTAT
53
+ gateway_sites_greedy = {
54
+ k: {
55
+ "forward_regex": compute_regex_site(v),
56
+ "reverse_regex": compute_regex_site(reverse_complement(v)),
57
+ "consensus_sequence": v,
58
+ }
59
+ for k, v in raw_gateway_sites_greedy.items()
60
+ }
145
61
 
62
+ gateway_sites_conservative = {
63
+ k: {
64
+ "forward_regex": compute_regex_site(v),
65
+ "reverse_regex": compute_regex_site(reverse_complement(v)),
66
+ "consensus_sequence": v,
67
+ }
68
+ for k, v in raw_gateway_sites_conservative.items()
69
+ }
146
70
 
147
- Name 13 bp 8 bp 13 bp
148
- Recognition Spacer Recognition
149
- Region Region Region
71
+ # From snapgene - ask Valerie
72
+ primer_design_attB = {
73
+ "attB1": "ACAAGTTTGTACAAAAAAGCAGGCT",
74
+ "attB2": "ACCACTTTGTACAAGAAAGCTGGGT",
75
+ "attB3": "ACAACTTTGTATAATAAAGTTGTA",
76
+ "attB4": "ACAACTTTGTATAGAAAAGTTGTA",
77
+ "attB5": "ACAACTTTGTATACAAAAGTTGTA",
78
+ }
150
79
 
151
- Wild-Type ATAACTTCGTATA ATGTATGC TATACGAAGTTAT
152
- lox511 ATAACTTCGTATA ATGTATaC TATACGAAGTTAT
153
- lox5171 ATAACTTCGTATA ATGTgTaC TATACGAAGTTAT
154
- lox2272 ATAACTTCGTATA AaGTATcC TATACGAAGTTAT
155
- M2 ATAACTTCGTATA AgaaAcca TATACGAAGTTAT
156
- M3 ATAACTTCGTATA taaTACCA TATACGAAGTTAT
157
- M7 ATAACTTCGTATA AgaTAGAA TATACGAAGTTAT
158
- M11 ATAACTTCGTATA cgaTAcca TATACGAAGTTAT
159
- lox71 TACCGTTCGTATA NNNTANNN TATACGAAGTTAT
160
- lox66 ATAACTTCGTATA NNNTANNN TATACGAACGGTA
161
80
 
162
- """
81
+ def gateway_overlap(
82
+ seqx: _Dseqrecord, seqy: _Dseqrecord, reaction: str, greedy: bool
83
+ ) -> list[tuple[int, int, int]]:
84
+ """
85
+ Find gateway overlaps. If greedy is True, it uses a more greedy consensus site to find attP sites,
86
+ which might give false positives
87
+ """
88
+ if reaction not in ["BP", "LR"]:
89
+ raise ValueError(f"Invalid overlap type: {reaction}")
90
+
91
+ gateway_sites = gateway_sites_greedy if greedy else gateway_sites_conservative
92
+ out = list()
93
+ # Iterate over the four possible att sites
94
+ for num in range(1, 5):
95
+ # Iterate over the two possible orientations
96
+ # The sites have to be in the same orientation (fwd + fwd or rev + rev)
97
+ for pattern in ["forward_regex", "reverse_regex"]:
98
+ # The overlap regex is the same for all types
99
+ overlap_regex = gateway_sites[f"overlap_{num}"][pattern]
100
+
101
+ # Iterate over pairs B, P and P, B for BP and L, R and R, L for LR
102
+ for site_x, site_y in zip(reaction, reaction[::-1]):
103
+ site_x_regex = gateway_sites[f"att{site_x}{num}"][pattern]
104
+ matches_x = list(dseqrecord_finditer(site_x_regex, seqx))
105
+ if len(matches_x) == 0:
106
+ continue
107
+
108
+ site_y_regex = gateway_sites[f"att{site_y}{num}"][pattern]
109
+ matches_y = list(dseqrecord_finditer(site_y_regex, seqy))
110
+ if len(matches_y) == 0:
111
+ continue
112
+
113
+ for match_x, match_y in _itertools.product(matches_x, matches_y):
114
+ # Find the overlap sequence within each match, and use the
115
+ # core 7 pbs that are constant
116
+ overlap_x = re.search(overlap_regex, match_x.group())
117
+ overlap_y = re.search(overlap_regex, match_y.group())
118
+
119
+ # Sanity check
120
+ assert (
121
+ overlap_x is not None and overlap_y is not None
122
+ ), "Something went wrong, no overlap found within the matches"
123
+
124
+ out.append(
125
+ (
126
+ match_x.start() + overlap_x.start() + 3,
127
+ match_y.start() + overlap_y.start() + 3,
128
+ 7,
129
+ )
130
+ )
131
+
132
+ return out
133
+
134
+
135
+ def find_gateway_sites(
136
+ seq: _Dseqrecord, greedy: bool
137
+ ) -> dict[str, list[SimpleLocation]]:
138
+ """Find all gateway sites in a sequence and return a dictionary with the name and positions of the sites."""
139
+ gateway_sites = gateway_sites_greedy if greedy else gateway_sites_conservative
140
+ out = dict()
141
+ for site in gateway_sites:
142
+ if not site.startswith("att"):
143
+ continue
144
+
145
+ for pattern in ["forward_regex", "reverse_regex"]:
146
+ matches = list(dseqrecord_finditer(gateway_sites[site][pattern], seq))
147
+ for match in matches:
148
+ if site not in out:
149
+ out[site] = []
150
+ strand = 1 if pattern == "forward_regex" else -1
151
+ loc = SimpleLocation(match.start(), match.end(), strand)
152
+ loc = shift_location(loc, 0, len(seq))
153
+ out[site].append(loc)
154
+ return out
155
+
156
+
157
+ def annotate_gateway_sites(seq: _Dseqrecord, greedy: bool) -> _Dseqrecord:
158
+ sites = find_gateway_sites(seq, greedy)
159
+ for site in sites:
160
+ for loc in sites[site]:
161
+ seq.features.append(
162
+ SeqFeature(loc, type="protein_bind", qualifiers={"label": [site]})
163
+ )
164
+ return seq
pydna/parsers.py CHANGED
@@ -208,3 +208,26 @@ def parse(data, ds=True):
208
208
  def parse_primers(data):
209
209
  """docstring."""
210
210
  return [_Primer(x) for x in parse(data, ds=False)]
211
+
212
+
213
+ def parse_snapgene(file_path: str) -> list[_Dseqrecord]:
214
+ """Parse a SnapGene file and return a Dseqrecord object.
215
+
216
+ Parameters
217
+ ----------
218
+ file_path : str
219
+ The path to the SnapGene file to parse.
220
+
221
+ Returns
222
+ -------
223
+ Dseqrecord
224
+ The parsed SnapGene file as a Dseqrecord object.
225
+
226
+ """
227
+ with open(file_path, "rb") as f:
228
+ parsed_seq = next(_SeqIO.parse(f, "snapgene"))
229
+ circular = (
230
+ "topology" in parsed_seq.annotations.keys()
231
+ and parsed_seq.annotations["topology"] == "circular"
232
+ )
233
+ return [_Dseqrecord(parsed_seq, circular=circular)]
pydna/seqrecord.py CHANGED
@@ -197,7 +197,7 @@ class SeqRecord(_SeqRecord):
197
197
  def translate(self):
198
198
  """docstring."""
199
199
  p = super().translate()
200
- return ProteinSeqRecord(_ProteinSeq(p.seq[:-1]))
200
+ return ProteinSeqRecord(_ProteinSeq(p.seq))
201
201
 
202
202
  def add_colors_to_features_for_ape(self):
203
203
  """Assign colors to features.
@@ -0,0 +1,44 @@
1
+ # -*- coding: utf-8 -*-
2
+ from pydna.dseqrecord import Dseqrecord as _Dseqrecord
3
+ import re
4
+ from Bio.Data.IUPACData import ambiguous_dna_values as _ambiguous_dna_values
5
+
6
+ ambiguous_only_dna_values = {**_ambiguous_dna_values}
7
+ for normal_base in "ACGT":
8
+ del ambiguous_only_dna_values[normal_base]
9
+
10
+
11
+ def compute_regex_site(site: str) -> str:
12
+ """
13
+ Creates a regex pattern from a string that may contain degenerate bases.
14
+
15
+ Args:
16
+ site: The string to convert to a regex pattern.
17
+
18
+ Returns:
19
+ The regex pattern.
20
+ """
21
+ upper_site = site.upper()
22
+ for k, v in ambiguous_only_dna_values.items():
23
+ if len(v) > 1:
24
+ upper_site = upper_site.replace(k, f"[{''.join(v)}]")
25
+
26
+ # Make case insensitive
27
+ upper_site = f"(?i){upper_site}"
28
+ return upper_site
29
+
30
+
31
+ def dseqrecord_finditer(pattern: str, seq: _Dseqrecord) -> list[re.Match]:
32
+ """
33
+ Finds all matches of a regex pattern in a Dseqrecord.
34
+
35
+ Args:
36
+ pattern: The regex pattern to search for.
37
+ seq: The Dseqrecord to search in.
38
+
39
+ Returns:
40
+ A list of matches.
41
+ """
42
+ query = str(seq.seq) if not seq.circular else str(seq.seq) * 2
43
+ matches = re.finditer(pattern, query)
44
+ return (m for m in matches if m.start() <= len(seq))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pydna
3
- Version: 5.5.2
3
+ Version: 5.5.3
4
4
  Summary: Representing double stranded DNA and functions for simulating cloning and homologous recombination between DNA molecules.
5
5
  License: BSD
6
6
  Author: Björn F. Johansson
@@ -49,9 +49,9 @@ Description-Content-Type: text/markdown
49
49
 
50
50
  # ![icon](https://github.com/pydna-group/pydna/blob/master/docs/_static/banner.png?raw=true)
51
51
 
52
- | [![Tests & Coverage](https://github.com/pydna-group/pydna/actions/workflows/pydna_test_and_coverage_workflow.yml/badge.svg?branch=dev_bjorn)](https://github.com/pydna-group/pydna/actions/workflows/pydna_test_and_coverage_workflow.yml) | [![codecov](https://codecov.io/gh/BjornFJohansson/pydna/branch/master/graph/badge.svg)](https://codecov.io/gh/BjornFJohansson/pydna/branch/master) | [![PyPI version](https://badge.fury.io/py/pydna.svg)](https://badge.fury.io/py/pydna) | [![Google group : pydna](https://img.shields.io/badge/Google%20Group-pydna-blue.svg)](https://groups.google.com/g/pydna) |
52
+ | [![Tests & Coverage](https://github.com/pydna-group/pydna/actions/workflows/pydna_test_and_coverage_workflow.yml/badge.svg?branch=master)](https://github.com/pydna-group/pydna/actions/workflows/pydna_test_and_coverage_workflow.yml) | [![codecov](https://codecov.io/gh/pydna-group/pydna/branch/master/graph/badge.svg)](https://codecov.io/gh/pydna-group/pydna/branch/master) | [![PyPI version](https://badge.fury.io/py/pydna.svg)](https://badge.fury.io/py/pydna) | [![Google group : pydna](https://img.shields.io/badge/Google%20Group-pydna-blue.svg)](https://groups.google.com/g/pydna) |
53
53
  | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
54
- | [![Documentation Status](https://github.com/pydna-group/pydna/actions/workflows/publish-docs.yml/badge.svg)](https://github.com/pydna-group/pydna/actions/workflows/publish-docs.yml) | [![GitHub issues](https://img.shields.io/github/issues/BjornFJohansson/pydna.svg)](https://github.com/pydna-group/pydna/issues) | [![GitHub stars](https://img.shields.io/github/stars/BjornFJohansson/pydna.svg)](https://github.com/pydna-group/pydna/stargazers) | |
54
+ | [![Documentation Status](https://github.com/pydna-group/pydna/actions/workflows/publish-docs.yml/badge.svg)](https://github.com/pydna-group/pydna/actions/workflows/publish-docs.yml) | [![GitHub issues](https://img.shields.io/github/issues/pydna-group/pydna.svg)](https://github.com/pydna-group/pydna/issues) | [![GitHub stars](https://img.shields.io/github/stars/pydna-group/pydna.svg)](https://github.com/pydna-group/pydna/stargazers) | |
55
55
 
56
56
  <!-- docs/index.rst-start -->
57
57
 
@@ -438,15 +438,11 @@ Feedback & suggestions are very welcome! Please create an issue with your questi
438
438
 
439
439
  If you don't have a github account, you can get in touch through the [google group](https://groups.google.com/d/forum/pydna) for pydna.
440
440
 
441
- Below are the instructions for developers who want to contribute to pydna. Please direct pull requests towards the `dev_bjorn` branch.
441
+ Below are the instructions for developers who want to contribute to pydna. Please direct pull requests towards the `master` branch.
442
442
 
443
443
  ### Fork the repository and set up a dev branch 🍴
444
444
 
445
- Fork the entire repository (not just the `master` branch by unticking the "Copy the `master` branch only" box)
446
-
447
- ![Fork](https://github.com/pydna-group/pydna/blob/master/docs/_static/create-fork.png?raw=true)
448
-
449
- Create your branch starting from `dev_bjorn`, and if your changes are related to an issue, call the branch `issue_<number>`.
445
+ Fork the repository. Create your branch starting from `master`, and if your changes are related to an issue, call the branch `issue_<number>`.
450
446
 
451
447
  ```bash
452
448
  # Clone the repository
@@ -455,12 +451,6 @@ git clone https://github.com/<your-username>/pydna.git
455
451
  # Change to the repository directory
456
452
  cd pydna
457
453
 
458
- # Go to the dev_bjorn branch
459
- git checkout -b dev_bjorn
460
-
461
- # Pull the current version of dev_bjorn
462
- git pull origin dev_bjorn
463
-
464
454
  # Create your own branch
465
455
  git checkout -b issue_<number>
466
456
  ```
@@ -540,7 +530,7 @@ pre-commit install
540
530
 
541
531
  ### Creating a PR 🔗
542
532
 
543
- * From your fork, make a PR towards the branch `dev_bjorn` in the original repository.
533
+ * From your fork, make a PR towards the branch `master` in the original repository.
544
534
  * Mention the issue number in the PR description (e.g., `Closes #123`).
545
535
  * Remember to click the "Allow edits from maintainers" checkbox so that we can make some changes to the PR if necessary.
546
536
 
@@ -596,7 +586,7 @@ Wang, Y., Xue, H., Pourcel, C., Du, Y., & Gautheret, D. (2021).
596
586
  In Cold Spring Harbor Laboratory (p. 2021.01.17.427048). [DOI](https://doi.org/10.1101/2021.01.17.427048)
597
587
  [PubMed](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8180056)
598
588
 
599
- [ShareYourCloning](https://shareyourcloning.org), a web application for designing and documenting DNA cloning strategies.
589
+ [OpenCloning](https://opencloning.org), a web application for designing and documenting DNA cloning strategies.
600
590
 
601
591
  [An Automated Protein Synthesis Pipeline with Transcriptic and Snakemake](http://blog.booleanbiotech.com/transcriptic_protein_synthesis_pipeline.html)
602
592
 
@@ -1,15 +1,16 @@
1
- pydna/__init__.py,sha256=a08F6v_bfQLzTDkNEbjeSa3hadO_cuKH0mIAkoG1AtU,12867
1
+ pydna/__init__.py,sha256=aHQGRBpQdABGgHMwN6CfDMKGvsOpCVSs2f5I5ir5DMw,12867
2
2
  pydna/_pretty.py,sha256=foRAxdL3Jiupuz7l38THBQZ7tu-5vQvLm1cKdDa7n6A,923
3
3
  pydna/_thermodynamic_data.py,sha256=9_w-97DpkbsWbJGHVijscMvUS_SFt7GxzrxspMRPZSg,10903
4
4
  pydna/all.py,sha256=xwkbR5Hn52xVfgLAXaEfIgtNwaBiGDbJFTQfa3Zi6HQ,1781
5
5
  pydna/amplicon.py,sha256=X4rCSanhlx1sPN0eAtcdAWg4Lw0WKrGQhv-cgZKtM3s,5343
6
6
  pydna/amplify.py,sha256=XRwmSMQ2d8Y379zcl56yU6rt1xWbSulWWHLqp-HRDc0,19260
7
7
  pydna/assembly.py,sha256=LM3-s3YysFvvkl1oooxoBjYLt0iMc3E1YLoqE05i8bs,19936
8
- pydna/assembly2.py,sha256=IN5tP5-FgdqLpIkAEKy9tXDG8x58iIgc6FUZSMr5kS0,73307
8
+ pydna/assembly2.py,sha256=gyn-R2Jz3D6Pze27iE3IZ6JLvnqg72my9r-J34ZjWqI,98202
9
9
  pydna/codon.py,sha256=Nxa_03n2wxXKACkzi55bUN1t5xUU_DBRRwh_ZLIb9_o,2568
10
10
  pydna/common_sub_strings.py,sha256=A-gJeA2cEyxKKGQSFoC0BKvcXUGJZcnTUU7x2xlAovc,11574
11
11
  pydna/conftest.py,sha256=T5-WmHWLZH3U3ifxnbxd_oOiIFibIrkYpwNacCHlvsY,999
12
12
  pydna/contig.py,sha256=m0XV0LO2AbArPZkjyNCf8c7_b1EkXFtYwXHJVG4eTY8,8168
13
+ pydna/cre_lox.py,sha256=sOj9R8_oFPGWs68vc4jf6LqWOXjMsVSwtJaeKl6ZF2M,4476
13
14
  pydna/crispr.py,sha256=iwu0Cjskzdb2r-In9633QIxQYKGmSNVOEM_dLK6lC54,3619
14
15
  pydna/design.py,sha256=BAoPb4M47yMkF1p4gGmbomZPFyTl0WuXkv8sLSY_Tg0,29067
15
16
  pydna/download.py,sha256=7tT8LAEy2Vg05spGfbCea_sol6pUOOBVbxOtyk2mnlQ,1085
@@ -17,7 +18,7 @@ pydna/dseq.py,sha256=2N_dXX36niJItQzN61PoVweee0xxP04_amJ3cSExAtU,54232
17
18
  pydna/dseqrecord.py,sha256=9OSuxLqcJse3aIVZCVeN7bZCyohGt7WEXnnv1qBIcB0,47983
18
19
  pydna/fakeseq.py,sha256=uxyu1PXF-sVasEqhmyhMcsbpTy84uUtubDiZuxHNb9c,1174
19
20
  pydna/fusionpcr.py,sha256=tfIfGGkNoZjg_dodcEx9wTc12aLRnC7J3g-Vg3Jg1uA,2821
20
- pydna/gateway.py,sha256=9OL6o9J_FQoQ5VExmHMIPDtDiJs3_4-whcS755BPCG0,8451
21
+ pydna/gateway.py,sha256=iwNHrDIOqKl6_3Rdz7z7c8n_kcLQZuuu72oxNIjyyL8,8686
21
22
  pydna/gel.py,sha256=QE1uhnjWXLl2nXgbLs_1TWbPixgUa0-z_UR8jZaByS4,3371
22
23
  pydna/genbank.py,sha256=rH677VRklVKBpPoFRsl7Az8fZvrC8TD2lNrNoHO1wU8,8856
23
24
  pydna/genbankfile.py,sha256=ii0_RjNGnsfUThTN01c5PRLSZkQT3WlYDvoC6R6ozAA,1451
@@ -26,18 +27,19 @@ pydna/genbankrecord.py,sha256=u9RNBifT0j8rrA2bSdWajodtwm42P52_VlXsxKeOvq0,5566
26
27
  pydna/goldengate.py,sha256=LvUWAzhG9OhN1wil7osJIkjfqwBLh355a18wCZO1TvI,1778
27
28
  pydna/ladders.py,sha256=fKfWwezxQpX4qon9YCMIwchMBkGVOu8-C02xXk90J-E,3310
28
29
  pydna/ligate.py,sha256=ap8xgS4aL9cH4w38e-kpw1Ixa7DtpYF_ipezrVXiHG0,1965
29
- pydna/parsers.py,sha256=RFYBCKrlqWzZbRWhg5lQE3pp31KjUNAarpAgHJuUpaU,6690
30
+ pydna/parsers.py,sha256=FW2RhZrxWX9wUYJcmt0qi1n7DZP0RfsNaXHhG0eVTWg,7319
30
31
  pydna/primer.py,sha256=k9Z_fHfBcY_rGnOtfys806rQBDtvyKwKl2ceSx3_w9A,2272
31
32
  pydna/readers.py,sha256=tKoonGlIB9ACeOMnzjhbCya1ooqhFMQIO_G36azN81E,1575
32
33
  pydna/seq.py,sha256=82gR1g2D8jfPy1So1pSJvlXYk4zkcKx_qmgvcydxth4,7579
33
- pydna/seqrecord.py,sha256=rzUUecmf9RkQdYHL0b9Pu8ofXM3Q6KThm-wv43jH0SA,23368
34
+ pydna/seqrecord.py,sha256=haLp1316KQkROkQ0HkJp-RfgWN-eDyLPzTGFLjgXwHk,23363
34
35
  pydna/sequence_picker.py,sha256=Pco9IrUwNSiS0wQ5hp5FMfE9kIN9XOwXasKLF9OA6DM,1402
36
+ pydna/sequence_regex.py,sha256=DYuAJkWm_GqEGMpd0pE-Mad_B6POUP8gwjSCFR8RfXw,1259
35
37
  pydna/threading_timer_decorator_exit.py,sha256=D91kqjKSavWDnXyc1Fo-CwPYtbmR2DjTXnBYSRXKmSA,2793
36
38
  pydna/tm.py,sha256=0r4Aqjt_qanfqR8GNvqNh8us7AKM6JvaQKqHYsswAz4,11143
37
39
  pydna/types.py,sha256=OE7iwA3b7f_T6EoBnYbRl9CFrY6OrSkAfuyY-R5kins,1389
38
40
  pydna/user_cloning.py,sha256=VSpYX1tdbcD_PzEt69Jz6Lud-yAkYMVXnzVd4v2usnE,692
39
41
  pydna/utils.py,sha256=BwBOcr2HyLAPAVdpXEEDiwJ5MeWW096EOekvfyXxbDM,25227
40
- pydna-5.5.2.dist-info/LICENSE.txt,sha256=u8QfcsnNXZM0UCexerK_MvyA2lPWgeGyUtSYXvLG6Oc,6119
41
- pydna-5.5.2.dist-info/METADATA,sha256=TsRUcktnk2S-D4iZncIM54BSgQJ3XYv8EyTRfAAOgJI,25439
42
- pydna-5.5.2.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
43
- pydna-5.5.2.dist-info/RECORD,,
42
+ pydna-5.5.3.dist-info/LICENSE.txt,sha256=u8QfcsnNXZM0UCexerK_MvyA2lPWgeGyUtSYXvLG6Oc,6119
43
+ pydna-5.5.3.dist-info/METADATA,sha256=Orph3mLdDMwKy21DsEucxGYPyLHX9p9FimxYMiaidYU,25090
44
+ pydna-5.5.3.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
45
+ pydna-5.5.3.dist-info/RECORD,,