[TurboGears] Re: With whom do you guys host with?
Has there been any progress on an offical deployment scenario? I'd like to throw up some turbogears apps on my site, which doesn't allow fastcgi, and I'm wondering what my options would be. Also, I just found Turbo Gears last night, stayed up for 3 hours longer than I should have just looking and finding my way around. Well done indeed! Scott
[TurboGears] Re: With whom do you guys host with?
Whoops.. just after I posted that I found this: http://www.turbogears.org/docs/deployment.html heh.. Thanks, Scott
[TurboGears] How to install TG on a webhost without root access?
What's the preferred method of installing TurboGears on a webhost where I don't have root access? Scott
[TurboGears] Re: How to install TG on a webhost without root access?
Hi Scott, This is something on my todo list to experiment with and write up. In the meantime, you should take a look at Phillip Eby's instructions for non-root installations using setuptools: http://peak.telecommunity.com/DevCenter/EasyInstall#non-root-installation Kevin On 10/8/05, Scott Benjamin [EMAIL PROTECTED] wrote: What's the preferred method of installing TurboGears on a webhost where I don't have root access? Scott -- Kevin Dangoor Author of the Zesty News RSS newsreader email: [EMAIL PROTECTED] company: http://www.BlazingThings.com blog: http://www.BlueSkyOnMars.com
[TurboGears] Re: With whom do you guys host with?
Yeah, that document is woefully inadequate, but will get you somewhere. The non-root installation instructions I just sent, plus using mod_proxy (ProxyPass/ProxyPassReverse) or mod_rewrite should get you a chunk of the way there. Kevin On 10/8/05, Scott Benjamin [EMAIL PROTECTED] wrote: Whoops.. just after I posted that I found this: http://www.turbogears.org/docs/deployment.html heh.. Thanks, Scott -- Kevin Dangoor Author of the Zesty News RSS newsreader email: [EMAIL PROTECTED] company: http://www.BlazingThings.com blog: http://www.BlueSkyOnMars.com
[TurboGears] Re: 0.8a1 incompatible with formencode 0.23dev ?
This one exists in 0.5 as well, I was going to mention it. You need to have a def validation _error method as the TG code works for that case but the if the method does not exist, the default raise a traceback code is missing arguments. I never bothered to figure out the fix, though. I just created a validation_error method on my controller. I am trying to say with virgin stable releases as much as possible for my project. Hope this helps. Krys [EMAIL PROTECTED] wrote: == 2005/10/07 16:44:22 INFO Traceback (most recent call last): File /home/gary/lib/python2.4/site-packages/CherryPy-2.1.0_rc1-py2.4.egg/cherrypy/_cphttptools.py, line 272, in run main() File /home/gary/lib/python2.4/site-packages/CherryPy-2.1.0_rc1-py2.4.egg/cherrypy/_cphttptools.py, line 498, in main body = page_handler(*args, **cherrypy.request.paramMap) File /home/gary/lib/python2.4/site-packages/TurboGears-0.8a1dev-py2.4.egg/turbogears/controllers.py, line 119, in newfunc raise turbogearsvalid.Invalid(str(errors)) TypeError: __init__() takes at least 4 arguments (2 given) = turbogearsvalid is simply validators from formencode, the Invalid class is like the following : class Invalid(Exception): This is raised in response to invalid input. It has several public attributes: msg: The message, *without* values substituted. For instance, if you want HTML quoting of values, you can apply that. substituteArgs: The arguments (a dictionary) to go with `msg`. str(self): The message describing the error, with values substituted. value: The offending (invalid) value. state: The state that went with this validator. This is an application-specific object. error_list: If this was a compound validator that takes a repeating value, and sub-validator(s) had errors, then this is a list of those exceptions. The list will be the same length as the number of values -- valid values will have None instead of an exception. error_dict: Like `error_list`, but for dictionary compound validators. def __init__(self, msg, value, state, error_list=None, error_dict=None): Exception.__init__(self, msg) self.msg = msg self.value = value self.state = state self.error_list = error_list self.error_dict = error_dict
[TurboGears] Re: How does the current validator mechanism works ?
I agree completely. In my project my validation_error method has to do just that: recall the original method with all arguments + and errors argument. This seems the best approach and the code is fairly boiler plate. It would be nice to see this as the default behaviour in TG. Krys [EMAIL PROTECTED] wrote: I begin to start using the validator and got confused of what is the design philosophy behind it. 1. There is an instance method validator_error that would be called if exist otherwise it would raise another exception. I believe this has to be mentioned in the documentation as otherwise, this exception would not be caught by anyone and it would be the ugly server get in trouble message, which is very scary but not the case. Just some data content error. If validator_error is defined, if will be called with the first parameter being the original function(the one that turbogears.expose supposed to be decorating). While the documentation said I can do whatever I want, I think it would be more natural to let the original function deal with it as this validator_error is a centralized function(sort of catch all) that is impossible to make meaningful error message/response. Would it be better to just have a convention that any exposed function that has validator enabled should expect one more argument error=None to indicate such condition and let it do its job there ?
[TurboGears] Re: How does the current validator mechanism works ?
What about a nested validation_error function. For example: @turbogears.expose( validators= mySchema() ) def index( self, arg1, arg2 ) def validation_failed( errors ): # do something clever here and ultimately # either retry index or bail pass # real code for index pass Is it legal to have a self parameter for the nested function? If so, I guess we'll have to pass it along explicitly when calling the nested validation_failed function. Of course, if no validation_failed function is defined, the class- based one should be tried next. -- Jeff Watkins http://metrocat.org/ Advertising directed at children is inherently deceptive and exploits children under eight years of age. -- American Academy of Pediatrics
[TurboGears] Re: Auth spec
I like this. I think groups are useful for organizational purposes on larger scale apps, but roles is a better conceptual idea for permission assignment and requirement. I actually like Zope's User, Group and Role 3-way system, complicated though it is. it's great for large scale systems like Zope is intended to be. I think for TG, thought groups can come later, if the is a need. KISS right? :-) Krys Lethalman wrote: I've seen how does multiauth work. I suggest this auth model for turbogears: MODEL class AuthRole: name = StringCol(alternateID=True) inherit = RelatedJoin(AuthRole) # Is it possible? users = RelatedJoin(AuthUser) class AuthUser: username = StringCol(alternateID=True) password = StringCol() roles = RelatedJoin(AuthRole) # Functions to get/save encrypted passwords CONTROLLER class Root: admin = Admin(['admin']) @turbogears.expose() def index(self) @turbogears.expose(secure=['user.vote_polls']) def vote(self) class Admin: @turbogears.expose() def index(self) @turbogears.expose(secure=['admin.view_polls']) def view_polls(self) @turbogears.secure(secure=['admin.edit_polls']) @turbogears.expose() def edit_polls(self) @turbogears.secure(secure=['admin.del_polls']) @turbogears.expose() def del_polls(self) Ok we have the following roles (- means inherit): user user.vote_polls - user user.all - user, user.vote_polls admin - user.all admin.view_polls - admin admin.edit_polls - admin.view_polls admin.del_polls - admin.view_polls admin.super - admin, admin.view_polls, admin.del_polls And we have these users with relative roles: A - user B - user.all C - admin D - admin, admin.del_polls E - admin.super Ok, roles are recursively inherited and fetched in a single list even if there're duplicates. These are the access for each user: A - Root.index B - All Root C - Admin.index D - Admin.index, Admin.view_polls, Admin.del_polls E - All Admin What about? I think (opposite to my former mail) groups are unuseful. -- www.italianpug.org - Italian Python User Group Founder
[TurboGears] Re: Building from subversion
It might be worth noting that easy_install.py -f . (note the period, i.e. current directory) works. -f can use local paths as well as urls. At work we have MS Proxy (NTLM auth) and McAfee WebShield, so downloading anything is a royal pain. I really like setuptools, but having a download and local install capability is critical in my work environment. That said, I had to write a script to get setuptools installed from a local egg. I will be working on using this knowledge with Inno Setup to make a nice and friendly stand-alone windows installer for my app. It could be used for TG too. Ian, if you are reading this, I'd really love to hear your thoughts on the use of setuptools (and getting setuptools initially installed) without needing a network connection. (Admittedly I am not well versed in eggs as TG is my first real exposure to them. :-) Hope this helps, Krys David Stanek wrote: That is probably better than what I had done. I just grabbed the eggs from the TurboGears download page and since I am on Linux I built a cElementTree egg. Then I wrote a little shell script to set my PATH and PYTHONPATH. David On 10/7/05, [EMAIL PROTECTED] [EMAIL PROTECTED] wrote: YES. I have gone through all these before. setuptools sounds great except that the infrastructure is not there yet. -- David Stanek www.roninds.net http://www.roninds.net
[TurboGears] Re: How does the current validator mechanism works ?
Ian Bicking wrote: [EMAIL PROTECTED] wrote: [snip] If validator_error is defined, if will be called with the first parameter being the original function(the one that turbogears.expose supposed to be decorating). While the documentation said I can do whatever I want, I think it would be more natural to let the original function deal with it as this validator_error is a centralized function(sort of catch all) that is impossible to make meaningful error message/response. It seems to me that another function should be called, but one that is a sister function, not a single validation_error function. A particularly common one would be the function that originally generated the form, so it could regenerate the form with the errors in it. So it might be: @expose(validators=..., on_error='register'): def do_registration(self, ...): # actually perform action @expose(html='form.html'): def register(self): # creates form with action=do_registration # maybe expose pipes the output through htmlfill if this # is in response to an error, or... something This works much better than a generic validation_error method, IMHO. Whether the same method is used to display the form and process the form data or not should be up to the programmer, but coding is much simpler if I can just say ok, were there any errors, rather than from which method did I get these errors and how to I tell it that there were errors. Krys
[TurboGears] Re: turbogears-admin shell initial data file
This works for me. :-) As for you point 1), if there is no tg_init_database, then the behaviour is exactly as before and SQLObject users will not be confused. That is to say, I have to do an explicit act to get the new behaviour and so I will know what will happen. As for point 2), I am thinking that a counterpart method like tg_clear_database or something would be nice so that old data can be torn down. And alternative would be to make your tg_init_database, check for the existence of any data you are trying to insert. Further a reset or rebuild method is a simple as tg_clear_database(); tg_init_database(). If that is useful. And then there is the blue-sky-on-mars wink thinking that this could be the base for model versioning with upgrade functions in each model to that can migrate old data structures to new ones. I think this is a bit far off, though. (Can you tell I have been played with Zope and Twisted?) :-) Krys Fabian Neumann wrote: Krys Wilken wrote: I think both ideas are of value. An exec command for running scripts, and a special module-level function in model.py that is run automatically by sql create. I might like it, too. What do you think of this: Index: turbogears/quickstart/projectname/model.py.source === --- turbogears/quickstart/projectname/model.py.source (Revision 43) +++ turbogears/quickstart/projectname/model.py.source (Arbeitskopie) @@ -6,3 +6,6 @@ # class YourDataClass(SQLObject): # pass + +# def tg_init_database(): +# pass Index: turbogears/command/__init__.py === --- turbogears/command/__init__.py (Revision 43) +++ turbogears/command/__init__.py (Arbeitskopie) @@ -104,6 +104,12 @@ from sqlobject.manager import command command.the_runner.run(sys.argv) +if sqlobjcommand == create: +mod = self.get_model() +if hasattr(mod, 'tg_init_database'): +print 'Filling database' +mod.tg_init_database() + def fix_egginfo(self, eggname): print Two issues with that: 1. This behaviour may be unexpected by people who are familiar with sqlobject-admin create. 2. If you run sql create twice or more, those init values are doubled. An alternative to a single module-level function would be a special method on each model that is responsible for populating itself, perhaps post_create(self) or something. Sql create could just call that method of each model after all the tables have been created. I don't think this granularity is useful, as you can only create all models at once (I think). Fabian
[TurboGears] Re: How does the current validator mechanism works ?
Exactly. Validation errors are not usually programming errors. They are usually user input errors. Telling the user that they have inputted invalid data should be simple and intuitive. A separate method for error handling is not intuitive to me. :-) Krys [EMAIL PROTECTED] wrote: To me it seems like it should be an error if there's no validation_error method and any validators are given. This way the error is caught early during development. Yes, but there are sometimes(many times I would say) soft-errors that don't need this kind of handling. A typical case would be the fields may come in as nothing(None) which can be a don't care and proceed. defining validation_error would grab the control of it without giving it a chance to go on. And I re-read the code, what validation_error received is not the original function, but the name of the function, making calling it back a bit difficult.
[TurboGears] 'quickstart' error handling
The quickstart project template has the interesting feature, inherited, I guess, from CherryPy... If you access 'http://localhost:8080/?var=5' you get the ugly display: Traceback (most recent call last): File /usr/local/lib/python2.4/site-packages/CherryPy-2.1.0_betadev-py2.4.egg/cherrypy/_cphttptools.py, line 276, in run main() File /usr/local/lib/python2.4/site-packages/CherryPy-2.1.0_betadev-py2.4.egg/cherrypy/_cphttptools.py, line 498, in main body = page_handler(*args, **cherrypy.request.paramMap) File /usr/local/lib/python2.4/site-packages/TurboGears-0.5.1-py2.4.egg/turbogears/controllers.py, line 93, in newfunc output = func(self, *args, **kw) TypeError: index() got an unexpected keyword argument 'var' Would it make sense to either have the root object take a dictionary arg, or explaing how to have the system catch errors such as these so they don't go to the screen?
[TurboGears] MochiKit 0.90 released
MochiKit 0.90 http://mochikit.com/download.html has been released! This release includes a new feature, some bug fixes. The new feature in 0.90 is JSON serialization and evaluation support via serializeJSON, evalJSON and registerJSON. 2005-10-08 v0.90 - Fixed ISO compliance with toISODate - Added missing operator.sub - Placated Mozilla's strict warnings a bit - Added JSON serialization and unserialization support to MochiKit.Base: serializeJSON, evalJSON, registerJSON. This is very similar to the repr API. - Fixed a bug in the script loader that failed in some scenarios when a script tag did not have a src attribute (thanks Ian!) - Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA, P, FORM - Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode and parseQueryString, when available.
[TurboGears] Re: turbogears.flash() only displays every other call
I ran into this too. I don't know if the behaviour is a bug, or just if we are misinterpreting the intended purpose of flash. How flash works is to set a cookie which is sent to the browser. The message only gets displayed when the cookie comes back from the browser. The cookie is then deleted once it has been read back by the server. That's why it only shows up every other time. It has to get to the browser and come back to be displayed. And once it is aback is it removed. If a new one is set at that time, then it has to do the full trip again to be displayed. I ended up just passing in my own message variable to the template and having the template show the message if it exists. (Basically duplicating the flash functionality but without using cookies.) If this is not a bug, then I'd love to see documentation explaining the purpose and semantics of using flash, particularly in conjunction with HTTPRedirect and InternalRedirect. Hope this helps, Krys Tim Lesher wrote: [Env: Turbogears 0.5, running on Windows XP] I have a template containing a form, which posts back to the same URL. My controller looks like this: @turbogears.expose(html=yadda) def showStuff(self, **kwargs): if 'submit' in kwargs: # [ Update the db ] turbogears.flash('DB Updated') return dict(...yadda...) This works fine--the db gets updated every time, but the flash message is only displayed on every _other_ try. In other words, if I just bounce on the Submit button, I see the flash message on one view, then nothing the next view, then I see the flash message on the third view, etc. Am I misusing flash here? If not, I'll cobble up a minimal example to show the problem. Thanks! -- Tim Lesher [EMAIL PROTECTED]
[TurboGears] Re: How does the current validator mechanism works ?
Interesting idea. :-) I am unsure what benefit it provides over just say just having an extra errors=None argument on the original method. I'd love to hear your thoughts on it though. :-) It seems to me that that there are two simple ways of handling validation errors: 1) Adding an errors=None argument to the method and letting it handle things (so the validators would just populate the errors dict and pass them on to the method), or 2) Ian's idea of an on_error='method_name' added to expose. Actually, now that I am thinking of it, I'd say combine the two ideas. If no on_error is provided assume the on_error method is the method being decorated, otherwise call the specified method. Whatever method is called would have and errors keyword argument which is a dictionary in the form of: {'form_field_name': [list of Invalid objects],...} That way you can have, as Ian believes, separate methods for presentation of a form and processing of it, or you can have one method responsible for both, as others prefer. In either case, the method that knows best about it's subject matter is responsible for handling the errors, instead of some generic validation_error method that knows nothing of the specifics of the original method that was called. Anyway, just my $.02. Shoot me down if out in left field. :-) Krys Jeff Watkins wrote: What about a nested validation_error function. For example: @turbogears.expose( validators= mySchema() ) def index( self, arg1, arg2 ) def validation_failed( errors ): # do something clever here and ultimately # either retry index or bail pass # real code for index pass Is it legal to have a self parameter for the nested function? If so, I guess we'll have to pass it along explicitly when calling the nested validation_failed function. Of course, if no validation_failed function is defined, the class- based one should be tried next. -- Jeff Watkins http://metrocat.org/ Advertising directed at children is inherently deceptive and exploits children under eight years of age. -- American Academy of Pediatrics
[TurboGears] Re: 'quickstart' error handling
What I like to do is add *args and **kwargs to controller methods, precisely for that reason. e.g. def index(self, expected_var, ..., *args, **kwargs): That way I catch any extra argument passed in and I can either ignore them or present the error in a friendlier way. Not sure if there are better ways to do it though. Hope this helps. Krys Mike Harding wrote: The quickstart project template has the interesting feature, inherited, I guess, from CherryPy... If you access 'http://localhost:8080/?var=5' you get the ugly display: Traceback (most recent call last): File */usr/local/lib/python2.4/site-packages/CherryPy- 2.1.0_betadev-py2.4.egg/cherrypy/*_cphttptools.py, line 276, in run main() File */usr/local/lib/python2.4/site-packages/CherryPy- 2.1.0_betadev-py2.4.egg/cherrypy/*_cphttptools.py, line 498, in main body = page_handler(*args, **cherrypy.request.paramMap) File /usr/local/lib/python2.4/site-packages/TurboGears-0.5.1-py2.4.egg/turbogears/controllers.py, line 93, in newfunc output = func(self, *args, **kw) TypeError: index() got an unexpected keyword argument 'var' Would it make sense to either have the root object take a dictionary arg, or explaing how to have the system catch errors such as these so they don't go to the screen?
[TurboGears] Re: How does the current validator mechanism works ?
Agree. In its(TurboGears) current form, I have changed all my functions to this form(thus ignore the validator feature) : func(self,**kwargs): Then I can define a formencode schema to validate against kwargs which is a dict. Basically achieve what you mentioned. The only issue is, a few line of code is needed to grab the keywords that is needed for processing, back from kwargs, rather than func(self, something=None,someother=None). But kwargs is needed anyway(as the kitchen sink) or any strange hidden fields in a form would bomb. Krys Wilken wrote: Interesting idea. :-) I am unsure what benefit it provides over just say just having an extra errors=None argument on the original method. I'd love to hear your thoughts on it though. :-) It seems to me that that there are two simple ways of handling validation errors: 1) Adding an errors=None argument to the method and letting it handle things (so the validators would just populate the errors dict and pass them on to the method), or 2) Ian's idea of an on_error='method_name' added to expose. Actually, now that I am thinking of it, I'd say combine the two ideas. If no on_error is provided assume the on_error method is the method being decorated, otherwise call the specified method. Whatever method is called would have and errors keyword argument which is a dictionary in the form of: {'form_field_name': [list of Invalid objects],...} That way you can have, as Ian believes, separate methods for presentation of a form and processing of it, or you can have one method responsible for both, as others prefer. In either case, the method that knows best about it's subject matter is responsible for handling the errors, instead of some generic validation_error method that knows nothing of the specifics of the original method that was called. Anyway, just my $.02. Shoot me down if out in left field. :-) Krys Jeff Watkins wrote: What about a nested validation_error function. For example: @turbogears.expose( validators= mySchema() ) def index( self, arg1, arg2 ) def validation_failed( errors ): # do something clever here and ultimately # either retry index or bail pass # real code for index pass Is it legal to have a self parameter for the nested function? If so, I guess we'll have to pass it along explicitly when calling the nested validation_failed function. Of course, if no validation_failed function is defined, the class- based one should be tried next. -- Jeff Watkins http://metrocat.org/ Advertising directed at children is inherently deceptive and exploits children under eight years of age. -- American Academy of Pediatrics
[TurboGears] Re: turbogears.flash() only displays every other call
On 10/8/05, Krys Wilken [EMAIL PROTECTED] wrote: I ran into this too. I don't know if the behaviour is a bug, or just if we are misinterpreting the intended purpose of flash. How flash works is to set a cookie which is sent to the browser. Aha. That's the problem. That means I was misusing flash--it's used when you want to display a message after a redirect. I ended up just passing in my own message variable to the template and having the template show the message if it exists. (Basically duplicating the flash functionality but without using cookies.) That was my solution, too. -- Tim Lesher [EMAIL PROTECTED]
[TurboGears] Re: Validator and None ?
[EMAIL PROTECTED] wrote: Is there a way to specify that None(empty, not present) is valid ? Something equivalent to : if my_string is None or my_string==: v = None else: v = validator.to_python(my_string) v = validator(if_empty=None).to_python(my_string) Note that you can clone any validator with modified arguments, by calling it with those arguments. I.e., these are the same: v = validators.Int(max=10)(if_empty=0) v = validators.Int(max=10, if_empty=0)