devtools.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #!/usr/bin/env python
  2. import os
  3. import sys
  4. import re
  5. import tempfile
  6. from cement.core.foundation import CementApp
  7. from cement.ext.ext_argparse import ArgparseController, expose
  8. from cement.utils.version import get_version
  9. from cement.utils import shell
  10. VERSION = get_version()
  11. class CementDevtoolsController(ArgparseController):
  12. class Meta:
  13. label = 'base'
  14. arguments = [
  15. (['-y, --noprompt'],
  16. dict(help='answer yes to prompts.', action='store_true',
  17. dest='noprompt')),
  18. (['--ignore-errors'],
  19. dict(help="don't stop operations because of errors",
  20. action='store_true', dest='ignore_errors')),
  21. (['--loud'], dict(help='add more verbose output',
  22. action='store_true', dest='loud')),
  23. ]
  24. def _do_error(self, msg):
  25. if self.app.pargs.ignore_errors:
  26. self.app.log.error(msg)
  27. else:
  28. raise Exception(msg)
  29. @expose(hide=True)
  30. def default(self):
  31. raise AssertionError("A sub-command is required. See --help.")
  32. def _do_git(self):
  33. # make sure we don't have any uncommitted changes
  34. print('Checking for Uncommitted Changes')
  35. out, err, res = shell.exec_cmd(['git', '--no-pager', 'diff'])
  36. if len(out) > 0:
  37. self._do_error('There are uncommitted changes. See `git status`.')
  38. # make sure we don't have any un-added files
  39. print('Checking for Untracked Files')
  40. out, err, res = shell.exec_cmd(['git', 'status'])
  41. if re.match('Untracked files', str(out)):
  42. self._do_error('There are untracked files. See `git status`.')
  43. # make sure there isn't an existing tag
  44. print("Checking for Duplicate Git Tag")
  45. out, err, res = shell.exec_cmd(['git', 'tag'])
  46. for ver in str(out).split('\n'):
  47. if ver == VERSION:
  48. self._do_error("Tag %s already exists" % VERSION)
  49. print("Tagging Git Release")
  50. out, err, res = shell.exec_cmd(['git', 'tag', '-a', '-m', VERSION,
  51. VERSION])
  52. if res > 0:
  53. self._do_error("Unable to tag release with git.")
  54. def _do_tests(self):
  55. print('Running Nose Tests')
  56. out, err, res = shell.exec_cmd(['which', 'nosetests'])
  57. nose = out.decode('utf-8').strip()
  58. if self.app.pargs.loud:
  59. cmd_args = ['coverage', 'run', nose, '--verbosity=3']
  60. res = shell.exec_cmd2(cmd_args)
  61. else:
  62. cmd_args = ['coverage', 'run', nose, '--verbosity=0']
  63. out, err, res = shell.exec_cmd(cmd_args)
  64. if res > 0:
  65. self._do_error("\n\nNose tests did not pass.\n\n" +
  66. "$ %s\n%s" % (' '.join(cmd_args), err))
  67. def _do_pep8(self):
  68. print("Checking PEP8 Compliance")
  69. cmd_args = ['pep8', '-r', 'cement/', '--exclude=*.pyc']
  70. out, err, res = shell.exec_cmd(cmd_args)
  71. if res > 0:
  72. self._do_error("\n\nPEP8 checks did not pass.\n\n" +
  73. "$ %s\n%s" % (' '.join(cmd_args), str(out)))
  74. @expose(help='run all unit tests')
  75. def run_tests(self):
  76. print('')
  77. print('Python Version: %s' % sys.version)
  78. print('')
  79. print("Running Tests for Cement Version %s" % VERSION)
  80. print('-' * 77)
  81. self._do_pep8()
  82. self._do_tests()
  83. print('')
  84. @expose(help='run pep8 tests')
  85. def pep8(self):
  86. self._do_pep8()
  87. def _do_sphinx(self, dest_path):
  88. print("Building Documentation")
  89. cmd_args = ['rm', '-rf', 'docs/build/*']
  90. cmd_args = ['sphinx-build', 'doc/source', dest_path]
  91. out, err, res = shell.exec_cmd(cmd_args)
  92. if res > 0:
  93. self._do_error("\n\nFailed to build sphinx documentation\n\n" +
  94. "$ %s\n%s" % (' '.join(cmd_args), str(out)))
  95. @expose(help='create a cement release')
  96. def make_release(self):
  97. print('')
  98. print("Making Release for Version %s" % VERSION)
  99. print('-' * 77)
  100. if not self.app.pargs.noprompt:
  101. res = input("Continue? [yN] ")
  102. if res not in ['Y', 'y', '1']:
  103. sys.exit(1)
  104. tmp = tempfile.mkdtemp()
  105. print("Destination: %s" % tmp)
  106. os.makedirs(os.path.join(tmp, 'source'))
  107. os.makedirs(os.path.join(tmp, 'doc'))
  108. self._do_pep8()
  109. self._do_tests()
  110. self._do_git()
  111. self._do_sphinx(os.path.join(tmp, 'doc'))
  112. tar_path = os.path.join(tmp, 'source', 'cement-%s.tar' % VERSION)
  113. gzip_path = "%s.gz" % tar_path
  114. print("Generating Release Files")
  115. cmd_args = ['git', 'archive', VERSION,
  116. '--prefix=cement-%s/' % VERSION,
  117. '--output=%s' % tar_path]
  118. out, err, res = shell.exec_cmd(cmd_args)
  119. cmd_args = ['gzip', tar_path]
  120. out, err, res = shell.exec_cmd(cmd_args)
  121. if res > 0:
  122. self._do_error("\n\nFailed generating git archive.\n\n" +
  123. "$ %s" % (' '.join(cmd_args), err))
  124. print('')
  125. @expose(help='get the current version of the sources')
  126. def get_version(self):
  127. print(VERSION)
  128. class CementDevtoolsApp(CementApp):
  129. class Meta:
  130. label = 'cement-devtools'
  131. base_controller = CementDevtoolsController
  132. def main():
  133. with CementDevtoolsApp() as app:
  134. try:
  135. app.run()
  136. except AssertionError as e:
  137. print("AssertionError => %s" % e.args[0])
  138. if __name__ == '__main__':
  139. main()