Guest User

Untitled

a guest
Mar 4th, 2018
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.99 KB | None | 0 0
  1. # Nose plugin to dump and restore a database, example of writing a Nose plugin
  2.  
  3. import logging
  4. import tempfile
  5. import os, sys
  6. import re
  7. import subprocess
  8.  
  9. from nose.plugins import Plugin
  10. from nose.util import tolist
  11.  
  12. ENGINES = ('mysql',)
  13.  
  14. engine_re = '(' + '|'.join(ENGINES) + ')'
  15.  
  16. r = engine_re + r'://(?:([\w]+)(?::([\w]+))?@)?([\w.-]+)(?::([\d]{1,5}))?'
  17. regex = re.compile(r)
  18.  
  19. def split_dsn(dsn):
  20. m = regex.match(dsn)
  21. if not m:
  22. raise ValueError('Cannot split DSN from %s' % dsn)
  23. else:
  24. return dict(zip(('engine','username','password','host','port'),
  25. m.groups()))
  26.  
  27.  
  28. def make_option_maker(parser, cmdline_prefix="", env_prefix="", dest_prefix=""):
  29. """Return a function that can be used to add_option with saner syntax.
  30.  
  31. Arguments:
  32. parser: the parser object that will be used by the returned function
  33. cmdline_prefix: will be used together with the name to build the command
  34. line option. a suffix of -- and a prefix of - will be added so you
  35. do not need to include those (--cmdline_prefix-<name>)
  36. env_prefix: will be used together with the name to specify the environment
  37. variable from which the option will default (ENV_PREFIX_<NAME>)
  38. dest_prefix: will be used together with name to specify the variable name
  39. in which the value of the option will be stored
  40. """
  41.  
  42. env_prefix = env_prefix.upper()
  43.  
  44. if cmdline_prefix and not cmdline_prefix.endswith("-"):
  45. cmdline_prefix += "-"
  46.  
  47. if env_prefix and not env_prefix.endswith("_"):
  48. env_prefix += "_"
  49.  
  50. if dest_prefix and not dest_prefix.endswith("_"):
  51. dest_prefix += "_"
  52.  
  53. def option_maker(name, action = "store", help = "", default = None):
  54. """Use the given name, action and help string to add an option"""
  55.  
  56. if default is None:
  57. _default = os.environ.get(env_prefix + name.upper())
  58. else:
  59. _default = default
  60.  
  61. parser.add_option("--" + cmdline_prefix + name.lower(),
  62. action = action, dest = dest_prefix + name.lower(),
  63. default= _default,
  64. help = help + " [" + env_prefix + name.upper() + "]")
  65.  
  66. return option_maker
  67.  
  68.  
  69. class DatabaseSnapshotPlugin(Plugin):
  70. """Plugin that takes a snapshot of Daisy before tests start and restores it
  71. """
  72.  
  73. enabled = True
  74. score = 1
  75.  
  76. def options(self, parser, env=None):
  77. Plugin.options(self, parser, env)
  78. omaker = make_option_maker(parser, dest_prefix = "dbdump",
  79. env_prefix = "NOSE_DBDUMP",
  80. cmdline_prefix = "dbdump")
  81.  
  82. omaker('databases', action="append", help="Dump the selected databases")
  83. omaker('output', help="Path to store the database dump")
  84. omaker('dsn', help="engine://[user[:password]@]hostname[:port]")
  85. omaker('keep', action='store_true', help="Don't delete the database dump")
  86.  
  87. def configure(self, options, config):
  88. self.conf = config
  89. self.databases = []
  90.  
  91. if options.dbdump_databases:
  92. for lst in [tolist(x) for x in options.dbdump_databases]:
  93. self.databases.extend(lst)
  94.  
  95. self.dsn = options.dbdump_dsn
  96. self.output = options.dbdump_output
  97. self.keep = options.dbdump_keep
  98.  
  99. if not (self.databases and self.dsn):
  100. self.enabled = False
  101. return
  102.  
  103. if not self.output:
  104. f,name = tempfile.mkstemp(suffix=".sql", prefix="nose-dbdump-")
  105. os.close(f)
  106. self.output = name
  107.  
  108. for k,v in split_dsn(self.dsn).items():
  109. self.__dict__[k] = v
  110.  
  111.  
  112. def begin(self):
  113. """Take a snapshot of the database"""
  114.  
  115. c = "mysqldump %s --databases %s > %s" % (self._get_connection_params(),
  116. ' '.join(self.databases),
  117. self.output)
  118. r = os.system(c)
  119. assert r == 0, "Got %s for %s" % (r, c)
  120.  
  121. def _get_connection_params(self):
  122. c = ''
  123. if self.engine == 'mysql':
  124. if self.username:
  125. c += ' --user=%s' % self.username
  126. if self.password:
  127. c += ' --password=%s' % self.password
  128.  
  129. if self.host == 'localhost' and not self.port:
  130. pass
  131. else:
  132. c += ' --host=%s' % self.host
  133.  
  134. if self.port:
  135. c += ' --port=%s' % self.port
  136.  
  137. return c
  138.  
  139.  
  140. def finalize(self, result):
  141. """Restore database to snapshot, if any"""
  142.  
  143. c = "mysql %s < %s" % (self._get_connection_params(), self.output)
  144. #print c
  145. r = os.system(c)
  146. assert r == 0, "Got %s for %s" % (r, c)
  147. if not self.keep:
  148. print "Removing output from %s" % self.output
  149. os.remove(self.output)
  150. else:
  151. print "Leaving output at %s" % self.output
Add Comment
Please, Sign In to add comment