From 89e16b6a35ef02be5abe1dd6b5ca4eb24495de2e Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Fri, 5 May 2023 00:18:38 -0500 Subject: [PATCH] Add custom project generator for apps based on Corporal and make related changes to support that use case --- corporal/projects/__init__.py | 0 corporal/projects/corporal.py | 37 ++++++++++++++ .../package/db/model/__init__.py.mako | 10 ++++ .../templates/installer/rattail.conf.mako | 14 ++++++ .../package/web/views/__init__.py.mako | 15 ++++++ corporal/web/menus.py | 13 +++++ corporal/web/views/__init__.py | 14 ++---- corporal/web/views/essentials.py | 48 +++++++++++++++++++ corporal/web/views/projects.py | 39 +++++++++++++++ corporal/web/views/supplemental.py | 8 ++++ setup.py | 6 +++ 11 files changed, 193 insertions(+), 11 deletions(-) create mode 100644 corporal/projects/__init__.py create mode 100644 corporal/projects/corporal.py create mode 100644 corporal/projects/corporal/package/db/model/__init__.py.mako create mode 100644 corporal/projects/corporal/package/templates/installer/rattail.conf.mako create mode 100644 corporal/projects/corporal/package/web/views/__init__.py.mako create mode 100644 corporal/web/views/essentials.py create mode 100644 corporal/web/views/projects.py create mode 100644 corporal/web/views/supplemental.py diff --git a/corporal/projects/__init__.py b/corporal/projects/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/corporal/projects/corporal.py b/corporal/projects/corporal.py new file mode 100644 index 0000000..ef7b1e5 --- /dev/null +++ b/corporal/projects/corporal.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8; -*- +""" +Corporal project generator +""" + +from rattail.projects import PoserProjectGenerator + + +class CorporalProjectGenerator(PoserProjectGenerator): + """ + Generator for projects based on Corporal. + """ + key = 'corporal' + + def normalize_context(self, context): + + # set these first + context['has_db'] = True + context['has_web'] = True + context['alembic_version_locations'] = [ + 'rattail.db:alembic/versions', + 'rattail_corepos.db:alembic/versions', + ] + context['mako_directories'] = [ + '{}.web:templates'.format(context['pkg_name']), + 'corporal.web:templates', + 'tailbone_corepos:templates', + 'tailbone:templates', + ] + + # then do parent logic + context = super(CorporalProjectGenerator, self).normalize_context(context) + + # add dependencies + context['requires']['Corporal'] = True + + return context diff --git a/corporal/projects/corporal/package/db/model/__init__.py.mako b/corporal/projects/corporal/package/db/model/__init__.py.mako new file mode 100644 index 0000000..50ae72e --- /dev/null +++ b/corporal/projects/corporal/package/db/model/__init__.py.mako @@ -0,0 +1,10 @@ +## -*- coding: utf-8; mode: python; -*- +# -*- coding: utf-8; -*- +""" +${name} data models +""" + +# bring in all of Corporal +from corporal.db.model import * + +# TODO: import other/custom models here... diff --git a/corporal/projects/corporal/package/templates/installer/rattail.conf.mako b/corporal/projects/corporal/package/templates/installer/rattail.conf.mako new file mode 100644 index 0000000..3e0ebe9 --- /dev/null +++ b/corporal/projects/corporal/package/templates/installer/rattail.conf.mako @@ -0,0 +1,14 @@ +## -*- coding: utf-8; mode: conf; -*- +<%inherit file="rattail.projects:poser/package/templates/installer/rattail.conf.mako" /> +${parent.body()} + +#################### +## preamble +#################### + +<%def name="render_group_preamble()"> +${parent.render_group_preamble()} + +[corepos] +foo = bar + diff --git a/corporal/projects/corporal/package/web/views/__init__.py.mako b/corporal/projects/corporal/package/web/views/__init__.py.mako new file mode 100644 index 0000000..8c92486 --- /dev/null +++ b/corporal/projects/corporal/package/web/views/__init__.py.mako @@ -0,0 +1,15 @@ +## -*- coding: utf-8; mode: python; -*- +# -*- coding: utf-8; -*- +""" +${name} Views +""" + +from corporal.web.views import essentials + + +def includeme(config): + + # include all views deemed "essential" for Corporal + essentials.defaults(config) + + # TODO: include more (e.g. custom) views here as needed diff --git a/corporal/web/menus.py b/corporal/web/menus.py index 24b708e..b082651 100644 --- a/corporal/web/menus.py +++ b/corporal/web/menus.py @@ -35,12 +35,25 @@ class CorporalMenuHandler(base.MenuHandler): reports_menu = self.make_reports_menu(request, include_poser=True) + other_menu = { + 'title': "Other", + 'type': 'menu', + 'items': [ + { + 'title': "Generate New Project", + 'route': 'generated_projects.create', + 'perm': 'generated_projects.create', + }, + ], + } + admin_menu = self.make_admin_menu(request, include_stores=False) menus = [ corepos_menu, batch_menu, reports_menu, + other_menu, admin_menu, ] diff --git a/corporal/web/views/__init__.py b/corporal/web/views/__init__.py index 9cf3882..87b3085 100644 --- a/corporal/web/views/__init__.py +++ b/corporal/web/views/__init__.py @@ -3,16 +3,8 @@ Corporal Views """ +from corporal.web.views import essentials + def includeme(config): - - # core views - config.include('tailbone.views.essentials') - config.include('tailbone.views.poser') - - # main views for CORE-POS - config.include('tailbone_corepos.views') - - # batches - config.include('tailbone_corepos.views.batch.vendorcatalog') - config.include('tailbone_corepos.views.batch.coremember') + essentials.defaults(config) diff --git a/corporal/web/views/essentials.py b/corporal/web/views/essentials.py new file mode 100644 index 0000000..032c64b --- /dev/null +++ b/corporal/web/views/essentials.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8; -*- +################################################################################ +# +# Rattail -- Retail Software Framework +# Copyright © 2010-2023 Lance Edgar +# +# This file is part of Rattail. +# +# Rattail is free software: you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# Rattail. If not, see . +# +################################################################################ +""" +Essential views for convenient includes +""" + + +def defaults(config, **kwargs): + mod = lambda spec: kwargs.get(spec, spec) + + # core views + config.include(mod('tailbone.views.essentials')) + config.include(mod('tailbone.views.poser')) + config.include(mod('tailbone.views.projects')) + + # main views for CORE-POS + config.include(mod('tailbone_corepos.views')) + + # batches + config.include(mod('tailbone_corepos.views.batch.vendorcatalog')) + config.include(mod('tailbone_corepos.views.batch.coremember')) + + # corporal-specific + config.include(mod('corporal.web.views.supplemental')) + + +def includeme(config): + defaults(config) diff --git a/corporal/web/views/projects.py b/corporal/web/views/projects.py new file mode 100644 index 0000000..07727bb --- /dev/null +++ b/corporal/web/views/projects.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8; -*- +""" +Project views +""" + +from tailbone.views import ViewSupplement + + +class GeneratedProjectViewSupplement(ViewSupplement): + """ + View supplement for generating projects + """ + route_prefix = 'generated_projects' + + def configure_form_corporal(self, f): + + f.set_grouping([ + ("Naming", [ + 'name', + 'pkg_name', + 'pypi_name', + 'organization', + ]), + ("Core", [ + 'extends_config', + 'has_cli', + ]), + ("Database", [ + 'extends_db', + ]), + ]) + + # default settings + f.set_default('extends_config', False) + f.set_default('extends_db', False) + + +def includeme(config): + GeneratedProjectViewSupplement.defaults(config) diff --git a/corporal/web/views/supplemental.py b/corporal/web/views/supplemental.py new file mode 100644 index 0000000..67dde0c --- /dev/null +++ b/corporal/web/views/supplemental.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8; -*- +""" +Include all supplemental views +""" + + +def includeme(config): + config.include('corporal.web.views.projects') diff --git a/setup.py b/setup.py index 8b3c92a..c23b897 100644 --- a/setup.py +++ b/setup.py @@ -107,5 +107,11 @@ setup( 'rattail.emails': [ 'corporal = corporal.emails', ], + + + 'rattail.projects': [ + 'corporal = corporal.projects.corporal:CorporalProjectGenerator', + ], + }, )