diff --git a/pyproject.toml b/pyproject.toml index 073ed88..0442f5b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,10 +42,9 @@ dependencies = [ "pyramid_fanstatic", "pyramid_mako", "pyramid_tm", - "SQLAlchemy-Utils", "waitress", "WebHelpers2", - "WuttJamaican[db]>=0.19.1", + "WuttJamaican[db]>=0.19.0", "zope.sqlalchemy>=1.5", ] diff --git a/src/wuttaweb/forms/schema.py b/src/wuttaweb/forms/schema.py index 7591a7a..b5e7667 100644 --- a/src/wuttaweb/forms/schema.py +++ b/src/wuttaweb/forms/schema.py @@ -155,28 +155,6 @@ class WuttaEnum(colander.Enum): return widgets.SelectWidget(**kwargs) -class WuttaMoney(colander.Money): - """ - Custom schema type for "money" fields. - - This is a subclass of :class:`colander:colander.Money`, but uses - the custom :class:`~wuttaweb.forms.widgets.WuttaMoneyInputWidget` - by default. - - :param request: Current :term:`request` object. - """ - - def __init__(self, request, *args, **kwargs): - super().__init__(*args, **kwargs) - self.request = request - self.config = self.request.wutta_config - self.app = self.config.get_app() - - def widget_maker(self, **kwargs): - """ """ - return widgets.WuttaMoneyInputWidget(self.request, **kwargs) - - class WuttaSet(colander.Set): """ Custom schema type for :class:`python:set` fields. diff --git a/src/wuttaweb/forms/widgets.py b/src/wuttaweb/forms/widgets.py index 2541195..0fa8773 100644 --- a/src/wuttaweb/forms/widgets.py +++ b/src/wuttaweb/forms/widgets.py @@ -41,7 +41,6 @@ in the namespace: """ import datetime -import decimal import os import colander @@ -195,42 +194,6 @@ class WuttaDateTimeWidget(DateTimeInputWidget): return super().serialize(field, cstruct, **kw) -class WuttaMoneyInputWidget(MoneyInputWidget): - """ - Custom widget for "money" fields. This is used by default for - :class:`~wuttaweb.forms.schema.WuttaMoney` type nodes. - - The main purpose of this widget is to leverage - :meth:`~wuttjamaican:wuttjamaican.app.AppHandler.render_currency()` - for the readonly display. - - This is a subclass of - :class:`deform:deform.widget.MoneyInputWidget` and uses these - Deform templates: - - * ``moneyinput`` - - :param request: Current :term:`request` object. - """ - - def __init__(self, request, *args, **kwargs): - super().__init__(*args, **kwargs) - self.request = request - self.config = self.request.wutta_config - self.app = self.config.get_app() - - def serialize(self, field, cstruct, **kw): - """ """ - readonly = kw.get('readonly', self.readonly) - if readonly: - if cstruct in (colander.null, None): - return "" - cstruct = decimal.Decimal(cstruct) - return self.app.render_currency(cstruct) - - return super().serialize(field, cstruct, **kw) - - class FileDownloadWidget(Widget): """ Widget for use with :class:`~wuttaweb.forms.schema.FileDownload` diff --git a/src/wuttaweb/grids/base.py b/src/wuttaweb/grids/base.py index b9f0de7..ba402ce 100644 --- a/src/wuttaweb/grids/base.py +++ b/src/wuttaweb/grids/base.py @@ -32,7 +32,6 @@ from collections import namedtuple, OrderedDict import sqlalchemy as sa from sqlalchemy import orm -from sqlalchemy_utils import get_columns import paginate from paginate_sqlalchemy import SqlalchemyOrmPage @@ -1117,16 +1116,19 @@ class Grid: filters = filters or {} if self.model_class: - # nb. i first tried self.get_model_columns() but my notes - # say that was too aggressive in many cases. then i tried - # using the *subset* of self.columns, just the ones which - # corresponded to a property on the model class. and now - # i am using sa-utils to give the "true" column list.. - for col in get_columns(self.model_class): - if col.key in filters: + # TODO: i tried using self.get_model_columns() here but in + # many cases that will be too aggressive. however it is + # often the case that the *grid* columns are a subset of + # the unerlying *table* columns. so until a better way + # is found, we choose "too few" instead of "too many" + # filters here. surely must improve it at some point. + for key in self.columns: + if key in filters: continue - prop = getattr(self.model_class, col.key) - filters[prop.key] = self.make_filter(prop) + prop = getattr(self.model_class, key, None) + if (prop and hasattr(prop, 'property') + and isinstance(prop.property, orm.ColumnProperty)): + filters[prop.key] = self.make_filter(prop) return filters diff --git a/src/wuttaweb/progress.py b/src/wuttaweb/progress.py index 047be83..759c2da 100644 --- a/src/wuttaweb/progress.py +++ b/src/wuttaweb/progress.py @@ -92,9 +92,6 @@ class SessionProgress(ProgressBase): """ def __init__(self, request, key, success_msg=None, success_url=None, error_url=None): - self.request = request - self.config = self.request.wutta_config - self.app = self.config.get_app() self.key = key self.success_msg = success_msg self.success_url = success_url @@ -140,7 +137,7 @@ class SessionProgress(ProgressBase): """ self.session.load() self.session['error'] = True - self.session['error_msg'] = self.app.render_error(error) + self.session['error_msg'] = str(error) self.session['error_url'] = error_url or self.error_url self.session.save() diff --git a/src/wuttaweb/util.py b/src/wuttaweb/util.py index f634c00..0697f03 100644 --- a/src/wuttaweb/util.py +++ b/src/wuttaweb/util.py @@ -32,7 +32,6 @@ import uuid as _uuid import warnings import sqlalchemy as sa -from sqlalchemy import orm import colander from webhelpers2.html import HTML, tags @@ -479,36 +478,24 @@ def render_csrf_token(request, name='_csrf'): return HTML.tag('div', tags.hidden(name, value=token, id=None), style='display:none;') -def get_model_fields(config, model_class, include_fk=False): +def get_model_fields(config, model_class=None): """ Convenience function to return a list of field names for the given - :term:`data model` class. + model class. This logic only supports SQLAlchemy mapped classes and will use that to determine the field listing if applicable. Otherwise this returns ``None``. - - :param config: App :term:`config object`. - - :param model_class: Data model class. - - :param include_fk: Whether to include foreign key column names in - the result. They are excluded by default, since the - relationship names are also included and generally preferred. - - :returns: List of field names, or ``None`` if it could not be - determined. """ + if not model_class: + return + try: mapper = sa.inspect(model_class) except sa.exc.NoInspectionAvailable: return - if include_fk: - fields = [prop.key for prop in mapper.iterate_properties] - else: - fields = [prop.key for prop in mapper.iterate_properties - if not prop_is_fk(mapper, prop)] + fields = [prop.key for prop in mapper.iterate_properties] # nb. we never want the continuum 'versions' prop app = config.get_app() @@ -518,20 +505,6 @@ def get_model_fields(config, model_class, include_fk=False): return fields -def prop_is_fk(mapper, prop): - """ """ - if not isinstance(prop, orm.ColumnProperty): - return False - - prop_columns = [col.name for col in prop.columns] - for rel in mapper.relationships: - rel_columns = [col.name for col in rel.local_columns] - if rel_columns == prop_columns: - return True - - return False - - def make_json_safe(value, key=None, warn=True): """ Convert a Python value as needed, to ensure it is compatible with diff --git a/tests/forms/test_schema.py b/tests/forms/test_schema.py index 564e8c2..7b15660 100644 --- a/tests/forms/test_schema.py +++ b/tests/forms/test_schema.py @@ -80,15 +80,6 @@ class TestWuttaEnum(WebTestCase): self.assertIsInstance(widget, widgets.SelectWidget) -class TestWuttaMoney(WebTestCase): - - def test_widget_maker(self): - enum = self.app.enum - typ = mod.WuttaMoney(self.request) - widget = typ.widget_maker() - self.assertIsInstance(widget, widgets.WuttaMoneyInputWidget) - - class TestObjectRef(DataTestCase): def setUp(self): diff --git a/tests/forms/test_widgets.py b/tests/forms/test_widgets.py index 71f0dc0..e324458 100644 --- a/tests/forms/test_widgets.py +++ b/tests/forms/test_widgets.py @@ -1,7 +1,6 @@ # -*- coding: utf-8; -*- import datetime -import decimal from unittest.mock import patch import colander @@ -108,36 +107,6 @@ class TestWuttaDateTimeWidget(WebTestCase): self.assertEqual(result, '2024-12-12 13:49+0000') -class TestWuttaMoneyInputWidget(WebTestCase): - - def make_field(self, node, **kwargs): - # TODO: not sure why default renderer is in use even though - # pyramid_deform was included in setup? but this works.. - kwargs.setdefault('renderer', deform.Form.default_renderer) - return deform.Field(node, **kwargs) - - def make_widget(self, **kwargs): - return mod.WuttaMoneyInputWidget(self.request, **kwargs) - - def test_serialize(self): - node = colander.SchemaNode(WuttaDateTime()) - field = self.make_field(node) - widget = self.make_widget() - amount = decimal.Decimal('12.34') - - # editable widget has normal text input - result = widget.serialize(field, str(amount)) - self.assertIn('