From eb7f96efbbcedd0f840a7685599cf5344aff1e8b Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 21 May 2014 13:24:39 +0200 Subject: [PATCH 01/23] --addons-path not required anymore --- openerpcommand/common.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/openerpcommand/common.py b/openerpcommand/common.py index 7572bb4efa6..48d1c16eae4 100644 --- a/openerpcommand/common.py +++ b/openerpcommand/common.py @@ -14,8 +14,7 @@ def add_addons_argument(parser): Add a common --addons argument to a parser. """ parser.add_argument('--addons', metavar='ADDONS', - **required_or_default('ADDONS', - 'colon-separated list of paths to addons')) + help='colon-separated list of paths to addons') def set_addons(args): """ Turn args.addons into a list instead of a column-separated strings. From df35de22b80df3a1e57dd38e44dc69de82ef4e50 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 21 May 2014 15:53:16 +0200 Subject: [PATCH 02/23] Disable logging during commands discovery --- openerp/cli/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openerp/cli/__init__.py b/openerp/cli/__init__.py index 27428369cbc..574898b1e24 100644 --- a/openerp/cli/__init__.py +++ b/openerp/cli/__init__.py @@ -47,6 +47,7 @@ def main(): # Subcommand discovery if len(args) and not args[0].startswith("-"): + logging.disable(logging.CRITICAL) for m in module.get_modules(): m = 'openerp.addons.' + m __import__(m) @@ -54,6 +55,7 @@ def main(): #except Exception, e: # raise # print e + logging.disable(logging.NOTSET) command = args[0] args = args[1:] From dec81728667c55df6189c36a2dfa3e748dfef89e Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Tue, 27 May 2014 14:22:28 +0200 Subject: [PATCH 03/23] [ADD] odoo deploy --- .../bin/oe_module_deploy.py | 86 ----------------- openerp/cli/__init__.py | 1 + openerp/cli/deploy.py | 92 +++++++++++++++++++ 3 files changed, 93 insertions(+), 86 deletions(-) delete mode 100755 addons/base_import_module/bin/oe_module_deploy.py create mode 100644 openerp/cli/deploy.py diff --git a/addons/base_import_module/bin/oe_module_deploy.py b/addons/base_import_module/bin/oe_module_deploy.py deleted file mode 100755 index 2412382cba5..00000000000 --- a/addons/base_import_module/bin/oe_module_deploy.py +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env python -import argparse -import os -import sys -import tempfile -import zipfile - - -try: - import requests -except ImportError: - # no multipart encoding in stdlib and this script is temporary - sys.exit("This script requires the 'requests' module. ( pip install requests )") - -session = requests.session() - -def deploy_module(module_path, url, login, password, db=''): - url = url.rstrip('/') - authenticate(url, login, password, db) - module_file = zip_module(module_path) - try: - return upload_module(url, module_file) - finally: - os.remove(module_file) - -def upload_module(server, module_file): - print("Uploading module file...") - url = server + '/base_import_module/upload' - files = dict(mod_file=open(module_file, 'rb')) - res = session.post(url, files=files) - if res.status_code != 200: - raise Exception("Could not authenticate on server '%s'" % server) - return res.text - -def authenticate(server, login, password, db=''): - print("Authenticating on server '%s' ..." % server) - - # Fixate session with a given db if any - session.get(server + '/web/login', params=dict(db=db)) - - args = dict(login=login, password=password, db=db) - res = session.post(server + '/base_import_module/login', args) - if res.status_code == 404: - raise Exception("The server '%s' does not have the 'base_import_module' installed." % server) - elif res.status_code != 200: - raise Exception(res.text) - -def zip_module(path): - path = os.path.abspath(path) - if not os.path.isdir(path): - raise Exception("Could not find module directory '%s'" % path) - container, module_name = os.path.split(path) - temp = tempfile.mktemp(suffix='.zip') - try: - print("Zipping module directory...") - with zipfile.ZipFile(temp, 'w') as zfile: - for root, dirs, files in os.walk(path): - for file in files: - file_path = os.path.join(root, file) - zfile.write(file_path, file_path.split(container).pop()) - return temp - except Exception: - os.remove(temp) - raise - -if __name__ == '__main__': - parser = argparse.ArgumentParser(description='Deploy a module on an OpenERP server.') - parser.add_argument('path', help="Path of the module to deploy") - parser.add_argument('--url', dest='url', help='Url of the server (default=http://localhost:8069)', default="http://localhost:8069") - parser.add_argument('--db', dest='db', help='Database to use if server does not use db-filter.') - parser.add_argument('--login', dest='login', default="admin", help='Login (default=admin)') - parser.add_argument('--password', dest='password', default="admin", help='Password (default=admin)') - parser.add_argument('--no-ssl-check', dest='no_ssl_check', action='store_true', help='Do not check ssl cert') - if len(sys.argv) == 1: - sys.exit(parser.print_help()) - - args = parser.parse_args() - - if args.no_ssl_check: - session.verify = False - - try: - result = deploy_module(args.path, args.url, args.login, args.password, args.db) - print(result) - except Exception, e: - sys.exit("ERROR: %s" % e) diff --git a/openerp/cli/__init__.py b/openerp/cli/__init__.py index 574898b1e24..71e2ae88b6c 100644 --- a/openerp/cli/__init__.py +++ b/openerp/cli/__init__.py @@ -31,6 +31,7 @@ class Help(Command): print " %s" % k import server +import deploy def main(): args = sys.argv[1:] diff --git a/openerp/cli/deploy.py b/openerp/cli/deploy.py new file mode 100644 index 00000000000..079099a406f --- /dev/null +++ b/openerp/cli/deploy.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import argparse +import os +import requests +import sys +import tempfile +import zipfile + +from . import Command + +class Deploy(Command): + """Deploy a module on an Odoo instance""" + def __init__(self): + super(Deploy, self).__init__() + self.session = requests.session() + + def deploy_module(self, module_path, url, login, password, db=''): + url = url.rstrip('/') + self.authenticate(url, login, password, db) + module_file = self.zip_module(module_path) + try: + return self.upload_module(url, module_file) + finally: + os.remove(module_file) + + def upload_module(self, server, module_file): + print("Uploading module file...") + url = server + '/base_import_module/upload' + files = dict(mod_file=open(module_file, 'rb')) + res = self.session.post(url, files=files) + if res.status_code != 200: + raise Exception("Could not authenticate on server '%s'" % server) + return res.text + + def authenticate(self, server, login, password, db=''): + print("Authenticating on server '%s' ..." % server) + + # Fixate session with a given db if any + self.session.get(server + '/web/login', params=dict(db=db)) + + args = dict(login=login, password=password, db=db) + res = self.session.post(server + '/base_import_module/login', args) + if res.status_code == 404: + raise Exception("The server '%s' does not have the 'base_import_module' installed." % server) + elif res.status_code != 200: + raise Exception(res.text) + + def zip_module(self, path): + path = os.path.abspath(path) + if not os.path.isdir(path): + raise Exception("Could not find module directory '%s'" % path) + container, module_name = os.path.split(path) + temp = tempfile.mktemp(suffix='.zip') + try: + print("Zipping module directory...") + with zipfile.ZipFile(temp, 'w') as zfile: + for root, dirs, files in os.walk(path): + for file in files: + file_path = os.path.join(root, file) + zfile.write(file_path, file_path.split(container).pop()) + return temp + except Exception: + os.remove(temp) + raise + + def run(self, args): + parser = argparse.ArgumentParser( + prog="%s deploy" % sys.argv[0].split(os.path.sep)[-1], + description='Deploy a module on an Odoo server.' + ) + parser.add_argument('path', help="Path of the module to deploy") + parser.add_argument('url', nargs='?', help='Url of the server (default=http://localhost:8069)', default="http://localhost:8069") + parser.add_argument('--db', dest='db', help='Database to use if server does not use db-filter.') + parser.add_argument('--login', dest='login', default="admin", help='Login (default=admin)') + parser.add_argument('--password', dest='password', default="admin", help='Password (default=admin)') + parser.add_argument('--no-ssl-check', dest='no_ssl_check', action='store_true', help='Do not check ssl cert') + if not args: + sys.exit(parser.print_help()) + + args = parser.parse_args(args=args) + + if args.no_ssl_check: + self.session.verify = False + + try: + if not args.url.startswith('http://'): + args.url = 'https://%s' % args.url + result = self.deploy_module(args.path, args.url, args.login, args.password, args.db) + print(result) + except Exception, e: + sys.exit("ERROR: %s" % e) From 3458eb3ef7f65d8977589fbe68c9581e9b5a847d Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Tue, 27 May 2014 17:07:40 +0200 Subject: [PATCH 04/23] Add docstring to help command --- openerp/cli/__init__.py | 6 +++++- openerp/cli/server.py | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/openerp/cli/__init__.py b/openerp/cli/__init__.py index 71e2ae88b6c..2f9caad3ba6 100644 --- a/openerp/cli/__init__.py +++ b/openerp/cli/__init__.py @@ -1,5 +1,6 @@ import logging import sys +import os import openerp from openerp import tools @@ -25,10 +26,13 @@ class Command(object): pass class Help(Command): + """Display the list of available commands""" def run(self, args): print "Available commands:\n" + padding = max([len(k) for k in commands.keys()]) + 2 for k, v in commands.items(): - print " %s" % k + print " %s%s" % (k.ljust(padding, ' '), v.__doc__ or '') + print "\nUse '%s --help' for individual command help." % sys.argv[0].split(os.path.sep)[-1] import server import deploy diff --git a/openerp/cli/server.py b/openerp/cli/server.py index 5d731a9ad41..70602634efc 100644 --- a/openerp/cli/server.py +++ b/openerp/cli/server.py @@ -169,6 +169,7 @@ def main(args): sys.exit(rc) class Server(Command): + """Start the odoo server (default command)""" def run(self, args): main(args) From 397784cef0dc481cb75c122e693755f87a82423c Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 28 May 2014 09:25:31 +0200 Subject: [PATCH 05/23] reuse cls.__doc__ for deploy command --- openerp/cli/deploy.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openerp/cli/deploy.py b/openerp/cli/deploy.py index 079099a406f..fddfcf7ec4d 100644 --- a/openerp/cli/deploy.py +++ b/openerp/cli/deploy.py @@ -67,7 +67,7 @@ class Deploy(Command): def run(self, args): parser = argparse.ArgumentParser( prog="%s deploy" % sys.argv[0].split(os.path.sep)[-1], - description='Deploy a module on an Odoo server.' + description=self.__doc__ ) parser.add_argument('path', help="Path of the module to deploy") parser.add_argument('url', nargs='?', help='Url of the server (default=http://localhost:8069)', default="http://localhost:8069") From ac0b9d066caeee2737d29415b852d27cf7fff0a0 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 28 May 2014 11:29:54 +0200 Subject: [PATCH 06/23] Added odoo.py command --- odoo.py | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100755 odoo.py diff --git a/odoo.py b/odoo.py new file mode 100755 index 00000000000..b9ff496c293 --- /dev/null +++ b/odoo.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python +import openerp + +if __name__ == "__main__": + openerp.cli.main() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: From ba85b80f32700c8367528a12f8923f7045916818 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 28 May 2014 11:31:00 +0200 Subject: [PATCH 07/23] Basic scaffolding --- openerp/cli/__init__.py | 1 + openerp/cli/scaffold.py | 106 ++++++++++++++++++++ openerp/cli/scaffold/__init__.jinja2 | 4 + openerp/cli/scaffold/__openerp__.jinja2 | 26 +++++ openerp/cli/scaffold/controllers.jinja2 | 9 ++ openerp/cli/scaffold/ir.model.access.jinja2 | 6 ++ openerp/cli/scaffold/models.jinja2 | 9 ++ 7 files changed, 161 insertions(+) create mode 100644 openerp/cli/scaffold.py create mode 100644 openerp/cli/scaffold/__init__.jinja2 create mode 100644 openerp/cli/scaffold/__openerp__.jinja2 create mode 100644 openerp/cli/scaffold/controllers.jinja2 create mode 100644 openerp/cli/scaffold/ir.model.access.jinja2 create mode 100644 openerp/cli/scaffold/models.jinja2 diff --git a/openerp/cli/__init__.py b/openerp/cli/__init__.py index 2f9caad3ba6..44141625121 100644 --- a/openerp/cli/__init__.py +++ b/openerp/cli/__init__.py @@ -36,6 +36,7 @@ class Help(Command): import server import deploy +import scaffold def main(): args = sys.argv[1:] diff --git a/openerp/cli/scaffold.py b/openerp/cli/scaffold.py new file mode 100644 index 00000000000..4d9304c6e9e --- /dev/null +++ b/openerp/cli/scaffold.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import argparse +import functools +import keyword +import os +import re +import sys + +import jinja2 + +from . import Command + +class Scaffold(Command): + "Generate an Odoo module skeleton." + + def __init__(self): + super(Scaffold, self).__init__() + env = jinja2.Environment(loader=jinja2.PackageLoader( + 'openerp.cli', 'scaffold')) + env.filters['snake'] = snake + self.env = env + + def scaffold(self, args): + # TODO: make this function callable even if the module already + # exists. (update mode for scaffolding) + from pudb import set_trace;set_trace() ############################## Breakpoint ############################## + args.dependency = 'base' + if args.web: + args.dependency = 'web' + elif args.theme: + args.dependency = 'website' + dest = os.path.abspath(os.path.expanduser(args.dest)) + + module_name = snake(args.module) + module = functools.partial(os.path.join, dest, module_name) + + if os.path.exists(module()): + message = "The path `%s` already exists." % module() + die(message) + + self.dump('__openerp__.jinja2', module('__openerp__.py'), config=args) + self.dump('__init__.jinja2', module('__init__.py'), modules=[ + args.controller and 'controllers', + args.model and 'models' + ]) + self.dump('ir.model.access.jinja2', module('security', 'ir.model.access.csv'), config=args) + + + def dump(self, template, dest, **kwargs): + outdir = os.path.dirname(dest) + if not os.path.exists(outdir): + os.makedirs(outdir) + self.env.get_template(template).stream(**kwargs).dump(dest) + # add trailing newline which jinja removes + with open(dest, 'a') as f: + f.write('\n') + + def run(self, args): + parser = argparse.ArgumentParser( + prog="%s scaffold" % sys.argv[0].split(os.path.sep)[-1], + description=self.__doc__ + ) + parser.add_argument('module', help="Name of the module to generate") + parser.add_argument('dest', nargs='?', help='Directory where the module should be created (default to current directory)', default=".") + + + if not args: + sys.exit(parser.print_help()) + + args = parser.parse_args(args=args) + + self.scaffold(args) + +def snake(s): + """ snake cases ``s`` + + :param str s: + :return: str + """ + # insert a space before each uppercase character preceded by a + # non-uppercase letter + s = re.sub(r'(?<=[^A-Z])\B([A-Z])', r' \1', s) + # lowercase everything, split on whitespace and join + return '_'.join(s.lower().split()) + +def identifier(s): + if keyword.iskeyword(s): + die("%s is a Python keyword and can not be used as a name" % s) + if not re.match('[A-Za-z_][A-Za-z0-9_]*', s): + die("%s is not a valid Python identifier" % s) + return s + +def directory(p): + expanded = os.path.abspath( + os.path.expanduser( + os.path.expandvars(p))) + if not os.path.exists(expanded): + os.makedirs(expanded) + if not os.path.isdir(expanded): + die("%s exists but is not a directory" % p) + return expanded + +def die(message, code=1): + print >>sys.stderr, message + sys.exit(code) diff --git a/openerp/cli/scaffold/__init__.jinja2 b/openerp/cli/scaffold/__init__.jinja2 new file mode 100644 index 00000000000..0124cdd2d93 --- /dev/null +++ b/openerp/cli/scaffold/__init__.jinja2 @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +{% for module in modules if module -%} +import {{ module }} +{% endfor %} diff --git a/openerp/cli/scaffold/__openerp__.jinja2 b/openerp/cli/scaffold/__openerp__.jinja2 new file mode 100644 index 00000000000..0dbd6f83fbc --- /dev/null +++ b/openerp/cli/scaffold/__openerp__.jinja2 @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +{ + 'name': "{{ config.module }}", + # short description, used as subtitles on modules listings + 'summary': """ + Short (1 phrase/line) summary of the module's purpose, used as + subtitle on modules listing or apps.openerp.com""", + # long description of module purpose + 'description': """ + """, + # Who you are + 'author': "Acme Corp.", + 'website': "http://www.example.com", + + # categories can be used to filter modules in modules listing + 'category': 'Uncategorized', + 'version': '0.1', + + # any module necessary for this one to work correctly + 'depends': ['{{ config.dependency }}'], + 'data': [ + {{- "'security/ir.model.access.csv'" if config.model -}} + ], + 'tests': [ + ], +} diff --git a/openerp/cli/scaffold/controllers.jinja2 b/openerp/cli/scaffold/controllers.jinja2 new file mode 100644 index 00000000000..3cc47365d40 --- /dev/null +++ b/openerp/cli/scaffold/controllers.jinja2 @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- + +from openerp import http +from openerp.addons.web.controllers import main + +class {{ config.controller }}(main.Home): + @http.route('/', auth='none') + def index(self): + return "Hello, world!" diff --git a/openerp/cli/scaffold/ir.model.access.jinja2 b/openerp/cli/scaffold/ir.model.access.jinja2 new file mode 100644 index 00000000000..e5e2fb35fe7 --- /dev/null +++ b/openerp/cli/scaffold/ir.model.access.jinja2 @@ -0,0 +1,6 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +{% if config.model -%} +access_{{ config.module|snake }}_{{ config.model|snake }},{{- '' -}} +access_{{ config.module|snake }}_{{ config.model|snake }},{{- '' -}} +model_{{ config.module|snake }}_{{ config.model|snake }},,1,0,0,0 +{%- endif %} diff --git a/openerp/cli/scaffold/models.jinja2 b/openerp/cli/scaffold/models.jinja2 new file mode 100644 index 00000000000..878bf9be4f6 --- /dev/null +++ b/openerp/cli/scaffold/models.jinja2 @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- +from openerp.osv import orm, fields + +class {{ config.model }}(orm.Model): + _name = "{{ config.module|snake }}.{{ config.model|snake }}" + + _columns = { + 'name': fields.char(), + } From ce764477e660dd49b1de1737ac0faa5c95bdc117 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 28 May 2014 17:10:56 +0200 Subject: [PATCH 08/23] [WIP] models and controllers for scaffolding --- openerp/cli/scaffold.py | 92 ++++++++++++++++++------- openerp/cli/scaffold/__init__.jinja2 | 3 +- openerp/cli/scaffold/__openerp__.jinja2 | 26 ++++--- openerp/cli/scaffold/controllers.jinja2 | 8 ++- 4 files changed, 92 insertions(+), 37 deletions(-) diff --git a/openerp/cli/scaffold.py b/openerp/cli/scaffold.py index 4d9304c6e9e..9e24156b792 100644 --- a/openerp/cli/scaffold.py +++ b/openerp/cli/scaffold.py @@ -20,32 +20,69 @@ class Scaffold(Command): 'openerp.cli', 'scaffold')) env.filters['snake'] = snake self.env = env + self.manifest = '__openerp__' def scaffold(self, args): - # TODO: make this function callable even if the module already - # exists. (update mode for scaffolding) - from pudb import set_trace;set_trace() ############################## Breakpoint ############################## args.dependency = 'base' - if args.web: - args.dependency = 'web' - elif args.theme: - args.dependency = 'website' - dest = os.path.abspath(os.path.expanduser(args.dest)) + # TODO: update dependencies according to --web and --theme + # if args.web: + # args.dependency = 'web' + # elif args.theme: + # args.dependency = 'website' - module_name = snake(args.module) - module = functools.partial(os.path.join, dest, module_name) + dest = directory(args.dest) + if args.init: + module_name = snake(args.init) + module = functools.partial(os.path.join, dest, module_name) + if os.path.exists(module()): + die("Can't initialize module in `%s`: Directory already exists." % module()) + else: + module_name = dest.split(os.path.sep)[-1] + # find the module's root directory + while not os.path.exists(os.path.join(dest, '%s.py' % self.manifest)): + new_dest = os.path.abspath(os.path.join(dest, os.pardir)) + if dest == new_dest: + die("Can't find module directory. Please `cd` to it's path or use --dest") + module_name = dest.split(os.path.sep)[-1] + dest = new_dest + module = functools.partial(os.path.join, dest) + args.module = module_name - if os.path.exists(module()): - message = "The path `%s` already exists." % module() - die(message) + if args.init: + self.dump('%s.jinja2' % self.manifest, module('%s.py' % self.manifest), config=args) - self.dump('__openerp__.jinja2', module('__openerp__.py'), config=args) - self.dump('__init__.jinja2', module('__init__.py'), modules=[ - args.controller and 'controllers', - args.model and 'models' - ]) - self.dump('ir.model.access.jinja2', module('security', 'ir.model.access.csv'), config=args) + if args.model: + model_module = snake(args.model) + model_file = module('models', '%s.py' % model_module) + if os.path.exists(model_file): + die("Model `%s` already exists !" % model_file) + self.add_init_import(module('__init__.py'), 'models') + self.add_init_import(module('models', '__init__.py'), model_module) + self.dump('models.jinja2', model_file, config=args) + if args.controller: + controller_module = snake(args.controller) + controller_file = module('controllers', '%s.py' % controller_module) + if os.path.exists(controller_file): + die("Controller `%s` already exists !" % controller_file) + self.add_init_import(module('__init__.py'), 'controllers') + self.add_init_import(module('controllers', '__init__.py'), controller_module) + self.dump('controllers.jinja2', module('controllers', controller_file), config=args) + + # self.dump('ir.model.access.jinja2', module('security', 'ir.model.access.csv'), config=args) + return + + def add_init_import(self, path, module): + if not os.path.exists(path): + self.dump('__init__.jinja2', path, modules=[module]) + else: + with open(path, "r") as f: + lines = f.readlines() + # TODO: regex + if ('import %s' % module) in lines: + return + with open(path, "a") as f: + f.write('\nimport %s' % module) def dump(self, template, dest, **kwargs): outdir = os.path.dirname(dest) @@ -61,15 +98,24 @@ class Scaffold(Command): prog="%s scaffold" % sys.argv[0].split(os.path.sep)[-1], description=self.__doc__ ) - parser.add_argument('module', help="Name of the module to generate") - parser.add_argument('dest', nargs='?', help='Directory where the module should be created (default to current directory)', default=".") + parser.add_argument('--init', type=identifier, help='Initialize a new Odoo module') + parser.add_argument('--dest', default=".", + help='Directory where the module should be created/updated (default to current directory)') + + parser.add_argument('--model', type=identifier, help="Name of the model to add") + + parser.add_argument('--controller', type=identifier, help="Name of the controller to add") + + parser.add_argument('--web', action='store_true', default=False, + help="Generate structure for a webclient module") + + parser.add_argument('--theme', action='store_true', default=False, + help="Generate structure for a Website theme") if not args: sys.exit(parser.print_help()) - args = parser.parse_args(args=args) - self.scaffold(args) def snake(s): diff --git a/openerp/cli/scaffold/__init__.jinja2 b/openerp/cli/scaffold/__init__.jinja2 index 0124cdd2d93..7a45c970f2c 100644 --- a/openerp/cli/scaffold/__init__.jinja2 +++ b/openerp/cli/scaffold/__init__.jinja2 @@ -1,4 +1,3 @@ # -*- coding: utf-8 -*- {% for module in modules if module -%} -import {{ module }} -{% endfor %} +import {{ module }}{% endfor %} diff --git a/openerp/cli/scaffold/__openerp__.jinja2 b/openerp/cli/scaffold/__openerp__.jinja2 index 0dbd6f83fbc..c8bd331d063 100644 --- a/openerp/cli/scaffold/__openerp__.jinja2 +++ b/openerp/cli/scaffold/__openerp__.jinja2 @@ -1,26 +1,32 @@ # -*- coding: utf-8 -*- { 'name': "{{ config.module }}", - # short description, used as subtitles on modules listings + 'summary': """ Short (1 phrase/line) summary of the module's purpose, used as subtitle on modules listing or apps.openerp.com""", - # long description of module purpose - 'description': """ - """, - # Who you are - 'author': "Acme Corp.", - 'website': "http://www.example.com", - # categories can be used to filter modules in modules listing + 'description': """ + Long description of module's purpose + """, + + 'author': "Your Company", + 'website': "http://www.yourcompany.com", + + # Categories can be used to filter modules in modules listing + # Check /addons/base/module/module_data.xml of the full list 'category': 'Uncategorized', 'version': '0.1', # any module necessary for this one to work correctly - 'depends': ['{{ config.dependency }}'], + 'depends': ['base'], 'data': [ - {{- "'security/ir.model.access.csv'" if config.model -}} + # {{- "'security/ir.model.access.csv'" if config.model -}} ], + + 'demo': [ + ], + 'tests': [ ], } diff --git a/openerp/cli/scaffold/controllers.jinja2 b/openerp/cli/scaffold/controllers.jinja2 index 3cc47365d40..db08e62c375 100644 --- a/openerp/cli/scaffold/controllers.jinja2 +++ b/openerp/cli/scaffold/controllers.jinja2 @@ -1,9 +1,13 @@ # -*- coding: utf-8 -*- - from openerp import http from openerp.addons.web.controllers import main class {{ config.controller }}(main.Home): - @http.route('/', auth='none') + @http.route('/{{ config.module }}/{{ config.controller }}', auth='public') def index(self): return "Hello, world!" +{% if config.model %} + @http.route('/{{ config.module }}/{{ config.controller }}/{{ config.model }}/'], type='http', auth='public') + def {{ config.model }}(self, {{ config.model }}, **kw): + return "Hello, %r!" % {{ config.model }} +{% endif %} From 6b678f376e322eaa4368231021acd49df2f64d4f Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 28 May 2014 18:49:16 +0200 Subject: [PATCH 09/23] Use ast module against __init__.py's for import discovery --- odoo.py | 2 -- openerp/cli/scaffold.py | 32 ++++++++++----------- openerp/cli/scaffold/__init__.jinja2 | 6 ++-- openerp/cli/scaffold/ir.model.access.jinja2 | 2 +- 4 files changed, 20 insertions(+), 22 deletions(-) diff --git a/odoo.py b/odoo.py index b9ff496c293..0a33d5e7d42 100755 --- a/odoo.py +++ b/odoo.py @@ -3,5 +3,3 @@ import openerp if __name__ == "__main__": openerp.cli.main() - -# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/cli/scaffold.py b/openerp/cli/scaffold.py index 9e24156b792..4fdd5a32137 100644 --- a/openerp/cli/scaffold.py +++ b/openerp/cli/scaffold.py @@ -1,6 +1,7 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- import argparse +import ast import functools import keyword import os @@ -59,6 +60,7 @@ class Scaffold(Command): self.add_init_import(module('__init__.py'), 'models') self.add_init_import(module('models', '__init__.py'), model_module) self.dump('models.jinja2', model_file, config=args) + self.dump('ir.model.access.jinja2', module('security', 'ir.model.access.csv'), config=args) if args.controller: controller_module = snake(args.controller) @@ -69,31 +71,29 @@ class Scaffold(Command): self.add_init_import(module('controllers', '__init__.py'), controller_module) self.dump('controllers.jinja2', module('controllers', controller_file), config=args) - # self.dump('ir.model.access.jinja2', module('security', 'ir.model.access.csv'), config=args) - return + def has_import(self, initfile, module): + with open(initfile, 'r') as f: + for imp in ast.parse(f.read()).body: + if isinstance(imp, ast.Import): + if module in [mod.name for mod in imp.names]: + return True + return False - def add_init_import(self, path, module): - if not os.path.exists(path): - self.dump('__init__.jinja2', path, modules=[module]) - else: - with open(path, "r") as f: - lines = f.readlines() - # TODO: regex - if ('import %s' % module) in lines: - return - with open(path, "a") as f: - f.write('\nimport %s' % module) + def add_init_import(self, initfile, module): + if not(os.path.exists(initfile) and self.has_import(initfile, module)): + self.dump('__init__.jinja2', initfile, modules=[module]) def dump(self, template, dest, **kwargs): outdir = os.path.dirname(dest) + kwargs['create'] = not os.path.exists(dest) if not os.path.exists(outdir): os.makedirs(outdir) - self.env.get_template(template).stream(**kwargs).dump(dest) - # add trailing newline which jinja removes + content = self.env.get_template(template).render(**kwargs) with open(dest, 'a') as f: - f.write('\n') + f.write(content) def run(self, args): + # TODO: bash completion file parser = argparse.ArgumentParser( prog="%s scaffold" % sys.argv[0].split(os.path.sep)[-1], description=self.__doc__ diff --git a/openerp/cli/scaffold/__init__.jinja2 b/openerp/cli/scaffold/__init__.jinja2 index 7a45c970f2c..b3cd02662e0 100644 --- a/openerp/cli/scaffold/__init__.jinja2 +++ b/openerp/cli/scaffold/__init__.jinja2 @@ -1,3 +1,3 @@ -# -*- coding: utf-8 -*- -{% for module in modules if module -%} -import {{ module }}{% endfor %} +{% if create -%}# -*- coding: utf-8 -*-{%- endif %} +{% for module in modules if module -%}import {{ module }} +{%- endfor %} diff --git a/openerp/cli/scaffold/ir.model.access.jinja2 b/openerp/cli/scaffold/ir.model.access.jinja2 index e5e2fb35fe7..e047031a15a 100644 --- a/openerp/cli/scaffold/ir.model.access.jinja2 +++ b/openerp/cli/scaffold/ir.model.access.jinja2 @@ -1,4 +1,4 @@ -id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +{% if create -%}id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink{%- endif %} {% if config.model -%} access_{{ config.module|snake }}_{{ config.model|snake }},{{- '' -}} access_{{ config.module|snake }}_{{ config.model|snake }},{{- '' -}} From a9eba4dc405a0d1f76e04ce0ba2d26fe5057fa80 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 28 May 2014 19:16:50 +0200 Subject: [PATCH 10/23] Detect if controller name correspond to a model name --- openerp/cli/scaffold.py | 2 ++ openerp/cli/scaffold/controllers.jinja2 | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/openerp/cli/scaffold.py b/openerp/cli/scaffold.py index 4fdd5a32137..8d580eba0b4 100644 --- a/openerp/cli/scaffold.py +++ b/openerp/cli/scaffold.py @@ -68,6 +68,8 @@ class Scaffold(Command): if os.path.exists(controller_file): die("Controller `%s` already exists !" % controller_file) self.add_init_import(module('__init__.py'), 'controllers') + # Check if the controller name correspond to a model and expose result to templates + args.has_model = self.has_import(module('models', '__init__.py'), controller_module) self.add_init_import(module('controllers', '__init__.py'), controller_module) self.dump('controllers.jinja2', module('controllers', controller_file), config=args) diff --git a/openerp/cli/scaffold/controllers.jinja2 b/openerp/cli/scaffold/controllers.jinja2 index db08e62c375..78099b1f939 100644 --- a/openerp/cli/scaffold/controllers.jinja2 +++ b/openerp/cli/scaffold/controllers.jinja2 @@ -6,8 +6,8 @@ class {{ config.controller }}(main.Home): @http.route('/{{ config.module }}/{{ config.controller }}', auth='public') def index(self): return "Hello, world!" -{% if config.model %} - @http.route('/{{ config.module }}/{{ config.controller }}/{{ config.model }}/'], type='http', auth='public') - def {{ config.model }}(self, {{ config.model }}, **kw): - return "Hello, %r!" % {{ config.model }} +{% if config.has_model %} + @http.route('/{{ config.module }}/{{ config.controller }}/'], type='http', auth='public') + def {{ config.controller }}(self, {{ config.controller }}, **kw): + return "Hello, %r!" % {{ config.controller }} {% endif %} From 4b8814fa9ef56dfe287c661de9f2156ce81fb33c Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Wed, 28 May 2014 19:32:55 +0200 Subject: [PATCH 11/23] Prevent scaffold --init to be executed in another module --- openerp/cli/scaffold.py | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/openerp/cli/scaffold.py b/openerp/cli/scaffold.py index 8d580eba0b4..4ea1fbd0200 100644 --- a/openerp/cli/scaffold.py +++ b/openerp/cli/scaffold.py @@ -33,21 +33,16 @@ class Scaffold(Command): dest = directory(args.dest) if args.init: - module_name = snake(args.init) - module = functools.partial(os.path.join, dest, module_name) + args.module = snake(args.init) + module = functools.partial(os.path.join, dest, args.module) if os.path.exists(module()): die("Can't initialize module in `%s`: Directory already exists." % module()) + if self.get_module_root(dest): + die("Can't init a new module in another module, you probably want to run this " + "command from your project's root") else: - module_name = dest.split(os.path.sep)[-1] - # find the module's root directory - while not os.path.exists(os.path.join(dest, '%s.py' % self.manifest)): - new_dest = os.path.abspath(os.path.join(dest, os.pardir)) - if dest == new_dest: - die("Can't find module directory. Please `cd` to it's path or use --dest") - module_name = dest.split(os.path.sep)[-1] - dest = new_dest + args.module, dest = self.get_module_root(dest) module = functools.partial(os.path.join, dest) - args.module = module_name if args.init: self.dump('%s.jinja2' % self.manifest, module('%s.py' % self.manifest), config=args) @@ -73,6 +68,17 @@ class Scaffold(Command): self.add_init_import(module('controllers', '__init__.py'), controller_module) self.dump('controllers.jinja2', module('controllers', controller_file), config=args) + def get_module_root(self, path): + module_name = path.split(os.path.sep)[-1] + # find the module's root directory + while not os.path.exists(os.path.join(path, '%s.py' % self.manifest)): + new_path = os.path.abspath(os.path.join(path, os.pardir)) + if path == new_path: + return None + module_name = path.split(os.path.sep)[-1] + path = new_path + return (module_name, path) + def has_import(self, initfile, module): with open(initfile, 'r') as f: for imp in ast.parse(f.read()).body: From 14f7d31a5f3d37f051b26d329eefd470ce010d5c Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 29 May 2014 16:25:30 +0200 Subject: [PATCH 12/23] Refactor scaffolding engine so it can be used from outside --- openerp/cli/scaffold.py | 204 +++++++++++--------- openerp/cli/scaffold/__init__.jinja2 | 2 +- openerp/cli/scaffold/__openerp__.jinja2 | 3 +- openerp/cli/scaffold/controllers.jinja2 | 12 +- openerp/cli/scaffold/ir.model.access.jinja2 | 10 +- openerp/cli/scaffold/models.jinja2 | 4 +- 6 files changed, 130 insertions(+), 105 deletions(-) diff --git a/openerp/cli/scaffold.py b/openerp/cli/scaffold.py index 4ea1fbd0200..930d454e831 100644 --- a/openerp/cli/scaffold.py +++ b/openerp/cli/scaffold.py @@ -12,94 +12,11 @@ import jinja2 from . import Command +MANIFEST = '__openerp__' + class Scaffold(Command): "Generate an Odoo module skeleton." - def __init__(self): - super(Scaffold, self).__init__() - env = jinja2.Environment(loader=jinja2.PackageLoader( - 'openerp.cli', 'scaffold')) - env.filters['snake'] = snake - self.env = env - self.manifest = '__openerp__' - - def scaffold(self, args): - args.dependency = 'base' - # TODO: update dependencies according to --web and --theme - # if args.web: - # args.dependency = 'web' - # elif args.theme: - # args.dependency = 'website' - - dest = directory(args.dest) - if args.init: - args.module = snake(args.init) - module = functools.partial(os.path.join, dest, args.module) - if os.path.exists(module()): - die("Can't initialize module in `%s`: Directory already exists." % module()) - if self.get_module_root(dest): - die("Can't init a new module in another module, you probably want to run this " - "command from your project's root") - else: - args.module, dest = self.get_module_root(dest) - module = functools.partial(os.path.join, dest) - - if args.init: - self.dump('%s.jinja2' % self.manifest, module('%s.py' % self.manifest), config=args) - - if args.model: - model_module = snake(args.model) - model_file = module('models', '%s.py' % model_module) - if os.path.exists(model_file): - die("Model `%s` already exists !" % model_file) - self.add_init_import(module('__init__.py'), 'models') - self.add_init_import(module('models', '__init__.py'), model_module) - self.dump('models.jinja2', model_file, config=args) - self.dump('ir.model.access.jinja2', module('security', 'ir.model.access.csv'), config=args) - - if args.controller: - controller_module = snake(args.controller) - controller_file = module('controllers', '%s.py' % controller_module) - if os.path.exists(controller_file): - die("Controller `%s` already exists !" % controller_file) - self.add_init_import(module('__init__.py'), 'controllers') - # Check if the controller name correspond to a model and expose result to templates - args.has_model = self.has_import(module('models', '__init__.py'), controller_module) - self.add_init_import(module('controllers', '__init__.py'), controller_module) - self.dump('controllers.jinja2', module('controllers', controller_file), config=args) - - def get_module_root(self, path): - module_name = path.split(os.path.sep)[-1] - # find the module's root directory - while not os.path.exists(os.path.join(path, '%s.py' % self.manifest)): - new_path = os.path.abspath(os.path.join(path, os.pardir)) - if path == new_path: - return None - module_name = path.split(os.path.sep)[-1] - path = new_path - return (module_name, path) - - def has_import(self, initfile, module): - with open(initfile, 'r') as f: - for imp in ast.parse(f.read()).body: - if isinstance(imp, ast.Import): - if module in [mod.name for mod in imp.names]: - return True - return False - - def add_init_import(self, initfile, module): - if not(os.path.exists(initfile) and self.has_import(initfile, module)): - self.dump('__init__.jinja2', initfile, modules=[module]) - - def dump(self, template, dest, **kwargs): - outdir = os.path.dirname(dest) - kwargs['create'] = not os.path.exists(dest) - if not os.path.exists(outdir): - os.makedirs(outdir) - content = self.env.get_template(template).render(**kwargs) - with open(dest, 'a') as f: - f.write(content) - def run(self, args): # TODO: bash completion file parser = argparse.ArgumentParser( @@ -124,7 +41,99 @@ class Scaffold(Command): if not args: sys.exit(parser.print_help()) args = parser.parse_args(args=args) - self.scaffold(args) + + dest = directory(args.dest) + if args.init: + dest = os.path.join(dest, args.init) + if os.path.exists(dest): + die("Can't initialize module in `%s`: Directory already exists." % dest) + if get_module_root(dest): + die("Can't init a new module in another Odoo module, you probably want to run this " + "command from your project's root") + else: + mroot = get_module_root(dest) + if not mroot: + die("The path `%s` provided does not point to an existing Odoo module. " + "Forgot to `--init` ?" % dest) + dest = mroot + + scaffold = ScaffoldModule(dest) + if args.model: + scaffold.add_model(args.model) + if args.controller: + scaffold.add_controller(args.controller) + +class ScaffoldModule(object): + """ + Object for scaffolding existing or new Odoo modules + + @param path: Path of an existing module or path of module to create + """ + def __init__(self, path): + env = jinja2.Environment(loader=jinja2.PackageLoader( + 'openerp.cli', 'scaffold')) + env.filters['snake'] = snake + self.env = env + self.path = functools.partial(os.path.join, directory(path)) + self.created = not os.path.exists(self.path()) + directory(path, create=True) + if self.created: + self.module_name = self.path().split(os.path.sep)[-1] + self.dump('%s.jinja2' % MANIFEST, self.path('%s.py' % MANIFEST)) + else: + # TODO: get this information from manifest + self.module_name = self.path().split(os.path.sep)[-1] + + def add_model(self, model): + model_module = snake(model) + model_file = self.path('models', '%s.py' % model_module) + if os.path.exists(model_file): + die("Model `%s` already exists !" % model_file) + self.add_init_import(self.path('__init__.py'), 'models') + self.add_init_import(self.path('models', '__init__.py'), model_module) + self.dump('models.jinja2', model_file, model=model) + self.dump('ir.model.access.jinja2', self.path('security', 'ir.model.access.csv'), model=model) + + def add_controller(self, controller): + controller_module = snake(controller) + controller_file = self.path('controllers', '%s.py' % controller_module) + if os.path.exists(controller_file): + die("Controller `%s` already exists !" % controller_file) + self.add_init_import(self.path('__init__.py'), 'controllers') + # Check if the controller name correspond to a model and expose result to templates + has_model = self.has_import(self.path('models', '__init__.py'), controller_module) + self.add_init_import(self.path('controllers', '__init__.py'), controller_module) + self.dump('controllers.jinja2', self.path('controllers', controller_file), + controller=controller, has_model=has_model) + + def has_import(self, initfile, module): + with open(initfile, 'r') as f: + for imp in ast.parse(f.read()).body: + if isinstance(imp, ast.Import): + if module in [mod.name for mod in imp.names]: + return True + return False + + def ensure_dependency_to(self, module): + # TODO: update dependencies according to --web and --theme + # if args.web: + # args.dependency = 'web' + # elif args.theme: + # args.dependency = 'website' + pass + + def add_init_import(self, initfile, module): + if not(os.path.exists(initfile) and self.has_import(initfile, module)): + self.dump('__init__.jinja2', initfile, modules=[module]) + + def dump(self, template, dest, **kwargs): + outdir = os.path.dirname(dest) + kwargs['file_created'] = not os.path.exists(dest) + if not os.path.exists(outdir): + os.makedirs(outdir) + content = self.env.get_template(template).render(module_name=self.module_name, **kwargs) + with open(dest, 'a') as f: + f.write(content) def snake(s): """ snake cases ``s`` @@ -145,16 +154,33 @@ def identifier(s): die("%s is not a valid Python identifier" % s) return s -def directory(p): +def directory(p, create=False): expanded = os.path.abspath( os.path.expanduser( os.path.expandvars(p))) - if not os.path.exists(expanded): + if create and not os.path.exists(expanded): os.makedirs(expanded) - if not os.path.isdir(expanded): + if create and not os.path.isdir(expanded): die("%s exists but is not a directory" % p) return expanded +def get_module_root(path): + """ + Get closest module's root begining from path + + @param path: Path from which the lookup should start + + @return: Module root path + """ + # find the module's root directory + while not os.path.exists(os.path.join(path, '%s.py' % MANIFEST)): + new_path = os.path.abspath(os.path.join(path, os.pardir)) + if path == new_path: + return None + path = new_path + return path + + def die(message, code=1): print >>sys.stderr, message sys.exit(code) diff --git a/openerp/cli/scaffold/__init__.jinja2 b/openerp/cli/scaffold/__init__.jinja2 index b3cd02662e0..e8b1efb3fc7 100644 --- a/openerp/cli/scaffold/__init__.jinja2 +++ b/openerp/cli/scaffold/__init__.jinja2 @@ -1,3 +1,3 @@ -{% if create -%}# -*- coding: utf-8 -*-{%- endif %} +{% if file_created -%}# -*- coding: utf-8 -*-{%- endif %} {% for module in modules if module -%}import {{ module }} {%- endfor %} diff --git a/openerp/cli/scaffold/__openerp__.jinja2 b/openerp/cli/scaffold/__openerp__.jinja2 index c8bd331d063..38f60d5241b 100644 --- a/openerp/cli/scaffold/__openerp__.jinja2 +++ b/openerp/cli/scaffold/__openerp__.jinja2 @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- { - 'name': "{{ config.module }}", + 'name': "{{ module_name }}", 'summary': """ Short (1 phrase/line) summary of the module's purpose, used as @@ -21,7 +21,6 @@ # any module necessary for this one to work correctly 'depends': ['base'], 'data': [ - # {{- "'security/ir.model.access.csv'" if config.model -}} ], 'demo': [ diff --git a/openerp/cli/scaffold/controllers.jinja2 b/openerp/cli/scaffold/controllers.jinja2 index 78099b1f939..d8756e76524 100644 --- a/openerp/cli/scaffold/controllers.jinja2 +++ b/openerp/cli/scaffold/controllers.jinja2 @@ -2,12 +2,12 @@ from openerp import http from openerp.addons.web.controllers import main -class {{ config.controller }}(main.Home): - @http.route('/{{ config.module }}/{{ config.controller }}', auth='public') +class {{ controller }}(main.Home): + @http.route('/{{ module_name }}/{{ controller }}', auth='public') def index(self): return "Hello, world!" -{% if config.has_model %} - @http.route('/{{ config.module }}/{{ config.controller }}/'], type='http', auth='public') - def {{ config.controller }}(self, {{ config.controller }}, **kw): - return "Hello, %r!" % {{ config.controller }} +{% if has_model %} + @http.route('/{{ module_name }}/{{ controller }}/'], type='http', auth='public') + def {{ controller }}(self, {{ controller }}, **kw): + return "Hello, %r!" % {{ controller }} {% endif %} diff --git a/openerp/cli/scaffold/ir.model.access.jinja2 b/openerp/cli/scaffold/ir.model.access.jinja2 index e047031a15a..96bec7ba9f2 100644 --- a/openerp/cli/scaffold/ir.model.access.jinja2 +++ b/openerp/cli/scaffold/ir.model.access.jinja2 @@ -1,6 +1,6 @@ -{% if create -%}id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink{%- endif %} -{% if config.model -%} -access_{{ config.module|snake }}_{{ config.model|snake }},{{- '' -}} -access_{{ config.module|snake }}_{{ config.model|snake }},{{- '' -}} -model_{{ config.module|snake }}_{{ config.model|snake }},,1,0,0,0 +{% if file_created -%}id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink{%- endif %} +{% if model -%} +access_{{ module_name|snake }}_{{ model|snake }},{{- '' -}} +access_{{ module_name|snake }}_{{ model|snake }},{{- '' -}} +model_{{ module_name|snake }}_{{ model|snake }},,1,0,0,0 {%- endif %} diff --git a/openerp/cli/scaffold/models.jinja2 b/openerp/cli/scaffold/models.jinja2 index 878bf9be4f6..6fe3aceadd3 100644 --- a/openerp/cli/scaffold/models.jinja2 +++ b/openerp/cli/scaffold/models.jinja2 @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- from openerp.osv import orm, fields -class {{ config.model }}(orm.Model): - _name = "{{ config.module|snake }}.{{ config.model|snake }}" +class {{ model }}(orm.Model): + _name = "{{ module_name|snake }}.{{ model|snake }}" _columns = { 'name': fields.char(), From 5f717cfdd2b638887fa11f5ed81ac24985c4fbcc Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 29 May 2014 18:01:43 +0200 Subject: [PATCH 13/23] Added basic scaffolding for webclient module --- openerp/cli/scaffold.py | 36 ++++++++++++++++------- openerp/cli/scaffold/webclient_css.jinja2 | 4 +++ openerp/cli/scaffold/webclient_js.jinja2 | 9 ++++++ openerp/cli/scaffold/webclient_xml.jinja2 | 7 +++++ 4 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 openerp/cli/scaffold/webclient_css.jinja2 create mode 100644 openerp/cli/scaffold/webclient_js.jinja2 create mode 100644 openerp/cli/scaffold/webclient_xml.jinja2 diff --git a/openerp/cli/scaffold.py b/openerp/cli/scaffold.py index 930d454e831..700ffbbd212 100644 --- a/openerp/cli/scaffold.py +++ b/openerp/cli/scaffold.py @@ -62,6 +62,8 @@ class Scaffold(Command): scaffold.add_model(args.model) if args.controller: scaffold.add_controller(args.controller) + if args.web: + scaffold.add_webclient_structure() class ScaffoldModule(object): """ @@ -79,7 +81,7 @@ class ScaffoldModule(object): directory(path, create=True) if self.created: self.module_name = self.path().split(os.path.sep)[-1] - self.dump('%s.jinja2' % MANIFEST, self.path('%s.py' % MANIFEST)) + self.render_file('%s.jinja2' % MANIFEST, self.path('%s.py' % MANIFEST)) else: # TODO: get this information from manifest self.module_name = self.path().split(os.path.sep)[-1] @@ -91,8 +93,9 @@ class ScaffoldModule(object): die("Model `%s` already exists !" % model_file) self.add_init_import(self.path('__init__.py'), 'models') self.add_init_import(self.path('models', '__init__.py'), model_module) - self.dump('models.jinja2', model_file, model=model) - self.dump('ir.model.access.jinja2', self.path('security', 'ir.model.access.csv'), model=model) + self.render_file('models.jinja2', model_file, model=model) + self.render_file('ir.model.access.jinja2', self.path('security', 'ir.model.access.csv'), + if_exists='append', model=model) def add_controller(self, controller): controller_module = snake(controller) @@ -103,8 +106,14 @@ class ScaffoldModule(object): # Check if the controller name correspond to a model and expose result to templates has_model = self.has_import(self.path('models', '__init__.py'), controller_module) self.add_init_import(self.path('controllers', '__init__.py'), controller_module) - self.dump('controllers.jinja2', self.path('controllers', controller_file), - controller=controller, has_model=has_model) + self.render_file('controllers.jinja2', controller_file, controller=controller, + has_model=has_model) + + def add_webclient_structure(self): + prefix = '%s.%%s' % self.module_name + for ext in ('js', 'css', 'xml'): + self.render_file('webclient_%s.jinja2' % ext, + self.path('static', 'src', ext, prefix % ext)) def has_import(self, initfile, module): with open(initfile, 'r') as f: @@ -124,15 +133,23 @@ class ScaffoldModule(object): def add_init_import(self, initfile, module): if not(os.path.exists(initfile) and self.has_import(initfile, module)): - self.dump('__init__.jinja2', initfile, modules=[module]) + self.render_file('__init__.jinja2', initfile, if_exists='append', modules=[module]) - def dump(self, template, dest, **kwargs): + def render_file(self, template, dest, if_exists='skip', **kwargs): + mode = 'a' + if os.path.exists(dest): + if if_exists == 'replace': + mode = 'w' + elif if_exists != 'append': + print "File `%s` already exists. Skipping it..." % dest + return + else: + kwargs['file_created'] = True outdir = os.path.dirname(dest) - kwargs['file_created'] = not os.path.exists(dest) if not os.path.exists(outdir): os.makedirs(outdir) content = self.env.get_template(template).render(module_name=self.module_name, **kwargs) - with open(dest, 'a') as f: + with open(dest, mode) as f: f.write(content) def snake(s): @@ -180,7 +197,6 @@ def get_module_root(path): path = new_path return path - def die(message, code=1): print >>sys.stderr, message sys.exit(code) diff --git a/openerp/cli/scaffold/webclient_css.jinja2 b/openerp/cli/scaffold/webclient_css.jinja2 new file mode 100644 index 00000000000..b4955fa33ce --- /dev/null +++ b/openerp/cli/scaffold/webclient_css.jinja2 @@ -0,0 +1,4 @@ +@charset "utf-8"; +.openerp .oe_{{ module_name|snake }} { + background: white; +} diff --git a/openerp/cli/scaffold/webclient_js.jinja2 b/openerp/cli/scaffold/webclient_js.jinja2 new file mode 100644 index 00000000000..2ee203baeb4 --- /dev/null +++ b/openerp/cli/scaffold/webclient_js.jinja2 @@ -0,0 +1,9 @@ +openerp.{{ module_name|snake }} = function (instance) { + +var _t = instance.web._t, + _lt = instance.web._lt; +var QWeb = instance.web.qweb; + +instance.{{ module_name|snake }}.MyClientAction = null; // TODO: scaffold client action + +}; diff --git a/openerp/cli/scaffold/webclient_xml.jinja2 b/openerp/cli/scaffold/webclient_xml.jinja2 new file mode 100644 index 00000000000..8ae117ce494 --- /dev/null +++ b/openerp/cli/scaffold/webclient_xml.jinja2 @@ -0,0 +1,7 @@ + From 0e01164842459a14ba76e6e4703a91d57ce90650 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 29 May 2014 18:23:48 +0200 Subject: [PATCH 14/23] Moved get_module_root in openerp.modules.module --- openerp/cli/scaffold.py | 17 +---------------- openerp/modules/module.py | 35 ++++++++++++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/openerp/cli/scaffold.py b/openerp/cli/scaffold.py index 700ffbbd212..7268bbc9cb7 100644 --- a/openerp/cli/scaffold.py +++ b/openerp/cli/scaffold.py @@ -11,6 +11,7 @@ import sys import jinja2 from . import Command +from openerp.modules.module import get_module_root MANIFEST = '__openerp__' @@ -181,22 +182,6 @@ def directory(p, create=False): die("%s exists but is not a directory" % p) return expanded -def get_module_root(path): - """ - Get closest module's root begining from path - - @param path: Path from which the lookup should start - - @return: Module root path - """ - # find the module's root directory - while not os.path.exists(os.path.join(path, '%s.py' % MANIFEST)): - new_path = os.path.abspath(os.path.join(path, os.pardir)) - if path == new_path: - return None - path = new_path - return path - def die(message, code=1): print >>sys.stderr, message sys.exit(code) diff --git a/openerp/modules/module.py b/openerp/modules/module.py index 0ccb2865796..0691c98768b 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -37,6 +37,8 @@ import openerp.tools as tools import openerp.release as release from openerp.tools.safe_eval import safe_eval as eval +MANIFEST = '__openerp__.py' + _logger = logging.getLogger(__name__) # addons path as a list @@ -169,6 +171,33 @@ def get_module_icon(module): return ('/' + module + '/') + '/'.join(iconpath) return '/base/' + '/'.join(iconpath) +def get_module_root(path): + """ + Get closest module's root begining from path + + # Given: + # /foo/bar/module_dir/static/src/... + + get_module_root('/foo/bar/module_dir/static/') + # returns '/foo/bar/module_dir' + + get_module_root('/foo/bar/module_dir/') + # returns '/foo/bar/module_dir' + + get_module_root('/foo/bar') + # returns None + + @param path: Path from which the lookup should start + + @return: Module root path or None if not found + """ + while not os.path.exists(os.path.join(path, MANIFEST)): + new_path = os.path.abspath(os.path.join(path, os.pardir)) + if path == new_path: + return None + path = new_path + return path + def load_information_from_description_file(module, mod_path=None): """ :param module: The name of the module (sale, purchase, ...) @@ -177,7 +206,7 @@ def load_information_from_description_file(module, mod_path=None): if not mod_path: mod_path = get_module_path(module) - terp_file = mod_path and opj(mod_path, '__openerp__.py') or False + terp_file = mod_path and opj(mod_path, MANIFEST) or False if terp_file: info = {} if os.path.isfile(terp_file): @@ -219,7 +248,7 @@ def load_information_from_description_file(module, mod_path=None): #TODO: refactor the logger in this file to follow the logging guidelines # for 6.0 - _logger.debug('module %s: no __openerp__.py file found.', module) + _logger.debug('module %s: no %s file found.', module, MANIFEST) return {} def init_module_models(cr, module_name, obj_list): @@ -291,7 +320,7 @@ def get_modules(): return name def is_really_module(name): - manifest_name = opj(dir, name, '__openerp__.py') + manifest_name = opj(dir, name, MANIFEST) zipfile_name = opj(dir, name) return os.path.isfile(manifest_name) return map(clean, filter(is_really_module, os.listdir(dir))) From 36485190acb2f68ebdda906aee6b250ffef68dc5 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Thu, 29 May 2014 20:02:30 +0200 Subject: [PATCH 15/23] Update manifest for dependencies --- openerp/cli/scaffold.py | 57 ++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 15 deletions(-) diff --git a/openerp/cli/scaffold.py b/openerp/cli/scaffold.py index 7268bbc9cb7..c882e33c0c3 100644 --- a/openerp/cli/scaffold.py +++ b/openerp/cli/scaffold.py @@ -4,16 +4,19 @@ import argparse import ast import functools import keyword +import logging import os import re +import simplejson import sys import jinja2 from . import Command -from openerp.modules.module import get_module_root -MANIFEST = '__openerp__' +from openerp.modules.module import (get_module_root, MANIFEST, + load_information_from_description_file as load_manifest) + class Scaffold(Command): "Generate an Odoo module skeleton." @@ -58,6 +61,7 @@ class Scaffold(Command): "Forgot to `--init` ?" % dest) dest = mroot + logging.disable(logging.CRITICAL) scaffold = ScaffoldModule(dest) if args.model: scaffold.add_model(args.model) @@ -80,12 +84,10 @@ class ScaffoldModule(object): self.path = functools.partial(os.path.join, directory(path)) self.created = not os.path.exists(self.path()) directory(path, create=True) + self.module_name = self.path().split(os.path.sep)[-1] if self.created: - self.module_name = self.path().split(os.path.sep)[-1] - self.render_file('%s.jinja2' % MANIFEST, self.path('%s.py' % MANIFEST)) - else: - # TODO: get this information from manifest - self.module_name = self.path().split(os.path.sep)[-1] + manifest_base = os.path.splitext(MANIFEST)[0] + self.render_file('%s.jinja2' % manifest_base, self.path('%s.py' % manifest_base)) def add_model(self, model): model_module = snake(model) @@ -111,6 +113,7 @@ class ScaffoldModule(object): has_model=has_model) def add_webclient_structure(self): + self.append_manifest_list('depends', 'web') prefix = '%s.%%s' % self.module_name for ext in ('js', 'css', 'xml'): self.render_file('webclient_%s.jinja2' % ext, @@ -124,13 +127,32 @@ class ScaffoldModule(object): return True return False - def ensure_dependency_to(self, module): - # TODO: update dependencies according to --web and --theme - # if args.web: - # args.dependency = 'web' - # elif args.theme: - # args.dependency = 'website' - pass + def get_manifest(self, key=None, default=None): + manifest = load_manifest(self.module_name, self.path()) + if key: + return manifest.get(key, default) + else: + return manifest + + def append_manifest_list(self, key, value, unique=True): + vals = self.get_manifest(key, []) + if unique and value in vals: + return + vals.append(value) + self.change_manifest_key(key, vals) + + def change_manifest_key(self, key, value): + value = simplejson.dumps(value) + with open(self.path(MANIFEST), 'r') as f: + data = f.read() + sdata = re.split('["\']%s["\']\s?:\s?\[[^\]]*\]' % key, data) + add = "'%s': %s" % (key, value) + if len(sdata) != 2: + warn("Could not update `%s` key in manifest. You should add this by yourself:" + "\n\n%s\n" % (key, add)) + else: + with open(self.path(MANIFEST), 'w') as f: + f.write(add.join(sdata)) def add_init_import(self, initfile, module): if not(os.path.exists(initfile) and self.has_import(initfile, module)): @@ -142,7 +164,7 @@ class ScaffoldModule(object): if if_exists == 'replace': mode = 'w' elif if_exists != 'append': - print "File `%s` already exists. Skipping it..." % dest + warn("File `%s` already exists. Skipping it..." % dest) return else: kwargs['file_created'] = True @@ -185,3 +207,8 @@ def directory(p, create=False): def die(message, code=1): print >>sys.stderr, message sys.exit(code) + +def warn(message): + # ASK: shall we use logger ? + print "WARNING: " + message + From 7f984dd6ef78d650046bdabf35fa314590b31ffd Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Fri, 30 May 2014 10:45:57 +0200 Subject: [PATCH 16/23] Added ir.model.access in manifest --- openerp/cli/scaffold.py | 4 +++- openerp/cli/scaffold/ir.model.access.jinja2 | 6 +++--- openerp/cli/scaffold/models.jinja2 | 2 +- openerp/cli/scaffold/webclient_css.jinja2 | 2 +- openerp/cli/scaffold/webclient_js.jinja2 | 9 +++++++-- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/openerp/cli/scaffold.py b/openerp/cli/scaffold.py index c882e33c0c3..58d63aed365 100644 --- a/openerp/cli/scaffold.py +++ b/openerp/cli/scaffold.py @@ -64,7 +64,7 @@ class Scaffold(Command): logging.disable(logging.CRITICAL) scaffold = ScaffoldModule(dest) if args.model: - scaffold.add_model(args.model) + scaffold.add_model(snake(args.model)) if args.controller: scaffold.add_controller(args.controller) if args.web: @@ -99,6 +99,7 @@ class ScaffoldModule(object): self.render_file('models.jinja2', model_file, model=model) self.render_file('ir.model.access.jinja2', self.path('security', 'ir.model.access.csv'), if_exists='append', model=model) + self.append_manifest_list('data', 'security/ir.model.access.csv') def add_controller(self, controller): controller_module = snake(controller) @@ -135,6 +136,7 @@ class ScaffoldModule(object): return manifest def append_manifest_list(self, key, value, unique=True): + # TODO: append value without altering serialized formatting vals = self.get_manifest(key, []) if unique and value in vals: return diff --git a/openerp/cli/scaffold/ir.model.access.jinja2 b/openerp/cli/scaffold/ir.model.access.jinja2 index 96bec7ba9f2..bf00ba51972 100644 --- a/openerp/cli/scaffold/ir.model.access.jinja2 +++ b/openerp/cli/scaffold/ir.model.access.jinja2 @@ -1,6 +1,6 @@ {% if file_created -%}id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink{%- endif %} {% if model -%} -access_{{ module_name|snake }}_{{ model|snake }},{{- '' -}} -access_{{ module_name|snake }}_{{ model|snake }},{{- '' -}} -model_{{ module_name|snake }}_{{ model|snake }},,1,0,0,0 +access_{{ module_name }}_{{ model }},{{- '' -}} +access_{{ module_name }}_{{ model }},{{- '' -}} +model_{{ module_name }}_{{ model }},,1,0,0,0 {%- endif %} diff --git a/openerp/cli/scaffold/models.jinja2 b/openerp/cli/scaffold/models.jinja2 index 6fe3aceadd3..d5c82cfa7c6 100644 --- a/openerp/cli/scaffold/models.jinja2 +++ b/openerp/cli/scaffold/models.jinja2 @@ -2,7 +2,7 @@ from openerp.osv import orm, fields class {{ model }}(orm.Model): - _name = "{{ module_name|snake }}.{{ model|snake }}" + _name = "{{ module_name }}.{{ model }}" _columns = { 'name': fields.char(), diff --git a/openerp/cli/scaffold/webclient_css.jinja2 b/openerp/cli/scaffold/webclient_css.jinja2 index b4955fa33ce..b1d4da5c22b 100644 --- a/openerp/cli/scaffold/webclient_css.jinja2 +++ b/openerp/cli/scaffold/webclient_css.jinja2 @@ -1,4 +1,4 @@ @charset "utf-8"; -.openerp .oe_{{ module_name|snake }} { +.openerp .oe_{{ module_name }} { background: white; } diff --git a/openerp/cli/scaffold/webclient_js.jinja2 b/openerp/cli/scaffold/webclient_js.jinja2 index 2ee203baeb4..34a168961ae 100644 --- a/openerp/cli/scaffold/webclient_js.jinja2 +++ b/openerp/cli/scaffold/webclient_js.jinja2 @@ -1,9 +1,14 @@ -openerp.{{ module_name|snake }} = function (instance) { +openerp.{{ module_name }} = function (instance) { var _t = instance.web._t, _lt = instance.web._lt; var QWeb = instance.web.qweb; -instance.{{ module_name|snake }}.MyClientAction = null; // TODO: scaffold client action +instance.web.WebClient.include({ + show_application: function () { + console.log("Show application"); + return this._super.apply(this, arguments); + }; +}); }; From 10fb6525e90313691bb1f5e769b05b0ed974ae93 Mon Sep 17 00:00:00 2001 From: Fabien Meghazi Date: Fri, 30 May 2014 11:35:28 +0200 Subject: [PATCH 17/23] Basic support for xml data files --- openerp/cli/scaffold.py | 29 ++++++++++++++++++--- openerp/cli/scaffold/__openerp__.jinja2 | 2 +- openerp/cli/scaffold/controllers.jinja2 | 4 +-- openerp/cli/scaffold/ir.model.access.jinja2 | 6 ++--- openerp/cli/scaffold/models.jinja2 | 2 +- openerp/cli/scaffold/record.jinja2 | 4 +++ openerp/cli/scaffold/webclient_css.jinja2 | 2 +- openerp/cli/scaffold/webclient_js.jinja2 | 2 +- openerp/cli/scaffold/webclient_xml.jinja2 | 4 +-- openerp/cli/scaffold/xmldata.jinja2 | 5 ++++ 10 files changed, 45 insertions(+), 15 deletions(-) create mode 100644 openerp/cli/scaffold/record.jinja2 create mode 100644 openerp/cli/scaffold/xmldata.jinja2 diff --git a/openerp/cli/scaffold.py b/openerp/cli/scaffold.py index 58d63aed365..d7b28740355 100644 --- a/openerp/cli/scaffold.py +++ b/openerp/cli/scaffold.py @@ -84,7 +84,7 @@ class ScaffoldModule(object): self.path = functools.partial(os.path.join, directory(path)) self.created = not os.path.exists(self.path()) directory(path, create=True) - self.module_name = self.path().split(os.path.sep)[-1] + self.module = self.path().split(os.path.sep)[-1] if self.created: manifest_base = os.path.splitext(MANIFEST)[0] self.render_file('%s.jinja2' % manifest_base, self.path('%s.py' % manifest_base)) @@ -96,11 +96,17 @@ class ScaffoldModule(object): die("Model `%s` already exists !" % model_file) self.add_init_import(self.path('__init__.py'), 'models') self.add_init_import(self.path('models', '__init__.py'), model_module) + self.render_file('models.jinja2', model_file, model=model) self.render_file('ir.model.access.jinja2', self.path('security', 'ir.model.access.csv'), if_exists='append', model=model) self.append_manifest_list('data', 'security/ir.model.access.csv') + demo_file = '%s_demo.xml' % self.module + self.append_xml_data('record.jinja2', self.path(demo_file), + model=model) + self.append_manifest_list('demo', demo_file) + def add_controller(self, controller): controller_module = snake(controller) controller_file = self.path('controllers', '%s.py' % controller_module) @@ -115,7 +121,7 @@ class ScaffoldModule(object): def add_webclient_structure(self): self.append_manifest_list('depends', 'web') - prefix = '%s.%%s' % self.module_name + prefix = '%s.%%s' % self.module for ext in ('js', 'css', 'xml'): self.render_file('webclient_%s.jinja2' % ext, self.path('static', 'src', ext, prefix % ext)) @@ -129,7 +135,7 @@ class ScaffoldModule(object): return False def get_manifest(self, key=None, default=None): - manifest = load_manifest(self.module_name, self.path()) + manifest = load_manifest(self.module, self.path()) if key: return manifest.get(key, default) else: @@ -173,10 +179,25 @@ class ScaffoldModule(object): outdir = os.path.dirname(dest) if not os.path.exists(outdir): os.makedirs(outdir) - content = self.env.get_template(template).render(module_name=self.module_name, **kwargs) + content = self.env.get_template(template).render(module=self.module, **kwargs) with open(dest, mode) as f: f.write(content) + def append_xml_data(self, template, dest, **kwargs): + if not os.path.exists(dest): + self.render_file('xmldata.jinja2', dest, **kwargs) + with open(dest, 'r') as f: + data = f.read() + m = re.search('(^\s*)?', data, re.MULTILINE) + content = self.env.get_template(template).render(module=self.module, **kwargs) + if not m: + warn("Could not add data in `%s`. You should add this by yourself:" + "\n\n%s\n" % (dest, content)) + else: + data = data[:m.start()] + content + m.group() + data[m.end():] + with open(self.path(dest), 'w') as f: + f.write(data) + def snake(s): """ snake cases ``s`` diff --git a/openerp/cli/scaffold/__openerp__.jinja2 b/openerp/cli/scaffold/__openerp__.jinja2 index 38f60d5241b..43559042818 100644 --- a/openerp/cli/scaffold/__openerp__.jinja2 +++ b/openerp/cli/scaffold/__openerp__.jinja2 @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- { - 'name': "{{ module_name }}", + 'name': "{{ module }}", 'summary': """ Short (1 phrase/line) summary of the module's purpose, used as diff --git a/openerp/cli/scaffold/controllers.jinja2 b/openerp/cli/scaffold/controllers.jinja2 index d8756e76524..dfed6fb9bc0 100644 --- a/openerp/cli/scaffold/controllers.jinja2 +++ b/openerp/cli/scaffold/controllers.jinja2 @@ -3,11 +3,11 @@ from openerp import http from openerp.addons.web.controllers import main class {{ controller }}(main.Home): - @http.route('/{{ module_name }}/{{ controller }}', auth='public') + @http.route('/{{ module }}/{{ controller }}', auth='public') def index(self): return "Hello, world!" {% if has_model %} - @http.route('/{{ module_name }}/{{ controller }}/'], type='http', auth='public') + @http.route('/{{ module }}/{{ controller }}/'], type='http', auth='public') def {{ controller }}(self, {{ controller }}, **kw): return "Hello, %r!" % {{ controller }} {% endif %} diff --git a/openerp/cli/scaffold/ir.model.access.jinja2 b/openerp/cli/scaffold/ir.model.access.jinja2 index bf00ba51972..af558a3b625 100644 --- a/openerp/cli/scaffold/ir.model.access.jinja2 +++ b/openerp/cli/scaffold/ir.model.access.jinja2 @@ -1,6 +1,6 @@ {% if file_created -%}id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink{%- endif %} {% if model -%} -access_{{ module_name }}_{{ model }},{{- '' -}} -access_{{ module_name }}_{{ model }},{{- '' -}} -model_{{ module_name }}_{{ model }},,1,0,0,0 +access_{{ module }}_{{ model }},{{- '' -}} +access_{{ module }}_{{ model }},{{- '' -}} +model_{{ module }}_{{ model }},,1,0,0,0 {%- endif %} diff --git a/openerp/cli/scaffold/models.jinja2 b/openerp/cli/scaffold/models.jinja2 index d5c82cfa7c6..36155a2566d 100644 --- a/openerp/cli/scaffold/models.jinja2 +++ b/openerp/cli/scaffold/models.jinja2 @@ -2,7 +2,7 @@ from openerp.osv import orm, fields class {{ model }}(orm.Model): - _name = "{{ module_name }}.{{ model }}" + _name = "{{ module }}.{{ model }}" _columns = { 'name': fields.char(), diff --git a/openerp/cli/scaffold/record.jinja2 b/openerp/cli/scaffold/record.jinja2 new file mode 100644 index 00000000000..53e4ff22383 --- /dev/null +++ b/openerp/cli/scaffold/record.jinja2 @@ -0,0 +1,4 @@ + + My first record for model '{{ module }}.{{ model }}' + + diff --git a/openerp/cli/scaffold/webclient_css.jinja2 b/openerp/cli/scaffold/webclient_css.jinja2 index b1d4da5c22b..dadce53503b 100644 --- a/openerp/cli/scaffold/webclient_css.jinja2 +++ b/openerp/cli/scaffold/webclient_css.jinja2 @@ -1,4 +1,4 @@ @charset "utf-8"; -.openerp .oe_{{ module_name }} { +.openerp .oe_{{ module }} { background: white; } diff --git a/openerp/cli/scaffold/webclient_js.jinja2 b/openerp/cli/scaffold/webclient_js.jinja2 index 34a168961ae..9845e6f0662 100644 --- a/openerp/cli/scaffold/webclient_js.jinja2 +++ b/openerp/cli/scaffold/webclient_js.jinja2 @@ -1,4 +1,4 @@ -openerp.{{ module_name }} = function (instance) { +openerp.{{ module }} = function (instance) { var _t = instance.web._t, _lt = instance.web._lt; diff --git a/openerp/cli/scaffold/webclient_xml.jinja2 b/openerp/cli/scaffold/webclient_xml.jinja2 index 8ae117ce494..98da7f73133 100644 --- a/openerp/cli/scaffold/webclient_xml.jinja2 +++ b/openerp/cli/scaffold/webclient_xml.jinja2 @@ -1,6 +1,6 @@