[TurboGears] Re: Forms declarative style

2005-11-17 Thread Kevin Dangoor

On 11/16/05, Ian Bicking [EMAIL PROTECTED] wrote:
 Basically this:

class MyForm(TableForm):
foo1 = TextField()
foo2 = TextField()

 Is exactly equivalent to:

MyForm = type(TableForm)('MyForm', (TableForm,), {'foo1':
 TextField(), 'foo2': TextField})

this is probably a little too wacky, it turns out. Consider this case:

class TableForm(Subclassable):
def important_behavior(self):
print foo

TableForm = TableForm()

class MyForm(TableForm):
def important_behavior(self):
print bar

type(MyForm) - TableForm
MyForm.important_behavior() - TypeError (takes 1 argument, 0 given)

Not being able to override behavior would be an evil side effect of it
looking like a class but not actually being a class. There's probably
a way to bind the function to the instance, is there not?

Kevin


[TurboGears] Re: Forms declarative style

2005-11-17 Thread Kevin Dangoor

Yeah, I've seen those. The order is only a problem because Python
gives us the dict... Using the somewhat hacky counter technique plus
an ordered dict may do the trick.

Kevin

On 11/17/05, Sean Cazzell [EMAIL PROTECTED] wrote:

 Kevin,

 The Python Cookbook has a couple of ordered dict implementations.
 Here's one:

 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/438823


 Sean Cazzell

 On Thu, 2005-11-17 at 11:06 -0500, Kevin Dangoor wrote:
  On 11/16/05, [EMAIL PROTECTED] [EMAIL PROTECTED] wrote:
   So for my CRUD requirement, I just use py:for in Kid and still control
   the order of how those fields appears. And if I later decide to
   customize the layout in Kid, the same dict can still be used for direct
   name access.
 
  Being able to access in order or as a dictionary is a nice thing. I'll
  have to keep that in mind.
 
  Kevin
 
  --
  Kevin Dangoor
  Author of the Zesty News RSS newsreader
 
  email: [EMAIL PROTECTED]
  company: http://www.BlazingThings.com
  blog: http://www.BlueSkyOnMars.com




--
Kevin Dangoor
Author of the Zesty News RSS newsreader

email: [EMAIL PROTECTED]
company: http://www.BlazingThings.com
blog: http://www.BlueSkyOnMars.com


[TurboGears] Re: Forms declarative style

2005-11-17 Thread David Bernard

In my TG CRUD work, I generate edit form, view list and view screen
from SQLObject. I use the similar approach of Kevin : using *arg or a
list in the contrustor of a CompositeWidget. I also add an append()
method. Advantages of this solution :
* easy to create and extends a form automaticaly
...
editWidgetMap = {
'container' : widget4edit.FormWidgetsList,
'default' : widget4edit.TextLineWidget,
'SOStringCol': widget4edit.TextLineWidget,
'SOStringCol+long': widget4edit.TextWidget,
'SOUnicodeCol': widget4edit.TextLineWidget,
'SOUnicodeCol+long': widget4edit.TextWidget,
'SOBoolCol': widget4edit.CheckBoxWidget,
'SOForeignKey' : widget4edit.VocabularyWidget,
'SOEnumCol' : widget4edit.VocabularyWidget,
#'SOIntCol':IntWidget,
#'SODateTimeCol':DateTimeWidget
}


def buildWidgetsList(self, sqlobj, widgetmap):

@param sqlobj the type (like app.model.Page) for wich create a
WidgetContainer
@param widgetmap the family of widgets to use for each
SQLObject field type

