|
@ -48,6 +48,7 @@ class ModulePrototyper(models.Model): |
|
|
by a developer to fix glitch that would sneak it during the generation of |
|
|
by a developer to fix glitch that would sneak it during the generation of |
|
|
files but also to add not supported features. |
|
|
files but also to add not supported features. |
|
|
""" |
|
|
""" |
|
|
|
|
|
|
|
|
_name = "module_prototyper" |
|
|
_name = "module_prototyper" |
|
|
_description = "Module Prototyper" |
|
|
_description = "Module Prototyper" |
|
|
|
|
|
|
|
@ -55,151 +56,214 @@ class ModulePrototyper(models.Model): |
|
|
""" |
|
|
""" |
|
|
Extract the content of default description |
|
|
Extract the content of default description |
|
|
""" |
|
|
""" |
|
|
filepath = '%s/../data/README.rst' % (os.path.dirname(__file__),) |
|
|
|
|
|
with open(filepath, 'r') as content_file: |
|
|
|
|
|
|
|
|
filepath = "%s/../data/README.rst" % (os.path.dirname(__file__),) |
|
|
|
|
|
with open(filepath, "r") as content_file: |
|
|
content = content_file.read() |
|
|
content = content_file.read() |
|
|
return content |
|
|
return content |
|
|
|
|
|
|
|
|
license = fields.Selection( |
|
|
license = fields.Selection( |
|
|
[ |
|
|
[ |
|
|
(licenses.GPL3, 'GPL Version 3'), |
|
|
|
|
|
(licenses.GPL3_L, 'GPL-3 or later version'), |
|
|
|
|
|
(licenses.LGPL3, 'LGPL-3'), |
|
|
|
|
|
(licenses.LGPL3_L, 'LGPL-3 or later version'), |
|
|
|
|
|
(licenses.AGPL3, 'Affero GPL-3'), |
|
|
|
|
|
(licenses.OSI, 'Other OSI Approved Licence'), |
|
|
|
|
|
('Other proprietary', 'Other Proprietary') |
|
|
|
|
|
|
|
|
(licenses.GPL3, "GPL Version 3"), |
|
|
|
|
|
(licenses.GPL3_L, "GPL-3 or later version"), |
|
|
|
|
|
(licenses.LGPL3, "LGPL-3"), |
|
|
|
|
|
(licenses.LGPL3_L, "LGPL-3 or later version"), |
|
|
|
|
|
(licenses.AGPL3, "Affero GPL-3"), |
|
|
|
|
|
(licenses.OSI, "Other OSI Approved Licence"), |
|
|
|
|
|
("Other proprietary", "Other Proprietary"), |
|
|
], |
|
|
], |
|
|
string='License', |
|
|
|
|
|
|
|
|
string="License", |
|
|
default=licenses.AGPL3, |
|
|
default=licenses.AGPL3, |
|
|
) |
|
|
) |
|
|
name = fields.Char( |
|
|
name = fields.Char( |
|
|
'Technical Name', required=True, |
|
|
|
|
|
help=('The technical name will be used to define the name of ' |
|
|
|
|
|
'the exported module, the name of the model.') |
|
|
|
|
|
|
|
|
"Technical Name", |
|
|
|
|
|
required=True, |
|
|
|
|
|
help=( |
|
|
|
|
|
"The technical name will be used to define the name of " |
|
|
|
|
|
"the exported module, the name of the model." |
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
category_id = fields.Many2one('ir.module.category', 'Category') |
|
|
|
|
|
|
|
|
category_id = fields.Many2one("ir.module.category", "Category") |
|
|
human_name = fields.Char( |
|
|
human_name = fields.Char( |
|
|
'Module Name', required=True, |
|
|
|
|
|
help=('The Module Name will be used as the displayed name of the ' |
|
|
|
|
|
'exported module.') |
|
|
|
|
|
|
|
|
"Module Name", |
|
|
|
|
|
required=True, |
|
|
|
|
|
help=( |
|
|
|
|
|
"The Module Name will be used as the displayed name of the " |
|
|
|
|
|
"exported module." |
|
|
|
|
|
), |
|
|
|
|
|
) |
|
|
|
|
|
summary = fields.Char( |
|
|
|
|
|
"Summary", required=True, help=("Enter a summary of your module") |
|
|
) |
|
|
) |
|
|
summary = fields.Char('Summary', required=True, |
|
|
|
|
|
help=('Enter a summary of your module')) |
|
|
|
|
|
description = fields.Text( |
|
|
description = fields.Text( |
|
|
'Description', |
|
|
|
|
|
|
|
|
"Description", |
|
|
required=True, |
|
|
required=True, |
|
|
help=('Enter the description of your module, what it does, how to ' |
|
|
|
|
|
'install, configure and use it, the roadmap or known issues. ' |
|
|
|
|
|
'The description will be exported in README.rst'), |
|
|
|
|
|
default=get_default_description |
|
|
|
|
|
) |
|
|
|
|
|
author = fields.Char('Author', required=True, help=('Enter your name')) |
|
|
|
|
|
|
|
|
help=( |
|
|
|
|
|
"Enter the description of your module, what it does, how to " |
|
|
|
|
|
"install, configure and use it, the roadmap or known issues. " |
|
|
|
|
|
"The description will be exported in README.rst" |
|
|
|
|
|
), |
|
|
|
|
|
default=get_default_description, |
|
|
|
|
|
) |
|
|
|
|
|
author = fields.Char("Author", required=True, help=("Enter your name")) |
|
|
maintainer = fields.Char( |
|
|
maintainer = fields.Char( |
|
|
'Maintainer', |
|
|
|
|
|
help=('Enter the name of the person or organization who will ' |
|
|
|
|
|
'maintain this module') |
|
|
|
|
|
|
|
|
"Maintainer", |
|
|
|
|
|
help=( |
|
|
|
|
|
"Enter the name of the person or organization who will " |
|
|
|
|
|
"maintain this module" |
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
website = fields.Char('Website', help=('Enter the URL of your website')) |
|
|
|
|
|
|
|
|
website = fields.Char("Website", help=("Enter the URL of your website")) |
|
|
icon_image = fields.Binary( |
|
|
icon_image = fields.Binary( |
|
|
'Icon', |
|
|
|
|
|
help=('The icon set up here will be used as the icon ' |
|
|
|
|
|
'for the exported module also') |
|
|
|
|
|
|
|
|
"Icon", |
|
|
|
|
|
help=( |
|
|
|
|
|
"The icon set up here will be used as the icon " |
|
|
|
|
|
"for the exported module also" |
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
version = fields.Char( |
|
|
version = fields.Char( |
|
|
'Version', |
|
|
|
|
|
|
|
|
"Version", |
|
|
size=10, |
|
|
size=10, |
|
|
default='10.0.1.0.0', |
|
|
|
|
|
help=('Enter the version of your module with 5 digits') |
|
|
|
|
|
|
|
|
default="10.0.1.0.0", |
|
|
|
|
|
help=("Enter the version of your module with 5 digits"), |
|
|
) |
|
|
) |
|
|
auto_install = fields.Boolean( |
|
|
auto_install = fields.Boolean( |
|
|
'Auto Install', |
|
|
|
|
|
|
|
|
"Auto Install", |
|
|
default=False, |
|
|
default=False, |
|
|
help='Check if the module should be install by default.' |
|
|
|
|
|
|
|
|
help="Check if the module should be install by default.", |
|
|
) |
|
|
) |
|
|
application = fields.Boolean( |
|
|
application = fields.Boolean( |
|
|
'Application', |
|
|
|
|
|
|
|
|
"Application", |
|
|
default=False, |
|
|
default=False, |
|
|
help='Check if the module is an Odoo application.' |
|
|
|
|
|
|
|
|
help="Check if the module is an Odoo application.", |
|
|
) |
|
|
) |
|
|
# Relations |
|
|
# Relations |
|
|
dependency_ids = fields.Many2many( |
|
|
dependency_ids = fields.Many2many( |
|
|
'ir.module.module', 'module_prototyper_module_rel', |
|
|
|
|
|
'module_prototyper_id', 'module_id', |
|
|
|
|
|
'Dependencies', |
|
|
|
|
|
help=('Enter the list of required modules that need to be installed ' |
|
|
|
|
|
'for your module to work properly') |
|
|
|
|
|
|
|
|
"ir.module.module", |
|
|
|
|
|
"module_prototyper_module_rel", |
|
|
|
|
|
"module_prototyper_id", |
|
|
|
|
|
"module_id", |
|
|
|
|
|
"Dependencies", |
|
|
|
|
|
help=( |
|
|
|
|
|
"Enter the list of required modules that need to be installed " |
|
|
|
|
|
"for your module to work properly" |
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
data_ids = fields.Many2many( |
|
|
data_ids = fields.Many2many( |
|
|
'ir.filters', |
|
|
|
|
|
'prototype_data_rel', |
|
|
|
|
|
'module_prototyper_id', 'filter_id', |
|
|
|
|
|
'Data filters', |
|
|
|
|
|
help="The records matching the filters will be added as data." |
|
|
|
|
|
|
|
|
"ir.filters", |
|
|
|
|
|
"prototype_data_rel", |
|
|
|
|
|
"module_prototyper_id", |
|
|
|
|
|
"filter_id", |
|
|
|
|
|
"Data filters", |
|
|
|
|
|
help="The records matching the filters will be added as data.", |
|
|
) |
|
|
) |
|
|
demo_ids = fields.Many2many( |
|
|
demo_ids = fields.Many2many( |
|
|
'ir.filters', |
|
|
|
|
|
'prototype_demo_rel', |
|
|
|
|
|
'module_prototyper_id', 'filter_id', |
|
|
|
|
|
'Demo filters', |
|
|
|
|
|
help="The records matching the filters will be added as demo data." |
|
|
|
|
|
|
|
|
"ir.filters", |
|
|
|
|
|
"prototype_demo_rel", |
|
|
|
|
|
"module_prototyper_id", |
|
|
|
|
|
"filter_id", |
|
|
|
|
|
"Demo filters", |
|
|
|
|
|
help="The records matching the filters will be added as demo data.", |
|
|
) |
|
|
) |
|
|
field_ids = fields.Many2many( |
|
|
field_ids = fields.Many2many( |
|
|
'ir.model.fields', 'prototype_fields_rel', |
|
|
|
|
|
'module_prototyper_id', 'field_id', 'Fields', |
|
|
|
|
|
help=('Enter the list of fields that you have created or modified ' |
|
|
|
|
|
'and want to export in this module. New models will be ' |
|
|
|
|
|
'exported as long as you choose one of his fields.') |
|
|
|
|
|
|
|
|
"ir.model.fields", |
|
|
|
|
|
"prototype_fields_rel", |
|
|
|
|
|
"module_prototyper_id", |
|
|
|
|
|
"field_id", |
|
|
|
|
|
"Fields", |
|
|
|
|
|
help=( |
|
|
|
|
|
"Enter the list of fields that you have created or modified " |
|
|
|
|
|
"and want to export in this module. New models will be " |
|
|
|
|
|
"exported as long as you choose one of his fields." |
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
menu_ids = fields.Many2many( |
|
|
menu_ids = fields.Many2many( |
|
|
'ir.ui.menu', 'prototype_menu_rel', |
|
|
|
|
|
'module_prototyper_id', 'menu_id', 'Menu Items', |
|
|
|
|
|
help=('Enter the list of menu items that you have created and want ' |
|
|
|
|
|
'to export in this module. Related windows actions will be ' |
|
|
|
|
|
'exported as well.') |
|
|
|
|
|
|
|
|
"ir.ui.menu", |
|
|
|
|
|
"prototype_menu_rel", |
|
|
|
|
|
"module_prototyper_id", |
|
|
|
|
|
"menu_id", |
|
|
|
|
|
"Menu Items", |
|
|
|
|
|
help=( |
|
|
|
|
|
"Enter the list of menu items that you have created and want " |
|
|
|
|
|
"to export in this module. Related windows actions will be " |
|
|
|
|
|
"exported as well." |
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
view_ids = fields.Many2many( |
|
|
view_ids = fields.Many2many( |
|
|
'ir.ui.view', 'prototype_view_rel', |
|
|
|
|
|
'module_prototyper_id', 'view_id', 'Views', |
|
|
|
|
|
help=('Enter the list of views that you have created and want to ' |
|
|
|
|
|
'export in this module.') |
|
|
|
|
|
|
|
|
"ir.ui.view", |
|
|
|
|
|
"prototype_view_rel", |
|
|
|
|
|
"module_prototyper_id", |
|
|
|
|
|
"view_id", |
|
|
|
|
|
"Views", |
|
|
|
|
|
help=( |
|
|
|
|
|
"Enter the list of views that you have created and want to " |
|
|
|
|
|
"export in this module." |
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
group_ids = fields.Many2many( |
|
|
group_ids = fields.Many2many( |
|
|
'res.groups', 'prototype_groups_rel', |
|
|
|
|
|
'module_prototyper_id', 'group_id', 'Groups', |
|
|
|
|
|
help=('Enter the list of groups that you have created and want to ' |
|
|
|
|
|
'export in this module.') |
|
|
|
|
|
|
|
|
"res.groups", |
|
|
|
|
|
"prototype_groups_rel", |
|
|
|
|
|
"module_prototyper_id", |
|
|
|
|
|
"group_id", |
|
|
|
|
|
"Groups", |
|
|
|
|
|
help=( |
|
|
|
|
|
"Enter the list of groups that you have created and want to " |
|
|
|
|
|
"export in this module." |
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
right_ids = fields.Many2many( |
|
|
right_ids = fields.Many2many( |
|
|
'ir.model.access', 'prototype_rights_rel', |
|
|
|
|
|
'module_prototyper_id', 'right_id', |
|
|
|
|
|
'Access Rights', |
|
|
|
|
|
help=('Enter the list of access rights that you have created and ' |
|
|
|
|
|
'want to export in this module.') |
|
|
|
|
|
|
|
|
"ir.model.access", |
|
|
|
|
|
"prototype_rights_rel", |
|
|
|
|
|
"module_prototyper_id", |
|
|
|
|
|
"right_id", |
|
|
|
|
|
"Access Rights", |
|
|
|
|
|
help=( |
|
|
|
|
|
"Enter the list of access rights that you have created and " |
|
|
|
|
|
"want to export in this module." |
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
rule_ids = fields.Many2many( |
|
|
rule_ids = fields.Many2many( |
|
|
'ir.rule', 'prototype_rule_rel', |
|
|
|
|
|
'module_prototyper_id', 'rule_id', 'Record Rules', |
|
|
|
|
|
help=('Enter the list of record rules that you have created and ' |
|
|
|
|
|
'want to export in this module.') |
|
|
|
|
|
|
|
|
"ir.rule", |
|
|
|
|
|
"prototype_rule_rel", |
|
|
|
|
|
"module_prototyper_id", |
|
|
|
|
|
"rule_id", |
|
|
|
|
|
"Record Rules", |
|
|
|
|
|
help=( |
|
|
|
|
|
"Enter the list of record rules that you have created and " |
|
|
|
|
|
"want to export in this module." |
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
report_ids = fields.Many2many( |
|
|
report_ids = fields.Many2many( |
|
|
'ir.actions.report.xml', 'prototype_report_rel', |
|
|
|
|
|
'module_prototyper_id', 'report_id', 'Reports', |
|
|
|
|
|
help=('Enter the list of reports that you have created and ' |
|
|
|
|
|
'want to export in this module.') |
|
|
|
|
|
|
|
|
"ir.actions.report.xml", |
|
|
|
|
|
"prototype_report_rel", |
|
|
|
|
|
"module_prototyper_id", |
|
|
|
|
|
"report_id", |
|
|
|
|
|
"Reports", |
|
|
|
|
|
help=( |
|
|
|
|
|
"Enter the list of reports that you have created and " |
|
|
|
|
|
"want to export in this module." |
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
activity_ids = fields.Many2many( |
|
|
activity_ids = fields.Many2many( |
|
|
'workflow.activity', 'prototype_wf_activity_rel', |
|
|
|
|
|
'module_prototyper_id', 'activity_id', 'Activities', |
|
|
|
|
|
help=('Enter the list of workflow activities that you have created ' |
|
|
|
|
|
'and want to export in this module') |
|
|
|
|
|
|
|
|
"workflow.activity", |
|
|
|
|
|
"prototype_wf_activity_rel", |
|
|
|
|
|
"module_prototyper_id", |
|
|
|
|
|
"activity_id", |
|
|
|
|
|
"Activities", |
|
|
|
|
|
help=( |
|
|
|
|
|
"Enter the list of workflow activities that you have created " |
|
|
|
|
|
"and want to export in this module" |
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
transition_ids = fields.Many2many( |
|
|
transition_ids = fields.Many2many( |
|
|
'workflow.transition', 'prototype_wf_transition_rel', |
|
|
|
|
|
'module_prototyper_id', 'transition_id', 'Transitions', |
|
|
|
|
|
help=('Enter the list of workflow transitions that you have created ' |
|
|
|
|
|
'and want to export in this module') |
|
|
|
|
|
|
|
|
"workflow.transition", |
|
|
|
|
|
"prototype_wf_transition_rel", |
|
|
|
|
|
"module_prototyper_id", |
|
|
|
|
|
"transition_id", |
|
|
|
|
|
"Transitions", |
|
|
|
|
|
help=( |
|
|
|
|
|
"Enter the list of workflow transitions that you have created " |
|
|
|
|
|
"and want to export in this module" |
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
_env = None |
|
|
_env = None |
|
@ -207,8 +271,8 @@ class ModulePrototyper(models.Model): |
|
|
_data_files = () |
|
|
_data_files = () |
|
|
_demo_files = () |
|
|
_demo_files = () |
|
|
_field_descriptions = None |
|
|
_field_descriptions = None |
|
|
File_details = namedtuple('file_details', ['filename', 'filecontent']) |
|
|
|
|
|
template_path = '%s/../templates/' % (os.path.dirname(__file__),) |
|
|
|
|
|
|
|
|
File_details = namedtuple("file_details", ["filename", "filecontent"]) |
|
|
|
|
|
template_path = "%s/../templates/" % (os.path.dirname(__file__),) |
|
|
|
|
|
|
|
|
@api.model |
|
|
@api.model |
|
|
def setup_env(self, api_version): |
|
|
def setup_env(self, api_version): |
|
@ -223,7 +287,7 @@ class ModulePrototyper(models.Model): |
|
|
trim_blocks=True, |
|
|
trim_blocks=True, |
|
|
loader=FileSystemLoader( |
|
|
loader=FileSystemLoader( |
|
|
os.path.join(self.template_path, api_version.name) |
|
|
os.path.join(self.template_path, api_version.name) |
|
|
) |
|
|
|
|
|
|
|
|
), |
|
|
) |
|
|
) |
|
|
self._api_version = api_version |
|
|
self._api_version = api_version |
|
|
return self._env |
|
|
return self._env |
|
@ -240,12 +304,14 @@ class ModulePrototyper(models.Model): |
|
|
# the mock will allow us to add data or modify the data |
|
|
# the mock will allow us to add data or modify the data |
|
|
# of the field (like for the name) with keeping all the |
|
|
# of the field (like for the name) with keeping all the |
|
|
# attributes of the record. |
|
|
# attributes of the record. |
|
|
field_description.update({ |
|
|
|
|
|
|
|
|
field_description.update( |
|
|
|
|
|
{ |
|
|
attr_name: getattr(field, attr_name) |
|
|
attr_name: getattr(field, attr_name) |
|
|
for attr_name in dir(field) |
|
|
for attr_name in dir(field) |
|
|
if not attr_name[0] == '_' |
|
|
|
|
|
}) |
|
|
|
|
|
field_description['name'] = self.unprefix(field.name) |
|
|
|
|
|
|
|
|
if not attr_name[0] == "_" |
|
|
|
|
|
} |
|
|
|
|
|
) |
|
|
|
|
|
field_description["name"] = self.unprefix(field.name) |
|
|
self._field_descriptions[field] = field_description |
|
|
self._field_descriptions[field] = field_description |
|
|
|
|
|
|
|
|
@api.model |
|
|
@api.model |
|
@ -253,8 +319,9 @@ class ModulePrototyper(models.Model): |
|
|
""" Generates the files from the details of the prototype. |
|
|
""" Generates the files from the details of the prototype. |
|
|
:return: tuple |
|
|
:return: tuple |
|
|
""" |
|
|
""" |
|
|
assert self._env is not None, \ |
|
|
|
|
|
'Run set_env(api_version) before to generate files.' |
|
|
|
|
|
|
|
|
assert ( |
|
|
|
|
|
self._env is not None |
|
|
|
|
|
), "Run set_env(api_version) before to generate files." |
|
|
|
|
|
|
|
|
# Avoid sharing these across instances |
|
|
# Avoid sharing these across instances |
|
|
self._data_files = [] |
|
|
self._data_files = [] |
|
@ -269,9 +336,7 @@ class ModulePrototyper(models.Model): |
|
|
file_details.extend(self.generate_data_files()) |
|
|
file_details.extend(self.generate_data_files()) |
|
|
# must be the last as the other generations might add information |
|
|
# must be the last as the other generations might add information |
|
|
# to put in the __openerp__: additional dependencies, views files, etc. |
|
|
# to put in the __openerp__: additional dependencies, views files, etc. |
|
|
file_details.append( |
|
|
|
|
|
self.generate_module_openerp_file_details() |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
file_details.append(self.generate_module_openerp_file_details()) |
|
|
if self.icon_image: |
|
|
if self.icon_image: |
|
|
file_details.append(self.save_icon()) |
|
|
file_details.append(self.save_icon()) |
|
|
|
|
|
|
|
@ -290,17 +355,17 @@ class ModulePrototyper(models.Model): |
|
|
# * add document as a dependency. |
|
|
# * add document as a dependency. |
|
|
# The second options seems to be better, as Document is a base module. |
|
|
# The second options seems to be better, as Document is a base module. |
|
|
return self.File_details( |
|
|
return self.File_details( |
|
|
os.path.join('static', 'description', 'icon.jpg'), |
|
|
|
|
|
base64.b64decode(self.icon_image) |
|
|
|
|
|
|
|
|
os.path.join("static", "description", "icon.jpg"), |
|
|
|
|
|
base64.b64decode(self.icon_image), |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
@api.model |
|
|
@api.model |
|
|
def generate_module_openerp_file_details(self): |
|
|
def generate_module_openerp_file_details(self): |
|
|
"""Wrapper to generate the __openerp__.py file of the module.""" |
|
|
"""Wrapper to generate the __openerp__.py file of the module.""" |
|
|
fn_inc_ext = '%s.py' % (self._api_version.manifest_file_name,) |
|
|
|
|
|
|
|
|
fn_inc_ext = "%s.py" % (self._api_version.manifest_file_name,) |
|
|
return self.generate_file_details( |
|
|
return self.generate_file_details( |
|
|
fn_inc_ext, |
|
|
fn_inc_ext, |
|
|
'%s.template' % (fn_inc_ext,), |
|
|
|
|
|
|
|
|
"%s.template" % (fn_inc_ext,), |
|
|
prototype=self, |
|
|
prototype=self, |
|
|
data_files=self._data_files, |
|
|
data_files=self._data_files, |
|
|
demo_fiels=self._demo_files, |
|
|
demo_fiels=self._demo_files, |
|
@ -310,11 +375,11 @@ class ModulePrototyper(models.Model): |
|
|
def generate_module_init_file_details(self): |
|
|
def generate_module_init_file_details(self): |
|
|
"""Wrapper to generate the __init__.py file of the module.""" |
|
|
"""Wrapper to generate the __init__.py file of the module.""" |
|
|
return self.generate_file_details( |
|
|
return self.generate_file_details( |
|
|
'__init__.py', |
|
|
|
|
|
'__init__.py.template', |
|
|
|
|
|
|
|
|
"__init__.py", |
|
|
|
|
|
"__init__.py.template", |
|
|
# no import models if no work of fields in |
|
|
# no import models if no work of fields in |
|
|
# the prototype |
|
|
# the prototype |
|
|
models=bool(self.field_ids) |
|
|
|
|
|
|
|
|
models=bool(self.field_ids), |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
@api.model |
|
|
@api.model |
|
@ -335,7 +400,7 @@ class ModulePrototyper(models.Model): |
|
|
relations = {} |
|
|
relations = {} |
|
|
field_descriptions = self._field_descriptions or {} |
|
|
field_descriptions = self._field_descriptions or {} |
|
|
for field in field_descriptions.itervalues(): |
|
|
for field in field_descriptions.itervalues(): |
|
|
model = field.get('model_id') |
|
|
|
|
|
|
|
|
model = field.get("model_id") |
|
|
relations.setdefault(model, []).append(field) |
|
|
relations.setdefault(model, []).append(field) |
|
|
# dependencies.add(model.id) |
|
|
# dependencies.add(model.id) |
|
|
|
|
|
|
|
@ -354,12 +419,11 @@ class ModulePrototyper(models.Model): |
|
|
def generate_models_init_details(self, ir_models): |
|
|
def generate_models_init_details(self, ir_models): |
|
|
"""Wrapper to generate the __init__.py file in models folder.""" |
|
|
"""Wrapper to generate the __init__.py file in models folder.""" |
|
|
return self.generate_file_details( |
|
|
return self.generate_file_details( |
|
|
'models/__init__.py', |
|
|
|
|
|
'models/__init__.py.template', |
|
|
|
|
|
|
|
|
"models/__init__.py", |
|
|
|
|
|
"models/__init__.py.template", |
|
|
models=[ |
|
|
models=[ |
|
|
self.friendly_name(ir_model.model) |
|
|
|
|
|
for ir_model in ir_models |
|
|
|
|
|
] |
|
|
|
|
|
|
|
|
self.friendly_name(ir_model.model) for ir_model in ir_models |
|
|
|
|
|
], |
|
|
) |
|
|
) |
|
|
|
|
|
|
|
|
@api.model |
|
|
@api.model |
|
@ -371,14 +435,12 @@ class ModulePrototyper(models.Model): |
|
|
|
|
|
|
|
|
views_details = [] |
|
|
views_details = [] |
|
|
for model, views in relations.iteritems(): |
|
|
for model, views in relations.iteritems(): |
|
|
filepath = 'views/%s_view.xml' % ( |
|
|
|
|
|
|
|
|
filepath = "views/%s_view.xml" % ( |
|
|
self.friendly_name(self.unprefix(model)), |
|
|
self.friendly_name(self.unprefix(model)), |
|
|
) |
|
|
) |
|
|
views_details.append( |
|
|
views_details.append( |
|
|
self.generate_file_details( |
|
|
self.generate_file_details( |
|
|
filepath, |
|
|
|
|
|
'views/model_views.xml.template', |
|
|
|
|
|
views=views |
|
|
|
|
|
|
|
|
filepath, "views/model_views.xml.template", views=views |
|
|
) |
|
|
) |
|
|
) |
|
|
) |
|
|
self._data_files.append(filepath) |
|
|
self._data_files.append(filepath) |
|
@ -393,20 +455,16 @@ class ModulePrototyper(models.Model): |
|
|
if menu.action and menu.action.res_model: |
|
|
if menu.action and menu.action.res_model: |
|
|
model = self.unprefix(menu.action.res_model) |
|
|
model = self.unprefix(menu.action.res_model) |
|
|
else: |
|
|
else: |
|
|
model = 'ir_ui' |
|
|
|
|
|
|
|
|
model = "ir_ui" |
|
|
relations.setdefault(model, []).append(menu) |
|
|
relations.setdefault(model, []).append(menu) |
|
|
|
|
|
|
|
|
menus_details = [] |
|
|
menus_details = [] |
|
|
for model_name, menus in relations.iteritems(): |
|
|
for model_name, menus in relations.iteritems(): |
|
|
model_name = self.unprefix(model_name) |
|
|
model_name = self.unprefix(model_name) |
|
|
filepath = 'views/%s_menus.xml' % ( |
|
|
|
|
|
self.friendly_name(model_name), |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
filepath = "views/%s_menus.xml" % (self.friendly_name(model_name),) |
|
|
menus_details.append( |
|
|
menus_details.append( |
|
|
self.generate_file_details( |
|
|
self.generate_file_details( |
|
|
filepath, |
|
|
|
|
|
'views/model_menus.xml.template', |
|
|
|
|
|
menus=menus, |
|
|
|
|
|
|
|
|
filepath, "views/model_menus.xml.template", menus=menus |
|
|
) |
|
|
) |
|
|
) |
|
|
) |
|
|
self._data_files.append(filepath) |
|
|
self._data_files.append(filepath) |
|
@ -423,8 +481,8 @@ class ModulePrototyper(models.Model): |
|
|
""" |
|
|
""" |
|
|
python_friendly_name = self.friendly_name(self.unprefix(model.model)) |
|
|
python_friendly_name = self.friendly_name(self.unprefix(model.model)) |
|
|
return self.generate_file_details( |
|
|
return self.generate_file_details( |
|
|
'models/%s.py' % (python_friendly_name,), |
|
|
|
|
|
'models/model_name.py.template', |
|
|
|
|
|
|
|
|
"models/%s.py" % (python_friendly_name,), |
|
|
|
|
|
"models/model_name.py.template", |
|
|
name=python_friendly_name, |
|
|
name=python_friendly_name, |
|
|
model=model, |
|
|
model=model, |
|
|
fields=field_descriptions, |
|
|
fields=field_descriptions, |
|
@ -434,12 +492,8 @@ class ModulePrototyper(models.Model): |
|
|
def generate_data_files(self): |
|
|
def generate_data_files(self): |
|
|
""" Generate data and demo files """ |
|
|
""" Generate data and demo files """ |
|
|
data, demo = {}, {} |
|
|
data, demo = {}, {} |
|
|
filters = [ |
|
|
|
|
|
(data, ir_filter) |
|
|
|
|
|
for ir_filter in self.data_ids |
|
|
|
|
|
] + [ |
|
|
|
|
|
(demo, ir_filter) |
|
|
|
|
|
for ir_filter in self.demo_ids |
|
|
|
|
|
|
|
|
filters = [(data, ir_filter) for ir_filter in self.data_ids] + [ |
|
|
|
|
|
(demo, ir_filter) for ir_filter in self.demo_ids |
|
|
] |
|
|
] |
|
|
|
|
|
|
|
|
for target, ir_filter in filters: |
|
|
for target, ir_filter in filters: |
|
@ -450,19 +504,22 @@ class ModulePrototyper(models.Model): |
|
|
|
|
|
|
|
|
res = [] |
|
|
res = [] |
|
|
for prefix, model_data, file_list in [ |
|
|
for prefix, model_data, file_list in [ |
|
|
('data', data, self._data_files), |
|
|
|
|
|
('demo', demo, self._demo_files)]: |
|
|
|
|
|
|
|
|
("data", data, self._data_files), |
|
|
|
|
|
("demo", demo, self._demo_files), |
|
|
|
|
|
]: |
|
|
for model_name, records in model_data.iteritems(): |
|
|
for model_name, records in model_data.iteritems(): |
|
|
fname = self.friendly_name(self.unprefix(model_name)) |
|
|
fname = self.friendly_name(self.unprefix(model_name)) |
|
|
filename = '%s/%s.xml' % (prefix, fname) |
|
|
|
|
|
|
|
|
filename = "%s/%s.xml" % (prefix, fname) |
|
|
self._data_files.append(filename) |
|
|
self._data_files.append(filename) |
|
|
|
|
|
|
|
|
res.append(self.generate_file_details( |
|
|
|
|
|
|
|
|
res.append( |
|
|
|
|
|
self.generate_file_details( |
|
|
filename, |
|
|
filename, |
|
|
'data/model_name.xml.template', |
|
|
|
|
|
|
|
|
"data/model_name.xml.template", |
|
|
model=model_name, |
|
|
model=model_name, |
|
|
records=records, |
|
|
records=records, |
|
|
)) |
|
|
|
|
|
|
|
|
) |
|
|
|
|
|
) |
|
|
|
|
|
|
|
|
return res |
|
|
return res |
|
|
|
|
|
|
|
@ -470,15 +527,15 @@ class ModulePrototyper(models.Model): |
|
|
def unprefix(cls, name): |
|
|
def unprefix(cls, name): |
|
|
if not name: |
|
|
if not name: |
|
|
return name |
|
|
return name |
|
|
return re.sub('^x_', '', name) |
|
|
|
|
|
|
|
|
return re.sub("^x_", "", name) |
|
|
|
|
|
|
|
|
@classmethod |
|
|
@classmethod |
|
|
def is_prefixed(cls, name): |
|
|
def is_prefixed(cls, name): |
|
|
return bool(re.match('^x_', name)) |
|
|
|
|
|
|
|
|
return bool(re.match("^x_", name)) |
|
|
|
|
|
|
|
|
@classmethod |
|
|
@classmethod |
|
|
def friendly_name(cls, name): |
|
|
def friendly_name(cls, name): |
|
|
return name.replace('.', '_') |
|
|
|
|
|
|
|
|
return name.replace(".", "_") |
|
|
|
|
|
|
|
|
@classmethod |
|
|
@classmethod |
|
|
def fixup_domain(cls, domain): |
|
|
def fixup_domain(cls, domain): |
|
@ -501,8 +558,10 @@ class ModulePrototyper(models.Model): |
|
|
try: |
|
|
try: |
|
|
attrs = safe_eval(elem.attrib["attrs"]) |
|
|
attrs = safe_eval(elem.attrib["attrs"]) |
|
|
except Exception: |
|
|
except Exception: |
|
|
_logger.error("Unable to eval attribute: %s, skipping", |
|
|
|
|
|
elem.attrib["attrs"]) |
|
|
|
|
|
|
|
|
_logger.error( |
|
|
|
|
|
"Unable to eval attribute: %s, skipping", |
|
|
|
|
|
elem.attrib["attrs"], |
|
|
|
|
|
) |
|
|
continue |
|
|
continue |
|
|
|
|
|
|
|
|
if isinstance(attrs, dict): |
|
|
if isinstance(attrs, dict): |
|
@ -530,17 +589,16 @@ class ModulePrototyper(models.Model): |
|
|
# keywords used in several templates. |
|
|
# keywords used in several templates. |
|
|
kwargs.update( |
|
|
kwargs.update( |
|
|
{ |
|
|
{ |
|
|
'export_year': date.today().year, |
|
|
|
|
|
'author': self.author, |
|
|
|
|
|
'website': self.website, |
|
|
|
|
|
'license_text': licenses.get_license_text(self.license), |
|
|
|
|
|
'cr': self._cr, |
|
|
|
|
|
|
|
|
"export_year": date.today().year, |
|
|
|
|
|
"author": self.author, |
|
|
|
|
|
"website": self.website, |
|
|
|
|
|
"license_text": licenses.get_license_text(self.license), |
|
|
|
|
|
"cr": self._cr, |
|
|
# Utility functions |
|
|
# Utility functions |
|
|
'fixup_arch': self.fixup_arch, |
|
|
|
|
|
'is_prefixed': self.is_prefixed, |
|
|
|
|
|
'unprefix': self.unprefix, |
|
|
|
|
|
'wrap': wrap, |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"fixup_arch": self.fixup_arch, |
|
|
|
|
|
"is_prefixed": self.is_prefixed, |
|
|
|
|
|
"unprefix": self.unprefix, |
|
|
|
|
|
"wrap": wrap, |
|
|
} |
|
|
} |
|
|
) |
|
|
) |
|
|
return self.File_details(filename, template.render(kwargs)) |
|
|
return self.File_details(filename, template.render(kwargs)) |
|
|