diff --git a/setup.py b/setup.py
index 2cf2565c..6a51fa05 100644
--- a/setup.py
+++ b/setup.py
@@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
-# Copyright © 2010-2015 Lance Edgar
+# Copyright © 2010-2016 Lance Edgar
#
# This file is part of Rattail.
#
@@ -20,8 +20,11 @@
# along with Rattail. If not, see .
#
################################################################################
+"""
+Setup script for Tailbone
+"""
-from __future__ import unicode_literals
+from __future__ import unicode_literals, absolute_import
import os.path
from setuptools import setup, find_packages
@@ -75,7 +78,6 @@ requires = [
# deprecated 'paster create' (and friends).
'pyramid>=1.3a1', # 1.3b2 1.4.5
- 'edbob', # 1.1.2
'humanize', # 0.5.1
'Mako', # 0.6.2
'pyramid_beaker>=0.6', # 0.6.1
@@ -92,7 +94,7 @@ requires = [
# TODO: Need to figure out what to do about this...
# # This is used to obtain POD image dimensions.
# 'PIL', # 1.1.7
- ]
+]
extras = {
diff --git a/tailbone/app.py b/tailbone/app.py
index 1c3c2187..c3472d42 100644
--- a/tailbone/app.py
+++ b/tailbone/app.py
@@ -31,8 +31,6 @@ import warnings
import sqlalchemy as sa
-from edbob.pyramid.forms.formalchemy import TemplateEngine
-
import rattail.db
from rattail.config import make_config
from rattail.exceptions import ConfigurationError
@@ -40,13 +38,14 @@ from rattail.db.util import get_engines
from rattail.db.continuum import configure_versioning
from rattail.db.types import GPCType
-import formalchemy
+import formalchemy as fa
from pyramid.config import Configurator
from pyramid.authentication import SessionAuthenticationPolicy
import tailbone.db
from tailbone.auth import TailboneAuthorizationPolicy
from tailbone.forms import renderers
+from tailbone.forms.alchemy import TemplateEngine
def make_rattail_config(settings):
@@ -135,12 +134,12 @@ def make_pyramid_config(settings):
config.add_tailbone_permission(groupkey, key, label)
# Configure FormAlchemy.
- formalchemy.config.engine = TemplateEngine()
- formalchemy.FieldSet.default_renderers[sa.Boolean] = renderers.YesNoFieldRenderer
- formalchemy.FieldSet.default_renderers[sa.Date] = renderers.DateFieldRenderer
- formalchemy.FieldSet.default_renderers[sa.DateTime] = renderers.DateTimeFieldRenderer
- formalchemy.FieldSet.default_renderers[sa.Time] = renderers.TimeFieldRenderer
- formalchemy.FieldSet.default_renderers[GPCType] = renderers.GPCFieldRenderer
+ fa.config.engine = TemplateEngine()
+ fa.FieldSet.default_renderers[sa.Boolean] = renderers.YesNoFieldRenderer
+ fa.FieldSet.default_renderers[sa.Date] = renderers.DateFieldRenderer
+ fa.FieldSet.default_renderers[sa.DateTime] = renderers.DateTimeFieldRenderer
+ fa.FieldSet.default_renderers[sa.Time] = renderers.TimeFieldRenderer
+ fa.FieldSet.default_renderers[GPCType] = renderers.GPCFieldRenderer
return config
@@ -150,7 +149,7 @@ def configure_postgresql(pyramid_config):
Add some PostgreSQL-specific tweaks to the final app config. Specifically,
adds the tween necessary for graceful handling of database restarts.
"""
- pyramid_config.add_tween('edbob.pyramid.tweens.sqlerror_tween_factory',
+ pyramid_config.add_tween('tailbone.tweens.sqlerror_tween_factory',
under='pyramid_tm.tm_tween_factory')
diff --git a/tailbone/auth.py b/tailbone/auth.py
index 02d0cac2..fae72752 100644
--- a/tailbone/auth.py
+++ b/tailbone/auth.py
@@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
-# Copyright © 2010-2015 Lance Edgar
+# Copyright © 2010-2016 Lance Edgar
#
# This file is part of Rattail.
#
@@ -24,12 +24,11 @@
Authentication & Authorization
"""
-from __future__ import unicode_literals
-
-from edbob.util import prettify
+from __future__ import unicode_literals, absolute_import
from rattail.db import model
from rattail.db.auth import has_permission
+from rattail.util import prettify
from zope.interface import implementer
from pyramid.interfaces import IAuthorizationPolicy
diff --git a/tailbone/forms/alchemy.py b/tailbone/forms/alchemy.py
index 40fc4057..0b9af0ff 100644
--- a/tailbone/forms/alchemy.py
+++ b/tailbone/forms/alchemy.py
@@ -28,11 +28,22 @@ from __future__ import unicode_literals, absolute_import
from rattail.core import Object
+import formalchemy as fa
from pyramid.renderers import render
from tailbone.db import Session
+class TemplateEngine(fa.templates.TemplateEngine):
+ """
+ Mako template engine for FormAlchemy.
+ """
+
+ def render(self, template, prefix='/forms/', suffix='.mako', **kwargs):
+ template = ''.join((prefix, template, suffix))
+ return render(template, kwargs)
+
+
class AlchemyForm(Object):
"""
Form to contain a :class:`formalchemy.FieldSet` instance.
diff --git a/tailbone/forms/core.py b/tailbone/forms/core.py
index 4a2be3a7..0d2728cd 100644
--- a/tailbone/forms/core.py
+++ b/tailbone/forms/core.py
@@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
-# Copyright © 2010-2015 Lance Edgar
+# Copyright © 2010-2016 Lance Edgar
#
# This file is part of Rattail.
#
@@ -26,9 +26,7 @@ Forms Core
from __future__ import unicode_literals, absolute_import
-from edbob.util import prettify
-
-from rattail.util import OrderedDict
+from rattail.util import OrderedDict, prettify
import formalchemy
from formalchemy.helpers import content_tag
diff --git a/tailbone/forms/simpleform.py b/tailbone/forms/simpleform.py
index b1510148..fa82b0b0 100644
--- a/tailbone/forms/simpleform.py
+++ b/tailbone/forms/simpleform.py
@@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
-# Copyright © 2010-2015 Lance Edgar
+# Copyright © 2010-2016 Lance Edgar
#
# This file is part of Rattail.
#
@@ -26,14 +26,13 @@ Simple Forms
from __future__ import unicode_literals, absolute_import
+from rattail.util import prettify
+
import pyramid_simpleform
from pyramid_simpleform import renderers
-
from webhelpers.html import tags
from webhelpers.html import HTML
-from edbob.util import prettify
-
from tailbone.forms import Form
diff --git a/tailbone/grids/__init__.py b/tailbone/grids/__init__.py
index dc9032b8..030c0da7 100644
--- a/tailbone/grids/__init__.py
+++ b/tailbone/grids/__init__.py
@@ -1,9 +1,8 @@
-#!/usr/bin/env python
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
################################################################################
#
# Rattail -- Retail Software Framework
-# Copyright © 2010-2012 Lance Edgar
+# Copyright © 2010-2016 Lance Edgar
#
# This file is part of Rattail.
#
@@ -21,12 +20,13 @@
# along with Rattail. If not, see .
#
################################################################################
-
"""
Grids
"""
+from __future__ import unicode_literals, absolute_import
+
from .core import *
-from .alchemy import *
+from .alchemy import AlchemyGrid
from . import util
from . import search
diff --git a/tailbone/grids/alchemy.py b/tailbone/grids/alchemy.py
index 7b32069a..c7e13bbb 100644
--- a/tailbone/grids/alchemy.py
+++ b/tailbone/grids/alchemy.py
@@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
-# Copyright © 2010-2014 Lance Edgar
+# Copyright © 2010-2016 Lance Edgar
#
# This file is part of Rattail.
#
@@ -24,7 +24,7 @@
FormAlchemy Grid Classes
"""
-from __future__ import unicode_literals
+from __future__ import unicode_literals, absolute_import
from sqlalchemy.orm import object_session
@@ -34,17 +34,14 @@ except ImportError:
inspect = None
from sqlalchemy.orm import class_mapper
+from rattail.util import prettify
+
+import formalchemy as fa
from webhelpers.html import tags
from webhelpers.html import HTML
-import formalchemy
-
-from edbob.util import prettify
-
-from .core import Grid
-from ..db import Session
-
-__all__ = ['AlchemyGrid']
+from tailbone.db import Session
+from tailbone.grids.core import Grid
class AlchemyGrid(Grid):
@@ -56,8 +53,8 @@ class AlchemyGrid(Grid):
def __init__(self, request, cls, instances, **kwargs):
super(AlchemyGrid, self).__init__(request, **kwargs)
- self._formalchemy_grid = formalchemy.Grid(
- cls, instances, session=Session(), request=request)
+ self._formalchemy_grid = fa.Grid(cls, instances, session=Session(),
+ request=request)
self._formalchemy_grid.prettify = prettify
def __delattr__(self, attr):
diff --git a/tailbone/grids/search.py b/tailbone/grids/search.py
index 74ced5ee..2bc2861f 100644
--- a/tailbone/grids/search.py
+++ b/tailbone/grids/search.py
@@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
-# Copyright © 2010-2015 Lance Edgar
+# Copyright © 2010-2016 Lance Edgar
#
# This file is part of Rattail.
#
@@ -24,7 +24,7 @@
Grid Search Filters
"""
-from __future__ import unicode_literals
+from __future__ import unicode_literals, absolute_import
import re
@@ -37,10 +37,9 @@ from pyramid.renderers import render
from pyramid_simpleform import Form
from pyramid_simpleform.renderers import FormRenderer
-from edbob.util import prettify
-
from rattail.core import Object
from rattail.gpc import GPC
+from rattail.util import prettify
class SearchFilter(Object):
diff --git a/tailbone/newgrids/alchemy.py b/tailbone/newgrids/alchemy.py
index a195b92a..8c358917 100644
--- a/tailbone/newgrids/alchemy.py
+++ b/tailbone/newgrids/alchemy.py
@@ -31,9 +31,8 @@ import logging
import sqlalchemy as sa
from sqlalchemy import orm
-from edbob.util import prettify
-
from rattail.db.types import GPCType
+from rattail.util import prettify
import formalchemy
from webhelpers import paginate
diff --git a/tailbone/newgrids/core.py b/tailbone/newgrids/core.py
index 28105487..ccdf1d4b 100644
--- a/tailbone/newgrids/core.py
+++ b/tailbone/newgrids/core.py
@@ -26,9 +26,8 @@ Core Grid Classes
from __future__ import unicode_literals, absolute_import
-from edbob.util import prettify
-
from rattail.db.api import get_setting, save_setting
+from rattail.util import prettify
from pyramid.renderers import render
from webhelpers.html import HTML, tags
diff --git a/tailbone/newgrids/filters.py b/tailbone/newgrids/filters.py
index cee4fc02..32c3778e 100644
--- a/tailbone/newgrids/filters.py
+++ b/tailbone/newgrids/filters.py
@@ -31,12 +31,11 @@ import logging
import sqlalchemy as sa
-from edbob.util import prettify
-
from rattail.gpc import GPC
from rattail.util import OrderedDict
from rattail.core import UNSPECIFIED
from rattail.time import localtime, make_utc
+from rattail.util import prettify
from pyramid_simpleform import Form
from pyramid_simpleform.renderers import FormRenderer
diff --git a/tailbone/tweens.py b/tailbone/tweens.py
new file mode 100644
index 00000000..b6bd0039
--- /dev/null
+++ b/tailbone/tweens.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+################################################################################
+#
+# Rattail -- Retail Software Framework
+# Copyright © 2010-2016 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 Affero 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 Affero General Public License for
+# more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with Rattail. If not, see .
+#
+################################################################################
+"""
+Tween Factories
+"""
+
+from __future__ import unicode_literals, absolute_import
+
+from sqlalchemy.exc import OperationalError
+from transaction.interfaces import TransientError
+
+
+def sqlerror_tween_factory(handler, registry):
+ """
+ Produces a tween which will convert ``sqlalchemy.exc.OperationalError``
+ instances (caused by database server restart) into a retryable
+ ``transaction.interfaces.TransientError`` instance, so that a second
+ attempt may be made to connect to the database before really giving up.
+
+ .. note::
+ This tween alone is not enough to cause the transaction to be retried;
+ it only marks the error as being *retryable*. If you wish more than one
+ attempt to be made, you must define the ``tm.attempts`` setting within
+ your Pyramid app configuration. For more info see `Retrying`_.
+
+ .. _Retrying: http://docs.pylonsproject.org/projects/pyramid_tm/en/latest/#retrying
+ """
+
+ def sqlerror_tween(request):
+ try:
+ response = handler(request)
+ except OperationalError as error:
+ if error.connection_invalidated:
+ raise TransientError(str(error))
+ raise
+ return response
+
+ return sqlerror_tween
diff --git a/tailbone/views/__init__.py b/tailbone/views/__init__.py
index 33605ac0..a1f6502f 100644
--- a/tailbone/views/__init__.py
+++ b/tailbone/views/__init__.py
@@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
-# Copyright © 2010-2014 Lance Edgar
+# Copyright © 2010-2016 Lance Edgar
#
# This file is part of Rattail.
#
@@ -20,16 +20,17 @@
# along with Rattail. If not, see .
#
################################################################################
-
"""
Pyramid Views
"""
+from __future__ import unicode_literals, absolute_import
+
from .core import View
from tailbone.views.grids import (
GridView, AlchemyGridView, SortableAlchemyGridView,
PagedAlchemyGridView, SearchableAlchemyGridView)
-from .crud import *
+from .crud import CrudView
from .master import MasterView
from tailbone.views.autocomplete import AutocompleteView
diff --git a/tailbone/views/crud.py b/tailbone/views/crud.py
index 31f03b7d..4dd492d1 100644
--- a/tailbone/views/crud.py
+++ b/tailbone/views/crud.py
@@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
-# Copyright © 2010-2015 Lance Edgar
+# Copyright © 2010-2016 Lance Edgar
#
# This file is part of Rattail.
#
@@ -24,7 +24,7 @@
CRUD View
"""
-from __future__ import unicode_literals
+from __future__ import unicode_literals, absolute_import
try:
from sqlalchemy.inspection import inspect
@@ -38,20 +38,14 @@ from sqlalchemy_continuum.utils import is_versioned
from rattail.db import model
from rattail.db.continuum import count_versions, model_transaction_query
+from rattail.util import prettify
+from formalchemy import FieldSet
from pyramid.httpexceptions import HTTPFound, HTTPNotFound
-from .core import View
-
-from ..forms import AlchemyForm
-from formalchemy import FieldSet
-
-from edbob.util import prettify
-
from tailbone.db import Session
-
-
-__all__ = ['CrudView']
+from tailbone.views.core import View
+from tailbone.forms import AlchemyForm
class CrudView(View):
diff --git a/tailbone/views/master.py b/tailbone/views/master.py
index 243d1621..a6490129 100644
--- a/tailbone/views/master.py
+++ b/tailbone/views/master.py
@@ -31,7 +31,7 @@ import re
import sqlalchemy as sa
from sqlalchemy import orm
-from edbob.util import prettify
+from rattail.util import prettify
import formalchemy
from pyramid import httpexceptions
diff --git a/tests/data/tailbone.conf b/tests/data/tailbone.conf
index 4bdf2b74..7308e6eb 100644
--- a/tests/data/tailbone.conf
+++ b/tests/data/tailbone.conf
@@ -1,6 +1,6 @@
[app:main]
-edbob.config = %(here)s/tailbone.conf
+rattail.config = %(__file__)s
[rattail.db]
keys = default, store
diff --git a/tests/test_app.py b/tests/test_app.py
index 33962fd0..c5180815 100644
--- a/tests/test_app.py
+++ b/tests/test_app.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
-from __future__ import unicode_literals
+from __future__ import unicode_literals, absolute_import
import os
from unittest import TestCase
@@ -28,7 +28,7 @@ class TestRattailConfig(TestCase):
# error raised if path not provided
self.assertRaises(ConfigurationError, app.make_rattail_config, {})
# get a config object if path provided
- result = app.make_rattail_config({'edbob.config': self.config_path})
+ result = app.make_rattail_config({'rattail.config': self.config_path})
self.assertTrue(isinstance(result, RattailConfig))
def test_settings_arg_may_override_config_and_engines(self):