back = []
columns = sqlobj.sqlmeta.columns
for col in sqlobj.sqlmeta.columnList:
name = col.origName
clazz = col.__class__.__name__
if (clazz == 'SOStringCol' or clazz == 'SOUnicodeCol') and
not(col.length):
clazz += '+long'
widget = widgetmap.get(clazz,
widgetmap['default'])(key=name)
if hasattr(widget, 'vocabulary') and (widget.vocabulary is
None):
if clazz == 'SOForeignKey':
referencedsql = findClass(col.foreignKey)
widget.vocabulary = SQLVocabulary(referencedsql)
elif clazz == 'SOEnumCol':
widget.vocabulary =
widgetsupport.Vocabulary(col.enumValues)
if hasattr(widget, 'defaultValue') and
(widget.defaultValue is None):
widget.defaultValue = col.enumValues[0]
if hasattr(widget, 'required') and (widget.required is
None):
widget.required = col.notNone
if hasattr(widget, 'validator') and (widget.validator is
None):
widget.validator = col.validator
back.append(widget)
return widgetmap['container'](*back) #IGNORE:W0142
...

* the WidgetContainer instance could be attach to a SQLObject type. In
my case after building a WidgetContainer I do :
if not(hasattr(sqlobj, 'editWidget')):
#autogeneration of the editwidget
sqlobj.editWidget = self.buildWidgetsList(sqlobj,
self.editWidgetMap)
sqlobj.editWidget.append(widget4edit.HiddenWidget('isNew',
validators.Bool(), True))
sqlobj.editWidget.append(widget4edit.HiddenWidget('id',
validators.Int(), -1))

* you could create 2 instances of the same WidgetContainer, an each one
could have it's own internal state without interference, like 2
instances of TextField... (may be my java background influence me too
much, but class state/field are share by all instance, and there is
only one class definition available in the system)

my 2 cents



[TurboGears] Re: Forms declarative style

2005-11-17 Thread Ian Bicking


Kevin Dangoor wrote:

On 11/16/05, Ian Bicking [EMAIL PROTECTED] wrote:


Basically this:

  class MyForm(TableForm):
  foo1 = TextField()
  foo2 = TextField()

Is exactly equivalent to:

  MyForm = type(TableForm)('MyForm', (TableForm,), {'foo1':
TextField(), 'foo2': TextField})



this is probably a little too wacky, it turns out. Consider this case:

class TableForm(Subclassable):
def important_behavior(self):
print foo

TableForm = TableForm()

class MyForm(TableForm):
def important_behavior(self):
print bar

type(MyForm) - TableForm
MyForm.important_behavior() - TypeError (takes 1 argument, 0 given)

Not being able to override behavior would be an evil side effect of it
looking like a class but not actually being a class. There's probably
a way to bind the function to the instance, is there not?


import new, types
for attr, value in new_attrs.values():
if isinstance(value, types.FunctionType):
setattr(self, attr, new.instancemethod(value, self, self.__class__)

These are things that I think are worthy of exploration, but you have to 
be ready to back them out if they don't pan out.


--
Ian Bicking  /  [EMAIL PROTECTED]  /  http://blog.ianbicking.org


[TurboGears] Re: Forms declarative style

2005-11-17 Thread Ronald Jaramillo


Love to se something like that =)
Cheers
Ronald

On Nov 18, 2005, at 6:55 AM, Michael Schneider wrote:



Can take a STAN-like approach for building DOM fragments that we could
pass to kid??

I will try to work up an example.

Here is a nice over link of stan

http://www.kieranholland.com/prose/meet-stan/

Thanks
Mike

PS.  Divmod uses formless to render forms, I have not used formless
yet, so I have not input on that system.




Ronald Jaramillo
mail: ronald AT checkandshare DOT com
blog: http://www.checkandshare.com/blog





[TurboGears] Re: Forms declarative style

2005-11-16 Thread Kevin Dangoor

On 11/16/05, Ronald Jaramillo [EMAIL PROTECTED] wrote:

 Hi,
 The discussion yesterday about Form styles got me thinking.
 Personally I don't like the proposed declarative style.
 I like the idea that this style has the same feel as SQLObject (+1),
 though I don't buy the point about subclassing.
 As it is now, you can already subclass a form.

