A fork of hyde, the static site generation. Some patches will be pushed upstream.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

162 lines
6.4 KiB

  1. # -*- coding: utf-8 -*-
  2. """
  3. Implements the hyde entry point commands
  4. """
  5. from hyde.exceptions import HydeException
  6. from hyde.layout import Layout, HYDE_DATA
  7. from hyde.model import Config
  8. from hyde.site import Site
  9. from hyde.version import __version__
  10. from commando import (
  11. Application,
  12. command,
  13. store,
  14. subcommand,
  15. true,
  16. version
  17. )
  18. from commando.util import getLoggerWithConsoleHandler
  19. from fswrap import FS, Folder
  20. HYDE_LAYOUTS = "HYDE_LAYOUTS"
  21. class Engine(Application):
  22. def __init__(self, raise_exceptions=False):
  23. logger = getLoggerWithConsoleHandler('hyde')
  24. super(Engine, self).__init__(
  25. raise_exceptions=raise_exceptions,
  26. logger=logger
  27. )
  28. @command(description='hyde - a python static website generator',
  29. epilog='Use %(prog)s {command} -h to get help'
  30. 'on individual commands')
  31. @true('-v', '--verbose', help="Show detailed information in console")
  32. @true('-x', '--raise-exceptions', default=None,
  33. help="Don't handle exceptions.")
  34. @version('--version', version='%(prog)s ' + __version__)
  35. @store('-s', '--sitepath', default='.', help="Location of the hyde site")
  36. def main(self, args):
  37. """
  38. Will not be executed. A sub command is required. This function exists
  39. to provide common parameters for the subcommands and some generic stuff
  40. like version and metadata
  41. """
  42. sitepath = Folder(args.sitepath).fully_expanded_path
  43. if args.raise_exceptions in (True, False):
  44. self.raise_exceptions = args.raise_exceptions
  45. return Folder(sitepath)
  46. @subcommand('create', help='Create a new hyde site.')
  47. @store('-l', '--layout', default='basic', help='Layout for the new site')
  48. @true('-f', '--force', default=False, dest='overwrite',
  49. help='Overwrite the current site if it exists')
  50. def create(self, args):
  51. """
  52. The create command. Creates a new site from the template at the given
  53. sitepath.
  54. """
  55. sitepath = self.main(args)
  56. markers = ['content', 'layout', 'site.yaml']
  57. exists = any((FS(sitepath.child(item)).exists for item in markers))
  58. if exists and not args.overwrite:
  59. raise HydeException(
  60. "The given site path [%s] already contains a hyde site."
  61. " Use -f to overwrite." % sitepath)
  62. layout = Layout.find_layout(args.layout)
  63. self.logger.info(
  64. "Creating site at [%s] with layout [%s]" % (sitepath, layout))
  65. if not layout or not layout.exists:
  66. raise HydeException(
  67. "The given layout is invalid. Please check if you have the"
  68. " `layout` in the right place and the environment variable(%s)"
  69. " has been setup properly if you are using custom path for"
  70. " layouts" % HYDE_DATA)
  71. layout.copy_contents_to(args.sitepath)
  72. self.logger.info("Site creation complete")
  73. @subcommand('gen', help='Generate the site')
  74. @store('-c', '--config-path', default='site.yaml', dest='config',
  75. help='The configuration used to generate the site')
  76. @store('-d', '--deploy-path', dest='deploy', default=None,
  77. help='Where should the site be generated?')
  78. @true('-r', '--regen', dest='regen', default=False,
  79. help='Regenerate the whole site, including unchanged files')
  80. def gen(self, args):
  81. """
  82. The generate command. Generates the site at the given
  83. deployment directory.
  84. """
  85. sitepath = self.main(args)
  86. site = self.make_site(sitepath, args.config, args.deploy)
  87. from hyde.generator import Generator
  88. gen = Generator(site)
  89. incremental = True
  90. if args.regen:
  91. self.logger.info("Regenerating the site...")
  92. incremental = False
  93. gen.generate_all(incremental=incremental)
  94. self.logger.info("Generation complete.")
  95. @subcommand('serve', help='Serve the website')
  96. @store('-a', '--address', default='localhost', dest='address',
  97. help='The address where the website must be served from.')
  98. @store('-p', '--port', type=int, default=8080, dest='port',
  99. help='The port where the website must be served from.')
  100. @store('-c', '--config-path', default='site.yaml', dest='config',
  101. help='The configuration used to generate the site')
  102. @store('-d', '--deploy-path', dest='deploy', default=None,
  103. help='Where should the site be generated?')
  104. def serve(self, args):
  105. """
  106. The serve command. Serves the site at the given
  107. deployment directory, address and port. Regenerates
  108. the entire site or specific files based on the request.
  109. """
  110. sitepath = self.main(args)
  111. site = self.make_site(sitepath, args.config, args.deploy)
  112. from hyde.server import HydeWebServer
  113. server = HydeWebServer(site, args.address, args.port)
  114. self.logger.info(
  115. "Starting webserver at [%s]:[%d]", args.address, args.port)
  116. try:
  117. server.serve_forever()
  118. except (KeyboardInterrupt, SystemExit):
  119. self.logger.info("Received shutdown request. Shutting down...")
  120. server.shutdown()
  121. self.logger.info("Server successfully stopped")
  122. exit()
  123. @subcommand('publish', help='Publish the website')
  124. @store('-c', '--config-path', default='site.yaml', dest='config',
  125. help='The configuration used to generate the site')
  126. @store('-p', '--publisher', dest='publisher', default='default',
  127. help='Points to the publisher configuration.')
  128. @store('-m', '--message', dest='message',
  129. help='Optional message.')
  130. def publish(self, args):
  131. """
  132. Publishes the site based on the configuration from the `target`
  133. parameter.
  134. """
  135. sitepath = self.main(args)
  136. site = self.make_site(sitepath, args.config)
  137. from hyde.publisher import Publisher
  138. publisher = Publisher.load_publisher(site,
  139. args.publisher,
  140. args.message)
  141. publisher.publish()
  142. def make_site(self, sitepath, config, deploy=None):
  143. """
  144. Creates a site object from the given sitepath and the config file.
  145. """
  146. config = Config(sitepath, config_file=config)
  147. if deploy:
  148. config.deploy_root = deploy
  149. return Site(sitepath, config)