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__:  # pragma: no branch 
 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 None: 87 symbols = {} 88 else: 89 symbols = dict(symbols) 90 for key, value in defaults.items(): 91 symbols.setdefault(key, value) 92 for name, symbol in dict(symbols).items(): 93 self[name] = symbol
94
95 - def __delitem__(self, name):
96 """ Remove symbol entry if available """ 97 try: 98 del self._symbols[name] 99 except KeyError: 100 pass
101
102 - def __setitem__(self, name, symbol):
103 """ 104 Set symbol table entry 105 106 :Parameters: 107 `name` : ``str`` 108 Symbol identifier 109 110 `symbol` : ``str`` 111 Symbol 112 113 :Exceptions: 114 - `SymbolException` : Symbol could not be set because of some 115 conflict 116 """ 117 if _util.py2 and not isinstance(name, unicode): # pragma: no cover 118 name = str(name).decode('ascii') 119 if _keyword.iskeyword(symbol): 120 raise SymbolException( 121 "Cannot use keyword %r as symbol" % (symbol,) 122 ) 123 elif symbol in list(self._symbols.values()): 124 raise SymbolException("Symbol conflict: %r" % (symbol,)) 125 elif name in self._symbols and self._symbols[name] != symbol: 126 raise SymbolException("Symbol identifier conflict: %r" % (name,)) 127 self._symbols[name] = symbol
128
129 - def __getitem__(self, name):
130 """ 131 Get symbol table entry 132 133 :Parameters: 134 `name` : ``str`` 135 Symbol identifier 136 137 :Return: The symbol 138 :Rtype: ``str`` 139 140 :Exceptions: 141 - `KeyError` : Symbol not found 142 """ 143 if _util.py2 and not isinstance(name, unicode): 144 name = str(name).decode('ascii') 145 return self._symbols[name]
146
147 - def __iter__(self):
148 """ 149 Make item iterator 150 151 :Return: The iterator 152 :Rtype: iterable 153 """ 154 return iter(list(self._symbols.items()))
155 156
157 -class _Types(object):
158 """ 159 Type container 160 161 :IVariables: 162 `_types` : ``dict`` 163 Type map 164 165 `_symbols` : `Symbols` 166 Symbol table 167 """ 168
169 - def __init__(self, symbols):
170 """ 171 Initialization 172 173 :Parameters: 174 `symbols` : `Symbols` 175 Symbol table 176 """ 177 self._types = {} 178 self._symbols = symbols
179
180 - def __setitem__(self, class_, symbol):
181 """ 182 Set type 183 184 :Parameters: 185 `class_` : ``type`` 186 Type to match 187 188 `symbol` : ``str`` 189 Type module symbol 190 191 :Exceptions: 192 - `SymbolException` : Type conflict 193 """ 194 if class_ in self._types: 195 if self._types[class_] != symbol: 196 raise SymbolException("Type conflict: %r" % (symbol,)) 197 else: 198 self._types[class_] = symbol
199
200 - def resolve(self, type_, dialect):
201 """ 202 Resolve type to module symbol 203 204 :Parameters: 205 `type_` : ``object`` 206 Type to resolve 207 208 `dialect` : ``str`` 209 Dialect name 210 211 :Return: Resolved symbol 212 :Rtype: ``str`` 213 214 :Exceptions: 215 - `SymbolException` : Type could not be resolved 216 """ 217 if type_.__class__ in self._types: 218 return self._symbols[self._types[type_.__class__]] 219 for class_, symbol in self._types.items(): 220 if isinstance(type_, class_): 221 return self._symbols[symbol] 222 223 mod = type_.__module__ 224 if mod.startswith('sqlalchemy.'): 225 mod = '.'.join(mod.split('.')[:3]) 226 if mod == 'sqlalchemy.dialects.%s' % dialect: 227 return self._symbols['type'] 228 else: 229 try: 230 _load_dotted('sqlalchemy.dialects.%s.%s' % ( 231 dialect, type_.__class__.__name__ 232 )) 233 return self._symbols['type'] 234 except ImportError: 235 pass 236 raise SymbolException( 237 "Don't know how to address type %r" % (type_,) 238 )
239 240
241 -class _Imports(object):
242 """ 243 Import table 244 245 :IVariables: 246 `_imports` : ``list`` 247 Import list 248 """ 249
250 - def __init__(self, imports=None):
251 """ Initialization """ 252 self._imports = list(imports or ())
253
254 - def __contains__(self, name):
255 """ Check if name is in imports """ 256 for key, _ in self._imports: 257 if key == name: 258 return True 259 return False
260
261 - def __setitem__(self, name, import_):
262 """ 263 Set import 264 265 :Parameters: 266 `name` : ``str`` 267 Symbolic name (to support import uniqueness) 268 269 `import_` : ``str`` 270 Import statement 271 272 :Exceptions: 273 - `SymbolException` : Import conflict 274 """ 275 if _util.py2 and not isinstance(name, unicode): # pragma: no cover 276 name = str(name).decode('ascii') 277 imports = dict(self._imports) 278 if name in imports: 279 if imports[name] != import_: 280 raise SymbolException("Import conflict: %r: %r vs. %r" % ( 281 name, imports[name], import_ 282 )) 283 else: 284 self._imports.append((name, import_))
285
286 - def __iter__(self):
287 """ 288 Make iterator over the import statements 289 290 :Return: The iterator 291 :Rtype: iterable 292 """ 293 return iter(map(_op.itemgetter(1), self._imports))
294 295
296 -def _load_dotted(name):
297 """ 298 Load a dotted name 299 300 (Stolen from wtf-server) 301 302 The dotted name can be anything, which is passively resolvable 303 (i.e. without the invocation of a class to get their attributes or 304 the like). 305 306 :Parameters: 307 `name` : ``str`` 308 The dotted name to load 309 310 :Return: The loaded object 311 :Rtype: any 312 313 :Exceptions: 314 - `ImportError` : A module in the path could not be loaded 315 """ 316 components = name.split('.') 317 path = [components.pop(0)] 318 obj = __import__(path[0]) 319 while components: 320 comp = components.pop(0) 321 path.append(comp) 322 try: 323 obj = getattr(obj, comp) 324 except AttributeError: 325 __import__('.'.join(path)) 326 try: 327 obj = getattr(obj, comp) 328 except AttributeError: 329 raise ImportError('.'.join(path)) 330 return obj
331