Package gensaschema :: Module _symbols
[frames] | no frames]

Source Code for Module gensaschema._symbols

  1  # -*- coding: ascii -*- 
  2  r""" 
  3  =================== 
  4   Symbol management 
  5  =================== 
  6   
  7  Symbol management. 
  8   
  9  :Copyright: 
 10   
 11   Copyright 2010 - 2016 
 12   Andr\xe9 Malo or his licensors, as applicable 
 13   
 14  :License: 
 15   
 16   Licensed under the Apache License, Version 2.0 (the "License"); 
 17   you may not use this file except in compliance with the License. 
 18   You may obtain a copy of the License at 
 19   
 20       http://www.apache.org/licenses/LICENSE-2.0 
 21   
 22   Unless required by applicable law or agreed to in writing, software 
 23   distributed under the License is distributed on an "AS IS" BASIS, 
 24   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 25   See the License for the specific language governing permissions and 
 26   limitations under the License. 
 27   
 28  """ 
 29  if __doc__: 
 30      # pylint: disable = redefined-builtin 
 31      __doc__ = __doc__.encode('ascii').decode('unicode_escape') 
 32  __author__ = r"Andr\xe9 Malo".encode('ascii').decode('unicode_escape') 
 33  __docformat__ = "restructuredtext en" 
 34   
 35  import keyword as _keyword 
 36  import operator as _op 
 37  import weakref as _weakref 
 38   
 39  from . import _util 
 40   
 41   
