Mercurial > piecrust2
comparison piecrust/commands/builtin/themes.py @ 273:d70a4adb61dd
themes: Add the `chef themes` command
The `themes` command lets the user create or override a theme easily.
| author | Ludovic Chabant <ludovic@chabant.com> |
|---|---|
| date | Sun, 01 Mar 2015 09:07:36 -0800 |
| parents | |
| children | c5df200354e8 |
comparison
equal
deleted
inserted
replaced
| 272:a561fbad0b7f | 273:d70a4adb61dd |
|---|---|
| 1 import os | |
| 2 import os.path | |
| 3 import shutil | |
| 4 import logging | |
| 5 import yaml | |
| 6 from piecrust import ( | |
| 7 RESOURCES_DIR, THEME_DIR, THEME_CONFIG_PATH, THEME_INFO_PATH) | |
| 8 from piecrust.commands.base import ChefCommand | |
| 9 | |
| 10 | |
| 11 logger = logging.getLogger(__name__) | |
| 12 | |
| 13 | |
| 14 class ThemesCommand(ChefCommand): | |
| 15 def __init__(self): | |
| 16 super(ThemesCommand, self).__init__() | |
| 17 self.name = 'themes' | |
| 18 self.description = "Manage the themes for the current website." | |
| 19 | |
| 20 def setupParser(self, parser, app): | |
| 21 if app.root_dir is None: | |
| 22 return | |
| 23 | |
| 24 subparsers = parser.add_subparsers() | |
| 25 p = subparsers.add_parser( | |
| 26 'create', | |
| 27 help="Create a new theme for the current website.") | |
| 28 p.add_argument( | |
| 29 '--from-default', | |
| 30 action='store_true', | |
| 31 help=("Create a new theme by copying the default PieCrust " | |
| 32 "theme into the theme directory")) | |
| 33 p.add_argument( | |
| 34 'theme_name', | |
| 35 help=("The name of the theme")) | |
| 36 p.set_defaults(sub_func=self._createTheme) | |
| 37 | |
| 38 p = subparsers.add_parser( | |
| 39 'override', | |
| 40 help="Copies a theme to the website for customization.") | |
| 41 p.set_defaults(sub_func=self._overrideTheme) | |
| 42 | |
| 43 def checkedRun(self, ctx): | |
| 44 ctx.args.sub_func(ctx) | |
| 45 | |
| 46 def _createTheme(self, ctx): | |
| 47 theme_dir = os.path.join(ctx.app.root_dir, THEME_DIR) | |
| 48 if os.path.exists(theme_dir): | |
| 49 logger.warning("A theme already exists, and will be overwritten. " | |
| 50 "Are you sure? [Y/n]") | |
| 51 ans = input() | |
| 52 if len(ans) > 0 and ans.lower() not in ['y', 'yes']: | |
| 53 return 1 | |
| 54 | |
| 55 shutil.rmtree(theme_dir) | |
| 56 | |
| 57 try: | |
| 58 if ctx.args.from_default: | |
| 59 def reporting_copy2(src, dst): | |
| 60 rel_dst = os.path.relpath(dst, ctx.app.root_dir) | |
| 61 logger.info(rel_dst) | |
| 62 shutil.copy2(src, dst) | |
| 63 | |
| 64 default_theme_dir = os.path.join(RESOURCES_DIR, 'theme') | |
| 65 shutil.copytree(default_theme_dir, theme_dir, | |
| 66 copy_function=reporting_copy2) | |
| 67 return 0 | |
| 68 | |
| 69 logger.info("Creating theme directory.") | |
| 70 os.makedirs(theme_dir) | |
| 71 | |
| 72 logger.info("Creating theme_config.yml") | |
| 73 config_path = os.path.join(theme_dir, THEME_CONFIG_PATH) | |
| 74 with open(config_path, 'w', encoding='utf8') as fp: | |
| 75 fp.write('') | |
| 76 | |
| 77 logger.info("Creating theme_info.yml") | |
| 78 info_path = os.path.join(theme_dir, THEME_INFO_PATH) | |
| 79 with open(info_path, 'w', encoding='utf8') as fp: | |
| 80 yaml.dump( | |
| 81 { | |
| 82 'name': ctx.args.theme_name or 'My New Theme', | |
| 83 'description': "A new PieCrust theme.", | |
| 84 'authors': ['Your Name Here <email or twitter>'], | |
| 85 'url': 'http://www.example.org'}, | |
| 86 fp, | |
| 87 default_flow_style=False) | |
| 88 return 0 | |
| 89 except: | |
| 90 logger.error("Error occured, deleting theme directory.") | |
| 91 shutil.rmtree(theme_dir) | |
| 92 raise | |
| 93 | |
| 94 def _overrideTheme(self, ctx): | |
| 95 app_dir = ctx.app.root_dir | |
| 96 theme_dir = ctx.app.theme_dir | |
| 97 if not theme_dir: | |
| 98 logger.error("There is not theme currently applied to override.") | |
| 99 return 1 | |
| 100 | |
| 101 copies = [] | |
| 102 for dirpath, dirnames, filenames in os.walk(theme_dir): | |
| 103 rel_dirpath = os.path.relpath(dirpath, theme_dir) | |
| 104 for name in filenames: | |
| 105 if (dirpath == theme_dir and | |
| 106 name in [THEME_CONFIG_PATH, THEME_INFO_PATH]): | |
| 107 continue | |
| 108 src_path = os.path.join(dirpath, name) | |
| 109 dst_path = os.path.join(app_dir, rel_dirpath, name) | |
| 110 copies.append((src_path, dst_path)) | |
| 111 | |
| 112 conflicts = [] | |
| 113 for c in copies: | |
| 114 if os.path.exists(c[1]): | |
| 115 conflicts.append(c[1]) | |
| 116 if conflicts: | |
| 117 logger.warning("Some website files will be overwritten:") | |
| 118 for c in conflicts: | |
| 119 logger.warning(os.path.relpath(c, app_dir)) | |
| 120 logger.warning("Are you sure? [Y/n]") | |
| 121 ans = input() | |
| 122 if len(ans) > 0 and ans.lower() not in ['y', 'yes']: | |
| 123 return 1 | |
| 124 | |
| 125 for c in copies: | |
| 126 logger.info(os.path.relpath(c[1], app_dir)) | |
| 127 if not os.path.exists(os.path.dirname(c[1])): | |
| 128 os.makedirs(os.path.dirname(c[1])) | |
| 129 shutil.copy2(c[0], c[1]) | |
| 130 |
