Add rattail_shopfoo
project generator
also *remove* the `db/alembic/env.py` script from rattail-adjacent generator. it didn't seem necessary..now we'll see if it ever is
This commit is contained in:
parent
9834e1276d
commit
4c331e3875
|
@ -30,12 +30,11 @@ import re
|
|||
import shutil
|
||||
import string
|
||||
import sys
|
||||
import unicodedata
|
||||
|
||||
import colander
|
||||
from mako.template import Template
|
||||
|
||||
from rattail.util import get_class_hierarchy
|
||||
from rattail.util import get_class_hierarchy, get_studly_prefix
|
||||
from rattail.mako import ResourceTemplateLookup
|
||||
|
||||
|
||||
|
@ -276,13 +275,6 @@ class PythonProjectGenerator(ProjectGenerator):
|
|||
|
||||
return schema
|
||||
|
||||
def get_studly_prefix(self, name):
|
||||
# cf. https://stackoverflow.com/a/3194567
|
||||
name = unicodedata.normalize('NFD', name)
|
||||
name = name.encode('ascii', 'ignore').decode('ascii')
|
||||
words = re.split(r'[\- ]', name)
|
||||
return ''.join([word.capitalize() for word in words])
|
||||
|
||||
def normalize_context(self, context):
|
||||
context = super(PythonProjectGenerator, self).normalize_context(context)
|
||||
|
||||
|
@ -296,7 +288,7 @@ class PythonProjectGenerator(ProjectGenerator):
|
|||
context['egg_name'] = context['pypi_name'].replace('-', '_')
|
||||
|
||||
if 'studly_prefix' not in context:
|
||||
context['studly_prefix'] = self.get_studly_prefix(context['name'])
|
||||
context['studly_prefix'] = get_studly_prefix(context['name'])
|
||||
|
||||
if 'env_name' not in context:
|
||||
context['env_name'] = context['folder']
|
||||
|
@ -478,8 +470,6 @@ class RattailAdjacentProjectGenerator(PythonProjectGenerator):
|
|||
# model
|
||||
####################
|
||||
|
||||
if context['has_model']:
|
||||
|
||||
model = os.path.join(db, 'model')
|
||||
os.makedirs(model)
|
||||
|
||||
|
@ -496,11 +486,6 @@ class RattailAdjacentProjectGenerator(PythonProjectGenerator):
|
|||
alembic = os.path.join(db, 'alembic')
|
||||
os.makedirs(alembic)
|
||||
|
||||
# TODO: can we get rid of this? why not?
|
||||
self.generate('package/db/alembic/env.py.mako',
|
||||
os.path.join(alembic, 'env.py'),
|
||||
context)
|
||||
|
||||
versions = os.path.join(alembic, 'versions')
|
||||
os.makedirs(versions)
|
||||
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
# -*- coding: utf-8; mode: python; -*-
|
||||
"""
|
||||
Alembic environment script
|
||||
"""
|
||||
|
||||
from alembic import context
|
||||
from sqlalchemy.orm import configure_mappers
|
||||
|
||||
from rattail.config import make_config
|
||||
from rattail.db.util import get_default_engine
|
||||
from rattail.db.continuum import configure_versioning
|
||||
|
||||
|
||||
# this is the Alembic Config object, which provides
|
||||
# access to the values within the .ini file in use.
|
||||
alembic_config = context.config
|
||||
|
||||
# use same config file for Rattail
|
||||
rattail_config = make_config(alembic_config.config_file_name, usedb=False, versioning=False)
|
||||
|
||||
# configure Continuum..this is trickier than we want but it works..
|
||||
configure_versioning(rattail_config, force=True)
|
||||
from ${pkg_name}.db import model
|
||||
configure_mappers()
|
||||
|
||||
# needed for 'autogenerate' support
|
||||
target_metadata = model.Base.metadata
|
||||
|
||||
|
||||
def run_migrations_offline():
|
||||
"""Run migrations in 'offline' mode.
|
||||
|
||||
This configures the context with just a URL
|
||||
and not an Engine, though an Engine is acceptable
|
||||
here as well. By skipping the Engine creation
|
||||
we don't even need a DBAPI to be available.
|
||||
|
||||
Calls to context.execute() here emit the given string to the
|
||||
script output.
|
||||
|
||||
"""
|
||||
engine = get_default_engine(rattail_config)
|
||||
context.configure(
|
||||
url=engine.url,
|
||||
target_metadata=target_metadata)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
def run_migrations_online():
|
||||
"""Run migrations in 'online' mode.
|
||||
|
||||
In this scenario we need to create an Engine
|
||||
and associate a connection with the context.
|
||||
|
||||
"""
|
||||
engine = get_default_engine(rattail_config)
|
||||
connection = engine.connect()
|
||||
context.configure(
|
||||
connection=connection,
|
||||
target_metadata=target_metadata)
|
||||
|
||||
try:
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
finally:
|
||||
connection.close()
|
||||
|
||||
|
||||
if context.is_offline_mode():
|
||||
run_migrations_offline()
|
||||
else:
|
||||
run_migrations_online()
|
|
@ -29,6 +29,7 @@ import os
|
|||
import colander
|
||||
|
||||
from rattail.projects import RattailAdjacentProjectGenerator
|
||||
from rattail.util import get_studly_prefix, get_package_name
|
||||
|
||||
|
||||
class RattailIntegrationProjectGenerator(RattailAdjacentProjectGenerator):
|
||||
|
@ -61,6 +62,14 @@ class RattailIntegrationProjectGenerator(RattailAdjacentProjectGenerator):
|
|||
'Topic :: Software Development :: Libraries :: Python Modules',
|
||||
]))
|
||||
|
||||
if 'integration_studly_prefix' not in context:
|
||||
context['integration_studly_prefix'] = get_studly_prefix(
|
||||
context['integration_name'])
|
||||
|
||||
if 'integration_pkgname' not in context:
|
||||
context['integration_pkgname'] = get_package_name(
|
||||
context['integration_name'])
|
||||
|
||||
if 'year' not in context:
|
||||
context['year'] = self.app.today().year
|
||||
|
||||
|
|
67
rattail/projects/rattail_shopfoo.py
Normal file
67
rattail/projects/rattail_shopfoo.py
Normal file
|
@ -0,0 +1,67 @@
|
|||
# -*- 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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Generator for 'rattail-shopfoo' integration projects
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from rattail.projects.rattail_integration import RattailIntegrationProjectGenerator
|
||||
|
||||
|
||||
class RattailShopfooProjectGenerator(RattailIntegrationProjectGenerator):
|
||||
"""
|
||||
Generator for projects which integrate Rattail with some type of
|
||||
e-commerce system. This is for generating projects such as
|
||||
rattail-instacart, rattail-mercato etc. which involve a nightly
|
||||
export/upload of product data to external server.
|
||||
"""
|
||||
key = 'rattail_shopfoo'
|
||||
|
||||
def normalize_context(self, context):
|
||||
|
||||
# nb. auto-set some flags
|
||||
context['extends_db'] = True
|
||||
context['has_model'] = True
|
||||
|
||||
# then do normal logic
|
||||
context = super(RattailShopfooProjectGenerator, self).normalize_context(context)
|
||||
|
||||
return context
|
||||
|
||||
def generate_project(self, output, context, **kwargs):
|
||||
super(RattailShopfooProjectGenerator, self).generate_project(
|
||||
output, context, **kwargs)
|
||||
|
||||
package = os.path.join(output, context['pkg_name'])
|
||||
|
||||
##############################
|
||||
# db/model
|
||||
##############################
|
||||
|
||||
db = os.path.join(package, 'db')
|
||||
model = os.path.join(db, 'model')
|
||||
|
||||
self.generate('package/db/model/shopfoo.py.mako',
|
||||
os.path.join(model, '{}.py'.format(context['integration_pkgname'])),
|
||||
context)
|
|
@ -0,0 +1,8 @@
|
|||
## -*- coding: utf-8; mode: python; -*-
|
||||
# -*- coding: utf-8; -*-
|
||||
"""
|
||||
${name} data models
|
||||
"""
|
||||
|
||||
# bring in all models for ${integration_name} integration
|
||||
from .${integration_pkgname} import ${integration_studly_prefix}Product, ${integration_studly_prefix}ProductExport
|
|
@ -0,0 +1,57 @@
|
|||
## -*- coding: utf-8; mode: python; -*-
|
||||
# -*- coding: utf-8; -*-
|
||||
"""
|
||||
Integration data models for ${integration_name}
|
||||
"""
|
||||
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.ext.declarative import declared_attr
|
||||
|
||||
from rattail.db import model
|
||||
from rattail.db.model.shopfoo import ShopfooProductBase, ShopfooProductExportBase
|
||||
|
||||
|
||||
class ${integration_studly_prefix}Product(ShopfooProductBase, model.Base):
|
||||
"""
|
||||
${integration_name} extensions to :class:`rattail:rattail.db.model.Product`.
|
||||
"""
|
||||
__tablename__ = '${integration_pkgname}_product'
|
||||
|
||||
@declared_attr
|
||||
def __table_args__(cls):
|
||||
return cls.__product_table_args__() + (
|
||||
sa.UniqueConstraint('${integration_pkgname}_id', name='${integration_pkgname}_product_uq_${integration_pkgname}_id'),
|
||||
)
|
||||
|
||||
__versioned__ = {
|
||||
# 'exclude': [
|
||||
# 'in_stock',
|
||||
# 'last_sold',
|
||||
# 'last_updated',
|
||||
# 'units_on_hand',
|
||||
# ],
|
||||
}
|
||||
|
||||
${integration_pkgname}_id = sa.Column(sa.String(length=25), nullable=False)
|
||||
|
||||
description = sa.Column(sa.String(length=512), nullable=True)
|
||||
|
||||
# price = sa.Column(sa.Numeric(precision=13, scale=2), nullable=True)
|
||||
|
||||
# in_stock = sa.Column(sa.Boolean(), nullable=True)
|
||||
|
||||
# last_sold = sa.Column(sa.Date(), nullable=True)
|
||||
|
||||
# last_updated = sa.Column(sa.Date(), nullable=True)
|
||||
|
||||
# units_on_hand = sa.Column(sa.Numeric(precision=13, scale=2), nullable=True)
|
||||
|
||||
def __str__(self):
|
||||
return self.description or ""
|
||||
|
||||
|
||||
class ${integration_studly_prefix}ProductExport(ShopfooProductExportBase, model.Base):
|
||||
"""
|
||||
History table for product exports which have been submitted to ${integration_name}
|
||||
"""
|
||||
__tablename__ = '${integration_pkgname}_product_export'
|
|
@ -28,6 +28,7 @@ import collections
|
|||
import importlib
|
||||
import re
|
||||
import shlex
|
||||
import unicodedata
|
||||
import datetime
|
||||
import decimal
|
||||
import subprocess
|
||||
|
@ -166,6 +167,32 @@ def get_class_hierarchy(klass, topfirst=True):
|
|||
return hierarchy
|
||||
|
||||
|
||||
def get_package_name(name):
|
||||
"""
|
||||
Generic logic to derive a "package name" from the given name.
|
||||
|
||||
E.g. if ``name`` is "Poser Plus" this will return "poser_plus"
|
||||
"""
|
||||
# cf. https://stackoverflow.com/a/3194567
|
||||
name = unicodedata.normalize('NFD', name)
|
||||
name = name.encode('ascii', 'ignore').decode('ascii')
|
||||
words = re.split(r'[\- ]', name)
|
||||
return '_'.join([word.lower() for word in words])
|
||||
|
||||
|
||||
def get_studly_prefix(name):
|
||||
"""
|
||||
Generic logic to derive a "studly prefix" from the given name.
|
||||
|
||||
E.g. if ``name`` is "Poser Plus" this will return "PoserPlus"
|
||||
"""
|
||||
# cf. https://stackoverflow.com/a/3194567
|
||||
name = unicodedata.normalize('NFD', name)
|
||||
name = name.encode('ascii', 'ignore').decode('ascii')
|
||||
words = re.split(r'[\- ]', name)
|
||||
return ''.join([word.capitalize() for word in words])
|
||||
|
||||
|
||||
def import_module_path(module_path):
|
||||
"""
|
||||
Import an arbitrary Python module.
|
||||
|
|
1
setup.py
1
setup.py
|
@ -272,6 +272,7 @@ setup(
|
|||
'fabric = rattail.projects.fabric:FabricProjectGenerator',
|
||||
'rattail = rattail.projects.rattail:RattailProjectGenerator',
|
||||
'rattail_integration = rattail.projects.rattail_integration:RattailIntegrationProjectGenerator',
|
||||
'rattail_shopfoo = rattail.projects.rattail_shopfoo:RattailShopfooProjectGenerator',
|
||||
'tailbone_integration = rattail.projects.tailbone_integration:TailboneIntegrationProjectGenerator',
|
||||
],
|
||||
|
||||
|
|
Loading…
Reference in a new issue