Correct, you could subclass Form if you want customized behavior.

 But my main objection has something to do with consistency.
 If a form is a widget (and a widget container as well), why should
 they differ in style to other widget elements.
 Say we have a CheckboxGroup widget. Should it be used like this?

 niceDogs(CheckboxGroupBase):
 chiguagua = widgets.CheckBox()
  rodesian = widgets.CheckBox()
  pitbull = widgets.CheckBox(checked=true)

 I will rather see widgets as elements that can embed and be embeded
 as well.

I think people were viewing forms as being different from individual
widgets. Implementation-wise, right now, Forms are widgets and it
functionally makes sense to have them that way.

I was just thinking about the actual implementation of making forms
support the declarative style and have two issues with the mechanics
of it:

1) maintaining the order of the widgets
2) mechanics of actually using a Form

As for #1, how does it work?

widgetcounter = 0

class Widget(object):
def __init__(...stuff...):
global widgetcounter
# acquire a lock
   self.widgetnum = widgetcounter
   widgetcounter += 1
# release lock

class MetaForm(MetaWidget):
def __init__(cls, name, bases, dct):
super(MetaForm, cls).__init__(name, bases, dct)
widgetlist =
# get all of the widgets from dct.values()
# sort them by widgetnum

I believe that will work. But, yuck.

As for the mechanics of using the form, what do people have in mind.
As normal Widget instances, you use a form by doing

form.insert(...)

Would you still do MyForm.insert(...)? (So insert on a Form would have
to be a classmethod, rather than an instance method?)

So, it's like Ronald said: do you want Forms to be consistent with
Widgets (and they *are* Widgets), or should they be consistent with
SQLObject? The devil, as they say, is in the details...

Kevin


[TurboGears] Re: Forms declarative style

2005-11-16 Thread Jeff Grimmett
On 11/16/05, Kevin Dangoor [EMAIL PROTECTED] wrote:
So, it's like Ronald said: do you want Forms to be consistent withWidgets (and they *are* Widgets), or should they be consistent withSQLObject? The devil, as they say, is in the details...
Personally, I favor a widget library that models known GUI idioms - that is, after all, what forms are - a GUI. The layout and handling of a GUI should be totally *indifferent* to what is handling the data. Maybe I'm reading too much into that last paragraph, but the implication is something unexpected.
*sigh* I appologize if I'm speaking out of turn here, and plead ignorance. I haven't had time to look at the widget stuff, and have just barely touched forms at all. But I have looked through the source a little and it *appears* to be a nice way of programatically generating forms and retrieving data from them, which to me sounds like a web-baed GUI library, and that suggests to me that it would be a good idea to follow standard GUI idioms here and be as flexible as possible. That means, to me, that the library gives the programmer the means to lay things out, respond to events, and retrieve data as needed, but nothing beyond that (
i.e. the programmer should be the one stuffing it into a database, not the widget itself).And again, I appologize for making any statements out of ignorance on this subject. I'm REALLY behind the curve here. Hope this is helpful in some way.
-- Things fall apart. The Center cannot hold.- Life as a QA geek, in a nutshell.Best,Jeff 


[TurboGears] Re: Forms declarative style

2005-11-16 Thread Kevin Dangoor

On 11/16/05, Jeff Grimmett [EMAIL PROTECTED] wrote:
 On 11/16/05, Kevin Dangoor [EMAIL PROTECTED] wrote:

  So, it's like Ronald said: do you want Forms to be consistent with
  Widgets (and they *are* Widgets), or should they be consistent with
  SQLObject? The devil, as they say, is in the details...
 

  Personally, I favor a widget library that models known GUI idioms - that
 is, after all, what forms are - a GUI. The layout and handling of a GUI
 should be totally *indifferent* to what is handling the data.

 Maybe I'm reading too much into that last paragraph, but the implication is
 something unexpected.

Yep, you're reading too much into that last paragraph. What I meant was...

forms are currently declared like this:

myform = TableForm([TextField(foo1), TextField(foo2)])

and SQLObjects are declared like this:

class MyTable(SQLObject):
foo1 = StringCol()
foo2 = StringCol()

Some folks have expressed that they'd like forms to be like this:

