2 Generate an OpenERP module skeleton.
15 env = jinja2.Environment(loader=jinja2.PackageLoader(
16 'openerpcommand', 'templates'))
17 env.filters['snake'] = snake
18 args.dependency = 'web' if args.controller else 'base'
20 module_name = snake(args.module)
21 module = functools.partial(
22 os.path.join, args.modules_dir, module_name)
24 if args.controller is True:
25 args.controller = module_name
27 if args.model is True:
28 args.model = module_name
30 if os.path.exists(module()):
31 message = "The path `%s` already exists." % module()
34 dump(env, '__openerp__.jinja2', module('__openerp__.py'), config=args)
35 dump(env, '__init__.jinja2', module('__init__.py'), modules=[
36 args.controller and 'controllers',
37 args.model and 'models'
39 dump(env, 'ir.model.access.jinja2', module('security', 'ir.model.access.csv'), config=args)
42 controller_module = snake(args.controller)
43 dump(env, '__init__.jinja2', module('controllers', '__init__.py'), modules=[controller_module])
44 dump(env, 'controllers.jinja2',
45 module('controllers', '%s.py' % controller_module),
49 model_module = snake(args.model)
50 dump(env, '__init__.jinja2', module('models', '__init__.py'), modules=[model_module])
51 dump(env, 'models.jinja2', module('models', '%s.py' % model_module), config=args)
53 def add_parser(subparsers):
54 parser = subparsers.add_parser('scaffold',
55 description='Generate an OpenERP module skeleton.')
56 parser.add_argument('module', metavar='MODULE',
57 help='the name of the generated module')
58 parser.add_argument('modules_dir', metavar='DIRECTORY', type=directory,
59 help="Modules directory in which the new module should be generated")
61 controller = parser.add_mutually_exclusive_group()
62 controller.add_argument('--controller', type=identifier,
63 help="The name of the controller to generate")
64 controller.add_argument('--no-controller', dest='controller',
65 action='store_const', const=None, help="Do not generate a controller")
67 model = parser.add_mutually_exclusive_group()
68 model.add_argument('--model', type=identifier,
69 help="The name of the model to generate")
70 model.add_argument('--no-model', dest='model',
71 action='store_const', const=None, help="Do not generate a model")
73 mod = parser.add_argument_group("Module information",
74 "these are added to the module metadata and displayed on e.g. "
75 "apps.openerp.com. For company-backed modules, the company "
76 "information should be used")
77 mod.add_argument('--name', dest='author_name', default="",
78 help="Name of the module author")
79 mod.add_argument('--website', dest='author_website', default="",
80 help="Website of the module author")
81 mod.add_argument('--category', default="Uncategorized",
82 help="Broad categories to which the module belongs, used for "
83 "filtering within OpenERP and on apps.openerp.com."
84 "Defaults to %(default)s")
85 mod.add_argument('--summary', default="",
86 help="Short (1 phrase/line) summary of the module's purpose, used as "
87 "subtitle on modules listing or apps.openerp.com")
89 parser.set_defaults(run=run, controller=True, model=True)
97 # insert a space before each uppercase character preceded by a
98 # non-uppercase letter
99 s = re.sub(r'(?<=[^A-Z])\B([A-Z])', r' \1', s)
100 # lowercase everything, split on whitespace and join
101 return '_'.join(s.lower().split())
103 def dump(env, template, dest, **kwargs):
104 outdir = os.path.dirname(dest)
105 if not os.path.exists(outdir):
107 env.get_template(template).stream(**kwargs).dump(dest)
108 # add trailing newline which jinja removes
109 with open(dest, 'a') as f:
113 if keyword.iskeyword(s):
114 die("%s is a Python keyword and can not be used as a name" % s)
115 if not re.match('[A-Za-z_][A-Za-z0-9_]*', s):
116 die("%s is not a valid Python identifier" % s)
120 expanded = os.path.abspath(
122 os.path.expandvars(p)))
123 if not os.path.exists(expanded):
124 os.makedirs(expanded)
125 if not os.path.isdir(expanded):
126 die("%s exists but is not a directory" % p)
129 def die(message, code=1):
130 print >>sys.stderr, message