Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/boto/sdb/db/sequence.py @ 0:26e78fe6e8c4 draft
"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
| author | shellac |
|---|---|
| date | Sat, 02 May 2020 07:14:21 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:26e78fe6e8c4 |
|---|---|
| 1 # Copyright (c) 2010 Chris Moyer http://coredumped.org/ | |
| 2 # | |
| 3 # Permission is hereby granted, free of charge, to any person obtaining a | |
| 4 # copy of this software and associated documentation files (the | |
| 5 # "Software"), to deal in the Software without restriction, including | |
| 6 # without limitation the rights to use, copy, modify, merge, publish, dis- | |
| 7 # tribute, sublicense, and/or sell copies of the Software, and to permit | |
| 8 # persons to whom the Software is furnished to do so, subject to the fol- | |
| 9 # lowing conditions: | |
| 10 # | |
| 11 # The above copyright notice and this permission notice shall be included | |
| 12 # in all copies or substantial portions of the Software. | |
| 13 # | |
| 14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |
| 15 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- | |
| 16 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT | |
| 17 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| 18 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| 19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |
| 20 # IN THE SOFTWARE. | |
| 21 | |
| 22 from boto.exception import SDBResponseError | |
| 23 from boto.compat import six | |
| 24 | |
| 25 class SequenceGenerator(object): | |
| 26 """Generic Sequence Generator object, this takes a single | |
| 27 string as the "sequence" and uses that to figure out | |
| 28 what the next value in a string is. For example | |
| 29 if you give "ABC" and pass in "A" it will give you "B", | |
| 30 and if you give it "C" it will give you "AA". | |
| 31 | |
| 32 If you set "rollover" to True in the above example, passing | |
| 33 in "C" would give you "A" again. | |
| 34 | |
| 35 The Sequence string can be a string or any iterable | |
| 36 that has the "index" function and is indexable. | |
| 37 """ | |
| 38 __name__ = "SequenceGenerator" | |
| 39 | |
| 40 def __init__(self, sequence_string, rollover=False): | |
| 41 """Create a new SequenceGenerator using the sequence_string | |
| 42 as how to generate the next item. | |
| 43 | |
| 44 :param sequence_string: The string or list that explains | |
| 45 how to generate the next item in the sequence | |
| 46 :type sequence_string: str,iterable | |
| 47 | |
| 48 :param rollover: Rollover instead of incrementing when | |
| 49 we hit the end of the sequence | |
| 50 :type rollover: bool | |
| 51 """ | |
| 52 self.sequence_string = sequence_string | |
| 53 self.sequence_length = len(sequence_string[0]) | |
| 54 self.rollover = rollover | |
| 55 self.last_item = sequence_string[-1] | |
| 56 self.__name__ = "%s('%s')" % (self.__class__.__name__, sequence_string) | |
| 57 | |
| 58 def __call__(self, val, last=None): | |
| 59 """Get the next value in the sequence""" | |
| 60 # If they pass us in a string that's not at least | |
| 61 # the lenght of our sequence, then return the | |
| 62 # first element in our sequence | |
| 63 if val is None or len(val) < self.sequence_length: | |
| 64 return self.sequence_string[0] | |
| 65 last_value = val[-self.sequence_length:] | |
| 66 if (not self.rollover) and (last_value == self.last_item): | |
| 67 val = "%s%s" % (self(val[:-self.sequence_length]), self._inc(last_value)) | |
| 68 else: | |
| 69 val = "%s%s" % (val[:-self.sequence_length], self._inc(last_value)) | |
| 70 return val | |
| 71 | |
| 72 def _inc(self, val): | |
| 73 """Increment a single value""" | |
| 74 assert(len(val) == self.sequence_length) | |
| 75 return self.sequence_string[(self.sequence_string.index(val) + 1) % len(self.sequence_string)] | |
| 76 | |
| 77 | |
| 78 # | |
| 79 # Simple Sequence Functions | |
| 80 # | |
| 81 def increment_by_one(cv=None, lv=None): | |
| 82 if cv is None: | |
| 83 return 0 | |
| 84 return cv + 1 | |
| 85 | |
| 86 def double(cv=None, lv=None): | |
| 87 if cv is None: | |
| 88 return 1 | |
| 89 return cv * 2 | |
| 90 | |
| 91 def fib(cv=1, lv=0): | |
| 92 """The fibonacci sequence, this incrementer uses the | |
| 93 last value""" | |
| 94 if cv is None: | |
| 95 cv = 1 | |
| 96 if lv is None: | |
| 97 lv = 0 | |
| 98 return cv + lv | |
| 99 | |
| 100 increment_string = SequenceGenerator("ABCDEFGHIJKLMNOPQRSTUVWXYZ") | |
| 101 | |
| 102 | |
| 103 class Sequence(object): | |
| 104 """A simple Sequence using the new SDB "Consistent" features | |
| 105 Based largly off of the "Counter" example from mitch garnaat: | |
| 106 http://bitbucket.org/mitch/stupidbototricks/src/tip/counter.py""" | |
| 107 | |
| 108 def __init__(self, id=None, domain_name=None, fnc=increment_by_one, init_val=None): | |
| 109 """Create a new Sequence, using an optional function to | |
| 110 increment to the next number, by default we just increment by one. | |
| 111 Every parameter here is optional, if you don't specify any options | |
| 112 then you'll get a new SequenceGenerator with a random ID stored in the | |
| 113 default domain that increments by one and uses the default botoweb | |
| 114 environment | |
| 115 | |
| 116 :param id: Optional ID (name) for this counter | |
| 117 :type id: str | |
| 118 | |
| 119 :param domain_name: Optional domain name to use, by default we get this out of the | |
| 120 environment configuration | |
| 121 :type domain_name:str | |
| 122 | |
| 123 :param fnc: Optional function to use for the incrementation, by default we just increment by one | |
| 124 There are several functions defined in this module. | |
| 125 Your function must accept "None" to get the initial value | |
| 126 :type fnc: function, str | |
| 127 | |
| 128 :param init_val: Initial value, by default this is the first element in your sequence, | |
| 129 but you can pass in any value, even a string if you pass in a function that uses | |
| 130 strings instead of ints to increment | |
| 131 """ | |
| 132 self._db = None | |
| 133 self._value = None | |
| 134 self.last_value = None | |
| 135 self.domain_name = domain_name | |
| 136 self.id = id | |
| 137 if init_val is None: | |
| 138 init_val = fnc(init_val) | |
| 139 | |
| 140 if self.id is None: | |
| 141 import uuid | |
| 142 self.id = str(uuid.uuid4()) | |
| 143 | |
| 144 self.item_type = type(fnc(None)) | |
| 145 self.timestamp = None | |
| 146 # Allow us to pass in a full name to a function | |
| 147 if isinstance(fnc, six.string_types): | |
| 148 from boto.utils import find_class | |
| 149 fnc = find_class(fnc) | |
| 150 self.fnc = fnc | |
| 151 | |
| 152 # Bootstrap the value last | |
| 153 if not self.val: | |
| 154 self.val = init_val | |
| 155 | |
| 156 def set(self, val): | |
| 157 """Set the value""" | |
| 158 import time | |
| 159 now = time.time() | |
| 160 expected_value = [] | |
| 161 new_val = {} | |
| 162 new_val['timestamp'] = now | |
| 163 if self._value is not None: | |
| 164 new_val['last_value'] = self._value | |
| 165 expected_value = ['current_value', str(self._value)] | |
| 166 new_val['current_value'] = val | |
| 167 try: | |
| 168 self.db.put_attributes(self.id, new_val, expected_value=expected_value) | |
| 169 self.timestamp = new_val['timestamp'] | |
| 170 except SDBResponseError as e: | |
| 171 if e.status == 409: | |
| 172 raise ValueError("Sequence out of sync") | |
| 173 else: | |
| 174 raise | |
| 175 | |
| 176 | |
| 177 def get(self): | |
| 178 """Get the value""" | |
| 179 val = self.db.get_attributes(self.id, consistent_read=True) | |
| 180 if val: | |
| 181 if 'timestamp' in val: | |
| 182 self.timestamp = val['timestamp'] | |
| 183 if 'current_value' in val: | |
| 184 self._value = self.item_type(val['current_value']) | |
| 185 if "last_value" in val and val['last_value'] is not None: | |
| 186 self.last_value = self.item_type(val['last_value']) | |
| 187 return self._value | |
| 188 | |
| 189 val = property(get, set) | |
| 190 | |
| 191 def __repr__(self): | |
| 192 return "%s('%s', '%s', '%s.%s', '%s')" % ( | |
| 193 self.__class__.__name__, | |
| 194 self.id, | |
| 195 self.domain_name, | |
| 196 self.fnc.__module__, self.fnc.__name__, | |
| 197 self.val) | |
| 198 | |
| 199 | |
| 200 def _connect(self): | |
| 201 """Connect to our domain""" | |
| 202 if not self._db: | |
| 203 import boto | |
| 204 sdb = boto.connect_sdb() | |
| 205 if not self.domain_name: | |
| 206 self.domain_name = boto.config.get("DB", "sequence_db", boto.config.get("DB", "db_name", "default")) | |
| 207 try: | |
| 208 self._db = sdb.get_domain(self.domain_name) | |
| 209 except SDBResponseError as e: | |
| 210 if e.status == 400: | |
| 211 self._db = sdb.create_domain(self.domain_name) | |
| 212 else: | |
| 213 raise | |
| 214 return self._db | |
| 215 | |
| 216 db = property(_connect) | |
| 217 | |
| 218 def next(self): | |
| 219 self.val = self.fnc(self.val, self.last_value) | |
| 220 return self.val | |
| 221 | |
| 222 def delete(self): | |
| 223 """Remove this sequence""" | |
| 224 self.db.delete_attributes(self.id) |
