sprox-0.9.6/0000755000076500000240000000000012546321746012766 5ustar amolstaff00000000000000sprox-0.9.6/MANIFEST.in0000644000076500000240000000050212472732352014516 0ustar amolstaff00000000000000recursive-include sprox/widgets/tw1widgets/templates * recursive-include sprox/widgets/tw1widgets/static * recursive-include sprox/widgets/tw2widgets/templates * recursive-include sprox/widgets/tw2widgets/static * global-exclude __pycache__/* global-exclude *.pyc recursive-exclude tests * recursive-exclude sprox/test * sprox-0.9.6/PKG-INFO0000644000076500000240000000125312546321746014064 0ustar amolstaff00000000000000Metadata-Version: 1.1 Name: sprox Version: 0.9.6 Summary: A package for creation of web widgets directly from database schema. Home-page: http://www.sprox.org Author: Christopher Perkins 2007-2009 major contributions by Michael Brickenstein Author-email: chris@percious.com License: MIT Description: UNKNOWN Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules sprox-0.9.6/README.rst0000644000076500000240000000135612472732435014461 0ustar amolstaff00000000000000Sprox ============== .. image:: https://travis-ci.org/TurboGears/sprox.png :target: https://travis-ci.org/TurboGears/sprox .. image:: https://coveralls.io/repos/TurboGears/sprox/badge.png :target: https://coveralls.io/r/TurboGears/sprox .. image:: https://pypip.in/v/sprox/badge.png :target: https://pypi.python.org/pypi/sprox .. image:: https://pypip.in/d/sprox/badge.png :target: https://pypi.python.org/pypi/sprox Form Generation from database schema for ToscaWidgets with support for various database backends License ----------- Sprox is licensed under an MIT-style license (see LICENSE.txt). Other incorporated projects may be licensed under different licenses. All licenses allow for non-commercial and commercial use. sprox-0.9.6/setup.cfg0000644000076500000240000000020112546321746014600 0ustar amolstaff00000000000000[aliases] release = egg_info -rDb "" sdist bdist_egg register upload [egg_info] tag_build = tag_svn_revision = 0 tag_date = 0 sprox-0.9.6/setup.py0000644000076500000240000000447212472732352014504 0ustar amolstaff00000000000000#setup.py import os from setuptools import setup, find_packages here = os.path.abspath(os.path.dirname(__file__)) exec(compile(open(os.path.join(here, 'sprox', 'release.py')).read(), 'release.py', 'exec'), globals(), locals()) import sys py_version = sys.version_info[:2] DEPENDENCIES = ['formencode>=1.3.0a1'] if py_version == (3, 2): DEPENDENCIES += ['markupsafe<0.16'] else: DEPENDENCIES += ['markupsafe'] TESTS_DEPENDENCIES = ['sqlalchemy', 'sieve'] TEST_SUITE_DEPENDENCIES = TESTS_DEPENDENCIES + ['tw2.forms', 'genshi', 'mako'] MONGODB_TEST_SUITE_DEPENDENCIES = TEST_SUITE_DEPENDENCIES + ['ming'] setup( name="sprox", version=__version__, zip_safe=False, include_package_data=True, description="""A package for creation of web widgets directly from database schema.""", author="Christopher Perkins 2007-2009 major contributions by Michael Brickenstein", author_email="chris@percious.com", license="MIT", url="http://www.sprox.org", install_requires=DEPENDENCIES, tests_require=TESTS_DEPENDENCIES, extras_require={ # Used by Travis and Coverage due to setup.py nosetests # causing a coredump when used with coverage 'testing': TEST_SUITE_DEPENDENCIES, 'testing_mongodb': MONGODB_TEST_SUITE_DEPENDENCIES }, packages = find_packages(), classifiers=[ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", "Topic :: Software Development :: Libraries :: Python Modules", ], entry_points = """[toscawidgets] # Use 'widgets' to point to the module where widgets should be imported # from to register in the widget browser widgets = sprox.widgets # Use 'samples' to point to the module where widget examples # should be imported from to register in the widget browser # samples = tw.samples # Use 'resources' to point to the module where resources # should be imported from to register in the widget browser #resources = sprox.widgets.resources """ # entry_points=""" # [paste.paster_create_template] # dbsprockets=sprox.instance.newSprox:Template # """, ) sprox-0.9.6/sprox/0000755000076500000240000000000012546321746014141 5ustar amolstaff00000000000000sprox-0.9.6/sprox/__init__.py0000644000076500000240000000000012472732352016235 0ustar amolstaff00000000000000sprox-0.9.6/sprox/_compat.py0000644000076500000240000000060312472732352016131 0ustar amolstaff00000000000000import platform, sys if platform.system() == 'Windows': # pragma: no cover WIN = True else: # pragma: no cover WIN = False # True if we are running on Python 3. PY2 = sys.version_info[0] == 2 if not PY2: # pragma: no cover string_type = str unicode_text = str byte_string = bytes else: string_type = basestring unicode_text = unicode byte_string = str sprox-0.9.6/sprox/_validatorselector.py0000644000076500000240000000356112472732352020402 0ustar amolstaff00000000000000""" validatorselecter Module this contains the class which allows the ViewConfig to select the appropriate validator for the given field Classes: Name Description ValidatorSelecter Parent Class SAValidatorSelector Selecter Based on sqlalchemy field types DatabaseViewValidatorSelector Database View always selects the same validator TableDefValidatorSelector Table def fields use the same validator Exceptions: None Functions: None Copyright (c) 2007-10 Christopher Perkins Original Version by Christopher Perkins 2007 Released under MIT license. """ from formencode import Invalid from formencode.validators import StringBool, Number, UnicodeString as FEUnicodeString, Email, Int try: #pragma: no cover import tw2.forms from tw2.core.validation import * class UnicodeString(FEUnicodeString): outputEncoding = None except ImportError: #pragma: no cover from tw.forms.validators import * DateTimeValidator = DateValidator class ValidatorSelector(object): _name_based_validators = {} def __new__(cls, *args, **kw): bases = cls.mro() chained_attrs = ['_name_based_validators'] for base in bases: for attr in chained_attrs: if hasattr(base, attr): current = getattr(cls, attr) current.update(getattr(base, attr)) return object.__new__(cls) def __getitem__(self, field): return self.select(field) def __init__(self, *args, **kw): pass @property def name_based_validators(self): validators = self._do_get_name_based_validators() validators.update(self._name_based_validators) return validators def select(self, field): return UnicodeString def _do_get_name_based_validators(self): return {} sprox-0.9.6/sprox/_widgetselector.py0000644000076500000240000000236512472732352017701 0ustar amolstaff00000000000000""" widgetselecter Module this contains the class which allows the ViewConfig to select the appropriate widget for the given field Classes: Name Description WidgetSelecter Parent Class SAWidgetSelector Selecter Based on sqlalchemy field types DatabaseViewWidgetSelector Database View always selects the same widget TableDefWidgetSelector Table def fields use the same widget Exceptions: None Functions: None Copyright (c) 2007 Christopher Perkins Original Version by Christopher Perkins 2007Database Released under MIT license. """ try: #pragma: no cover from tw2.core import Widget from tw2.forms.widgets import * except ImportError as e: #pragma: no cover from tw.api import Widget from tw.forms.fields import * from sprox.widgets import * class WidgetSelector(object): def select(self, field): return Widget class EntitiesViewWidgetSelector(WidgetSelector): def select(self, field): return EntityLabelWidget class EntityDefWidgetSelector(WidgetSelector): def select(self, field): return EntityDefWidget class RecordViewWidgetSelector(WidgetSelector): def select(self, field): return RecordFieldWidget sprox-0.9.6/sprox/configbase.py0000644000076500000240000002021412472732352016607 0ustar amolstaff00000000000000from formencode.validators import Validator from sprox.providerselector import ProviderTypeSelector import copy class ConfigBaseError(Exception):pass class ConfigBase(object): """ Base class for all configurable classes in Sprox. :Modifiers: +-----------------------------------+--------------------------------------------+------------------------------+ | Name | Description | Default | +===================================+============================================+==============================+ | __entity__ (__model__) | Entity used for metadata extraction. | None | +-----------------------------------+--------------------------------------------+------------------------------+ | __sprox_id_ | Id for use in the widget. | None | +-----------------------------------+--------------------------------------------+------------------------------+ | __provider_type_selector_type__ | A type for selecting the provider. | ProviderTypeSelector | +-----------------------------------+--------------------------------------------+------------------------------+ | __field_order__ | A list of ordered field names. | None | +-----------------------------------+--------------------------------------------+------------------------------+ | __hide_fields__ | Fields marked as hidden. | [] | +-----------------------------------+--------------------------------------------+------------------------------+ | __add_fields__ | Additional fields to add to the config. | {} | +-----------------------------------+--------------------------------------------+------------------------------+ | __disable_fields__ | Field marked as disabled. | [] | +-----------------------------------+--------------------------------------------+------------------------------+ | __omit_fields__ | Fields removed from the field list. | [] | +-----------------------------------+--------------------------------------------+------------------------------+ | __limit_fields__ | Limit the field list to this. | None | +-----------------------------------+--------------------------------------------+------------------------------+ | __field_attrs__ | attr parmater to set to the field. | {} | +-----------------------------------+--------------------------------------------+------------------------------+ | __metadata_type__ | Metadata associated with this config. | None | +-----------------------------------+--------------------------------------------+------------------------------+ | __possible_field_name_defaults__ | Default foreign field name list for | ['name', 'title', '_name', | | | relationship columns. | 'description', | | | Used when there is no entry in | '_description'] | | | __possible_field_names__. | | +-----------------------------------+--------------------------------------------+------------------------------+ """ # what object does will this object use for metadata extraction # model and entity are one in the same __model__ = __entity__ = None # this is used by catwalk's validate decorator to lookup the sprocket in the cache __sprox_id__ = None #How should we select a provider __provider_type_selector_type__ = ProviderTypeSelector # field overrides __field_order__ = None __hide_fields__ = None __disable_fields__ = None __omit_fields__ = None __add_fields__ = None __limit_fields__ = None __field_attrs__ = None __metadata_type__ = None __possible_field_name_defaults__ = ['name', 'title', '_name', 'description', '_description'] def __init__(self, provider_hint=None, **provider_hints): #map __model__ to __entity__, this may be deprecated if self.__entity__ is None and self.__model__ is not None: self.__entity__ = self.__model__ self.__provider_type_selector__ = self.__provider_type_selector_type__() self.provider_hint = provider_hint self.provider_hints = provider_hints self._do_init_defaults_from_entity() self._do_init_attrs() def __remove_duplicates(self, l): l2 = [] for i in l: if i not in l2 and i is not None: l2.append(i) return l2 @property def __fields__(self): return self._do_get_fields() def _do_get_fields(self): fields = [] if self.__field_order__ is not None: #this makes sure all the ordered fields bubble to the start of the list fields.extend(self.__field_order__) if self.__limit_fields__ is not None: fields.extend(self.__limit_fields__) fields.extend(self.__hide_fields__) fields.extend(list(self.__add_fields__.keys())) fields = self.__remove_duplicates(fields) return fields else: fields = list(self.__metadata__.keys()) fields.extend(list(self.__add_fields__.keys())) fields.extend(self.__hide_fields__) if self.__field_order__ is not None: fields = set(fields) field_order = set(self.__field_order__) extra_fields = fields.difference(field_order) fields = self.__field_order__+list(extra_fields) for field in self.__omit_fields__: while field in fields: fields.remove(field) r = [] for field in fields: if field not in r and field is not None: r.append(field) return r @property def __metadata__(self): if not hasattr(self, '___metadata__'): if self.__metadata_type__ is None: raise ConfigBaseError('You must define a __metadata_type__ attribute for this object') self.___metadata__=self.__metadata_type__(self.__provider__, self.__entity__) return self.___metadata__ @property def __provider__(self): if self.__entity__ is None: raise ConfigBaseError('You must define a __entity__ attribute for this object') return self.__provider_type_selector__.get_selector(self.__entity__).get_provider(self.__entity__, self.provider_hint, **self.provider_hints) def _do_init_attrs(self): if self.__hide_fields__ is None: self.__hide_fields__ = [] if self.__disable_fields__ is None: self.__disable_fields__ = [] if self.__omit_fields__ is None: self.__omit_fields__ = [] if self.__add_fields__ is None: self.__add_fields__ = {} if self.__field_attrs__ is None: self.__field_attrs__ = {} def _do_init_defaults_from_entity(self): """ Users model __sprox__ attribute to setup some defaults. This is useful for TGAdmin to make possible for people to customize its behavior without having to write a custom AdminConfig """ sprox_meta = getattr(self.__entity__, '__sprox__', None) if sprox_meta: for attr, value in list(vars(sprox_meta).items()): if not attr.startswith('_'): setattr(self, '__'+attr+'__', copy.deepcopy(value)) sprox-0.9.6/sprox/dojo/0000755000076500000240000000000012546321746015074 5ustar amolstaff00000000000000sprox-0.9.6/sprox/dojo/__init__.py0000644000076500000240000000000012472732352017170 0ustar amolstaff00000000000000sprox-0.9.6/sprox/dojo/fillerbase.py0000755000076500000240000000157312472732352017564 0ustar amolstaff00000000000000""" fillerbase Module Classes to help fill widgets with data Copyright (c) 2008 Christopher Perkins Original Version by Christopher Perkins 2008 Released under MIT license. """ from sprox.fillerbase import TableFiller class DojoTableFiller(TableFiller): def get_value(self, value=None, **kw): offset = kw.pop('start', None) limit = kw.pop('count', None) order_by = kw.pop('sort', None) desc = False if order_by is not None and order_by.startswith('-'): order_by = order_by[1:] desc = True items = super(DojoTableFiller, self).get_value(value, limit=limit, offset=offset, order_by=order_by, desc=desc, **kw) count = self.get_count() identifier = self.__provider__.get_primary_field(self.__entity__) return dict(identifier=identifier, numRows=count, totalCount=len(items), items=items) sprox-0.9.6/sprox/dojo/formbase.py0000644000076500000240000002040412472732352017241 0ustar amolstaff00000000000000""" fillerbase Module Classes to help fill widgets with data Copyright (c) 2008 Christopher Perkins Original Version by Christopher Perkins 2008 Released under MIT license. """ from sprox.formbase import FormBase, EditableForm, AddRecordForm from sprox.widgets.tw1widgets.dojo import SproxDojoSelectShuttleField, SproxDojoSortedSelectShuttleField SAWidgetSelector = None SAORMProvider = None try: from sprox.sa.widgetselector import SAWidgetSelector from sprox.sa.provider import SAORMProvider except ImportError: # pragma: no cover pass class DojoSAWidgetSelector(SAWidgetSelector): """Dojo-Specific Widget Selector""" default_multiple_select_field_widget_type = SproxDojoSelectShuttleField class DojoFormBase(FormBase): """FormBase for Dojo see :class:`sprox.formbase.FormBase` """ @property def __widget_selector_type__(self): if isinstance(self.__provider__, SAORMProvider): return DojoSAWidgetSelector return super(DojoFormBase, self).__widget_selector_type__ class DojoEditableForm(EditableForm): """Creates a form for editing records that has select shuttles for the multiple relations. :Modifiers: see :class:`sprox.formbase.FormBase` :Usage: >>> from sprox.dojo.formbase import DojoEditableForm >>> from formencode import Schema >>> from formencode.validators import FieldsMatch >>> class Form(DojoEditableForm): ... __model__ = User ... __limit_fields__ = ['user_name', 'groups'] >>> edit_form = Form() >>> print edit_form() # doctest: +XML
Available



Selected
""" @property def __widget_selector_type__(self): if isinstance(self.__provider__, SAORMProvider): return DojoSAWidgetSelector return super(EditableForm, self).__widget_selector_type__ class DojoAddRecordForm(AddRecordForm): """ Creates a form for adding records that has select shuttles for the multiple relations. :Modifiers: see :class:`sprox.formbase.FormBase` :Usage: >>> from sprox.dojo.formbase import DojoAddRecordForm >>> from formencode import Schema >>> from formencode.validators import FieldsMatch >>> class Form(DojoAddRecordForm): ... __model__ = User ... __limit_fields__ = ['user_name', 'groups'] >>> add_form = Form() >>> print add_form() # doctest: +XML
Available



Selected
""" @property def __widget_selector_type__(self): if isinstance(self.__provider__, SAORMProvider): return DojoSAWidgetSelector return super(AddRecordForm, self).__widget_selector_type__ sprox-0.9.6/sprox/dojo/sprockets.py0000644000076500000240000000360612472732352017465 0ustar amolstaff00000000000000""" Sprockets Module This is sort of like the central nervous system of sprox. Views and Sessions are collected in separate caches and served up as sprockets. The cache objects may be solidified at some point with a parent class. They work for right now. Classes: Name Description SprocketCache A cache of Sprockets Sprocket A binding of Filler and View configs ConfigCache Individual configs cached Functions: None Copyright (c) 2007 Christopher Perkins Original Version by Christopher Perkins 2007 Released under MIT license. """ from sprox.sprockets import ConfigCache, SprocketCache from sprox.providerselector import SAORMSelector from sprox.formbase import FormBase, AddRecordForm, EditableForm from sprox.entitiesbase import EntitiesBase, EntityDefBase from sprox.fillerbase import ModelsFiller, ModelDefFiller, EditFormFiller, AddFormFiller, FormFiller from .fillerbase import DojoTableFiller from .tablebase import DojoTableBase class ViewCache(ConfigCache): default_configs = { 'model_view' : EntitiesBase, 'edit' : EditableForm, 'add' : AddRecordForm, 'listing' : DojoTableBase, 'metadata' : EntityDefBase, } json_url = 'data' def __getitem__(self, key): view = super(ViewCache, self).__getitem__(key) return view class FillerCache(ConfigCache): default_configs = { 'model_view' : ModelsFiller, 'metadata' : ModelDefFiller, 'view' : FormFiller, 'listing' : DojoTableFiller, 'edit' : EditFormFiller, 'add' : AddFormFiller, } class DojoSprocketCache(SprocketCache): view_type = ViewCache filler_type = FillerCachesprox-0.9.6/sprox/dojo/tablebase.py0000755000076500000240000000474512472732352017402 0ustar amolstaff00000000000000from tw.dojo import DojoJsonRestStore from sprox.widgets.tw1widgets.dojo import SproxEditableDojoGrid, SproxDojoGrid from sprox.tablebase import TableBase from sprox.metadata import FieldsMetadata class DojoTableBase(TableBase): """This class allows you to credate a table widget. :Modifiers: +-----------------------------------+--------------------------------------------+------------------------------+ | Name | Description | Default | +===================================+============================================+==============================+ | __url__ | url that points to the method for data | None | | | filler for this table | | +-----------------------------------+--------------------------------------------+------------------------------+ | __column_options__ | a pass-thru to the Dojo Table Widget | {} | | | column_options attribute | | +-----------------------------------+--------------------------------------------+------------------------------+ also see modifiers in :mod:`sprox.tablebase` """ #object overrides __base_widget_type__ = SproxDojoGrid __url__ = None __column_options__ = {} def _do_get_widget_args(self): args = super(DojoTableBase, self)._do_get_widget_args() if self.__url__ is not None: args['action'] = self.__url__ args['columns'] = self.__fields__ args['column_options'] = self.__column_options__ args['headers'] = self.__headers__ args['jsId'] = self.__sprox_id__ return args """ Experimental for next version. Will not be included in 0.5""" class DojoEditableTableBase(TableBase): __base_widget_type__ = SproxEditableDojoGrid __url__ = None __column_options__ = {} def _do_get_widget_args(self): args = super(DojoEditableTableBase, self)._do_get_widget_args() if self.__url__ is not None: args['action'] = self.__url__ args['columns'] = self.__fields__ args['column_options'] = self.__column_options__ args['headers'] = self.__headers__ args['jsId'] = self.__sprox_id__ return args sprox-0.9.6/sprox/dummyentity.py0000644000076500000240000000002712472732352017077 0ustar amolstaff00000000000000class DummyEntity:pass sprox-0.9.6/sprox/entitiesbase.py0000644000076500000240000001055412472732352017174 0ustar amolstaff00000000000000from sprox.widgets import ContainerWidget, TableWidget from .viewbase import ViewBase from .widgetselector import EntitiesViewWidgetSelector, EntityDefWidgetSelector from sprox.metadata import EntitiesMetadata, FieldsMetadata class EntityDefBase(ViewBase): """This view can display all of the entities for a given provider. :Modifiers: see :mod:`sprox.viewbase.ViewBase` :Usage: >>> from sprox.entitiesbase import EntityDefBase >>> class UserEntityDef(EntityDefBase): ... __entity__ = User >>> base = UserEntityDef(session) >>> print(base())
NameDefinition
password VARCHAR(40)
user_id INTEGER
user_name VARCHAR(16)
email_address VARCHAR(255)
display_name VARCHAR(255)
created DATETIME
town_id INTEGER
town relation
password relation
groups relation
""" __base_widget_type__ = TableWidget __widget_selector_type__ = EntityDefWidgetSelector __metadata_type__ = FieldsMetadata from .dummyentity import DummyEntity class EntitiesBase(ViewBase): """This view can display all of the entities for a given provider. :Modifiers: see :mod:`sprox.viewbase.ViewBase` :Usage: >>> from sprox.entitiesbase import EntitiesBase >>> class MyEntitiesBase(EntitiesBase): ... __entity__ = User >>> base = MyEntitiesBase(session, metadata=metadata) >>> print(base())
Department
Document
DocumentCategory
DocumentCategoryReference
DocumentCategoryTag
Example
File
Group
Permission
Town
User
WithoutName
WithoutNameOwner
""" __entity__ = DummyEntity __base_widget_type__ = ContainerWidget __widget_selector_type__ = EntitiesViewWidgetSelector __metadata_type__ = EntitiesMetadata sprox-0.9.6/sprox/fillerbase.py0000644000076500000240000003243612472732366016635 0ustar amolstaff00000000000000""" fillerbase Module Classes to help fill widgets with data Copyright (c) 2008-10 Christopher Perkins Original Version by Christopher Perkins 2008 Released under MIT license. """ from .configbase import ConfigBase, ConfigBaseError from .metadata import FieldsMetadata import inspect from datetime import datetime from sprox._compat import string_type, byte_string, unicode_text from markupsafe import Markup encoding = 'utf-8' class FillerBase(ConfigBase): """ :Modifiers: see :mod:`sprox.configbase`. The base filler class. :Arguments: values pass through of values. This is typically a set of default values that is updated by the filler. This is useful when updating an existing form. kw Set of keyword arguments for assisting the fill. This is for instance information like offset and limit for a TableFiller. :Usage: >>> filler = FillerBase() >>> filler.get_value() {} """ def get_value(self, values=None, **kw): """ The main function for getting data to fill widgets, """ if values is None: values = {} return values class ModelsFiller(FillerBase): pass class ModelDefFiller(FillerBase): pass class FormFiller(FillerBase): __metadata_type__ = FieldsMetadata def get_value(self, values=None, **kw): values = super(FormFiller, self).get_value(values) values['sprox_id'] = self.__sprox_id__ return values class TableFiller(FillerBase): """ This is the base class for generating table data for use in table widgets. The TableFiller uses it's provider to obtain a dictionary of information about the __entity__ this Filler defines. This class is especially useful when you need to return a json stream, because it allows for customization of attributes. A package which has similar functionality to this is TurboJson, but TurboJson is rules-based, where the semantics for generating dictionaries follows the same :mod:`sprox.configbase` methodology. Modifiers defined in this class +-----------------------------------+--------------------------------------------+------------------------------+ | Name | Description | Default | +===================================+============================================+==============================+ | __actions__ | An overridable function to define how to | a function that creates an | | | display action links in the form. | edit and delete link. | +-----------------------------------+--------------------------------------------+------------------------------+ | __metadata_type__ | How should we get data from the provider. | FieldsMetadata | +-----------------------------------+--------------------------------------------+------------------------------+ | __possible_field_names__ | list or dict of names to use for discovery | None | | | of field names for relationship columns. | (See below.) | | | (None uses the default list from | | | | :class:`sprox.configbase:ConfigBase`.) | | | | A dict provides field-level granularity | | | | (See also explanation below.) | | +-----------------------------------+--------------------------------------------+------------------------------+ | __datetime_formatstr__ | format string for the strftime function of | '%Y-%m-%d %H:%M:%S' | | | datetime objects. | ("simplified" ISO-8601) | | | Classical american format would be | | | | '%m/%d/%Y %H:%M%p'. | | +-----------------------------------+--------------------------------------------+------------------------------+ see modifiers also in :mod:`sprox.configbase`. :Relations: By default, TableFiller will populate relations (join or foreign_key) with either the value from the related table, or a comma-separated list of values. These values are derived from the related object given the field names provided by the __possible_field_names__ modifier. For instance, if you have a User class which is related to Groups, the groups item in the result dictionaries will be populated with Group.group_name. The default field names are specified in __possible_field_name_defaults__: _name, name, description, title. :RESTful Actions: By default, Table filler provides an "__actions__" item in the resultant dictionary list. This provides and edit, and (javascript) delete link which provide edit and DELETE functionality as HTML verbs in REST. For more information on developing RESTful URLs, please visit `http://microformats.org/wiki/rest/urls `_ . :Usage: Here is how we would get the values to fill up a user's table, minus the action column, and created date. >>> class UsersFiller(TableFiller): ... __model__ = User ... __actions__ = False ... __omit_fields__ = ['created'] >>> users_filler = UsersFiller(session) >>> value = users_filler.get_value(values={}, limit=20, offset=0) >>> print value #doctest: +IGNORE_WHITESPACE [{'town': u'Arvada', 'user_id': u'1', 'user_name': u'asdf', 'town_id': u'1', 'groups': u'4', '_password': '******', 'password': '******', 'email_address': u'asdf@asdf.com', 'display_name': u'None'}] """ __actions__ = True __metadata_type__ = FieldsMetadata __possible_field_names__ = None __datetime_formatstr__ = '%Y-%m-%d %H:%M:%S' def _do_init_attrs(self): super(TableFiller, self)._do_init_attrs() if self.__possible_field_names__ is None: self.__possible_field_names__ = self.__possible_field_name_defaults__ def _get_list_data_value(self, field, values): l = [] if isinstance(self.__possible_field_names__, dict) and field in self.__possible_field_names__: view_names = self.__possible_field_names__[field] if not isinstance(view_names, list): view_names = [view_names] elif isinstance(self.__possible_field_names__, list): view_names = self.__possible_field_names__ else: view_names = self.__possible_field_name_defaults__ for value in values: if not isinstance(value, string_type): name = self.__provider__.get_view_field_name(value.__class__, view_names, value) l.append(unicode_text(getattr(value, name))) else: #this is needed for postgres to see array values return values return ', '.join(l) def _get_relation_value(self, field, value): #this may be needed for catwalk, but I am not sure what conditions cause it to be needed #if value is None: # return None name = self.__provider__.get_view_field_name(value.__class__, self.__possible_field_names__) return getattr(value, name) def get_count(self): """Returns the total number of items possible for retrieval. This can only be executed after a get_value() call. This call is useful for creating pagination in the context of a user interface. """ if not hasattr(self, '__count__'): raise ConfigBaseError('Count not yet set for filler. try calling get_value() first.') return self.__count__ def _do_get_fields(self): fields = super(TableFiller, self)._do_get_fields() if '__actions__' not in self.__omit_fields__ and '__actions__' not in fields: fields.insert(0, '__actions__') return fields def __actions__(self, obj): """Override this function to define how action links should be displayed for the given record.""" primary_fields = self.__provider__.get_primary_fields(self.__entity__) pklist = '/'.join(map(lambda x: str(getattr(obj, x)), primary_fields)) value = '
 edit'\ '
'\ '
'\ ''\ ''\ '
'\ '
' return value def _do_get_provider_count_and_objs(self, **kw): limit = kw.pop('limit', None) offset = kw.pop('offset', None) order_by = kw.pop('order_by', None) desc = kw.pop('desc', False) substring_filters = kw.pop('substring_filters', []) count, objs = self.__provider__.query(self.__entity__, limit, offset, self.__limit_fields__, order_by, desc, substring_filters=substring_filters, filters=kw, search_related=True, related_field_names=self.__possible_field_names__) self.__count__ = count return count, objs def get_value(self, values=None, **kw): """ Get the values to fill a form widget. :Arguments: offset offset into the records limit number of records to return order_by name of the column to the return values ordered by desc order the columns in descending order All the other arguments will be used to filter the result """ count, objs = self._do_get_provider_count_and_objs(**kw) self.__count__ = count rows = [] for obj in objs: row = {} for field in self.__fields__: field_method = getattr(self, field, None) if inspect.ismethod(field_method): argspec = inspect.getargspec(field_method) if argspec and (len(argspec[0])-2>=len(kw) or argspec[2]): value = getattr(self, field)(obj, **kw) else: value = getattr(self, field)(obj) else: value = getattr(obj, field) if 'password' in field.lower(): row[field] = '******' continue elif isinstance(value, list) or self.__provider__.is_query(self.__entity__, value): value = self._get_list_data_value(field, value) elif isinstance(value, datetime): value = value.strftime(self.__datetime_formatstr__) elif self.__provider__.is_relation(self.__entity__, field) and value is not None: value = self._get_relation_value(field, value) elif self.__provider__.is_binary(self.__entity__, field) and value is not None: value = Markup('<file>') if isinstance(value, byte_string): value = unicode_text(value, encoding='utf-8') row[field] = unicode_text(value) rows.append(row) return rows class EditFormFiller(FormFiller): """ This class will help to return a single record for use within a form or otherwise. The values are returned in dictionary form. :Modifiers: see :mod:`sprox.configbase`. :Usage: >>> class UserFiller(EditFormFiller): ... __model__ = User >>> users_filler = UsersFiller(session) >>> value = users_filler.get_value(values={'user_id':'1'}) >>> value # doctest: +SKIP {'town': u'Arvada', 'user_id': u'1', 'created': u'2008-12-28 17:33:11.078931', 'user_name': u'asdf', 'town_id': u'1', 'groups': u'4', '_password': '******', 'password': '******', 'email_address': u'asdf@asdf.com', 'display_name': u'None'} """ def get_value(self, values=None, **kw): obj = self.__provider__.get_obj(self.__entity__, params=values, fields=self.__fields__) values = self.__provider__.dictify(obj, self.__fields__, self.__omit_fields__) for key in self.__fields__: method = getattr(self, key, None) if method: if inspect.ismethod(method): values[key] = method(obj, **kw) return values class RecordFiller(EditFormFiller):pass class AddFormFiller(FormFiller): def get_value(self, values=None, **kw): """xxx: get the server/entity defaults.""" kw = super(AddFormFiller, self).get_value(values, **kw) return self.__provider__.get_default_values(self.__entity__, params=values) sprox-0.9.6/sprox/formbase.py0000644000076500000240000006135712472732366016327 0ustar amolstaff00000000000000""" formbase Module Classes to create form widgets. Copyright (c) 2008 Christopher Perkins Original Version by Christopher Perkins 2008 Released under MIT license. """ import warnings try: #pragma: no cover from tw2.core import Widget from tw2.core.widgets import WidgetMeta from tw2.forms import HiddenField, TableForm except ImportError: #pragma: no cover from tw.api import Widget from tw.forms import HiddenField, TableForm class WidgetMeta(object): """TW2 WidgetMetaClass""" import inspect from sprox.util import name2label, is_widget, is_widget_class from sprox.widgets import SproxMethodPutHiddenField, CalendarBase, CalendarDatePicker, CalendarDateTimePicker from .viewbase import ViewBase, ViewBaseError from formencode import Schema, All from formencode import Validator from formencode.validators import String from sprox.validators import UnicodeString, NotEmpty from sprox.validators import UniqueValue from sprox.metadata import FieldsMetadata from sprox.viewbase import ViewBase, ViewBaseError class FilteringSchema(Schema): """This makes formencode work for most forms, because some wsgi apps append extra values to the parameter list.""" filter_extra_fields = True allow_extra_fields = True class Field(object): """Used to handle the case where you want to override both a validator and a widget for a given field""" def __init__(self, widget=None, validator=None): self.widget = widget self.validator = validator class FormBase(ViewBase): """ :Modifiers: Modifiers defined in this class +-----------------------------------+--------------------------------------------+------------------------------+ | Name | Description | Default | +===================================+============================================+==============================+ | __base_widget_type__ | What widget to use for the form. | TableForm | +-----------------------------------+--------------------------------------------+------------------------------+ | __widget_selector_type__ | What class to use for widget selection. | SAWidgetSelector | +-----------------------------------+--------------------------------------------+------------------------------+ | __validator_selector_type__ | What class to use for validator selection. | SAValidatorSelector | +-----------------------------------+--------------------------------------------+------------------------------+ | __require_fields__ | Specifies which fields are required. | [] | +-----------------------------------+--------------------------------------------+------------------------------+ | __check_if_unique__ | Set this to True for "new" forms. This | False | | | causes Sprox to check if there is an | | | | existing record in the database which | | | | matches the field data. | | +-----------------------------------+--------------------------------------------+------------------------------+ | __field_validators__ | A dictionary of validators indexed by | {} | | | fieldname. | | +-----------------------------------+--------------------------------------------+------------------------------+ | __field_validator_types__ | Types of validators to use for each field | {} | | | (allow sprox to set the attribute of the | | | | validators). | | +-----------------------------------+--------------------------------------------+------------------------------+ | __base_validator__ | A validator to attch to the form. | None | +-----------------------------------+--------------------------------------------+------------------------------+ | __validator_selector__ | What object to use to select field | None | | | validators. | | +-----------------------------------+--------------------------------------------+------------------------------+ | __metadata_type__ | What metadata type to use to get schema | FieldsMetadata | | | info on this object | | +-----------------------------------+--------------------------------------------+------------------------------+ | __possible_field_names__ | list or dict of names to use for discovery | None | | | of field names for dropdowns. | | | | (None uses the default list from | | | | :class:`sprox.configbase:ConfigBase`.) | | | | A dict provides field-level granularity | | +-----------------------------------+--------------------------------------------+------------------------------+ Modifiers inherited from :class:`sprox.viewbase.ViewBase` +-----------------------------------+--------------------------------------------+------------------------------+ | Name | Description | Default | +===================================+============================================+==============================+ | __field_widgets__ | A dictionary of widgets to replace the | {} | | | ones that would be chosen by the selector | | +-----------------------------------+--------------------------------------------+------------------------------+ | __field_widget_types__ | A dictionary of types of widgets, allowing | {} | | | sprox to determine the widget args | | +-----------------------------------+--------------------------------------------+------------------------------+ | __widget_selector__ | an instantiated object to use for widget | None | | | selection. | | +-----------------------------------+--------------------------------------------+------------------------------+ Modifiers inherited from :class:`sprox.configbase.ConfigBase` :Example Usage: One of the more useful things sprox does for you is to fill in the arguments to a drop down automatically. Here is the userform, limited to just the town field, which gets populated with the towns. >>> from sprox.formbase import FormBase >>> class UserOnlyTownForm(FormBase): ... __model__ = User ... __limit_fields__ = ['town'] >>> >>> town_form = UserOnlyTownForm(session) >>> >>> print(town_form()) # doctest: +XML
Forms created with sprox can be validated as you would any other widget. >>> class UserOnlyTownForm(FormBase): ... __model__ = User ... __limit_fields__ = ['town'] ... __require_fields__ = ['town'] >>> town_form = UserOnlyTownForm(session) >>> town_form.validate(params={'sprox_id':1}) Traceback (most recent call last): ... ValidationError """ __require_fields__ = None __check_if_unique__ = False #object overrides __base_widget_type__ = TableForm @property def __widget_selector_type__(self): return self.__provider__.default_widget_selector_type __validator_selector__ = None @property def __validator_selector_type__(self): return self.__provider__.default_validator_selector_type __field_validators__ = None __field_validator_types__ = None __base_validator__ = FilteringSchema __metadata_type__ = FieldsMetadata __possible_field_names__ = None __dropdown_field_names__ = None def _do_init_attrs(self): super(FormBase, self)._do_init_attrs() if self.__require_fields__ is None: self.__require_fields__ = [] if self.__field_validators__ is None: self.__field_validators__ = {} if self.__validator_selector__ is None: self.__validator_selector__ = self.__validator_selector_type__(self.__provider__) if self.__field_validator_types__ is None: self.__field_validator_types__ = {} if self.__possible_field_names__ is None: if self.__dropdown_field_names__ is not None: warnings.warn('The __dropdown_field_names__ attribute is deprecated', DeprecationWarning) self.__possible_field_names__ = self.__dropdown_field_names__ else: self.__possible_field_names__ = self.__possible_field_name_defaults__ #bring in custom declared validators for attr in dir(self): if not attr.startswith('__'): value = getattr(self, attr) if isinstance(value, Field): widget = value.widget if is_widget(widget): if not getattr(widget, 'id', None): raise ViewBaseError('Widgets must provide an id argument for use as a field within a ViewBase') self.__add_fields__[attr] = widget try: if is_widget_class(widget): self.__field_widget_types__[attr] = widget except TypeError: pass validator = value.validator if isinstance(validator, Validator): self.__field_validators__[attr] = validator try: if issubclass(validator, Validator): self.__field_validator_types__[attr] = validator except TypeError: pass if isinstance(value, Validator): self.__field_validators__[attr] = value continue try: if issubclass(value, Validator): self.__field_validator_types__[attr] = value except TypeError: pass def validate(self, params, state=None): """A pass-thru to the widget's validate function.""" return self.__widget__.validate(params, state) def _do_get_widget_args(self): """Override this method to define how the class get's the arguments for the main widget """ d = super(FormBase, self)._do_get_widget_args() if self.__base_validator__ is not None: d['validator'] = self.__base_validator__ #TW2 widgets cannot have a FormEncode Schema as validator, only plain validators instances if hasattr(Widget, 'req'): current_validator = d.get('validator') if current_validator is FilteringSchema: d.pop('validator', None) return d def _do_get_field_widget_args(self, field_name, field): """Override this method do define how this class gets the field widget arguemnts """ args = super(FormBase, self)._do_get_field_widget_args( field_name, field) v = self.__field_validators__.get(field_name, self._do_get_field_validator(field_name, field)) if self.__provider__.is_relation(self.__entity__, field_name): args['entity'] = self.__entity__ args['field_name'] = field_name if isinstance(self.__possible_field_names__, dict) and field_name in self.__possible_field_names__: view_names = self.__possible_field_names__[field_name] if not isinstance(view_names, list): view_names = [view_names] args['dropdown_field_names'] = view_names elif isinstance(self.__possible_field_names__, list): args['dropdown_field_names'] = self.__possible_field_names__ if v: args['validator'] = v return args def _do_get_fields(self): """Override this function to define what fields are available to the widget. """ fields = super(FormBase, self)._do_get_fields() provider = self.__provider__ field_order = self.__field_order__ or [] add_fields = list(self.__add_fields__.keys()) for relation in provider.get_relations(self.__entity__): # do not remove field if it is listed in field_order for rel in provider.relation_fields(self.__entity__, relation): if rel not in field_order and rel in fields and rel not in add_fields: fields.remove(rel) if 'sprox_id' not in fields: fields.append('sprox_id') return fields def _do_get_field_widgets(self, fields): widgets = super(FormBase, self)._do_get_field_widgets(fields) widgets['sprox_id'] = HiddenField('sprox_id', validator=String(if_missing=None)) return widgets def _do_get_field_validator(self, field_name, field): """Override this function to define how a field validator is chosen for a given field. """ v_type = self.__field_validator_types__.get(field_name, self.__validator_selector__[field]) if field_name in self.__require_fields__ and v_type is None: v_type = NotEmpty if v_type is None: return args = self._do_get_validator_args(field_name, field, v_type) v = v_type(**args) if self.__check_if_unique__ and self.__provider__.is_unique_field(self.__entity__, field_name): v = All(UniqueValue(self.__provider__, self.__entity__, field_name), v) return v def _do_get_validator_args(self, field_name, field, validator_type): """Override this function to define how to get the validator arguments for the field's validator. """ args = {} args['not_empty'] = (not self.__provider__.is_nullable(self.__entity__, field_name)) or \ field_name in self.__require_fields__ args['required'] = args['not_empty'] widget_type = self._do_get_field_widget_type(field_name, field) if widget_type and (issubclass(widget_type, CalendarBase) or issubclass(widget_type, CalendarDatePicker) or issubclass(widget_type, CalendarDateTimePicker)): widget_args = super(FormBase, self)._do_get_field_widget_args(field_name, field) args['format'] = widget_args.get('date_format', widget_type.date_format) if hasattr(field, 'type') and hasattr(field.type, 'length') and\ issubclass(validator_type, String): args['max'] = field.type.length return args class EditableForm(FormBase): """A form for editing a record. :Modifiers: see :class:`sprox.formbase.FormBase` """ def _do_get_disabled_fields(self): fields = self.__disable_fields__[:] fields.append(self.__provider__.get_primary_field(self.__entity__)) return fields def _do_get_fields(self): """Override this function to define what fields are available to the widget. """ fields = super(EditableForm, self)._do_get_fields() primary_field = self.__provider__.get_primary_field(self.__entity__) if primary_field not in fields: fields.append(primary_field) if '_method' not in fields: fields.append('_method') return fields def _do_get_field_widgets(self, fields): widgets = super(EditableForm, self)._do_get_field_widgets(fields) widgets['_method'] = SproxMethodPutHiddenField(id='sprox_method', validator=UnicodeString(if_missing=None)) return widgets __check_if_unique__ = False class AddRecordForm(FormBase): """An editable form who's purpose is record addition. :Modifiers: see :class:`sprox.formbase.FormBase` +-----------------------------------+--------------------------------------------+------------------------------+ | Name | Description | Default | +===================================+============================================+==============================+ | __check_if_unique__ | Set this to True for "new" forms. This | True | | | causes Sprox to check if there is an | | | | existing record in the database which | | | | matches the field data. | | +-----------------------------------+--------------------------------------------+------------------------------+ Here is an example registration form, as generated from the vase User model. >>> from sprox.formbase import AddRecordForm >>> from formencode.validators import FieldsMatch >>> from sprox.widgets import PasswordField, TextField >>> form_validator = FieldsMatch('password', 'verify_password', ... messages={'invalidNoMatch': 'Passwords do not match'}) >>> class RegistrationForm(AddRecordForm): ... __model__ = User ... __require_fields__ = ['password', 'user_name', 'email_address'] ... __omit_fields__ = ['_password', 'groups', 'created', 'user_id', 'town'] ... __field_order__ = ['user_name', 'email_address', 'display_name', 'password', 'verify_password'] ... __base_validator__ = form_validator ... email_address = TextField ... display_name = TextField ... verify_password = PasswordField('verify_password') >>> registration_form = RegistrationForm() >>> print(registration_form()) # doctest: +XML
What is unique about the AddRecord form, is that if the fields in the database are labeled unique, it will automatically vaidate against uniqueness for that field. Here is a simple user form definition, where the user_name in the model is unique: >>> class AddUserForm(AddRecordForm): ... __entity__ = User ... __limit_fields__ = ['user_name'] >>> user_form = AddUserForm(session) >>> user_form.validate(params={'sprox_id':'asdf', 'user_name':'asdf'}) # doctest: +SKIP Traceback (most recent call last): ... Invalid: user_name: That value already exists The validation fails because there is already a user with the user_name 'asdf' in the database """ __check_if_unique__ = True def _do_init_attrs(self): super(AddRecordForm, self)._do_init_attrs() pkey = self.__provider__.get_primary_field(self.__entity__) if pkey not in self.__omit_fields__: self.__omit_fields__.append(pkey) def _do_get_disabled_fields(self): fields = self.__disable_fields__[:] fields.append(self.__provider__.get_primary_field(self.__entity__)) return fields class DisabledForm(FormBase): """A form who's set of fields is disabled. :Modifiers: see :class:`sprox.formbase.FormBase` Here is an example disabled form with only the user_name and email fields. >>> from sprox.test.model import User >>> from sprox.formbase import DisabledForm >>> class DisabledUserForm(DisabledForm): ... __model__ = User ... __limit_fields__ = ['user_name', 'email_address'] >>> disabled_user_form = DisabledUserForm() >>> print(disabled_user_form(values=dict(user_name='percious', email='chris@percious.com'))) # doctest: +XML
You may notice in the above example that disabled fields pass in a hidden value for each disabled field. """ def _do_get_disabled_fields(self): return self.__fields__ sprox-0.9.6/sprox/iprovider.py0000644000076500000240000002134512472732352016520 0ustar amolstaff00000000000000""" iprovider Module This contains the class which allows sprox to interface with any database via an object-relational mapper (ORM) or object-document mapper (ODM). Definitions: Mapped object An object which is implemented by the ORM/ODM and represents a record or document in the database. Entity An object that represents a set of mapped objects that are part of the same collection or table in the database. Field A definition of aproperty of a mapped object which is accessible using attribute notation. An entity contains a set of fields, and each field has unique name within the entity. Property field A field which contains a value which is presentable to the user. Foreign key field A field which contains a value that refers to another object in the database, and which is hidden from the user. Relation field A field whose value is another mapped object in the database, or a list or set of such objects. The referened objects are presented to the user using a selection or prompting widget. Primary key field A set of fields which identify the mapped object within the entity. Need not be user-presentable. Dictify An alternative representation of a mapped object as a dictionary; see the dictify method docstring for details. Copyright © 2008 Christopher Perkins Original Version by Christopher Perkins 2008 Released under MIT license. """ class IProvider: def __init__(self, hint=None, **hints): pass def get_field(self, entity, name): """Get a field with the given field name.""" raise NotImplementedError def get_fields(self, entity): """Get all of the fields for a given entity, excluding foreign key fields. :Arguments: entity An entity or entity thunk. :Returns: A list of names of the fields that are not foreign keys in the entity. """ raise NotImplementedError def get_entity(self, name): """Get an entity with the given name.""" raise NotImplementedError def get_entities(self): """Get all entities available for this provider.""" raise NotImplementedError def get_primary_fields(self, entity): """Get the fields in the entity which uniquely identifies a record. :Returns: A sequence of fields which when taken together uniquely identify a record. """ raise NotImplementedError def get_primary_field(self, entity): """Get the single primary field for an entity. A single primary field is required for EditableForm and AddRecordForm-based forms. :Returns: A field which unique identifies a record. Raises an exception if there is no such field. """ raise NotImplementedError def get_view_field_name(self, entity, possible_names): """Get the name of the field which first matches the possible colums :Arguments: entity the entity where the field is located possible_names a list of names which define what the view field may contain. This allows the first field that has a name in the list of names will be returned as the view field. """ raise NotImplementedError def get_dropdown_options(self, entity_or_field, field_name=None, view_names=None): """Get all dropdown options for a given entity field. :Arguments: entity_or_field either the entity where the field is located, or the field itself field_name if the entity is specified, name of the field in the entity. Otherwise, None view_names a list of names which define what the view field may contain. This allows the first field that has a name in the list of names will be returned as the view field. :Returns: A list of tuples with (id, view_value) as items. """ raise NotImplementedError def get_relations(self, entity): """Get all of the field names in an enity which are relation fields. :Returns: A list of names of relation fields in the entity. """ raise NotImplementedError def is_relation(self, entity, field_name): """Determine if a field is a relation field.""" raise NotImplementedError def is_nullable(self, entity, field_name): """Determine if a field is nullable.""" raise NotImplementedError def get_default_values(self, entity, params): """Get the default values for form filling based on the database schema.""" # XXX stubbed out in the SA provider and might not be a good API raise NotImplementedError def create(self, entity, params): """Create an entry of type entity with the given params.""" raise NotImplementedError def get_obj(self, entity, params): """Get a single mapped object of type entity which matches the params.""" raise NotImplementedError def get(self, entity, params, fields=None, omit_fields=None): """Get a single dictify of type entity which matches the params. Equivalent to dictify(get(entity, params), fields, omit_fields).""" raise NotImplementedError def update(self, entity, params): """Update an entry of type entity which matches the params.""" raise NotImplementedError def delete(self, entity, params): """Delete an entry of typeentity which matches the params.""" raise NotImplementedError def query(self,entity,limit=None,offset=None,limit_fields=None,order_by=None,desc=False): """Perform a query against this entity. :Arguments: entity the entity to be queried limit the maximum number of objects to return. If unspecified, returns all objects offset the number of objects at the start of the result set to skip. Defaults to 0 limit_fields XXX order_by the name of a field to sort by. If unspecified, no sorting is done desc if true, the sort order is descending. Otherwise, it is ascending. :Returns: A tuple (count, iter) where iter is an iterator of mapped objects. """ raise NotImplementedError def is_binary(self,entity,name): """Determine if the field in the entity is a binary field.""" raise NotImplementedError def relation_fields(self, entity, field_name): """For the relation field with the given name, return the corresponding foreign key field(s) in the entity. :Returns: A list of the names of the foreign key fields. """ raise NotImplementedError def get_field_widget_args(self, entity, field_name, field): """Return a dict with any additional arguments that should be passed for the widget for the field in the entity. :Returns: A dict of additional widget arguments.""" return {} def is_unique(self, entity, field_name, value): """Return true if the value for field is not yet used within the entity.""" # XXX rename this method to something better return True def is_unique_field(self, entity, field_name): """Return true if the field within the entity is a primary or alternate key.""" return False def dictify(self, obj, fields=None, omit_fields=None): """Return a dictionary with keys being the names of fields in te object and values being the values of those fields, except that values that are mapped objects are replaced with the value of the corresponding primary key of the related object instead of the actual mapped object. :Arguments: obj a mapped object or None. If None, the return value is {} fields a container of field names or None. If None, all fields that are not in omit_fields are returned. Otherwise only those fields that are in fields and not in omit_fields are returned. omit_fields: a container of field names or None. If None, no fields are omitted. :Returns: A dictionary of {field_name: value} where field_name is the name of a property field or relation field, and value is the value of the property field or the related primary key value. """ # XXX this api is going to have trouble with subdocuments, because # we may not necessary be able to derive a primary key reference to # a subdocument. (if they embedded in a non-relational db) raise NotImplementedError sprox-0.9.6/sprox/metadata.py0000644000076500000240000000566512472732352016304 0ustar amolstaff00000000000000""" matadata Module This contains the class which defines the generic interface for metadata. Basically, it provides an interface for how data is extracted from the provider for widget generation. Copyright (c) 2008 Christopher Perkins Original Version by Christopher Perkins 2007 Released under MIT license. """ from sprox.iprovider import IProvider class MetadataError(Exception):pass class NotFoundError(Exception):pass class Metadata(dict): """Base Metadata class Metadatas are dictionary-like. They map attributes of the entity they wrap, so that attributes of the entity can be examined without being explicitly set. Elements of a metadata can be set if they are not already part of the wrapped entity. This allows for customization of the metadata without modification to the wrapped metadata. """ def __init__(self, provider, entity=None): self.provider = provider self.entity = entity def __setitem__(self, key, value): self._do_check_set_item(key, value) dict.__setitem__(self, key, value) def _do_get_item(self, item): raise NotImplementedError def _do_keys(sekf): raise NotImplementedError def _do_check_set_item(self, key, value): raise NotImplementedError def __getitem__(self, item): try: value = self._do_get_item(item) return value except NotFoundError: return dict.__getitem__(self, item) def keys(self): r = self._do_keys() r.extend(dict.keys(self)) return r class EntitiesMetadata(Metadata): """A class to extract entities from a database definition. """ def _do_get_item(self, name): if name in self.provider.get_entities(): return self.provider.get_entity(name) raise NotFoundError def _do_keys(self): entities = sorted(self.provider.get_entities()) return entities class FieldsMetadata(Metadata): """A class to extract fields from an entity. """ def __init__(self, provider, entity): Metadata.__init__(self, provider, entity) self.provider = provider self.entity = entity def _do_check_set_item(self, key, value): if key in self.provider.get_fields(self.entity): raise MetadataError('%s is already found in entity: %s'%(key, self.entity)) def _do_get_item(self, item): try: return self.provider.get_field(self.entity, item) except AttributeError: #XXX I'm not sure if we should change the type,but we shouldn't swallow with except: if dict.__contains__(self, item): return dict.get(self, item) raise NotFoundError(self.entity,item) def _do_keys(self): return self.provider.get_fields(self.entity) class FieldMetadata(Metadata): """In the future, if the Field attributes need to be extracted, this is where it will happen. """ pass sprox-0.9.6/sprox/mg/0000755000076500000240000000000012546321746014544 5ustar amolstaff00000000000000sprox-0.9.6/sprox/mg/__init__.py0000644000076500000240000000000012472732352016640 0ustar amolstaff00000000000000sprox-0.9.6/sprox/mg/provider.py0000644000076500000240000004512512512761312016745 0ustar amolstaff00000000000000""" mingprovider Module This contains the class which allows sprox to interface with any database. Copyright © 2009 Jorge Vargas Original Version by Jorge Vargas 2009 Released under MIT license. """ from bson.errors import InvalidId import itertools from sprox.iprovider import IProvider from sprox.util import timestamp import datetime, inspect try: from ming.odm import mapper, ForeignIdProperty, FieldProperty, RelationProperty from ming.odm.declarative import MappedClass from ming.odm.property import OneToManyJoin, ManyToOneJoin, ORMProperty from ming.odm.icollection import InstrumentedObj except ImportError: #pragma nocover from ming.orm import mapper, ForeignIdProperty, FieldProperty, RelationProperty from ming.orm.declarative import MappedClass from ming.orm.property import OneToManyJoin, ManyToOneJoin, ORMProperty from ming.orm.icollection import InstrumentedObj from ming import schema as S import bson from bson import ObjectId import re from .widgetselector import MingWidgetSelector from .validatorselector import MingValidatorSelector from pymongo import ASCENDING, DESCENDING from sprox._compat import string_type class MingProvider(IProvider): default_view_names = ['_name', 'name', 'description', 'title'] default_widget_selector_type = MingWidgetSelector default_validator_selector_type = MingValidatorSelector def __init__(self, hint, **hints): self.session = hint def get_field(self, entity, name): """Get a field with the given field name.""" return mapper(entity).property_index[name] def get_fields(self, entity): """Get all of the fields for a given entity.""" if inspect.isfunction(entity): entity = entity() return [prop.name for prop in mapper(entity).properties if isinstance(prop, ORMProperty)] @property def _entities(self): entities = getattr(self, '__entities', None) if entities is None: entities = dict(((m.mapped_class.__name__, m) for m in MappedClass._registry.values())) self.__entities = entities return entities def get_entity(self, name): """Get an entity with the given name.""" return self._entities[name].mapped_class def get_entities(self): """Get all entities available for this provider.""" return iter(self._entities.keys()) def get_primary_fields(self, entity): """Get the fields in the entity which uniquely identifies a record.""" return [self.get_primary_field(entity)] def get_primary_field(self, entity): """Get the single primary field for an entity""" return '_id' def _get_meta(self, entity, field_name, metaprop): """Returns the value of the given sprox meta property for the field.""" field = self.get_field(entity, field_name) return getattr(field, "sprox_meta", {}).get(metaprop, None) def get_view_field_name(self, entity, possible_names, item=None): """Get the name of the field which first matches the possible colums :Arguments: entity the entity where the field is located possible_names a list of names which define what the view field may contain. This allows the first field that has a name in the list of names will be returned as the view field. """ if entity is InstrumentedObj: # Cope with subdocuments if item is not None: fields = list(item.keys()) else: fields = ['_impl'] else: fields = self.get_fields(entity) for field in fields: if self._get_meta(entity, field, 'title'): return field view_field = None for column_name in possible_names: for actual_name in fields: if column_name == actual_name: view_field = actual_name break if view_field: break for actual_name in fields: if column_name in actual_name: view_field = actual_name break if view_field: break if view_field is None: view_field = fields[0] return view_field def get_dropdown_options(self, entity_or_field, field_name, view_names=None): """Get all dropdown options for a given entity field. :Arguments: entity_or_field either the entity where the field is located, or the field itself field_name if the entity is specified, name of the field in the entity. Otherwise, None view_names a list of names which define what the view field may contain. This allows the first field that has a name in the list of names will be returned as the view field. :Returns: A list of tuples with (id, view_value) as items. """ if view_names is None: view_names = self.default_view_names if field_name is not None: field = self.get_field(entity_or_field, field_name) else: field = entity_or_field if isinstance(field, FieldProperty): field_type = getattr(field, 'field_type', None) if field_type is None: f = getattr(field, 'field', None) if f is not None: field = field.field field_type = field.type schemaitem = field_type if isinstance(schemaitem, S.OneOf): return [ (opt,opt) for opt in schemaitem.options ] raise NotImplementedError("get_dropdown_options doesn't know how to get the options for field %r of type %r" % (field, schemaitem)) if not isinstance(field, RelationProperty): raise NotImplementedError("get_dropdown_options expected a FieldProperty or RelationProperty field, but got %r" % field) try: join = field.join iter = join.rel_cls.query.find() rel_cls = join.rel_cls #this seems like a work around for a bug in ming. except KeyError: # pragma: no cover join = field.related iter = join.query.find() rel_cls = join view_field = self.get_view_field_name(rel_cls, view_names) return [ (str(obj._id), getattr(obj, view_field)) for obj in iter ] def get_relations(self, entity): """Get all of the field names in an enity which are related to other entities.""" return [prop.name for prop in mapper(entity).properties if isinstance(prop, RelationProperty)] def is_relation(self, entity, field_name): """Determine if a field is related to a field in another entity.""" return isinstance(self.get_field(entity, field_name), RelationProperty) def is_query(self, entity, value): """determines if a field is a query instead of actual list of data""" #Currently not supported in MING return False def is_nullable(self, entity, field_name): """Determine if a field is nullable.""" fld = self.get_field(entity, field_name) if isinstance(fld, RelationProperty): # check the required attribute on the corresponding foreign key field fld = fld.join.prop return not getattr(fld, 'kwargs', {}).get("required", False) def get_field_default(self, field): field = getattr(field, 'field', None) if field is not None: if_missing = field.schema.if_missing if if_missing is not None: return (True, if_missing) return (False, None) def get_field_provider_specific_widget_args(self, entity, field, field_name): return {} def get_default_values(self, entity, params): return params def _related_object_id(self, value): if isinstance(value, MappedClass): return value._id return ObjectId(value) def _cast_value(self, entity, key, value): # handles the case where an record with no id is being created if key == '_id' and value == '': value = ObjectId() if value is None: # Let none pass as is as it actually means a "null" on mongodb return value field = getattr(entity, key) relations = self.get_relations(entity) if key in relations: related = field.related if isinstance(value, list): return related.query.find({'_id':{'$in':[self._related_object_id(i) for i in value]}}).all() else: return self.get_obj(related, {'_id':self._related_object_id(value)}) field = getattr(field, 'field', None) if field is not None: if field.type is S.DateTime or field.type is datetime.datetime: if isinstance(value, string_type): return datetime.datetime.strptime(value, "%Y-%m-%d %H:%M:%S") else: return value elif field.type is S.Binary: return bson.Binary(value) elif field.type in (S.Int, int): return int(value) elif field.type in (S.Bool, bool): if value in ('true', 'false'): return value == 'true' and True or False else: return bool(value) return value def create(self, entity, params): """Create an entry of type entity with the given params.""" values = {} fields = self.get_fields(entity) for key, value in params.items(): if key not in fields: continue value = self._cast_value(entity, key, value) if value is not None: values[key] = value obj = entity(**values) self.flush() return obj def flush(self): self.session.flush_all() self.session.close_all() def get_obj(self, entity, params, fields=None, omit_fields=None): try: return entity.query.get(_id=ObjectId(params['_id'])) except InvalidId: return None except KeyError: return entity.query.find_by(**params).first() def get(self, entity, params, fields=None, omit_fields=None): return self.dictify(self.get_obj(entity, params), fields, omit_fields) def update(self, entity, params, omit_fields=None): """Update an entry of type entity which matches the params.""" obj = self.get_obj(entity, params) params.pop('_id') try: params.pop('sprox_id') except KeyError: pass try: params.pop('_method') except KeyError: pass fields = self.get_fields(entity) for key, value in params.items(): if key not in fields: continue if omit_fields and key in omit_fields: continue value = self._cast_value(entity, key, value) setattr(obj, key, value) self.flush() return obj def delete(self, entity, params): """Delete an entry of typeentity which matches the params.""" obj = self.get_obj(entity, params) obj.delete() return obj def _modify_params_for_related_searches(self, entity, params, view_names=None, substrings=()): if view_names is None: view_names = self.default_view_names relations = self.get_relations(entity) for relation in relations: if relation in params: value = params[relation] if not isinstance(value, string_type): # When not a string consider it the related class primary key params.update({relation: value}) continue if not value: # As we use ``contains``, searching for an empty text # will just lead to all results so we just remove the filter. del params[relation] continue relationship = getattr(entity, relation) target_class = relationship.related view_name = self.get_view_field_name(target_class, view_names) if relation in substrings: filter = {view_name: {'$regex': re.compile(re.escape(value), re.IGNORECASE)}} else: filter = {view_name: value} value = target_class.query.find(filter).all() params[relation] = value return params def _modify_params_for_relationships(self, entity, params): relations = self.get_relations(entity) for relation in relations: if relation in params: relationship = getattr(entity, relation) value = params[relation] if not isinstance(value, list): value = [value] adapted_value = [] for v in value: if isinstance(v, ObjectId) or isinstance(v, string_type): obj = self.get_obj(relationship.related, dict(_id=v)) if obj is not None: adapted_value.append(obj) else: adapted_value.append(v) value = adapted_value join = relationship.join my_foreign_key = relationship._detect_foreign_keys(relationship.mapper, join.rel_cls, False) rel_foreign_key = relationship._detect_foreign_keys(mapper(relationship.related), join.own_cls, False) params.pop(relation) if my_foreign_key: my_foreign_key = my_foreign_key[0] params[my_foreign_key.name] = {'$in': [r._id for r in value]} elif rel_foreign_key: rel_foreign_key = rel_foreign_key[0] value = [getattr(r, rel_foreign_key.name) for r in value] if rel_foreign_key.uselist: value = list(itertools.chain(*value)) params['_id'] = {'$in': value} return params def query(self, entity, limit=None, offset=0, limit_fields=None, order_by=None, desc=False, filters={}, substring_filters=[], search_related=False, related_field_names=None, **kw): if '_id' in filters: try: filters['_id'] = ObjectId(filters['_id']) except InvalidId: pass if search_related: # Values for related fields contain the text to search filters = self._modify_params_for_related_searches(entity, filters, view_names=related_field_names, substrings=substring_filters) filters = self._modify_params_for_relationships(entity, filters) for field in substring_filters: if self.is_string(entity, field): filters[field] = {'$regex': re.compile(re.escape(filters[field]), re.IGNORECASE)} iter = entity.query.find(filters) if offset: iter = iter.skip(int(offset)) if limit is not None: iter = iter.limit(int(limit)) if order_by is not None: if desc: dir = DESCENDING else: dir = ASCENDING iter.sort(order_by, dir) count = iter.count() return count, iter.all() def is_string(self, entity, field_name): fld = self.get_field(entity, field_name) if isinstance(fld, RelationProperty): # check the required attribute on the corresponding foreign key field fld = fld.join.prop fld = getattr(fld, 'field', None) return isinstance(fld.schema, S.String) def is_binary(self, entity, field_name): fld = self.get_field(entity, field_name) if isinstance(fld, RelationProperty): # check the required attribute on the corresponding foreign key field fld = fld.join.prop fld = getattr(fld, 'field', None) return isinstance(fld.schema,S.Binary) def relation_fields(self, entity, field_name): field = self.get_field(entity, field_name) if not isinstance(field, RelationProperty): raise TypeError("The field %r is not a relation field" % field) #This is here for many-to-many turbogears-ming relations if not field.join.prop: return [] return [field.join.prop.name] def relation_entity(self, entity, field_name): """If the field in the entity is a relation field, then returns the entity which it relates to. :Returns: Related entity for the field """ field = self.get_field(entity, field_name) return field.related def get_field_widget_args(self, entity, field_name, field): args = {} args['provider'] = self args['nullable'] = self.is_nullable(entity, field_name) return args def is_unique(self, entity, field_name, value): iter = entity.query.find({ field_name: value }) return iter.count() == 0 def is_unique_field(self, entity, field_name): for idx in getattr(entity.__mongometa__, "unique_indexes", ()): if idx == (field_name,): return True return False def dictify(self, obj, fields=None, omit_fields=None): if obj is None: return {} r = {} for prop in self.get_fields(obj.__class__): if fields and prop not in fields: continue if omit_fields and prop in omit_fields: continue value = getattr(obj, prop) if value is not None: if self.is_relation(obj.__class__, prop): klass = self.relation_entity(obj.__class__, prop) pk_name = self.get_primary_field(klass) if isinstance(value, list): #joins value = [getattr(value, pk_name) for value in value] else: #fks value = getattr(value, pk_name) r[prop] = value return r sprox-0.9.6/sprox/mg/validatorselector.py0000644000076500000240000000437612472732366020660 0ustar amolstaff00000000000000""" validatorselecter Module this contains the class which allows the ViewConfig to select the appropriate validator for the given field Classes: Name Description MongoValidatorSelecter Class to aid in the selection of a validator for a mongo document field Exceptions: None Functions: None Copyright (c) 2009 Christopher Perkins Original Version by Christopher Perkins 2009 Released under MIT license. """ from sprox.validatorselector import ValidatorSelector from ming import schema as s try: import ming.odm as o except ImportError: #pragma: no cover import ming.orm as o import inspect from formencode.validators import StringBool, Number, UnicodeString as FEUnicodeString, Email, Int try: #pragma: no cover import tw2.forms from tw2.core.validation import * class UnicodeString(FEUnicodeString): outputEncoding = None except ImportError: #pragma: no cover from tw.forms.validators import * DateTimeValidator = DateValidator BoolValidator = StringBool class MingValidatorSelector(ValidatorSelector): default_validators = { s.Bool: BoolValidator, s.Int: Int, s.Float: Number, s.DateTime: DateTimeValidator, s.Binary: None, s.Value: None, s.ObjectId: None, s.String: UnicodeString } def select(self, field): #xxx: make this a "one of" validator if isinstance(field, o.RelationProperty): return UnicodeString schema_type = getattr(field, 'schema', None) field_type = getattr(field, 'field_type', None) if field_type is None: f = getattr(field, 'field', None) if f is not None: field = field.field field_type = field.type schema_type = field.schema type_ = s.String for t in list(self.default_validators.keys()): if isinstance(field_type, s.OneOf): break if inspect.isclass(field_type) and issubclass(field_type, t): type_ = t break if schema_type is not None and isinstance(schema_type, t): type_ = t break validator_type = self.default_validators.get(type_, None) return validator_type sprox-0.9.6/sprox/mg/widgetselector.py0000644000076500000240000000537612472732352020152 0ustar amolstaff00000000000000""" widgetselecter Module this contains the class which allows the ViewConfig to select the appropriate widget for the given field Classes: Name Description MingWidgetSelecter Aid for the selection of a widget to correspond to a Ming Document field Exceptions: None Functions: None Copyright (c) 2009 Christopher Perkins Original Version by Christopher Perkins 2009 Released under MIT license. Mongo Contributions by Jorge Vargas """ from sprox.widgetselector import WidgetSelector from sprox.widgets import * from ming import schema as S try: from ming.odm.property import RelationProperty, ManyToOneJoin, OneToManyJoin except ImportError: #pragma: no cover from ming.orm.property import RelationProperty, ManyToOneJoin, OneToManyJoin try: from ming.odm.property import ManyToManyListJoin except: #pragma: no cover class ManyToManyListJoin: pass class MingWidgetSelector(WidgetSelector): default_multiple_select_field_widget_type = PropertyMultipleSelectField default_single_select_field_widget_type = PropertySingleSelectField default_name_based_widgets = {} default_widgets = { S.Bool: SproxCheckBox, S.Int: TextField, S.Float: TextField, S.String: TextField, S.DateTime: SproxCalendarDateTimePicker, S.Binary: FileField, S.Value: Label, S.ObjectId: TextField } def select(self,field): if hasattr(field, 'name') and field.name: if field.name in self.default_name_based_widgets: return self.default_name_based_widgets[field.name] if field.name.lower() == 'password': return PasswordField if isinstance(field, RelationProperty): join = field.join if isinstance(join, ManyToOneJoin): return self.default_single_select_field_widget_type if isinstance(join, (OneToManyJoin, ManyToManyListJoin)): return self.default_multiple_select_field_widget_type raise NotImplementedError("Unknown join type %r" % join) # pragma: no cover f = getattr(field, 'field', None) if f is not None: schemaitem = S.SchemaItem.make(field.field.type) if isinstance(schemaitem, S.OneOf): return self.default_single_select_field_widget_type else: return TextField #i don't think this works in the latest ming sprox_meta = getattr(field, "sprox_meta", {}) if sprox_meta.get("narrative"): return TextArea sprox_meta = getattr(field, 'sprox_meta', None) if sprox_meta and 'password' in sprox_meta: return PasswordField return self.default_widgets.get(schemaitem.__class__, TextField) sprox-0.9.6/sprox/mk/0000755000076500000240000000000012546321746014550 5ustar amolstaff00000000000000sprox-0.9.6/sprox/mk/__init__.py0000644000076500000240000000000012472732352016644 0ustar amolstaff00000000000000sprox-0.9.6/sprox/mk/provider.py0000644000076500000240000001516112472732352016755 0ustar amolstaff00000000000000""" mongokitprovider Module This contains the class which allows sprox to interface with any database. Copyright © 2009 Jorge Vargas Original Version by Jorge Vargas 2009 Released under MIT license. """ from sprox.iprovider import IProvider from sprox.util import timestamp from mongokit.pylons.document import MongoDocument from pymongo.binary import Binary import datetime from .widgetselector import MongoKitWidgetSelector from .validatorselector import MongoKitValidatorSelector class MongoKitProvider(IProvider): default_widget_selector_type = MongoKitWidgetSelector default_validator_selector_type = MongoKitValidatorSelector def __init__(self,mapper): self.mapper = mapper def get_field(self, entity, name): """Get a field with the given field name.""" return entity.structure[name] def get_fields(self, entity): """Get all of the fields for a given entity.""" return list(entity.structure.keys()) def get_entity(self, name): """Get an entity with the given name.""" for entity in mapper: if name == entity.name: return entity raise KeyError('could not find model by the name %s'%(name)) def get_entities(self): """Get all entities available for this provider.""" return mapper def get_primary_fields(self, entity): """Get the fields in the entity which uniquely identifies a record.""" return [self.get_primary_field(entity)] def get_primary_field(self, entity): """Get the single primary field for an entity""" #FIXME is this correct? it seems like a SA thing but in mongo _id is required return '_id' def get_view_field_name(self, entity, possible_names): """Get the name of the field which first matches the possible colums :Arguments: entity the entity where the field is located possible_names a list of names which define what the view field may contain. This allows the first field that has a name in the list of names will be returned as the view field. """ fields = self.get_fields(entity) view_field = None for column_name in possible_names: for actual_name in fields: if column_name == actual_name: view_field = actual_name break if view_field: break; for actual_name in fields: if column_name in actual_name: view_field = actual_name break if view_field: break; if view_field is None: view_field = fields[0] return view_field def get_dropdown_options(self, entity, field_name, view_names=None): """Get all dropdown options for a given entity field. :Arguments: entity the entity where the field is located field_name name of the field in the entity view_names a list of names which define what the view field may contain. This allows the first field that has a name in the list of names will be returned as the view field. :Returns: A list of tuples with (id, view_value) as items. """ raise NotImplementedError def get_relations(self, entity): """Get all of the field names in an enity which are related to other entities.""" # return [fieldname for fieldname,field in entity.structure.items() if issubclass(field,Document) raise NotImplementedError def is_relation(self, entity, field_name): """Determine if a field is related to a field in another entity.""" #TODO improve on this method to decouple from mongokit fieldtype = entity.structure[field_name] return issubclass(MongoDocument,fieldtype) def is_nullable(self, entity, field_name): """Determine if a field is nullable.""" return field_name in entity.required_fields def get_field_default(self, field): return (False, None) def get_field_provider_specific_widget_args(self, field_name, field): return {} def get_default_values(self, entity, params): """Get the default values for form filling based on the database schema.""" return entity.default_values def _cast_value(self, entity, key, value): if entity.structure[key] == datetime.datetime: return timestamp(value) return value def create(self, entity, params): """Create an entry of type entity with the given params.""" obj = entity() for key,value in params.items(): if key not in entity.structure: continue; value = self._cast_value(entity, key, value) if value is not None: setattr(obj,key,value) obj.save() return obj def get(self, entity, params): """Get a single entry of type entity which matches the params.""" # if params: # raise NotImplementedError pk_name = self.get_primary_field(entity) return entity.get_from_id(params[pk_name]) def update(self, entity, params): """Update an entry of type entity which matches the params.""" pk_name = self.get_primary_field(entity) obj = entity.get_from_id(params[pk_name]) params.pop('_id') params.pop('sprox_id') params.pop('_method') for key, value in params.items(): if key not in entity.structure: continue; value = self._cast_value(entity, key, value) if value is not None: setattr(obj,key,value) obj.save() return obj def delete(self, entity, params): """Delete an entry of typeentity which matches the params.""" pk_name = self.get_primary_field(entity) obj = entity.get_from_id(params[pk_name]) obj.delete() return obj def query(self, entity, limit=None, offset=None, limit_fields=None, order_by=None, desc=False, **kw): query = entity.all() #XXX is count supposed to be ALL records or all records returned? count = query.count() if order_by is not None: pass #TODO if desc: pass #TODO if offset is not None: pass #TODO if limit is not None: query.limit(limit=int(limit)) objs = entity.all() return count, objs def is_binary(self, entity, name): field = self.get_field(entity, name) return isinstance(field,Binary) sprox-0.9.6/sprox/mk/validatorselector.py0000644000076500000240000000114212472732352020643 0ustar amolstaff00000000000000""" validatorselecter Module this contains the class which allows the ViewConfig to select the appropriate validator for the given field Classes: Name Description MongoValidatorSelecter Class to aid in the selection of a validator for a mongo document field Exceptions: None Functions: None Copyright (c) 2009 Christopher Perkins Original Version by Christopher Perkins 2009 Released under MIT license. Mongo Contributions by Jorge Vargas """ from sprox.validatorselector import ValidatorSelector class MongoKitValidatorSelector(ValidatorSelector): pass sprox-0.9.6/sprox/mk/widgetselector.py0000644000076500000240000000227312472732352020147 0ustar amolstaff00000000000000""" widgetselecter Module this contains the class which allows the ViewConfig to select the appropriate widget for the given field Classes: Name Description MongoWidgetSelecter Aid for the selection of a widget to correspond to a Mongo Document field Exceptions: None Functions: None Copyright (c) 2009 Christopher Perkins Original Version by Christopher Perkins 2009 Released under MIT license. Mongo Contributions by Jorge Vargas """ from sprox.widgetselector import WidgetSelector from sprox.widgets import * from tw.forms import TextField, FileField import datetime import pymongo class MongoKitWidgetSelector(WidgetSelector): #XXX this is a copy of authorized_types from monogokit/pylons/document default_widgets = { # type(None): bool: SproxCheckBox, int: TextField, float: TextField, unicode: TextField, # list: # dict: datetime.datetime: SproxCalendarDateTimePicker, pymongo.binary.Binary:FileField # pymongo.objectid.ObjectId: # pymongo.dbref.DBRef: # pymongo.code.Code: # type(re.compile("")): # MongoDocument: } def select(self,field): return self.default_widgets[field] sprox-0.9.6/sprox/mootools/0000755000076500000240000000000012546321746016014 5ustar amolstaff00000000000000sprox-0.9.6/sprox/mootools/__init__.py0000644000076500000240000000000012472732352020110 0ustar amolstaff00000000000000sprox-0.9.6/sprox/mootools/formbase.py0000644000076500000240000000175312472732352020167 0ustar amolstaff00000000000000""" Mootools Formbase Module Classes to create Mootools forms (client side validation!) Copyright (c) 2008 Christopher Perkins Original Version by Christopher Perkins 2008 Released under MIT license. """ from sprox.formbase import FormBase, EditableForm, AddRecordForm from sprox.sa.widgetselector import SAWidgetSelector from sprox.widgets import TableForm from tw.mootools.forms import CustomisedForm #class MootoolsSAWidgetSelector(SAWidgetSelector): # """Mootools-Specific Widget Selector""" # default_multiple_select_field_widget_type = SproxMootoolsSelectShuttleField class MootoolsTableForm(TableForm, CustomisedForm):pass class MootoolsFormBase(FormBase): """FormBase for Mootools see :class:`sprox.formbase.FormBase` """ __base_widget_type__ = MootoolsTableForm # __widget_selector_type__ = MootoolsSAWidgetSelector class MootoolsEditableForm(EditableForm): # __widget_selector_type__ = MootoolsSAWidgetSelector __base_widget_type__ = MootoolsTableForm sprox-0.9.6/sprox/providerselector.py0000644000076500000240000001333412472732352020107 0ustar amolstaff00000000000000""" Provider Locator Module a module to help dbsprockets automatically find providers Copyright (c) 2008 Christopher Perkins Original Version by Christopher Perkins 2007 Released under MIT license. """ import inspect try: from sqlalchemy import MetaData from sqlalchemy.engine import Engine from sqlalchemy.orm import _mapper_registry, class_mapper from sqlalchemy.orm.session import Session from sqlalchemy.orm.scoping import ScopedSession except ImportError: # pragma: no cover pass try: #pragma:no cover from sqlalchemy.orm.instrumentation import ClassManager except ImportError: #pragma:no cover try: # pragma: no cover #sa 0.6- support from sqlalchemy.orm.attributes import ClassManager except ImportError: pass SAORMProvider = None try: from sprox.sa.provider import SAORMProvider except ImportError: # pragma: no cover pass #MongoKitProvider = None #try: # from sprox.mk.provider import MongoKitProvider #except ImportError: # pragma: no cover # pass MingProvider = None MappedClass = None try: from sprox.mg.provider import MingProvider try: from ming.odm.declarative import MappedClass except ImportError: #pragma: no cover from ming.orm.declarative import MappedClass except ImportError: # pragma: no cover pass from sprox.dummyentity import DummyEntity class ProviderSelector: def __init__(self): self._identifiers = {} self._entities = {} def get_entity(self, name, **hints): raise NotImplementedError def get_identifier(self, entity, **hints): raise NotImplementedError def get_provider(self, entity, **hints): raise NotImplementedError #class _MongoKitSelector(ProviderSelector): # def get_identifier(self, entity, **hints): # return entity.__name__ # def get_provider(self, entity=None, hint=None, **hints): # #TODO cache # return MongoKitProvider(None) class _MingSelector(ProviderSelector): #def get_identifier(self, entity, **hints): # return entity.__name__ def get_provider(self, entity=None, hint=None, **hints): #TODO cache return MingProvider(entity.__mongometa__.session) class _SAORMSelector(ProviderSelector): def __init__(self): self._providers = {} def _get_engine(self, hint, hints): metadata = hints.get('metadata', None) engine = hints.get('engine', None) session = hints.get('session', None) if isinstance(hint, Engine): engine=hint if isinstance(hint, MetaData): metadata=hint if isinstance(hint, (Session, ScopedSession)): session = hint if session is not None and engine is None: engine = session.bind if metadata is not None and engine is None: engine = metadata.bind return engine def get_entity(self, identifier, hint=None, **hints): engine = self._get_engine(hint, hints) for mapper in _mapper_registry: if mapper.class_.__name__ == identifier: if engine is None: return mapper.class_ if engine is not None and mapper.tables[0].bind == engine: return mapper.class_ raise KeyError('could not find model by the name %s in %s'%(model_name, metadata)) def get_identifier(self, entity, **hints): return entity.__name__ def get_provider(self, entity=None, hint=None, **hints): """ :Arguments: Entity Mapped class to find a provider for hint/hints variables sent in to the provider to give more information about how the provider connects to the database. Get a provider related to the entity. (They should share the same engine) The provider's are cached as not to waste computation/memory. :Usage: >>> from sprox.providerselector import SAORMSelector >>> provider = SAORMSelector.get_provider(User, session=session) >>> str(provider.engine.url.drivername) 'sqlite' """ if entity is None and isinstance(hint, Engine): engine = hint if engine not in self._providers: self._providers[engine] = SAORMProvider(hint, **hints) return self._providers[engine] if hint is None and entity is not None: mapper = class_mapper(entity) hint = mapper.tables[0].bind engine = self._get_engine(hint, hints) if engine not in self._providers: if hint is None and len(hints) == 0: hint = engine self._providers[engine] = SAORMProvider(hint, **hints) return self._providers[engine] SAORMSelector = _SAORMSelector() #MongoKitSelector = _MongoKitSelector() MingSelector = _MingSelector() #XXX: #StormSelector = _StormSelector() #SOSelector = _SOSelector() class ProviderTypeSelectorError(Exception):pass class ProviderTypeSelector(object): def get_selector(self, entity=None, **hints): #use a SA Helper if hasattr(entity, '_sa_class_manager') and isinstance(entity._sa_class_manager, ClassManager): return SAORMSelector elif inspect.isclass(entity) and issubclass(entity, DummyEntity): return SAORMSelector #elif hasattr(entity, '_use_pylons') or hasattr(entity,'_enable_autoref'): #xxx: find a better marker # return MongoKitSelector elif inspect.isclass(entity) and MappedClass is not None and issubclass(entity, MappedClass): return MingSelector #other helper definitions are going in here else: raise ProviderTypeSelectorError('Entity %s has no known provider mapping.'%entity) sprox-0.9.6/sprox/recordviewbase.py0000644000076500000240000000561212472732352017520 0ustar amolstaff00000000000000from .viewbase import ViewBase from .metadata import FieldsMetadata from .widgetselector import RecordViewWidgetSelector from .widgets import RecordViewWidget class RecordViewBase(ViewBase): """This class allows you to create a view for a single record. :Modifiers: see modifiers in :mod:`sprox.viewbase` Here is an example listing of the first user in the test database. >>> from sprox.test.base import User >>> from sprox.recordviewbase import RecordViewBase >>> class UserRecordView(RecordViewBase): ... __model__ = User ... __omit_fields__ = ['created'] >>> user_view = UserRecordView(session) >>> from sprox.fillerbase import RecordFiller >>> class UserRecordFiller(RecordFiller): ... __model__ = User >>> user_filler = UserRecordFiller(session) >>> value = user_filler.get_value({'user_id':1}) >>> print(user_view(value=value))
NameValue
_password
user_id 1
user_name asdf
email_address asdf@asdf.com
display_name
town_id 1
town 1
password
groups 5
""" __metadata_type__ = FieldsMetadata __widget_selector_type__ = RecordViewWidgetSelector __base_widget_type__ = RecordViewWidget def _do_get_field_widget_args(self, field_name, field): """Override this method do define how this class gets the field widget arguemnts """ args = super(RecordViewBase, self)._do_get_field_widget_args( field_name, field) args['field_name'] = field_name if self.__provider__.is_relation(self.__entity__, field_name): args['entity'] = self.__entity__ args['field_name'] = field_name return args sprox-0.9.6/sprox/release.py0000644000076500000240000000002612546321653016126 0ustar amolstaff00000000000000__version__ = "0.9.6" sprox-0.9.6/sprox/sa/0000755000076500000240000000000012546321746014544 5ustar amolstaff00000000000000sprox-0.9.6/sprox/sa/__init__.py0000644000076500000240000000000012472732352016640 0ustar amolstaff00000000000000sprox-0.9.6/sprox/sa/provider.py0000644000076500000240000006152312546303426016752 0ustar amolstaff00000000000000""" saprovider Module this contains the class which allows dbsprockets to interface with sqlalchemy. Classes: Name Description SAProvider sqlalchemy metadata/crud provider Exceptions: None Functions: None Copyright (c) 2007 Christopher Perkins Original Version by Christopher Perkins 2007 Released under MIT license. """ import inspect import re from sqlalchemy import and_, or_, DateTime, Date, Interval, Integer, MetaData, desc as _desc, func from sqlalchemy import String from sqlalchemy.engine import Engine from sqlalchemy.orm.session import Session from sqlalchemy.orm.scoping import ScopedSession from sqlalchemy.orm.query import Query from sqlalchemy.orm import Mapper, _mapper_registry, SynonymProperty, object_mapper, class_mapper from sqlalchemy.orm.exc import UnmappedClassError, NoResultFound, UnmappedInstanceError from sqlalchemy.exc import InvalidRequestError from sqlalchemy.schema import Column from sprox.sa.support import PropertyLoader, resolve_entity, Binary, LargeBinary from sprox.iprovider import IProvider from cgi import FieldStorage from datetime import datetime, date, timedelta from warnings import warn from sprox.sa.widgetselector import SAWidgetSelector from sprox.sa.validatorselector import SAValidatorSelector from sprox._compat import string_type class SAORMProviderError(Exception):pass class SAORMProvider(IProvider): default_view_names = ['_name', 'name', 'description', 'title'] default_widget_selector_type = SAWidgetSelector default_validator_selector_type = SAValidatorSelector def __init__(self, hint=None, **hints): """ initialize me with a engine, bound metadata or bound session object or a combination of the above. """ #if hint is None and len(hints) == 0: # raise SAORMProviderError('You must provide a hint to this provider') self.engine, self.session, self.metadata = self._get_engine(hint, hints) def _get_engine(self, hint, hints): metadata = hints.get('metadata', None) engine = hints.get('engine', None) session = hints.get('session', None) if isinstance(hint, Engine): engine=hint if isinstance(hint, MetaData): metadata=hint if isinstance(hint, (Session, ScopedSession)): session = hint if session is not None and engine is None: engine = session.bind if metadata is not None and engine is None: engine = metadata.bind return engine, session, metadata def get_fields(self, entity): entity = resolve_entity(entity) mapper = class_mapper(entity) field_names = list(mapper.c.keys()) for prop in mapper.iterate_properties: try: mapper.c[prop.key] field_names.append(prop.key) except KeyError: mapper.get_property(prop.key) field_names.append(prop.key) return field_names def get_entity(self, name): for mapper in _mapper_registry: if mapper.class_.__name__ == name: engine = mapper.tables[0].bind if engine is not None and mapper.tables[0].bind != self.engine: continue return mapper.class_ raise KeyError('could not find model by the name %s'%(name)) def get_entities(self): entities = [] for mapper in _mapper_registry: engine = mapper.tables[0].bind if engine is not None and mapper.tables[0].bind != self.engine: continue entities.append(mapper.class_.__name__) return entities def get_field(self, entity, name): entity = resolve_entity(entity) mapper = class_mapper(entity) try: return mapper.c[name] except (InvalidRequestError, KeyError): try: return mapper.get_property(name) except InvalidRequestError: raise AttributeError def is_binary(self, entity, name): field = self.get_field(entity, name) if isinstance(field, PropertyLoader): field = self._relationship_local_side(field)[0] if isinstance(field, SynonymProperty): field = self.get_field(entity, field.name) return isinstance(field.type, (Binary, LargeBinary)) def is_nullable(self, entity, name): field = self.get_field(entity, name) if isinstance(field, SynonymProperty): field = self.get_field(entity, field.name) if isinstance(field, PropertyLoader): return getattr(self._relationship_local_side(field)[0], 'nullable') return getattr(field, 'nullable', True) def is_string(self, entity, name): field = self.get_field(entity, name) if isinstance(field, PropertyLoader): field = self._relationship_local_side(field)[0] if isinstance(field, SynonymProperty): field = self.get_field(entity, field.name) #should cover Unicode, UnicodeText, Text and so on by inheritance return isinstance(field.type, String) def get_primary_fields(self, entity): entity = resolve_entity(entity) mapper = class_mapper(entity) fields = [] for field_name in self.get_fields(entity): try: value = mapper.c[field_name] except KeyError: # Relations won't be attributes, but can't be primary anyway. continue if value.primary_key and not field_name in fields: fields.append(field_name) return fields def get_primary_field(self, entity): fields = self.get_primary_fields(entity) assert len(fields) > 0 return fields[0] def _find_title_column(self, entity): entity = resolve_entity(entity) for column in class_mapper(entity).columns: if 'title' in column.info and column.info['title']: return column.key return None def get_view_field_name(self, entity, possible_names, item=None): view_field = self._find_title_column(entity) fields = self.get_fields(entity) for column_name in possible_names: for actual_name in fields: if column_name == actual_name: view_field = actual_name break if view_field: break for actual_name in fields: if column_name in actual_name: view_field = actual_name break if view_field: break if view_field is None: view_field = fields[0] return view_field def get_dropdown_options(self, entity, field_name, view_names=None): if view_names is None: view_names = self.default_view_names if self.session is None: warn('No dropdown options will be shown for %s. ' 'Try passing the session into the initialization ' 'of your form base object so that this sprocket ' 'can have values in the drop downs'%entity) return [] field = self.get_field(entity, field_name) target_field = entity if isinstance(field, PropertyLoader): target_field = field.argument target_field = resolve_entity(target_field) #some kind of relation if isinstance(target_field, Mapper): target_field = target_field.class_ pk_fields = self.get_primary_fields(target_field) view_name = self.get_view_field_name(target_field, view_names) rows = self.session.query(target_field).all() if len(pk_fields) == 1: def build_pk(row): return getattr(row, pk_fields[0]) else: def build_pk(row): return "/".join([str(getattr(row, pk)) for pk in pk_fields]) return [ (build_pk(row), getattr(row, view_name)) for row in rows ] def get_relations(self, entity): entity = resolve_entity(entity) mapper = class_mapper(entity) return [prop.key for prop in mapper.iterate_properties if isinstance(prop, PropertyLoader)] def is_relation(self, entity, field_name): entity = resolve_entity(entity) mapper = class_mapper(entity) try: property = mapper.get_property(field_name) except InvalidRequestError: return False if isinstance(property, PropertyLoader): return True def _relates_many(self, entity, field_name): entity = resolve_entity(entity) mapper = class_mapper(entity) property = mapper.get_property(field_name) return property.uselist def relation_fields(self, entity, field_name): field = getattr(entity, field_name) return [col.name for col in self._relationship_local_side(field.property)] def is_query(self, entity, value): """determines if a field is a query instead of actual list of data""" return isinstance(value, Query) def is_unique(self, entity, field_name, value): entity = resolve_entity(entity) field = getattr(entity, field_name) try: self.session.query(entity).filter(field==value).one() except NoResultFound: return True return False def get_synonyms(self, entity): entity = resolve_entity(entity) mapper = class_mapper(entity) return [prop.key for prop in mapper.iterate_properties if isinstance(prop, SynonymProperty)] def _adapt_type(self, value, primary_key): if isinstance(primary_key.type, Integer): value = int(value) return value def _relationship_local_side(self, relationship): if hasattr(relationship, 'local_columns'): return list(relationship.local_columns) return list(relationship.local_side) #pragma: no cover def _modify_params_for_relationships(self, entity, params): entity = resolve_entity(entity) mapper = class_mapper(entity) relations = self.get_relations(entity) for relation in relations: if relation in params: prop = mapper.get_property(relation) target = prop.argument target = resolve_entity(target) value = params[relation] if value: if prop.uselist and isinstance(value, list): target_obj = [] for v in value: try: object_mapper(v) target_obj.append(v) except UnmappedInstanceError: if hasattr(target, 'primary_key'): pk = target.primary_key else: pk = class_mapper(target).primary_key if isinstance(v, string_type) and "/" in v: v = map(self._adapt_type, v.split("/"), pk) v = tuple(v) else: v = self._adapt_type(v, pk[0]) #only add those items that come back new_v = self.session.query(target).get(v) if new_v is not None: target_obj.append(new_v) elif prop.uselist: try: object_mapper(value) target_obj = [value] except UnmappedInstanceError: mapper = target if not isinstance(target, Mapper): mapper = class_mapper(target) value = self._adapt_type(value, mapper.primary_key[0]) target_obj = [self.session.query(target).get(value)] else: try: object_mapper(value) target_obj = value except UnmappedInstanceError: if isinstance(value, string_type) and "/" in value: value = map(self._adapt_type, value.split("/"), prop.remote_side) value = tuple(value) else: value = self._adapt_type(value, list(prop.remote_side)[0]) target_obj = self.session.query(target).get(value) params[relation] = target_obj else: if prop.uselist: params[relation] = [] else: params[relation] = None return params def create(self, entity, params): entity = resolve_entity(entity) params = self._modify_params_for_dates(entity, params) params = self._modify_params_for_relationships(entity, params) obj = entity() relations = self.get_relations(entity) mapper = class_mapper(entity) for key, value in params.items(): if value is not None: if isinstance(value, FieldStorage): value = value.file.read() try: if key not in relations and value and isinstance(mapper.columns[key].type, Integer): value = int(value) except KeyError: pass setattr(obj, key, value) self.session.add(obj) self.session.flush() return obj def flush(self): self.session.flush() def dictify(self, obj, fields=None, omit_fields=None): if obj is None: return {} r = {} mapper = class_mapper(obj.__class__) for prop in mapper.iterate_properties: if fields and prop.key not in fields: continue if omit_fields and prop.key in omit_fields: continue value = getattr(obj, prop.key) if value is not None: if isinstance(prop, PropertyLoader): klass = prop.argument if isinstance(klass, Mapper): klass = klass.class_ pk_name = self.get_primary_field(klass) if isinstance(value, list) or isinstance(value, Query): #joins value = [getattr(value, pk_name) for value in value] else: #fks value = getattr(value, pk_name) r[prop.key] = value return r def get_field_default(self, field): if isinstance(field, Column) and field.default and getattr(field.default, 'arg', None) is not None: if isinstance(field.default.arg, (string_type, int, float)): return (True, field.default.arg) elif callable(field.default.arg): # SQLAlachemy wraps default so that they receive a context, but TW can't provide one return (True, lambda: field.default.arg(None)) return (False, None) def get_field_provider_specific_widget_args(self, entity, field, field_name): args = {} if isinstance(field, PropertyLoader): args['provider'] = self args['nullable'] = self.is_nullable(entity, field_name) return args def get_default_values(self, entity, params): return params def get_obj(self, entity, params, fields=None, omit_fields=None): obj = self._get_obj(entity, params) return obj def get(self, entity, params, fields=None, omit_fields=None): obj = self.get_obj(entity, params, fields) return self.dictify(obj, fields, omit_fields) def _escape_like(self, value): return value.replace('*', '**').replace('%', '*%').replace('_', '*_') def _get_related_class(self, entity, relation): entity = resolve_entity(entity) mapper = class_mapper(entity) prop = mapper.get_property(relation) target = resolve_entity(prop.argument) if not hasattr(target, 'class_'): target = class_mapper(target) return target.class_ def _modify_params_for_related_searches(self, entity, params, view_names=None, substrings=()): if view_names is None: view_names = self.default_view_names relations = self.get_relations(entity) for relation in relations: if relation in params: value = params[relation] if not isinstance(value, string_type): # When not a string consider it the related class primary key params.update(self._modify_params_for_relationships(entity, {relation: value})) continue if not value: # As we use ``contains``, searching for an empty text # will just lead to all results so we just remove the filter. del params[relation] continue target_class = self._get_related_class(entity, relation) view_name = self.get_view_field_name(target_class, view_names) related_column = getattr(target_class, view_name) if relation in substrings: escaped_value = self._escape_like(value.lower()) filter = func.lower(related_column).contains( escaped_value, escape='*' ) else: filter = (func.lower(related_column) == value.lower()) params[relation] = self.session.query(target_class).filter(filter).all() return params def query(self, entity, limit=None, offset=None, limit_fields=None, order_by=None, desc=False, field_names=[], filters={}, substring_filters=[], search_related=False, related_field_names=None, **kw): entity = resolve_entity(entity) query = self.session.query(entity) filters = self._modify_params_for_dates(entity, filters) if search_related: # Values for related fields contain the text to search filters = self._modify_params_for_related_searches(entity, filters, view_names=related_field_names, substrings=substring_filters) else: # Values for related fields contain the primary key filters = self._modify_params_for_relationships(entity, filters) for field_name, value in filters.items(): field = getattr(entity, field_name) if self.is_relation(entity, field_name) and isinstance(value, list): related_class = self._get_related_class(entity, field_name) related_pk = self.get_primary_field(related_class) related_pk_col = getattr(related_class, related_pk) related_pk_values = (getattr(v, related_pk) for v in value) if self._relates_many(entity, field_name): field_filter = field.any(related_pk_col.in_(related_pk_values)) else: field_filter = field.has(related_pk_col.in_(related_pk_values)) query = query.filter(field_filter) elif field_name in substring_filters and self.is_string(entity, field_name): escaped_value = self._escape_like(value.lower()) query = query.filter(func.lower(field).contains(escaped_value, escape='*')) else: query = query.filter(field==value) count = query.count() if order_by is not None: if self.is_relation(entity, order_by): mapper = class_mapper(entity) class_ = None for prop in mapper.iterate_properties: try: class_ = prop.mapper.class_ except (AttributeError, KeyError): pass query = self.session.query(entity).join(order_by) f = self.get_view_field_name(class_, field_names) field = self.get_field(class_, f) else: field = self.get_field(entity, order_by) if desc: field = _desc(field) query = query.order_by(field) if offset is not None: query = query.offset(offset) if limit is not None: query = query.limit(limit) objs = query.all() return count, objs def _modify_params_for_dates(self, entity, params): entity = resolve_entity(entity) mapper = class_mapper(entity) for key, value in list(params.items()): if key in mapper.c and value is not None: field = mapper.c[key] if hasattr(field, 'type'): if isinstance(field.type, DateTime): if not isinstance(value, datetime): dt = datetime.strptime(value[:19], '%Y-%m-%d %H:%M:%S') params[key] = dt elif isinstance(field.type, Date): if not isinstance(value, date): dt = datetime.strptime(value, '%Y-%m-%d').date() params[key] = dt elif isinstance(field.type, Interval): if not isinstance(value, timedelta): d = re.match( r'((?P\d+) days, )?(?P\d+):' r'(?P\d+):(?P\d+)', str(value)).groupdict(0) dt = timedelta(**dict(( (key, int(value)) for key, value in list(d.items()) ))) params[key] = dt return params def _remove_related_empty_params(self, obj, params, omit_fields=None): entity = obj.__class__ mapper = class_mapper(entity) relations = self.get_relations(entity) for relation in relations: if omit_fields and relation in omit_fields: continue #clear out those items which are not found in the params list. if relation not in params or not params[relation]: related_items = getattr(obj, relation) if related_items is not None: if hasattr(related_items, '__iter__'): setattr(obj, relation, []) else: setattr(obj, relation, None) def _get_obj(self, entity, pkdict): entity = resolve_entity(entity) pk_names = self.get_primary_fields(entity) pks = tuple([pkdict[n] for n in pk_names]) return self.session.query(entity).get(pks) def update(self, entity, params, omit_fields=None): params = self._modify_params_for_dates(entity, params) params = self._modify_params_for_relationships(entity, params) obj = self._get_obj(entity, params) relations = self.get_relations(entity) mapper = object_mapper(obj) for key, value in params.items(): if omit_fields and key in omit_fields: continue if isinstance(value, FieldStorage): value = value.file.read() # this is done to cast any integer columns into ints before they are # sent off to the interpreter. Oracle really needs this. try: if key not in relations and value: value = self._adapt_type(value, mapper.columns[key]) except KeyError: pass setattr(obj, key, value) self._remove_related_empty_params(obj, params, omit_fields) self.session.flush() return obj #this is hard to test because of some kind of rollback issue in the test framework def delete(self, entity, params): obj = self._get_obj(entity, params) # pragma: no cover self.session.delete(obj) # pragma: no cover return obj # pragma: no cover def get_field_widget_args(self, entity, field_name, field): args = {} prop = getattr(field, 'property', None) if prop and isinstance(prop, PropertyLoader): args['provider'] = self args['nullable'] = self.is_nullable(entity, field_name) return args def is_unique_field(self, entity, field_name): field = self.get_field(entity, field_name) if hasattr(field, 'unique') and field.unique: return True return False sprox-0.9.6/sprox/sa/support.py0000644000076500000240000000166612472732352016640 0ustar amolstaff00000000000000import inspect try: from sqlalchemy.orm import PropertyLoader except ImportError: # Compatibility with SQLA0.9 from sqlalchemy.orm import RelationshipProperty as PropertyLoader try: from sqlalchemy.ext.declarative.clsregistry import _class_resolver except ImportError as e: # pragma: no cover # Compatibility with SQLA < 0.9 _class_resolver = None try: # Not available in some SQLA versions from sqlalchemy.types import LargeBinary except ImportError: # pragma: no cover class LargeBinary: pass try: # Future proof as it will probably be removed as deprecated from sqlalchemy.types import Binary except ImportError: # pragma: no cover class Binary(LargeBinary): pass def resolve_entity(entity): if inspect.isfunction(entity): entity = entity() if _class_resolver is not None and isinstance(entity, _class_resolver): entity = entity() return entity sprox-0.9.6/sprox/sa/validatorselector.py0000644000076500000240000000525412472732352020647 0ustar amolstaff00000000000000""" validatorselecter Module this contains the class which allows the ViewConfig to select the appropriate validator for the given field Classes: Name Description ValidatorSelecter Parent Class SAValidatorSelector Selecter Based on sqlalchemy field types DatabaseViewValidatorSelector Database View always selects the same validator TableDefValidatorSelector Table def fields use the same validator Exceptions: None Functions: None Copyright (c) 2007-10 Christopher Perkins Original Version by Christopher Perkins 2007 Released under MIT license. """ from sqlalchemy.schema import Column from sqlalchemy.types import * from sqlalchemy.types import String as StringType from formencode.compound import All from formencode import Invalid from formencode.validators import StringBool, Number, UnicodeString as FEUnicodeString, Email, Int from sqlalchemy.orm import SynonymProperty from sprox.sa.support import PropertyLoader, Binary, LargeBinary from sprox._validatorselector import ValidatorSelector try: #pragma: no cover import tw2.forms from tw2.core.validation import * class UnicodeString(FEUnicodeString): outputEncoding = None except ImportError: #pragma: no cover from tw.forms.validators import * DateTimeValidator = DateValidator try: import tw2.forms from tw2.forms import FileValidator except ImportError: # pragma: no cover from formencode.validators import FieldStorageUploadConverter as FileValidator class SAValidatorSelector(ValidatorSelector): default_validators = { StringType: UnicodeString, Integer: Int, Numeric: Number, DateTime: DateTimeValidator, Date: DateValidator, Time: DateTimeValidator, Binary: FileValidator, LargeBinary: FileValidator, PickleType: UnicodeString, # Boolean: UnicodeString, # NullType: TextField } _name_based_validators = {'email_address':Email} def __init__(self, provider): self.provider = provider def select(self, field): if isinstance(field, PropertyLoader): return if isinstance(field, SynonymProperty): return #do not validate boolean or binary arguments if isinstance(field.type, (Boolean, )): return None if field.name in self.name_based_validators: return self.name_based_validators[field.name] type_ = StringType for t in list(self.default_validators.keys()): if isinstance(field.type, t): type_ = t break validator_type = self.default_validators[type_] return validator_type sprox-0.9.6/sprox/sa/widgetselector.py0000644000076500000240000000550412472732352020143 0ustar amolstaff00000000000000""" widgetselecter Module this contains the class which allows the ViewConfig to select the appropriate widget for the given field Classes: Name Description WidgetSelecter Parent Class SAWidgetSelector Selecter Based on sqlalchemy field types DatabaseViewWidgetSelector Database View always selects the same widget TableDefWidgetSelector Table def fields use the same widget Exceptions: None Functions: None Copyright (c) 2007 Christopher Perkins Original Version by Christopher Perkins 2007Database Released under MIT license. """ from sqlalchemy.types import * from sprox.widgets import * from sqlalchemy.schema import Column from sqlalchemy.orm import SynonymProperty from sprox.sa.support import PropertyLoader, Binary, LargeBinary from sprox._widgetselector import WidgetSelector text_field_limit=100 class SAWidgetSelector(WidgetSelector): default_widgets = { String: TextField, Integer: TextField, Numeric: TextField, DateTime: SproxCalendarDateTimePicker, Date: SproxCalendarDatePicker, Time: SproxTimePicker, Binary: FileField, LargeBinary: FileField, BLOB: FileField, PickleType: TextField, Boolean: SproxCheckBox, # NullType: TextField } default_name_based_widgets = {} default_multiple_select_field_widget_type = PropertyMultipleSelectField default_single_select_field_widget_type = PropertySingleSelectField def select(self, field): if hasattr(field, 'name'): if field.name in self.default_name_based_widgets: return self.default_name_based_widgets[field.name] if field.name.lower() == 'password': return PasswordField if hasattr(field, 'key') and field.key.lower() == 'password': return PasswordField # this is really the best we can do, since we cannot know # what type the field represents until execution occurs. if isinstance(field, SynonymProperty): #fix to handle weird synonym prop stuff if isinstance(field.descriptor, property) or field.descriptor.__class__.__name__.endswith('SynonymProp'): return TextField if isinstance(field, PropertyLoader): if field.uselist: return self.default_multiple_select_field_widget_type return self.default_single_select_field_widget_type type_ = String for t in list(self.default_widgets.keys()): if isinstance(field.type, t): type_ = t break widget = self.default_widgets[type_] if widget is TextField and hasattr(field.type, 'length') and (field.type.length is None or field.type.length>text_field_limit): widget = TextArea return widget sprox-0.9.6/sprox/saormprovider.py0000644000076500000240000000167112472732352017411 0ustar amolstaff00000000000000""" saprovider Module this contains the class which allows dbsprockets to interface with sqlalchemy. Classes: Name Description SAProvider sqlalchemy metadata/crud provider Exceptions: None Functions: None This module is deprecated Copyright (c) 2007-10 Christopher Perkins Original Version by Christopher Perkins 2007 Released under MIT license. """ from .sa.provider import SAORMProvider as _SAORMProvider, SAORMProviderError as _SAORMProviderError import warnings class SAORMProviderError(_SAORMProviderError): def __init__(self, *args, **kw): warnings.warn('This class has moved to the sprox.sa.provider module.') _SAORMProviderError.__init__(self, *args, **kw) class SAORMProvider(_SAORMProvider): def __init__(self, *args, **kw): warnings.warn('This class has moved to the sprox.sa.provider module.') _SAORMProvider.__init__(self, *args, **kw) sprox-0.9.6/sprox/sprockets.py0000644000076500000240000001054512472732352016532 0ustar amolstaff00000000000000""" Sprockets Module This is sort of like the central nervous system of sprox. Views and Sessions are collected in separate caches and served up as sprockets. The cache objects may be solidified at some point with a parent class. They work for right now. Classes: Name Description SprocketCache A cache of Sprockets Sprocket A binding of Filler and View configs ConfigCache Individual configs cached Functions: None Copyright (c) 2007 Christopher Perkins Original Version by Christopher Perkins 2007 Released under MIT license. """ from .providerselector import SAORMSelector from .formbase import FormBase, AddRecordForm, EditableForm from .tablebase import TableBase from .entitiesbase import EntitiesBase, EntityDefBase from .fillerbase import ModelsFiller, ModelDefFiller, EditFormFiller, AddFormFiller, FormFiller, TableFiller class ConfigCacheError(Exception): pass class ConfigCache(object): default_configs = {} def __init__(self, session, metadata=None): self.session = session self.metadata = metadata self._provider = SAORMSelector.get_provider(hint=session.bind, metadata=self.metadata) separator = '__' def _split_identifiers(self, key): separator = '__' if self.separator not in key: identifier = None view_type = key else: view_type, identifier = key.split(self.separator) return view_type, identifier def _get(self, key): view_type, identifier = self._split_identifiers(key) if view_type not in self.default_configs: raise ConfigCacheError('view_type:%s not found in default bases'%view_type) base = self.default_configs[view_type] if key != 'model_view': base.__entity__ = self._provider.get_entity(identifier) base.__provider__ = self._provider base.__sprox_id__ = key return base(self.session) def __getitem__(self, key): #xxx: turn caching back on #if key in self.__dict__: # return self.__dict__[key] view = self._get(key) #self.__dict__[key] = view return view class ViewCache(ConfigCache): default_configs = { 'model_view' : EntitiesBase, 'edit' : EditableForm, 'add' : AddRecordForm, 'listing' : TableBase, 'metadata' : EntityDefBase, } class FillerCache(ConfigCache): """ Container for Fillers """ default_configs = { 'model_view' : ModelsFiller, 'metadata' : ModelDefFiller, 'view' : FormFiller, 'listing' : TableFiller, 'edit' : EditFormFiller, 'add' : AddFormFiller, } class Sprocket: """Association between a view and a sessionConfig""" def __init__(self, view, filler): """Construct a Sprocket Object view a ``view`` object which has been instantiated from a ``ViewConfig`` filler defines how the view should be filled """ self.view = view self.filler = filler class SprocketCache(object): """Set of Associations between widgets and the method to obtain their data caching is disabled for now """ def __init__(self, session, metadata=None): self.views = self.view_type(session, metadata=metadata) self.fillers = self.filler_type(session, metadata=metadata) view_type = ViewCache filler_type = FillerCache sprocket_type = Sprocket def __getitem__(self, key): """ """ #xxx: enable caching #if key in self.__dict__: # import pdb; pdb.set_trace() # return self.__dict__.__getitem__(key) sprocket = self._get_sprocket(key) #self.__dict__[key] = sprocket return sprocket def _get_sprocket(self, key): view = self.views[key] filler = self.fillers[key] return self.sprocket_type(view, filler) #xxx: enable caching #def __setitem__(self, key, item): # return #if not isinstance(item, Sprocket): # raise TypeError('item must be of type Sprocket') #return self.__dict__.__setitem__(key, item) sprox-0.9.6/sprox/tablebase.py0000644000076500000240000002521612472732352016440 0ustar amolstaff00000000000000""" tablebase Module Classes to create table widgets. Copyright (c) 2008-10 Christopher Perkins Original Version by Christopher Perkins 2008 Released under MIT license. """ from operator import itemgetter try: #pragma: no cover import tw2.forms from tw2.core import Widget from tw2.core.widgets import WidgetMeta from tw2.forms.datagrid import Column except ImportError: #pragma: no cover from tw.forms.datagrid import Column from tw.api import Widget class WidgetMeta(object): pass from sprox.widgets import SproxDataGrid from sprox.viewbase import ViewBase from sprox.metadata import FieldsMetadata class TableBase(ViewBase): """This class allows you to create a table widget. :Modifiers: +-----------------------------------+--------------------------------------------+------------------------------+ | Name | Description | Default | +===================================+============================================+==============================+ | __base_widget_type__ | Base widget for fields to go into. | SproxDataGrid | +-----------------------------------+--------------------------------------------+------------------------------+ | __metadata_type__ | Type the widget is based on. | FieldsMetadata | +-----------------------------------+--------------------------------------------+------------------------------+ | __headers__ | A dictionary of field/header pairs. | {} | +-----------------------------------+--------------------------------------------+------------------------------+ | __column_widths__ | A dictionary of field/width(string) pairs. | {} | +-----------------------------------+--------------------------------------------+------------------------------+ | __default_column_width__ | Header size to use when not specified in | '10em' | | | __column_widths__ | | +-----------------------------------+--------------------------------------------+------------------------------+ | __xml_fields__ | fields whose values should show as html | | +-----------------------------------+--------------------------------------------+------------------------------+ see modifiers in :mod:`sprox.viewbase` Here is an example listing of the towns in the test database. >>> from sprox.tablebase import TableBase >>> class TownTable(TableBase): ... __model__ = Town >>> town_table = TownTable(session) >>> print(town_table()) #doctest: +XML
actions town_id name
No Records Found.
As you can see, this is none too interesting, because there is no data in the table. Here is how we fill the table with data using TableFillerBase >>> from sprox.fillerbase import TableFiller >>> class TownFiller(TableFiller): ... __model__ = Town >>> town_filler = TownFiller(session) >>> value = town_filler.get_value() >>> print(town_table(value=value)) #doctest: +SKIP
town_id name
1 Arvada
2 Denver
3 Golden
4 Boulder
And now you can see the table has some data in it, and some restful links to the data. But what if you don't want those links? You can omit the links by adding '__actions__' to omitted fields as follows: >>> class TownTable(TableBase): ... __model__ = Town ... __omit_fields__ = ['__actions__'] >>> town_table = TownTable(session) >>> print(town_table(value=value)) #doctest: +XML
town_id name
1 Arvada
2 Denver
3 Golden
4 Boulder
""" #object overrides __base_widget_type__ = SproxDataGrid __metadata_type__ = FieldsMetadata __headers__ = None __column_widths__ = None __xml_fields__ = None __default_column_width__ = "10em" def _do_get_fields(self): fields = super(TableBase, self)._do_get_fields() if '__actions__' not in self.__omit_fields__ and '__actions__' not in fields: fields.insert(0, '__actions__') if '__actions__' not in self.__headers__: self.__headers__['__actions__'] = 'actions' return fields def _do_init_attrs(self): super(TableBase, self)._do_init_attrs() if self.__headers__ is None: self.__headers__ = {} if self.__column_widths__ is None: self.__column_widths__ = {} if self.__xml_fields__ is None: self.__xml_fields__ = {} def _table_field_is_plain_widget(self, widget): if widget.__class__ == Widget or\ (widget.__class__ == WidgetMeta and Widget in widget.__bases__): return True return False def _do_get_widget_args(self): args = super(TableBase, self)._do_get_widget_args() args['pks'] = None args['column_widths'] = self.__column_widths__ args['default_column_width'] = self.__default_column_width__ # Okay: the trunk version of Sprox creates its args['fields'] # very simply, as a list of lambdas that do an item lookup on # the field name. This means that TableBase inherently ignores # any attempt to specify widgets for displaying or formatting # model values; in fact, the field widget list that the # TableBase grows at some point during processing appears to be # completely ignored. (You will see if it you add "print" # statements around your code to watch how your tables are # behaving.) # To make widgets active, we need to put the widgets in place of # the lambdas in the the args['fields'] that we build. There # are challenges to building this list, however: # 1. The widgets supplied by default are useless. Instead of # being something that can actually display text, the list of # widgets somehow winds up just being bare Widget instances, # which seem to display absolutely nothing when rendered. # Therefore, when we see a bare Widget supplied for a # particular column, we need to ignore it. # 2. Some fields (like '__action__') do not even appear in our # list of fields-plus-widgets called self.__fields__, so we # have to be willing to fall back to a lambda in that case # too. # 3. For some reason, the list of field widgets is not always # present, so we have to wastefully re-compute it here by # calling the _do_get_field_widgets() method. It would be # nice if this were produced once before these computations # started and could be relied upon to be present, but it's # not so far as I could tell. But, then, I was reading code # late at night. # Anyway, with the stanza below, I am able to provide my table # classes with a __field_widget_types__ dictionary and have # those fields rendered differently. field_widget_dict = self._do_get_field_widgets(self.__fields__) field_columns = [] for field in self.__fields__: widget = field_widget_dict.get(field, None) if widget is None or self._table_field_is_plain_widget(widget): # yuck column = Column(field, itemgetter(field), self.__headers__.get(field, field)) else: column = Column(field, widget, self.__headers__.get(field, field)) field_columns.append(column) args['fields'] = field_columns # And, now back to our regularly-scheduled trunk-derived Sprox. if '__actions__' not in self.__omit_fields__: args['pks'] = self.__provider__.get_primary_fields(self.__entity__) args['xml_fields'] = self.__xml_fields__ args.pop('children', None) return args sprox-0.9.6/sprox/util.py0000644000076500000240000000777512472732352015505 0ustar amolstaff00000000000000""" util Module this contains the class which allows dbsprockets to interface with sqlalchemy. Copyright (c) 2007 Christopher Perkins Original Version by Christopher Perkins 2007 Released under MIT license. """ from copy import deepcopy, copy """ A good portion of this code was lifted from the PyYaml Codebase. http://pyyaml.org/: Copyright (c) 2006 Kirill Simonov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. """ import re, datetime class ConverterError(Exception):pass timestamp_regexp = re.compile( r'''^(?P[0-9][0-9][0-9][0-9]) -(?P[0-9][0-9]?) -(?P[0-9][0-9]?) (?:(?:[Tt]|[ \t]+) (?P[0-9][0-9]?) :(?P[0-9][0-9]) :(?P[0-9][0-9]) (?:\.(?P[0-9]*))? (?:[ \t]*(?PZ|(?P[-+])(?P[0-9][0-9]?) (?::(?P[0-9][0-9]))?))?)?$''', re.X) def timestamp(value): match = timestamp_regexp.match(value) if match is None: raise ConverterError('Unknown DateTime format, %s try %%Y-%%m-%%d %%h:%%m:%%s.d'%value) values = match.groupdict() year = int(values['year']) month = int(values['month']) day = int(values['day']) if not values['hour']: return datetime.date(year, month, day) hour = int(values['hour']) minute = int(values['minute']) second = int(values['second']) fraction = 0 if values['fraction']: fraction = values['fraction'][:6] while len(fraction) < 6: fraction += '0' fraction = int(fraction) delta = None if values['tz_sign']: tz_hour = int(values['tz_hour']) tz_minute = int(values['tz_minute'] or 0) delta = datetime.timedelta(hours=tz_hour, minutes=tz_minute) if values['tz_sign'] == '-': delta = -delta data = datetime.datetime(year, month, day, hour, minute, second, fraction) if delta: data -= delta return data def name2label(name): """ Took from ToscaWidgets2. Convert a column name to a Human Readable name. 1) Strip _id from the end 2) Convert _ to spaces 3) Convert CamelCase to Camel Case 4) Upcase first character of Each Word """ if name.endswith('_id'): name = name[:-3] return ' '.join([s.capitalize() for s in re.findall(r'([A-Z][a-z0-9]+|[a-z0-9]+|[A-Z0-9]+)', name)]) try: #pragma: no cover from tw2.core import Widget from tw2.core.widgets import WidgetMeta from tw2.forms import HiddenField except ImportError: #pragma: no cover from tw.api import Widget from tw.forms import HiddenField class WidgetMeta(object): """TW2 WidgetMetaClass""" def is_widget(w): if hasattr(w, 'req'): return isinstance(w, Widget) or isinstance(w, WidgetMeta) and w.__name__.endswith('_s') else: return isinstance(w, Widget) def is_widget_class(w): if hasattr(w, 'req'): return isinstance(w, WidgetMeta) and not w.__name__.endswith('_s') else: return issubclass(w, Widget) sprox-0.9.6/sprox/validators.py0000644000076500000240000000153712472732366016673 0ustar amolstaff00000000000000""" validators Module Copyright (c) 2008 Christopher Perkins Original Version by Christopher Perkins 2008 Released under MIT license. """ from formencode import FancyValidator, Invalid from formencode.validators import UnicodeString as FEUnicodeString from formencode.validators import NotEmpty class UnicodeString(FEUnicodeString): outputEncoding = None class UniqueValue(FancyValidator): def __init__(self, provider, entity, field_name, *args, **kw): self.provider = provider self.entity = entity self.field_name = field_name FancyValidator.__init__(self, *args, **kw) def _to_python(self, value, state): if not self.provider.is_unique(self.entity, self.field_name, value): raise Invalid( 'That value already exists', value, state) return value sprox-0.9.6/sprox/validatorselector.py0000644000076500000240000000220412472732352020234 0ustar amolstaff00000000000000""" validatorselecter Module this contains the class which allows the ViewConfig to select the appropriate validator for the given field Classes: Name Description ValidatorSelecter Parent Class SAValidatorSelector Selecter Based on sqlalchemy field types DatabaseViewValidatorSelector Database View always selects the same validator TableDefValidatorSelector Table def fields use the same validator Exceptions: None Functions: None Copyright (c) 2007-10 Christopher Perkins Original Version by Christopher Perkins 2007 Released under MIT license. """ from sprox._validatorselector import ValidatorSelector import warnings try: from .sa.validatorselector import SAValidatorSelector as _SAValidatorSelector class SAValidatorSelector(_SAValidatorSelector): def __init__(self, *args, **kw): warnings.warn('This class has moved to the sprox.sa.validatorselector module.') # pragma: no cover _SAValidatorSelector.__init__(self, *args, **kw) # pragma: no cover except ImportError: # pragma: no cover pass # pragma: no coversprox-0.9.6/sprox/viewbase.py0000644000076500000240000002622712472732352016326 0ustar amolstaff00000000000000import inspect from sprox.util import name2label, is_widget, is_widget_class try: #pragma: no cover from tw2.core import Widget, Deferred from tw2.core.widgets import WidgetMeta from tw2.forms import HiddenField except ImportError: #pragma: no cover from tw.api import Widget from tw.forms import HiddenField class WidgetMeta(object): """TW2 WidgetMetaClass""" from .configbase import ConfigBase, ConfigBaseError from .widgetselector import WidgetSelector #sa 0.5 support try: #pragma:no cover from sqlalchemy.types import Enum except: #pragma:no cover class Enum: pass class ClassViewer(object): """class wrapper to expose items of a class. Needed to pass classes to TW as params""" def __init__(self, klass): self.__name__ = klass.__name__ class ViewBaseError(Exception):pass class ViewBase(ConfigBase): """ :Modifiers: +-----------------------------------+--------------------------------------------+------------------------------+ | Name | Description | Default | +===================================+============================================+==============================+ | __widget_selector_type__ | What class to use for widget selection. | WidgetSelector | +-----------------------------------+--------------------------------------------+------------------------------+ | __field_widgets__ | A dictionary of widgets to replace the | {} | | | ones that would be chosen by the selector | | +-----------------------------------+--------------------------------------------+------------------------------+ | __field_widget_types__ | A dictionary of types of widgets, allowing | {} | | | sprox to determine the widget args | | +-----------------------------------+--------------------------------------------+------------------------------+ | __field_widget_args__ | A dictionary of types of args for widgets, | {} | | | you to override the args sent to the fields| | +-----------------------------------+--------------------------------------------+------------------------------+ | __base_widget_type__ | The base widget for this config | Widget | +-----------------------------------+--------------------------------------------+------------------------------+ | __base_widget_args__ | Args to pass into the widget overrides any | {} | | | defaults that are set in sprox creation | | +-----------------------------------+--------------------------------------------+------------------------------+ | __widget_selector__ | an instantiated object to use for widget | None | | | selection. | | +-----------------------------------+--------------------------------------------+------------------------------+ Also, see the :mod:`sprox.configbase` modifiers. """ __field_widgets__ = None __field_widget_types__ = None __field_widget_args__ = None __ignore_field_names__ = None #object overrides __base_widget_type__ = Widget __base_widget_args__ = None __widget_selector_type__ = WidgetSelector __widget_selector__ = None def _do_init_attrs(self): super(ViewBase, self)._do_init_attrs() if self.__base_widget_args__ is None: self.__base_widget_args__ = {} if self.__field_widgets__ is None: self.__field_widgets__ = {} if self.__field_widget_args__ is None: self.__field_widget_args__ = {} if self.__field_widget_types__ is None: self.__field_widget_types__ = {} if self.__widget_selector__ is None: self.__widget_selector__ = self.__widget_selector_type__() if self.__ignore_field_names__ is None: self.__ignore_field_names__ = ['sprox_id', '_method'] for attr in dir(self): if not attr.startswith('__'): value = getattr(self, attr) if is_widget(value): if not getattr(value, 'id', None): raise ViewBaseError('Widgets must provide an id argument for use as a field within a ViewBase') self.__add_fields__[attr] = value try: if is_widget_class(value): self.__field_widget_types__[attr] = value except TypeError: pass @property def __widget__(self): widget = getattr(self, '___widget__', None) if not widget: self.___widget__ = self.__base_widget_type__(**self.__widget_args__) return self.___widget__ #try to act like a widget as much as possible def __call__(self, *args, **kw): return self.display(*args, **kw) def display(self, *args, **kw): if 'value' not in kw and args: args = list(args) kw['value'] = args.pop(0) return self.__widget__.display(*args, **kw) @property def __widget_args__(self): return self._do_get_widget_args() def _do_get_widget_args(self): widget_dict = self._do_get_field_widgets(self.__fields__) field_widgets = [] for key in self.__fields__: if key not in widget_dict: continue value = widget_dict[key] #sometimes a field will have two widgets associated with it (disabled fields) if hasattr(value,'__iter__'): field_widgets.extend(value) continue field_widgets.append(value) d = dict(children=field_widgets) d.update(self.__base_widget_args__) return d def _do_get_disabled_fields(self): return self.__disable_fields__ def _do_get_field_widget_args(self, field_name, field): # toscawidgets does not like ids that have '.' in them. This does not # work for databases with schemas. field_name = field_name.replace('.', '_') args = {} #this is sort of a hack around TW evaluating _some_ params that are classes. entity = field if inspect.isclass(field): entity = ClassViewer(field) if hasattr(Widget, 'req'): args.update({'id':'sx_'+field_name, 'key':field_name}) else: #pragma: no cover args.update({'id':field_name}) args.update({'name':field_name, 'identity':self.__entity__.__name__+'_'+field_name, 'entity':entity, 'provider':self.__provider__, 'label':name2label(field_name), 'label_text':name2label(field_name)}) field_default_value = self.__provider__.get_field_default(entity) if field_default_value[0]: if hasattr(Widget, 'req'): if callable(field_default_value[1]): args['value'] = Deferred(field_default_value[1]) else: args['value'] = field_default_value[1] else: #pragma: no cover args['default'] = field_default_value[1] #enum support works completely differently. #if isinstance(entity, Column) and isinstance(entity.type, Enum): # args['options'] = entity.type.enums if field_name in self.__field_attrs__: args['attrs'] = self.__field_attrs__[field_name] provider_widget_args = self.__provider__.get_field_provider_specific_widget_args(self.__entity__, field, field_name) if provider_widget_args: args.update(provider_widget_args) if field_name in self.__field_widget_args__: args.update(self.__field_widget_args__[field_name]) return args def __create_hidden_fields(self): fields = {} fields['sprox_id'] = HiddenField(id='sprox_id') for field_name in self.__hide_fields__: if field_name not in self.__omit_fields__: args = {} try: field = self.__metadata__[field_name] args = self._do_get_field_widget_args(field_name, field) except KeyError: #pragma: no cover pass if field_name in self.__field_widget_args__: args.update(self.__field_widget_args__[field_name]) fields[field_name] = HiddenField(**args) return fields def _do_get_field_widget_type(self, field_name, field): return self.__field_widget_types__.get(field_name, self.__widget_selector__.select(field)) # This was a typo once, keeping it around for backwards compatibility _do_get_field_wiget_type = _do_get_field_widget_type def _do_get_field_widgets(self, fields): metadata_keys = list(self.__metadata__.keys()) widgets = {} for field_name in fields: if field_name in self.__field_widgets__: widgets[field_name] = self.__field_widgets__[field_name] continue if field_name in self.__add_fields__: widget = self.__add_fields__[field_name] if widget is None: widget = Widget(field_name) widgets[field_name] = widget continue if field_name in self.__ignore_field_names__: continue if field_name in self.__hide_fields__: continue if field_name not in metadata_keys: continue field = self.__metadata__[field_name] field_widget_type = self._do_get_field_widget_type(field_name, field) field_widget_args = self._do_get_field_widget_args(field_name, field) if field_name in self._do_get_disabled_fields(): # in this case, we display the current field, disabling it, and also add # a hidden field into th emix field_widget_args['disabled'] = True field_widget_args['attrs'] = {'disabled':True} if hasattr(Widget, 'req'): hidden_id='disabled_' + field_name.replace('.','_') else: #pragma: no cover hidden_id=field_name.replace('.','_') widgets[field_name] = (HiddenField(id=hidden_id, key=field_name, name=field_name, identifier=field_name), field_widget_type(**field_widget_args)) else: widgets[field_name] = field_widget_type(**field_widget_args) widgets.update(self.__create_hidden_fields()) return widgets sprox-0.9.6/sprox/widgets/0000755000076500000240000000000012546321746015607 5ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/__init__.py0000644000076500000240000000041712472732366017724 0ustar amolstaff00000000000000try: #pragma: no cover from .tw2widgets.widgets import * except ImportError: #pragma: no cover from .tw1widgets.widgets import * try: #pragma: no cover from tw2.forms import CalendarBase except: #pragma: no cover class CalendarBase(object): pass sprox-0.9.6/sprox/widgets/tw1widgets/0000755000076500000240000000000012546321746017711 5ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw1widgets/__init__.py0000644000076500000240000000000012472732352022005 0ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw1widgets/dojo.py0000755000076500000240000001036012472732352021216 0ustar amolstaff00000000000000"""Dojo Specific Widgets""" from tw.dojo import DojoQueryReadStore, DojoBase, grid_css, tundragrid_css, DojoJsonRestStore, buildService from tw.dojo.selectshuttle import DojoSelectShuttleField, DojoSortedSelectShuttleField from tw.api import JSSource from sprox.widgets import PropertyMixin from tw.dojo import DojoBase, tundragrid_css, tundra_css, dojo_css, dojo_js from tw.core import JSLink sprox_grid_js = JSLink(modname="sprox", filename="widgets/tw1widgets/static/dojo_grid.js", ) class SproxDojoGrid(DojoBase): engine_name=None available_engines = ['mako', 'genshi'] css = [grid_css, tundragrid_css, tundra_css] javascript=[dojo_js, sprox_grid_js] dojoType = 'dojox.grid.DataGrid' require = ['dojox.grid.DataGrid', 'twdojo.data.TWDojoRestStore'] params = ['id', 'attrs', 'columns', 'jsId', 'action', 'rowsPerPage', 'model', 'delayScroll', 'cssclass', 'actions', 'columnResizing', 'columnReordering', 'column_widths', 'default_column_width', 'headers','column_options', 'default_column_options','dojoStoreType','dojoStoreWidget', 'autoHeight' ] autoHeight="false" delayScroll = "true" cssclass="sprox-dojo-grid" rowsPerPage = 20 columns = [] columnReordering = "false" columnResizing="false" column_widths = {} column_options = {} default_column_options = {} headers = {} default_column_width = "30px" include_dynamic_js_calls = True action='.json' model = None actions = True dojoStoreType = 'dojox.data.QueryReadStore' dojoStoreWidget = None template = "sprox.widgets.tw1widgets.templates.dojogrid" #attrs = {'style':"height:200px"} def update_params(self,d): d['dojoStoreWidget']=DojoQueryReadStore() super(SproxDojoGrid, self).update_params(d) class DojoJsonRestStoreInstance(JSSource): engine_name='mako' require = ['twdojo.data.TWDojoRestStore'] target='.json' url = '.json' idAttribute = 'id' autoSave = 'true' source_vars = ["varId","target","url","idAttribute","autoSave"] src = """ dojo.require("twdojo.data.TWDojoRestStore") var ${varId}=new twdojo.data.TWDojoRestStore({target:"${target}",autoSave:"${autoSave and 'true' or 'false'}", service:buildService("${url}"),idAttribute:"${idAttribute}"}) """ class SproxEditableDojoGrid(DojoBase): engine_name=None available_engines = ['genshi', 'mako'] css = [grid_css, tundragrid_css] require = ['dojox.grid.DataGrid', 'twdojo.data.TWDojoRestStore'] dojoType = 'dojox.grid.DataGrid' params = ['id', 'attrs', 'columns', 'jsId', 'action', 'rowsPerPage', 'model', 'delayScroll', 'cssclass', 'actions', 'columnResizing', 'columnReordering', 'column_widths', 'default_column_width', 'headers','column_options', 'default_column_options','dojoStoreType','dojoStoreWidget', 'autoHeight' ] delayScroll = "true" cssclass="sprox-dojo-grid" rowsPerPage = 20 columns = [] columnReordering = "false" columnResizing="false" column_widths = {} column_options = {} default_column_options = {'editable':"true"} headers = {} default_column_width = "10em" include_dynamic_js_calls = True action='.json' model = None actions = True dojoStoreType = 'twdojo.data.TWDojoRestStore' dojoStoreWidget = None template = "sprox.widgets.tw1widgets.templates.dojogrid" def __init__(self,**kw): super(SproxEditableDojoGrid, self).__init__(**kw) storeName = kw.get('jsId','') or '' storeName = storeName+'_store' self.javascript.append(buildService) self.javascript.append(DojoJsonRestStoreInstance(varId=storeName,target=kw['action'],url=kw['action'])) class SproxDojoSelectShuttleField(DojoSelectShuttleField, PropertyMixin): def update_params(self, d): self._my_update_params(d) super(SproxDojoSelectShuttleField, self).update_params(d) class SproxDojoSortedSelectShuttleField(DojoSortedSelectShuttleField, PropertyMixin): def update_params(self, d): self._my_update_params(d) super(SproxDojoSortedSelectShuttleField, self).update_params(d) sprox-0.9.6/sprox/widgets/tw1widgets/static/0000755000076500000240000000000012546321746021200 5ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw1widgets/static/dojo_grid.js0000644000076500000240000000023612472732352023474 0ustar amolstaff00000000000000//alert('here'); dojo.require("dojo.parser"); dojo.require("dojox.data.QueryReadStore"); dojo.require("dojox.grid.DataGrid"); dojo.require("dojo._base.xhr"); sprox-0.9.6/sprox/widgets/tw1widgets/templates/0000755000076500000240000000000012546321746021707 5ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw1widgets/templates/__init__.py0000644000076500000240000000000012472732352024003 0ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw1widgets/templates/checkbox.html0000644000076500000240000000045712472732352024366 0ustar amolstaff00000000000000 sprox-0.9.6/sprox/widgets/tw1widgets/templates/checkbox.mak0000644000076500000240000000025012472732352024161 0ustar amolstaff00000000000000<%namespace name="tw" module="tw.core.mako_util"/>\ sprox-0.9.6/sprox/widgets/tw1widgets/templates/container.html0000644000076500000240000000037512472732352024561 0ustar amolstaff00000000000000
${child(value, controller=controller)}
sprox-0.9.6/sprox/widgets/tw1widgets/templates/datagrid.html0000644000076500000240000000204512472732352024352 0ustar amolstaff00000000000000
${col.title}
${Markup(col.get_field(row, displays_on='genshi'))} ${col.get_field(row, displays_on='genshi')}
No Records Found.
sprox-0.9.6/sprox/widgets/tw1widgets/templates/datagrid.mak0000644000076500000240000000156012472732352024157 0ustar amolstaff00000000000000
% for i, col in enumerate(columns): % endfor % if value: % for i, row in enumerate(value): % for j, col in enumerate(columns): %endfor % endfor % endif
${col.title}
% if col.title == 'actions' or col.title in xml_fields: ${col.get_field(row, displays_on='mako') | n} % else: ${col.get_field(row, displays_on='mako')} % endif
% if not value: No Records Found. % endif
sprox-0.9.6/sprox/widgets/tw1widgets/templates/dojogrid.html0000644000076500000240000000205312472732352024373 0ustar amolstaff00000000000000
${headers.get(column, column)}
sprox-0.9.6/sprox/widgets/tw1widgets/templates/dojogrid.mak0000644000076500000240000000232012472732352024174 0ustar amolstaff00000000000000<%namespace name="tw" module="tw.core.mako_util"/>\
% if not(dojoStoreWidget is None):
% endif % for column in columns: % endfor
${headers.get(column, column)}
sprox-0.9.6/sprox/widgets/tw1widgets/templates/entityDef.html0000644000076500000240000000056012472732352024526 0ustar amolstaff00000000000000 $entity.key $entity.type relation sprox-0.9.6/sprox/widgets/tw1widgets/templates/entityLabel.html0000644000076500000240000000033112472732352025043 0ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw1widgets/templates/hidden_put.html0000644000076500000240000000031312472732352024712 0ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw1widgets/templates/hidden_put.mak0000644000076500000240000000013012472732352024513 0ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw1widgets/templates/modelLabel.html0000644000076500000240000000034012472732352024627 0ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw1widgets/templates/recordField.html0000644000076500000240000000035712472732352025021 0ustar amolstaff00000000000000 $field_name ${value[field_name]} sprox-0.9.6/sprox/widgets/tw1widgets/templates/recordViewTable.html0000644000076500000240000000042312472732352025652 0ustar amolstaff00000000000000 ${child.display(value)}
NameValue
sprox-0.9.6/sprox/widgets/tw1widgets/templates/table.html0000644000076500000240000000051512472732352023662 0ustar amolstaff00000000000000 ${child.display(value, css_class=((i%2 and 'even') or 'odd'))}
NameDefinition
sprox-0.9.6/sprox/widgets/tw1widgets/templates/tableDef.html0000644000076500000240000000036212472732352024301 0ustar amolstaff00000000000000 $identifier.name $identifier.type sprox-0.9.6/sprox/widgets/tw1widgets/templates/tableForm.html0000644000076500000240000000327512472732352024514 0ustar amolstaff00000000000000
${error_message}
${field.display(value_for(field), **args_for(field))}
sprox-0.9.6/sprox/widgets/tw1widgets/templates/tableLabel.html0000644000076500000240000000032312472732352024617 0ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw1widgets/test/0000755000076500000240000000000012546321746020670 5ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw1widgets/test/__init__.py0000644000076500000240000000000012472732352022764 0ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw1widgets/widgets.py0000644000076500000240000000764312472732352021740 0ustar amolstaff00000000000000from tw.api import Widget from tw.forms import CalendarDatePicker, CalendarDateTimePicker, TableForm, DataGrid from tw.forms.fields import (SingleSelectField, MultipleSelectField, InputField, HiddenField, TextField, FileField, PasswordField, TextArea, Label) from formencode.schema import Schema from formencode.validators import StringBool from formencode import Invalid class SproxMethodPutHiddenField(HiddenField): available_engines = ['mako', 'genshi'] template="sprox.widgets.tw1widgets.templates.hidden_put" class SproxCalendarDatePicker(CalendarDatePicker): date_format = '%Y-%m-%d' class SproxTimePicker(CalendarDateTimePicker): date_format = '%H:%M:%S' class SproxCalendarDateTimePicker(CalendarDateTimePicker): date_format = '%Y-%m-%d %H:%M:%S' class SproxDataGrid(DataGrid): available_engines = ['mako', 'genshi'] template = "sprox.widgets.tw1widgets.templates.datagrid" params = ['pks', 'controller', 'xml_fields'] xml_fields = ['actions'] class ContainerWidget(Widget): template = "genshi:sprox.widgets.tw1widgets.templates.container" params = ["controller",] class TableLabelWidget(Widget): template = "genshi:sprox.widgets.tw1widgets.templates.tableLabel" params = ["identifier", "controller"] class ModelLabelWidget(Widget): available_engines = ['mako', 'genshi'] template = "sprox.widgets.tw1widgets.templates.modelLabel" params = ["identifier", "controller"] class EntityLabelWidget(Widget): template = "genshi:sprox.widgets.tw1widgets.templates.entityLabel" params = ["entity", "controller"] class RecordViewWidget(Widget): template = "genshi:sprox.widgets.tw1widgets.templates.recordViewTable" params = ["entity"] class RecordFieldWidget(Widget): template = "genshi:sprox.widgets.tw1widgets.templates.recordField" params = ['field_name'] class TableDefWidget(Widget): template = "genshi:sprox.widgets.tw1widgets.templates.tableDef" params = ["identifier"] class EntityDefWidget(Widget): available_engines = ['genshi'] template = "sprox.widgets.tw1widgets.templates.entityDef" params = ["entity"] class TableWidget(Widget): available_engines = ['genshi'] template = "genshi:sprox.widgets.tw1widgets.templates.table" class SproxTableForm(TableForm): available_engines = ['mako', 'genshi'] validator = Schema(ignore_missing_keys=True, allow_extra_fields=True) template = "sprox.widgets.tw1widgets.templates.tableForm" #custom checkbox widget since I am not happy with the behavior of the TW one class SproxCheckBox(InputField): available_engines = ['mako', 'genshi'] template = "sprox.widgets.tw1widgets.templates.checkbox" validator = StringBool def update_params(self, d): InputField.update_params(self, d) try: checked = self.validator.to_python(d.value) except Invalid: checked = False d.attrs['checked'] = checked or None class PropertyMixin(Widget): params = ['entity', 'field_name', 'provider', 'dropdown_field_names'] def _my_update_params(self, d, nullable=False): entity = self.entity options = self.provider.get_dropdown_options(self.entity, self.field_name, self.dropdown_field_names) if nullable: options.append([None,"-----------"]) if len(options) == 0: return {} d['options']= options return d class PropertySingleSelectField(SingleSelectField, PropertyMixin): params=["nullable", "disabled"] nullable=False disabled=False def update_params(self, d): self._my_update_params(d,nullable=self.nullable) SingleSelectField.update_params(self, d) return d class PropertyMultipleSelectField(MultipleSelectField, PropertyMixin): params=["disabled"] disabled=False def update_params(self, d): self._my_update_params(d) MultipleSelectField.update_params(self, d) return d sprox-0.9.6/sprox/widgets/tw2widgets/0000755000076500000240000000000012546321746017712 5ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw2widgets/__init__.py0000644000076500000240000000000012472732352022006 0ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw2widgets/templates/0000755000076500000240000000000012546321746021710 5ustar amolstaff00000000000000sprox-0.9.6/sprox/widgets/tw2widgets/templates/__init__.py0000644000076500000240000000000212472732352024006 0ustar amolstaff00000000000000 sprox-0.9.6/sprox/widgets/tw2widgets/templates/container.html0000644000076500000240000000034712472732352024561 0ustar amolstaff00000000000000
${child.display(displays_on='genshi', value=w.value, controller=w.controller)}
sprox-0.9.6/sprox/widgets/tw2widgets/templates/datagrid.genshi0000644000076500000240000000177112472732352024671 0ustar amolstaff00000000000000
${col.title}
${Markup(col.get_field(row, displays_on='genshi'))} ${col.get_field(row, displays_on='genshi')}
No Records Found.
sprox-0.9.6/sprox/widgets/tw2widgets/templates/datagrid.mak0000644000076500000240000000163612472732352024164 0ustar amolstaff00000000000000
% if w.columns: % for i, col in enumerate(w.columns): % endfor % endif % if w.value: % for i, row in enumerate(w.value): % for j, col in enumerate(w.columns): %endfor % endfor % endif
${col.title}
% if col.title == 'actions' or col.name in w.xml_fields: ${col.get_field(row, displays_on='mako') | n} % else: ${col.get_field(row, displays_on='mako')} % endif
% if not w.value: No Records Found. % endif
sprox-0.9.6/sprox/widgets/tw2widgets/templates/entityDef.html0000644000076500000240000000050412472732352024525 0ustar amolstaff00000000000000 $w.entity.key $w.entity.type relation sprox-0.9.6/sprox/widgets/tw2widgets/templates/entityLabel.html0000644000076500000240000000026212472732352025047 0ustar amolstaff00000000000000 sprox-0.9.6/sprox/widgets/tw2widgets/templates/modelLabel.html0000644000076500000240000000026612472732352024637 0ustar amolstaff00000000000000 sprox-0.9.6/sprox/widgets/tw2widgets/templates/recordField.html0000644000076500000240000000030012472732352025006 0ustar amolstaff00000000000000 $w.field_name ${w.value[w.field_name]} sprox-0.9.6/sprox/widgets/tw2widgets/templates/recordViewTable.html0000644000076500000240000000036312472732352025656 0ustar amolstaff00000000000000 ${child.display(value=w.value, displays_on='genshi')}
NameValue
sprox-0.9.6/sprox/widgets/tw2widgets/templates/table.html0000644000076500000240000000045512472732352023666 0ustar amolstaff00000000000000 ${child.display(value=w.value, displays_on='genshi', css_class=((i%2 and 'even') or 'odd'))}
NameDefinition
sprox-0.9.6/sprox/widgets/tw2widgets/templates/tableDef.html0000644000076500000240000000027412472732352024304 0ustar amolstaff00000000000000 $w.identifier.name $w.identifier.type sprox-0.9.6/sprox/widgets/tw2widgets/templates/tableLabel.html0000644000076500000240000000025012472732352024617 0ustar amolstaff00000000000000 sprox-0.9.6/sprox/widgets/tw2widgets/widgets.py0000644000076500000240000001274412472732352021737 0ustar amolstaff00000000000000from formencode import Invalid from tw2.core import Widget, Param, DisplayOnlyWidget, ValidationError from tw2.forms import (CalendarDatePicker, CalendarDateTimePicker, TableForm, DataGrid, SingleSelectField, MultipleSelectField, InputField, HiddenField, TextField, FileField, CheckBox, PasswordField, TextArea) from tw2.forms import Label as tw2Label from sprox._compat import unicode_text class Label(tw2Label): def prepare(self): self.text = unicode_text(self.value) super(Label, self).prepare() class SproxMethodPutHiddenField(HiddenField): name = '_method' def prepare(self): self.value = 'PUT' super(SproxMethodPutHiddenField, self).prepare() class ContainerWidget(DisplayOnlyWidget): template = "genshi:sprox.widgets.tw2widgets.templates.container" controller = Param('controller', attribute=False, default=None) css_class = "containerwidget" id_suffix = 'container' class TableLabelWidget(Widget): template = "genshi:sprox.widgets.tw2widgets.templates.tableLabel" controller = Param('controller', attribute=False, default=None) identifier = Param('identifier', attribute=False) class ModelLabelWidget(Widget): template = "genshi:sprox.widgets.tw2widgets.templates.modelLabel" controller = Param('controller', attribute=False, default=None) identifier = Param('identifier', attribute=False) class EntityLabelWidget(Widget): template = "genshi:sprox.widgets.tw2widgets.templates.entityLabel" controller = Param('controller', attribute=False, default=None) entity = Param('entity', attribute=False) css_class = "entitylabelwidget" class RecordViewWidget(Widget): template = "genshi:sprox.widgets.tw2widgets.templates.recordViewTable" entity = Param('entity', attribute=False, default=None) class RecordFieldWidget(Widget): template = "genshi:sprox.widgets.tw2widgets.templates.recordField" field_name = Param('field_name', attribute=False) css_class = "recordfieldwidget" class TableDefWidget(Widget): template = "genshi:sprox.widgets.tw2widgets.templates.tableDef" identifier = Param('identifier', attribute=False) class EntityDefWidget(Widget): template = "genshi:sprox.widgets.tw2widgets.templates.entityDef" entity = Param('entity', attribute=False) class TableWidget(Widget): template = "genshi:sprox.widgets.tw2widgets.templates.table" class SproxCalendarDatePicker(CalendarDatePicker): date_format = '%Y-%m-%d' class SproxTimePicker(CalendarDateTimePicker): date_format = '%H:%M:%S' class SproxCalendarDateTimePicker(CalendarDateTimePicker): date_format = '%Y-%m-%d %H:%M:%S' class SproxDataGrid(DataGrid): template = "sprox.widgets.tw2widgets.templates.datagrid" pks = Param('pks', attribute=False), xml_fields = Param('xml_fields', attribute=False, default=['actions']) value = [] class SproxCheckBox(CheckBox): def prepare(self): super(SproxCheckBox, self).prepare() self.attrs['value'] = 'true' class PropertySingleSelectField(SingleSelectField): entity = Param('entity', attribute=False, default=None) provider = Param('provider', attribute=False, default=None) field_name = Param('field_name', attribute=False, default=None) dropdown_field_names = Param('dropdown_field_names', attribute=False, default=None) nullable = Param('nullable', attribute=False, default=False) disabled = Param('disabled', attribute=False, default=False) prompt_text = None def prepare(self): #This is required for ming entity = self.__class__.entity options = self.provider.get_dropdown_options(entity, self.field_name, self.dropdown_field_names) self.options = [(unicode_text(k), unicode_text(v)) for k,v in options] if self.nullable: self.options.append(['', "-----------"]) if not self.value: self.value = '' self.value = unicode_text(self.value) super(PropertySingleSelectField, self).prepare() class PropertyMultipleSelectField(MultipleSelectField): entity = Param('entity', attribute=False, default=None) provider = Param('provider', attribute=False, default=None) field_name = Param('field_name', attribute=False, default=None) dropdown_field_names = Param('dropdown_field_names', attribute=False, default=None) nullable = Param('nullable', attribute=False, default=False) disabled = Param('disabled', attribute=False, default=False) def _safe_validate(self, validator, value, state=None): try: value = validator.to_python(value, state=state) validator.validate_python(value, state=state) return value except Invalid: return Invalid def _validate(self, value, state=None): value = value or [] if not isinstance(value, (list, tuple)): value = [value] if self.validator: value = [self._safe_validate(self.validator, v) for v in value] self.value = [v for v in value if v is not Invalid] return self.value def prepare(self): #This is required for ming entity = self.__class__.entity options = self.provider.get_dropdown_options(entity, self.field_name, self.dropdown_field_names) self.options = [(unicode_text(k), unicode_text(v)) for k,v in options] if not self.value: self.value = [] self.value = [unicode_text(v) for v in self.value] super(PropertyMultipleSelectField, self).prepare() sprox-0.9.6/sprox/widgetselector.py0000644000076500000240000000212512472732352017534 0ustar amolstaff00000000000000""" widgetselecter Module this contains the class which allows the ViewConfig to select the appropriate widget for the given field Classes: Name Description WidgetSelecter Parent Class SAWidgetSelector Selecter Based on sqlalchemy field types DatabaseViewWidgetSelector Database View always selects the same widget TableDefWidgetSelector Table def fields use the same widget Exceptions: None Functions: None Copyright (c) 2007-10 Christopher Perkins Original Version by Christopher Perkins 2007Database Released under MIT license. """ import warnings from sprox._widgetselector import * try: from sprox.sa.widgetselector import SAWidgetSelector as _SAWidgetSelector class SAWidgetSelector(_SAWidgetSelector): def __init__(self, *args, **kw): warnings.warn('This class has moved to the sprox.sa.widgetselector module.') # pragma: no cover _SAWidgetSelector.__init__(self, *args, **kw) # pragma: no cover except ImportError: # pragma: no cover pass # pragma: no cover sprox-0.9.6/sprox.egg-info/0000755000076500000240000000000012546321746015633 5ustar amolstaff00000000000000sprox-0.9.6/sprox.egg-info/dependency_links.txt0000644000076500000240000000000112546321746021701 0ustar amolstaff00000000000000 sprox-0.9.6/sprox.egg-info/entry_points.txt0000644000076500000240000000102112546321746021123 0ustar amolstaff00000000000000[toscawidgets] # Use 'widgets' to point to the module where widgets should be imported # from to register in the widget browser widgets = sprox.widgets # Use 'samples' to point to the module where widget examples # should be imported from to register in the widget browser # samples = tw.samples # Use 'resources' to point to the module where resources # should be imported from to register in the widget browser #resources = sprox.widgets.resources sprox-0.9.6/sprox.egg-info/not-zip-safe0000644000076500000240000000000112334112717020050 0ustar amolstaff00000000000000 sprox-0.9.6/sprox.egg-info/pbr.json0000644000076500000240000000005712546303441017303 0ustar amolstaff00000000000000{"is_release": false, "git_version": "7846ee9"}sprox-0.9.6/sprox.egg-info/PKG-INFO0000644000076500000240000000125312546321746016731 0ustar amolstaff00000000000000Metadata-Version: 1.1 Name: sprox Version: 0.9.6 Summary: A package for creation of web widgets directly from database schema. Home-page: http://www.sprox.org Author: Christopher Perkins 2007-2009 major contributions by Michael Brickenstein Author-email: chris@percious.com License: MIT Description: UNKNOWN Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python Classifier: Topic :: Internet :: WWW/HTTP Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content Classifier: Topic :: Software Development :: Libraries :: Python Modules sprox-0.9.6/sprox.egg-info/requires.txt0000644000076500000240000000021712546321746020233 0ustar amolstaff00000000000000formencode>=1.3.0a1 markupsafe [testing_mongodb] sqlalchemy sieve tw2.forms genshi mako ming [testing] sqlalchemy sieve tw2.forms genshi makosprox-0.9.6/sprox.egg-info/SOURCES.txt0000644000076500000240000000576112546321746017530 0ustar amolstaff00000000000000MANIFEST.in README.rst setup.cfg setup.py sprox/__init__.py sprox/_compat.py sprox/_validatorselector.py sprox/_widgetselector.py sprox/configbase.py sprox/dummyentity.py sprox/entitiesbase.py sprox/fillerbase.py sprox/formbase.py sprox/iprovider.py sprox/metadata.py sprox/providerselector.py sprox/recordviewbase.py sprox/release.py sprox/saormprovider.py sprox/sprockets.py sprox/tablebase.py sprox/util.py sprox/validators.py sprox/validatorselector.py sprox/viewbase.py sprox/widgetselector.py sprox.egg-info/PKG-INFO sprox.egg-info/SOURCES.txt sprox.egg-info/dependency_links.txt sprox.egg-info/entry_points.txt sprox.egg-info/not-zip-safe sprox.egg-info/pbr.json sprox.egg-info/requires.txt sprox.egg-info/top_level.txt sprox/dojo/__init__.py sprox/dojo/fillerbase.py sprox/dojo/formbase.py sprox/dojo/sprockets.py sprox/dojo/tablebase.py sprox/mg/__init__.py sprox/mg/provider.py sprox/mg/validatorselector.py sprox/mg/widgetselector.py sprox/mk/__init__.py sprox/mk/provider.py sprox/mk/validatorselector.py sprox/mk/widgetselector.py sprox/mootools/__init__.py sprox/mootools/formbase.py sprox/sa/__init__.py sprox/sa/provider.py sprox/sa/support.py sprox/sa/validatorselector.py sprox/sa/widgetselector.py sprox/widgets/__init__.py sprox/widgets/tw1widgets/__init__.py sprox/widgets/tw1widgets/dojo.py sprox/widgets/tw1widgets/widgets.py sprox/widgets/tw1widgets/static/dojo_grid.js sprox/widgets/tw1widgets/templates/__init__.py sprox/widgets/tw1widgets/templates/checkbox.html sprox/widgets/tw1widgets/templates/checkbox.mak sprox/widgets/tw1widgets/templates/container.html sprox/widgets/tw1widgets/templates/datagrid.html sprox/widgets/tw1widgets/templates/datagrid.mak sprox/widgets/tw1widgets/templates/dojogrid.html sprox/widgets/tw1widgets/templates/dojogrid.mak sprox/widgets/tw1widgets/templates/entityDef.html sprox/widgets/tw1widgets/templates/entityLabel.html sprox/widgets/tw1widgets/templates/hidden_put.html sprox/widgets/tw1widgets/templates/hidden_put.mak sprox/widgets/tw1widgets/templates/modelLabel.html sprox/widgets/tw1widgets/templates/recordField.html sprox/widgets/tw1widgets/templates/recordViewTable.html sprox/widgets/tw1widgets/templates/table.html sprox/widgets/tw1widgets/templates/tableDef.html sprox/widgets/tw1widgets/templates/tableForm.html sprox/widgets/tw1widgets/templates/tableLabel.html sprox/widgets/tw1widgets/test/__init__.py sprox/widgets/tw2widgets/__init__.py sprox/widgets/tw2widgets/widgets.py sprox/widgets/tw2widgets/templates/__init__.py sprox/widgets/tw2widgets/templates/container.html sprox/widgets/tw2widgets/templates/datagrid.genshi sprox/widgets/tw2widgets/templates/datagrid.mak sprox/widgets/tw2widgets/templates/entityDef.html sprox/widgets/tw2widgets/templates/entityLabel.html sprox/widgets/tw2widgets/templates/modelLabel.html sprox/widgets/tw2widgets/templates/recordField.html sprox/widgets/tw2widgets/templates/recordViewTable.html sprox/widgets/tw2widgets/templates/table.html sprox/widgets/tw2widgets/templates/tableDef.html sprox/widgets/tw2widgets/templates/tableLabel.htmlsprox-0.9.6/sprox.egg-info/top_level.txt0000644000076500000240000000001412546321746020360 0ustar amolstaff00000000000000sprox tests