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