PageRenderTime 43ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/sqlautocode/util.py

https://code.google.com/p/sqlautocode/
Python | 188 lines | 164 code | 12 blank | 12 comment | 15 complexity | 1beb03d4e7b31f056f2482a51fa629ff MD5 | raw file
  1. import fnmatch, os, re, sys
  2. import config
  3. _defaultencoding = sys.getdefaultencoding()
  4. _python_identifier_re = re.compile(r'^[a-z_][a-z0-9_]*$', re.I)
  5. def emit(*lines):
  6. """Emit one or more output strings."""
  7. for line in lines:
  8. if not line:
  9. config.out.write(os.linesep)
  10. else:
  11. if isinstance(line, unicode):
  12. encoding = 'utf-8'
  13. if getattr(config, 'options', None):
  14. encoding = config.options.encoding
  15. line = line.encode(encoding)
  16. config.out.write(line)
  17. if line[-1] != '\n':
  18. config.out.write(os.linesep)
  19. def is_python_identifier(string):
  20. """True if string is a valid Python identifier."""
  21. # unicode-ok.
  22. return _python_identifier_re.match(string)
  23. def as_out_str(obj):
  24. """Like str(), but convert unicode to configured encoding."""
  25. if isinstance(obj, unicode):
  26. encoding = 'utf-8'
  27. if getattr(config, 'options', None):
  28. encoding = config.options.encoding
  29. return obj.encode(encoding)
  30. elif not isinstance(obj, str):
  31. return str(obj)
  32. else:
  33. return obj
  34. def as_sys_str(obj, escape='backslashreplace'):
  35. """Like str(), but safely convert unicode to the system encoding."""
  36. if isinstance(obj, unicode):
  37. return obj.encode(_defaultencoding, escape)
  38. elif not isinstance(obj, str):
  39. return str(obj)
  40. else:
  41. return obj
  42. def unique(iterable):
  43. seen = set()
  44. for item in iterable:
  45. if item not in seen:
  46. seen.add(item)
  47. yield item
  48. def glob_intersection(collection, subset):
  49. """Return elements of subset in collection, with glob support.
  50. collection
  51. A collection of strings, need not be a set.
  52. subset
  53. Any iterable of strings.
  54. Items in the subset may be plain strings, "quoted strings" or
  55. strings with*glob? characters. Quoted strings are not globbed.
  56. """
  57. found, missing, unmatched = [], [], []
  58. for identifier in unique(subset):
  59. if identifier[0] == '"':
  60. name = identifier[1:-1]
  61. if name in collection:
  62. found.append(name)
  63. else:
  64. missing.append(name)
  65. elif '*' not in identifier:
  66. if identifier in collection:
  67. found.append(identifier)
  68. else:
  69. missing.append(identifier)
  70. else:
  71. globbed = fnmatch.filter(collection, identifier)
  72. if globbed:
  73. found.extend(globbed)
  74. else:
  75. unmatched.append(identifier)
  76. # ordered sets sure would be nice.
  77. return list(unique(found)), missing, unmatched
  78. # lifted from http://www.daniweb.com/forums/thread70647.html
  79. # (pattern, search, replace) regex english plural rules tuple
  80. plural_rule_tuple = (
  81. ('[ml]ouse$', '([ml])ouse$', '\\1ice'),
  82. ('child$', 'child$', 'children'),
  83. ('booth$', 'booth$', 'booths'),
  84. ('foot$', 'foot$', 'feet'),
  85. ('ooth$', 'ooth$', 'eeth'),
  86. ('l[eo]af$', 'l([eo])af$', 'l\\1aves'),
  87. ('sis$', 'sis$', 'ses'),
  88. ('man$', 'man$', 'men'),
  89. ('ife$', 'ife$', 'ives'),
  90. ('eau$', 'eau$', 'eaux'),
  91. ('lf$', 'lf$', 'lves'),
  92. ('[xz]$', '$', 'es'),
  93. ('[s]$', '$', ''),
  94. ('[^aeioudgkprt]h$', '$', 'es'),
  95. ('(qu|[^aeiou])y$', 'y$', 'ies'),
  96. ('$', '$', 's')
  97. )
  98. singular_rule_tuple = (
  99. ('[ml]ouse$', '([ml])ouse$', '\\1ice'),
  100. ('children$', 'children$', 'child'),
  101. ('feet$', 'fee$', 'foot'),
  102. ('eeth$', 'eeth$', 'ooth'),
  103. ('l[eo]aves', 'l([eo])af$', 'l\\1af$'),
  104. ('ses$', 'ses$', 's'),
  105. ('men$', 'men$', 'man'),
  106. ('ives$', 'ives$', 'ife'),
  107. ('eaux$', 'eaux$', 'eau'),
  108. ('lves$', 'lves$', 'lf'),
  109. #('[xz]$', '$', 'es'), not sure how to unplural this one
  110. #('[s]$', '$', ''),
  111. ('pies$' , 'pies$', 'pie'),
  112. ('ovies$' , 'ovies$', 'ovie'),
  113. ('ies$' , 'ies$', 'y'),
  114. ('xes$' , 'xes$', 'x'),
  115. #('(qu|[^aeiou])y$', 'y$', 'ies'),
  116. ('s$', 's$', '')
  117. )
  118. def regex_rules(rules):
  119. for line in rules:
  120. pattern, search, replace = line
  121. yield lambda word: re.search(pattern, word) and re.sub(search, replace, word)
  122. plural_rules = regex_rules(plural_rule_tuple)
  123. def plural(noun):
  124. for rule in regex_rules(plural_rule_tuple):
  125. result = rule(noun)
  126. if result:
  127. return result
  128. return noun
  129. def singular(noun):
  130. for rule in regex_rules(singular_rule_tuple):
  131. result = rule(noun)
  132. if result:
  133. return result
  134. return noun
  135. def name2label(name, schema=None):
  136. """
  137. Convert a column name to a Human Readable name.
  138. borrowed from old TG fastdata code
  139. """
  140. # Create label from the name:
  141. # 1) Convert _ to Nothing
  142. # 2) Convert CamelCase to Camel Case
  143. # 3) Upcase first character of Each Word
  144. # Note: I *think* it would be thread-safe to
  145. # memoize this thing.
  146. if schema:
  147. if name.startswith(schema+'.'):
  148. name = '.'.join(name.split('.')[1:])
  149. label = str(''.join([s.capitalize() for s in
  150. re.findall(r'([A-Z][a-z0-9]+|[a-z0-9]+|[A-Z0-9]+)', name)]))
  151. return label
  152. def select_imports(x):
  153. """
  154. Try import modules used in output file eg: dialect.
  155. Return first valid string or ''.
  156. """
  157. for i in x:
  158. try:
  159. exec(i)
  160. return i
  161. except:
  162. pass
  163. return ''