class MyForm(TableForm):
foo1 = TextField()
foo2 = TextField()

which is consistent with the SQLObject style, but is not consistent
with how other widgets (TextField, for example) work.

 But I have looked through the source a little and it *appears* to be a nice
 way of programatically generating forms and retrieving data from them, which
 to me sounds like a web-baed GUI library, and that suggests to me that it
 would be a good idea to follow standard GUI idioms here and be as flexible
 as possible. That means, to me, that the library gives the programmer the
 means to lay things out, respond to events, and retrieve data as needed, but
 nothing beyond that ( i.e. the programmer should be the one stuffing it into
 a database, not the widget itself).

Yep. While some day someone may write a data-aware widget, the core,
basic widgets know nothing and care nothing about what happens to the
information once it gets into your controller method.

Kevin


[TurboGears] Re: Forms declarative style

2005-11-16 Thread Don Hopkins

Some folks have expressed that they'd like forms to be like this:

class MyForm(TableForm):
foo1 = TextField()
foo2 = TextField()

which is consistent with the SQLObject style, but is not consistent
with how other widgets (TextField, for example) work.

The problem with the class based approach is that there's no way to
reconstruct the order of the fields in the class, which is required for
generating forms (of more than one field ;-). Since the fields are
defined in the class's dictionary, which is unordered, there's no way to
determine the order they appear in the source code, so you have to use
an array of fields instead. 

Maybe you could hack around it by using a @decorator that recorded the
order it was applied to methods in another class variable. Oh, but those
are fields not methods. You can't apply decorators to fields, but you
could still call a function for every field that remembered its order.
Eww, that's gross, never mind...

-Don
 



[TurboGears] Re: Forms declarative style

2005-11-16 Thread Ian Bicking


Don Hopkins wrote:

Some folks have expressed that they'd like forms to be like this:



class MyForm(TableForm):
foo1 = TextField()
foo2 = TextField()



which is consistent with the SQLObject style, but is not consistent
with how other widgets (TextField, for example) work.



The problem with the class based approach is that there's no way to
reconstruct the order of the fields in the class, which is required for
generating forms (of more than one field ;-). Since the fields are
defined in the class's dictionary, which is unordered, there's no way to
determine the order they appear in the source code, so you have to use
an array of fields instead. 


If you control the source of TextField(), you can make it increment a 
counter everytime it is instantiated.  Then you sort according to this 
counter, essentially sorting them by their creation time.


This is how SQLObject started (if only recently) to keep track of the 
order of its columns.


--
Ian Bicking  /  [EMAIL PROTECTED]  /  http://blog.ianbicking.org


[TurboGears] Re: Forms declarative style

2005-11-16 Thread Ian Bicking


Kevin Dangoor wrote:

myform = TableForm([TextField(foo1), TextField(foo2)])

and SQLObjects are declared like this:

class MyTable(SQLObject):
foo1 = StringCol()
foo2 = StringCol()

Some folks have expressed that they'd like forms to be like this:

class MyForm(TableForm):
foo1 = TextField()
foo2 = TextField()


I'd played around unsuccessfully with weird dual object/class objects, 
but I never quite figured it out.  But I must know more now, because it 
wasn't too hard.  Here's an example with a very brief test:


  http://svn.colorstudy.com/home/ianb/subclass_instance/

Basically this:

  class MyForm(TableForm):
  foo1 = TextField()
  foo2 = TextField()

Is exactly equivalent to:

  MyForm = type(TableForm)('MyForm', (TableForm,), {'foo1': 
TextField(), 'foo2': TextField})


So if TableForm is an instance, then type(TableForm) is the class, and 
the class is called with those arguments (i.e., instantiating).


It's all a little wacky, so I don't know that I'd recommend the trick. 
But it does make large keyword-based instanciation easier on the eye.



--
Ian Bicking  /  [EMAIL PROTECTED]  /  http://blog.ianbicking.org


[TurboGears] Re: Forms declarative style

2005-11-16 Thread Don Hopkins