42 -class SymbolException(Exception):
43 """ Symbol error """
44 45
46 -class Symbols(object):
47 """ 48 Symbol table 49 50 :IVariables: 51 `_symbols` : ``dict`` 52 Symbols 53 54 `imports` : `Imports` 55 Import container 56 57 `types` : `Types` 58 Type container 59 """ 60
61 - def __init__(self, symbols=None, imports=None):
62 """ 63 Initialization 64 65 :Parameters: 66 `symbols` : ``dict`` 67 Initial symbols 68 """ 69 self._symbols = {} 70 defaults = dict( 71 sa="_sa", # SQLAlchemy shortname 72 meta="m", # MetaData shortname 73 table="T", # Table shortname 74 type="t", # Type module shortname 75 column="C", # Column shortname 76 default="D", # DefaultClause shortname 77 pk="PrimaryKey", # PrimaryKey function name 78 fk="ForeignKey", # ForeignKey function name 79 uk="Unique", # UniqueKey function name 80 constraints=( # constraint function module 81 __name__.rsplit('.', 1)[0] + '.constraints' 82 ), 83 ) 84 self.imports = _Imports(imports=imports) 85 self.types = _Types(_weakref.proxy(self)) 86 if symbols is not None: 87 symbols = dict(symbols) 88 for key, value in defaults.items(): 89 symbols.setdefault(key, value) 90 for name, symbol in dict(symbols).items(): 91 self[name] = symbol
92
93 - def __delitem__(self, name):
94 """ Remove symbol entry if available """ 95 try: 96 del self._symbols[name] 97 except KeyError: 98 pass
99
100 - def __setitem__(self, name, symbol):
101 """ 102 Set symbol table entry 103 104 :Parameters: 105 `name` : ``str`` 106 Symbol identifier 107 108 `symbol` : ``str`` 109 Symbol 110 111 :Exceptions: 112 - `SymbolException` : Symbol could not be set because of some 113 conflict 114 """ 115 if _util.py2 and not isinstance(name, unicode): 116 name = str(name).decode('ascii') 117 if _keyword.iskeyword(symbol): 118 raise SymbolException( 119 "Cannot use keyword %r as symbol" % (symbol,) 120 ) 121 elif symbol in list(self._symbols.values()): 122 raise SymbolException("Symbol conflict: %r" % (symbol,)) 123 elif name in self._symbols and self._symbols[name] != symbol: 124 raise SymbolException("Symbol identifier conflict: %r" % (name,)) 125 self._symbols[name] = symbol
126
127 - def __getitem__(self, name):
128 """ 129 Get symbol table entry 130 131 :Parameters: 132 `name` : ``str`` 133 Symbol identifier 134 135 :Return: The symbol 136 :Rtype: ``str`` 137 138 :Exceptions: 139 - `KeyError` : Symbol not found 140 """ 141 if _util.py2 and not isinstance(name, unicode): 142 name = str(name).decode('ascii') 143 return self._symbols[name]
144
145 - def __iter__(self):
146 """ 147 Make item iterator 148 149 :Return: The iterator 150 :Rtype: iterable 151 """ 152 return iter(list(self._symbols.items()))
153 154
155 -class _Types(object):
156 """ 157 Type container 158 159 :IVariables: 160 `_types` : ``dict`` 161 Type map 162 163 `_symbols` : `Symbols` 164 Symbol table 165 """ 166
167 - def __init__(self, symbols):
168 """ 169 Initialization 170 171 :Parameters: 172 `symbols` : `Symbols` 173 Symbol table 174 """ 175 self._types = {} 176 self._symbols = symbols
177
178 - def __setitem__(self, class_, symbol):
179 """ 180 Set type 181 182 :Parameters: 183 `class_` : ``type`` 184 Type to match 185 186 `symbol` : ``str`` 187 Type module symbol 188 189 :Exceptions: 190 - `SymbolException` : Type conflict 191 """ 192 if class_ in self._types: 193 if self._types[class_] != symbol: 194 raise SymbolException("Type conflict: %r" % (symbol,)) 195 else: 196 self._types[class_] = symbol
197
198 - def resolve(self, type_, dialect):
199 """ 200 Resolve type to module symbol 201 202 :Parameters: 203 `type_` : ``object`` 204 Type to resolve 205 206 `dialect` : ``str`` 207 Dialect name 208 209 :Return: Resolved symbol 210 :Rtype: ``str`` 211 212 :Exceptions: 213 - `SymbolException` : Type could not be resolved 214 """ 215 if type_.__class__ in self._types: 216 return self._symbols[self._types[type_.__class__]] 217 for class_, symbol in self._types.items(): 218 if isinstance(type_, class_): 219 return self._symbols[symbol] 220 221 mod = type_.__module__ 222 if mod.startswith('sqlalchemy.'): 223 mod = '.'.join(mod.split('.')[:3]) 224 if mod == 'sqlalchemy.dialects.%s' % dialect: 225 return self._symbols['type'] 226 else: 227 try: 228 _load_dotted('sqlalchemy.dialects.%s.%s' % ( 229 dialect, type_.__class__.__name__ 230 )) 231 return self._symbols['type'] 232 except ImportError: 233 pass 234 raise SymbolException( 235 "Don't know how to address type %r" % (type_,) 236 )
237 238
239 -class _Imports(object):
240 """ 241 Import table 242 243 :IVariables: 244 `_imports` : ``list`` 245 Import list 246 """ 247
248 - def __init__(self, imports=None):
249 """ Initialization """ 250 self._imports = list(imports or ())
251
252 - def __contains__(self, name):
253 """ Check if name is in imports """ 254 for key, _ in self._imports: 255 if key == name: 256 return True 257 return False
258
259 - def __setitem__(self, name, import_):
260 """ 261 Set import 262 263 :Parameters: 264 `name` : ``str`` 265 Symbolic name (to support import uniqueness) 266 267 `import_` : ``str`` 268 Import statement 269 270 :Exceptions: 271 - `SymbolException` : Import conflict 272 """ 273 if _util.py2 and not isinstance(name, unicode): 274 name = str(name).decode('ascii') 275 imports = dict(self._imports) 276 if name in imports: 277 if imports[name] != import_: 278 raise SymbolException("Import conflict: %r: %r vs. %r" % ( 279 name, imports[name], import_ 280 )) 281 else: 282 self._imports.append((name, import_))
283
284 - def __iter__(self):
285 """ 286 Make iterator over the import statements 287 288 :Return: The iterator 289 :Rtype: iterable 290 """ 291 return iter(map(_op.itemgetter(1), self._imports))
292 293
294 -def _load_dotted(name):
295 """ 296 Load a dotted name 297 298 (Stolen from wtf-server) 299 300 The dotted name can be anything, which is passively resolvable 301 (i.e. without the invocation of a class to get their attributes or 302 the like). 303 304 :Parameters: 305 `name` : ``str`` 306 The dotted name to load 307 308 :Return: The loaded object 309 :Rtype: any 310 311 :Exceptions: 312 - `ImportError` : A module in the path could not be loaded 313 """ 314 components = name.split('.') 315 path = [components.pop(0)] 316 obj = __import__(path[0]) 317 while components: 318 comp = components.pop(0) 319 path.append(comp) 320 try: 321 obj = getattr(obj, comp) 322 except AttributeError: 323 __import__('.'.join(path)) 324 try: 325 obj = getattr(obj, comp) 326 except AttributeError: 327 raise ImportError('.'.join(path)) 328 return obj
329