If you control the source of TextField(), you can make it increment a 
counter everytime it is instantiated.  Then you sort according to this 
counter, essentially sorting them by their creation time.

This is how SQLObject started (if only recently) to keep track of the 
order of its columns.

Great point, bravo! I had wished there was a way to get the order of
SQLObject fields, but I didn't realize you've already figured out a way
to do it! 

There is nothing wrong with your television set. Do not attempt to
adjust the picture. We are controlling the transmission. If we wish to
make it louder, we will bring up the volume. If we wish to make it
softer, we will tune it to a whisper. We will control the horizontal. We
will control the vertical. We can roll the image; make it flutter. We
can change the focus to a soft blur or sharpen it to crystal clarity.
For the next hour, sit quietly and we will control all that you see and
hear. We repeat: there is nothing wrong with your television set. You
are about to participate in a great adventure. You are about to
experience the awe and mystery which reaches from the inner mind to the
Outer SQLObject.

-Don




[TurboGears] Re: Forms declarative style

2005-11-16 Thread [EMAIL PROTECTED]


Don Hopkins wrote:
 The problem with the class based approach is that there's no way to
 reconstruct the order of the fields in the class, which is required for
 generating forms (of more than one field ;-). Since the fields are
 defined in the class's dictionary, which is unordered, there's no way to
 determine the order they appear in the source code, so you have to use
 an array of fields instead.

 Maybe you could hack around it by using a @decorator that recorded the
 order it was applied to methods in another class variable. Oh, but those
 are fields not methods. You can't apply decorators to fields, but you
 could still call a function for every field that remembered its order.
 Eww, that's gross, never mind...


To me, the order in the class doesn't matter. What usually matter is
when it is passed to the view in MVC which in TurboGear's case is a
dict for Kid to consume. I just created a preferred ordered dict
which has an optional field sequence list member.

So for my CRUD requirement, I just use py:for in Kid and still control
the order of how those fields appears. And if I later decide to
customize the layout in Kid, the same dict can still be used for direct
name access.



[TurboGears] Re: Forms declarative style

2005-11-16 Thread Jeff Grimmett
On 11/16/05, Kevin Dangoor [EMAIL PROTECTED] wrote:
Yep, you're reading too much into that last paragraph. What I meant was...forms are currently declared like this:myform = TableForm([TextField(foo1), TextField(foo2)])and SQLObjects are declared like this:
class MyTable(SQLObject):foo1 = StringCol()foo2 = StringCol()Some folks have expressed that they'd like forms to be like this:class MyForm(TableForm):foo1 = TextField()foo2 = TextField()
which is consistent with the SQLObject style, but is not consistentwith how other widgets (TextField, for example) work.Well, I can see the point of some folks in this case since it certainly jibes with typical GUI idioms I've used, at their simplest.
Yep. While some day someone may write a data-aware widget, the core, basic widgets know nothing and care nothing about what happens to the information once it gets into your controller method.
To me, that just seems like the right way to do it, but I'm fairly naive with regards to web apps.-- Things fall apart. The Center cannot hold.- Life as a QA geek, in a nutshell.
Best,Jeff 


[TurboGears] Re: Forms declarative style

2005-11-16 Thread Jeff Grimmett
On 11/16/05, Don Hopkins [EMAIL PROTECTED] wrote:
The problem with the class based approach is that there's no way toreconstruct the order of the fields in the class, which is required forgenerating forms (of more than one field ;-). Since the fields are
Beware of stupid question.Here it is.Why is it important to reconstruct the order of the fields?-- Things fall apart. The Center cannot hold.- Life as a QA geek, in a nutshell.
Best,Jeff 


[TurboGears] Re: Forms declarative style

2005-11-16 Thread [EMAIL PROTECTED]


Jeff Grimmett wrote:
 On 11/16/05, Don Hopkins [EMAIL PROTECTED] wrote:

 The problem with the class based approach is that there's no way to
  reconstruct the order of the fields in the class, which is required for
  generating forms (of more than one field ;-). Since the fields are


 Beware of stupid question.

 Here it is.

 Why is it important to reconstruct the order of the fields?

presentation. But I don't think class level definition order is the
solution(see my other post about this).

Take the current catwalk module.

It allows you to drag/drop columns for presentation purpose. However, a
refresh would wipe it. It would be nice these things can be changed
easily and stored.



[TurboGears] Re: Forms declarative style

2005-11-16 Thread Don Hopkins








Good question actually. 

Its user friendly to group related
elements together in the form (like x and y coordinates), and put important
ones near the top (like title and description), so you need some way to control
the order of dynamically generated form elements (and also a way to further
customize each element). 



Now that Ians invented a way to
order the fields of an SQLObject, its possible to automatically generate
forms to edit their fields in the same order they were specified by the
database designer (or declared in the python class). 



I want to be able to declare not only the
order, but also other metadata about each field. 



I made a database browser for OpenLaszlo
based on SQLObject, but I resorted to awkward kludgery to order the fields with
sequence numbers. 

http://www.donhopkins.com/drupal/node/44



Using an older version of SQLObject, I subclassed
the various field and join classes so the constructors took an extra user
defined data parameter that I could retrieve later. 

So I could hang a dictionary off of each
field, to give it a sequence number to sort by, and store other presentation
related information. 

I also had to subclass the various join
fields so they had data parameters too. 



The goal was to declare extra information
about each field and join, like its sequence number, the name of a custom
editor, user friendly label, help text, and other presentation parameters, so
the server can automatically generate XML to drive a Laszlo user interface for
browsing and editing the database, with custom widgets like checkboxes, image
views, date pickers, map widgets, etc. 

(BTW: I cant wait till Google Base
drops the other shoe and publishes a web API!)



The new version of SQLObject now has a
similar but undocumented feature that I dont quite understand, with the _extra_vars
Field instance variable, so I may be able to clean up my code and use that,
instead of wrapping everything with my own subclasses. 



Ian, how did you intend _extra_vars to be
used: is it meant to hang user data off of fields, or am I subverting its true goal
in life (remaining secret and behind the scenes in an undisclosed location)? 

The Join classes would also need to
support _extra_vars as well. 

It would be great for dynamic user
interface generation, if SQLObject supported an easy, documented way to attach metadata
to fields and joins, and officially exposed the field order too, please! 



 -Don





-Original Message-
From: turbogears@googlegroups.com
[mailto:[EMAIL PROTECTED] On
Behalf Of Jeff Grimmett
Sent: Wednesday,
 November 16, 2005 8:40 PM
To: turbogears@googlegroups.com
Subject: [TurboGears] Re: Forms
declarative style



On 11/16/05, Don Hopkins [EMAIL PROTECTED] wrote:





The problem with the class based approach is that
there's no way to
reconstruct the order of the fields in the class, which is required for
generating forms (of more than one field ;-). Since the fields are






Beware of stupid question.

Here it is.

Why is it important to reconstruct the order of the fields?





-- 
Things fall apart. The Center cannot hold.
-
Life as a QA geek, in a nutshell. 

Best,

Jeff








[TurboGears] Re: Forms declarative style

2005-11-16 Thread Ian Bicking

Don Hopkins wrote:
 The new version of SQLObject now has a similar but undocumented feature
 that I don’t quite understand, with the _extra_vars Field instance
 variable, so I may be able to clean up my code and use that, instead of
 wrapping everything with my own subclasses.
 
  
 
 Ian, how did you intend _extra_vars to be used: is it meant to hang user
 data off of fields, or am I subverting its true goal in life (remaining
 secret and behind the scenes in an undisclosed location)?
 
 The Join classes would also need to support _extra_vars as well.

It is meant to hang data user off of it; I could add it to the other
objects as well, and probably a __getattr__ as well.  The reason they
are specially collected is so that the values can also be transfered to
the SO* version of the classes.



-- 
Ian Bicking  |  [EMAIL PROTECTED]  |  http://blog.ianbicking.org