Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book
[19:10] Remi: Anyway, let's get started :-)
[19:10] Remi: First item on the agenda: what should be included in CP, what should not
[19:11] Remi: My plan is to give people a way to write high-level "modules", like a weblog or a web forum
[19:11] *** carribeiro has joined #cherrypy.
[19:11] Remi: And to do that, we have to povide a somewhat standard way of doing form handling, database operations and a few other things
[19:12] Remi: Oh, and templating as well
[19:12] gwork: remi, do you mean Carlos's previously mentioned 'products'?
[19:12] Remi: gwork: yes
[19:12] Remi: so, who things that CP should provide a standard way of doing form handling, database operations and templating ?
[19:12] Remi: s/things/thinks
[19:12] carribeiro: Remi, I saw the email you posted today, and even if I mispart of the discusison, I think I get it...
[19:13] gwork: remi, i don't think we should. 
[19:13] carribeiro: At this point, I don't believe that this is something that should be done by CP.
[19:13] carribeiro: It's the ZOpe route, and it points to a monolithic approach.
[19:13] gwork: many have written they like CP2 because it doesn't get in their way. . so i think we should provide functionality, but not make any of it standard. . 
[19:14] carribeiro: But - I believe that in the spirit of CherryTempalte, some additional packages could be built on to of CP,
[19:14] carribeiro: and also, benefit of strong integration.
[19:14] carribeiro: So that's two votes against ;)
[19:14] carribeiro: Remi, what's your take?
[19:15] carribeiro: Is there a reasoning, or better - an specific reason, to raise this issue?
[19:15] Remi: the things is, if we don't do that, there isn't much more we can add to CP ... Everything I want to add requires forms and persistend storage
[19:15] carribeiro: ok.
[19:15] carribeiro: But... can't it be a CherryApp, or CherryForms, extension?
[19:16] chappie: What about spending time beefing up the server of CP?  Am I the only one here interested in this? :)
[19:16] gwork: remi, i agree. but let's not make things a 'standard'
[19:16] carribeiro: beefing up -> optimizing?
[19:16] Remi: Carlos: Sure. I had written something called "CherryObjects"
[19:16] chappie: No. Making it do HTTP 1.1/HTTPS reliably.
[19:16] Remi: chappie: we'll talk about this next ...
[19:16] carribeiro: That's a great point.
[19:16] chappie: ok.
[19:16] carribeiro: Also, I believe that some effort on optimization and also on measurements...
[19:17] carribeiro: Many people ask what's the real load capacity of CP2. We should measure it.
[19:17] Remi: let's talk about HTTP/performance next
[19:17] carribeiro: Sorry for jumping the topic, Remi.
[19:17] gwork: i think it would be wiser for us to create some api for these 'applications'.. how users could simply connect different products, independant from what the product would do.. LIke karrigell's components
[19:17] Remi: I want to finish the previous topic :-)
[19:17] gwork: me 2
[19:18] Remi: So u agree that we need such functionalities, but u think they should be kept outside of the core, right ?
[19:18] gwork: outside the core, but some might come along as modules or filters etc. 
[19:18] Remi: right
[19:18] carribeiro: I see CP2 now as a pretty much "transparent" server. It imposes so little on the application as to make any such addition to the core to appear as not necessary...
[19:18] gwork: just think of all functionality that can be done in different ways, the same as filters
[19:19] Remi: I understand this point of view, but at the same time, people like Rails because it comes with everything they need ...
[19:19] chappie: ... not part of the core.  For instance, if I don't like CherryTemplate, I should have to use it and it shouldn't get in the way.
[19:19] gwork: we can include a directory for this functionality, and give standard implementations, but do not assume anywhere the users will use it. 
[19:20] carribeiro: Remi: i see your point. But we already started doing it... it's just a matter of doing alittle bit more.
[19:20] carribeiro: Let's me give an example
[19:20] carribeiro: I have included a utility class wrapper on the utils module, ExposeItems. 
[19:20] carribeiro: Ont the basis of ExposeItems, I thought about a few more classes. ExposeImage & ExposeDicts.
[19:21] carribeiro: Sorry, ExposeDir (not dicts)
[19:21] carribeiro: ExposeImage allows one to expose an image at some point in the tree...
[19:21] carribeiro: And ExposeDir allows one to expose an entire dir.
[19:22] carribeiro: It's something like the static dir list, but in code (not in the config file).
[19:22] carribeiro: My guess is: 
[19:22] carribeiro: By adding such utility functions, as need appear, we will buil;d a strong library. Is that the stuff that attracts developers.
[19:22] carribeiro: ?
[19:23] gwork: carlos, i think i agree :)
[19:23] Remi: That's my point ... I see it like the python standard library ...
[19:23] carribeiro: Yeh.
[19:23] gwork: but also for complete forums and wiki's and all. . 
[19:23] gwork: remi: yeah!
[19:23] Remi: Part of why we all like python is because it comes with so many modules
[19:23] carribeiro: By adding stuff - the simple stuff, the boring work is removed... that';s the point.
[19:23] chappie: yep, but we're not forced to use any of htem.
[19:23] gwork: i can use pickle or cPickle, but noone should give a damn about what exactly i'm using. . Some goes for databases and all
[19:23] chappie: s/htem/them
[19:24] Remi: gwork: well, we would use SQLObject ...
[19:24] carribeiro: The same with the library. We already have one simple class in there. Let's add more, one at a time.
[19:24] gwork: remi: thank you, no please :) 
[19:25] carribeiro: I keep pointing people to SQLObject. For XML, given my recent exposition to it, I would recommend the effbot lib whose name escapes me now.
[19:25] gwork: carlos, where is it?
[19:25] Remi: gwork: what do you prefer ?
[19:25] carribeiro: import cherrypy.lib.cptools
[19:25] gwork: remi, for storage?
[19:25] Remi: yep
[19:25] carribeiro: I have working versions of ExposeImage and ExposeDict. But that's something that requires a patch on the URL code also... so that's better discussed later.
[19:26] carribeiro: Remi: I prefer SQLObject.
[19:26] chappie: Requiring patches would be a no-no in a very modular environment?
[19:26] gwork: i prefer a different storage method for every different sollution. Sometimes a stored pickle is enough, sometimes  i simply use shelve, other times i'm bound to odbc with mssql. . 
[19:26] chappie: I'd not tie things to sqlobject.
[19:26] carribeiro: chappie: why patches? there's no need to IMHO...
[19:27] gwork: chappie, i agree. . why not make a directory for things in cptools?
[19:27] gwork: can't we make a util directory in the lib?
[19:27] chappie: carribeiro: "But that's something that requires a patch on the URL code"
[19:27] carribeiro: SQLObject is interesting, because it exposes the relation data as objects, using the standard getitem interface.
[19:27] Remi: gwork: well, we have to choose something ... SQLObject is just an abstraction layer. It can store data in a variety of backends ...
[19:27] gwork: remi, why do we have to choose?
[19:27] chappie: I'd make a backend storage that allows you to plug in database of choice; use DBAPI.
[19:28] carribeiro: So - in a broad sense - it's possible to write code that works with SQLObject or normal classes, using getattr & setattr, without the need to import SQLObject directly.
[19:28] gwork: i don't see it. . why can't you use sqlobject, and i use some custom made storage?
[19:28] Remi: chappie: but then u'd end up re-inventing SQLObject ...
[19:28] carribeiro: Of course you do lose some of the more advanced features.
[19:28] Remi: gwork: have u used an ORM before ?
[19:28] gwork: yeah. .
[19:29] Remi: didn't u think it saved u some work ?
[19:29] gwork: but maybe we're talking about different things here.. first of all, what's the goal of the _usage_ of sql object?
[19:29] *** devil has joined #cherrypy.
[19:29] devil: hi all
[19:29] carribeiro: gwork: I think that the point is that Remi wants to provide a higher-level API for persistency, and make it available for forms, validation, etc.
[19:29] Remi: ok, here is the idea behind it ...
[19:29] gwork: if we're busy here trying to cook some prefab data storage, i'm fine with it. As long as CP2 doesn't force me to use it
[19:29] Remi: If someone wants to write a web forum for CP, right
[19:29] gwork: yeah
[19:30] *** vi has signed off IRC (Remote host closed the connection).
[19:30] carribeiro: chappie: now I get what did you mean by patch, sorry, you were quoting me :-P I'll explain it later.
[19:30] Remi: if we let them choose the tools that they want, they might pick MySql and CherryTemplate for instance
[19:30] gwork: true
[19:31] Remi: And they'll have to write their own DB->object code and form rendering and validation code, etc ...
[19:31] Remi: Then someone else wants to use that web forum in their site
[19:31] Remi: If they don't have MySql or want to use Cheetah, they're screwed !
[19:32] gwork: remi, u just made my point clear :)
[19:32] chappie: So for the sake of making really modular pieces you're saying some "standard" has to be adopted.
[19:32] carribeiro: Remi: part of the problem is that the abstraction provided by CherryTemplate isn't "high level" enough. So a CherryForms module makes sense. I have some code that I can contribute, declarative style, if you want to play with it...
[19:32] Remi: whereas if we have some kind of "standard", components will be reusable by other people
[19:32] gwork: true
[19:33] Remi: If everybody uses SQLObject/Cheetah, then you can just import their module and "mount" it anywhere in your site
[19:33] gwork: remi, i agree with you so far. . but it's good design for us all, to let the developer choose different backends. . this would be like the anydb. . 
[19:33] Remi: Just change the templates to match your site design ...
[19:33] chappie: Then I'd suggest sqlobject and Cheetah as part of the "standard". I can plug a lot of different databases behind sqlobject, right?
[19:33] Remi: But SQLObject can run on top of many databases ...
[19:33] carribeiro: Remi: the problem is that you're probably talking about the two more disperse parts of the extensive Python library. The DBAPI is a mess, everyone knows it. And there many templating libraries around, who know how much...
[19:34] martin: yes...and wrting the code for a new db fro sqlobject should be fairly easy
[19:34] carribeiro: I _could_ second SQLObject, because it's pythonic, and imposes very little on the application...
[19:34] carribeiro: But I'm not that sure about Cheetah. It's fast, a lot of people love it...
[19:34] Remi: Well, choosing SQLObject is a no brainer I think
[19:34] carribeiro: But cheetah is not as Pythonic and inobstrusive as either CP or SQLObject.
[19:35] chappie: I'm thinking of Cheetah because it gives me a migration path to Apache that's pretty straightforward.
[19:35] Remi: what do u vote for the templating language ?
[19:35] carribeiro: I'm using HTMLTemplate, a light module. It's similar in concept top nevow, in some places... But much simpler.
[19:35] devil: custom built i don't like any of the ones that are around
[19:35] gwork: if our builtin applications would require SQLObject, but can be made into using some other storage, i'm fine with it. . for example, if sqlobject maps to mysql, or sqlite it's nice (sqlite is python only, so that's nice)
[19:35] devil: but yeah HTMLTemplate looks nice
[19:36] chappie: sqlite is not python only.
[19:36] carribeiro: I tried to write my own. But I could not get it the way I liked. I've kept only the form library, that's what I do use.
[19:36] gwork: xyaptu 
[19:36] gwork: full python
[19:36] martin: i am really not qualified to have an oppinion re the templating..just meddled a little with cheetha and CT...CT is by far the easiest for a newbie but I guess Cheetah is more powerful ?
[19:36] devil: well if i have to choose one over all i guess PyMeld anyway
[19:36] chappie: gwork: I see.  Yup.
[19:36] gwork: seperation of logic and view
[19:36] Remi: CT = CherryTemplate ?
[19:36] martin: yes
[19:36] chappie: Cheetah is more powerful and pythonic.
[19:37] gwork: Cheetah required compiled libraries : ( 
[19:37] carribeiro: Remi: sincerely. Chosing a standard template tool is not something that I'm looking forward to.
[19:37] chappie: So does sqlite:)
[19:37] chappie: (require compiled libraries).
[19:37] carribeiro: sqlite is better packaged than Cheetah, it fells better integrated out of the box. 
[19:37] Remi: carlos: but if you want to use a web forum module written by someone else, you'll have to customize the templates so they match your site's design ...
[19:37] carribeiro: I see you point, Remi.
[19:38] chappie: I think choosing a standard templating toolkit is needed unless the modular approach is made _very_ high level.
[19:38] *** Dan_ has joined #cherrypy.
[19:38] carribeiro: But it's also a big problem... because it may turn people out of CP< if they don't like the tool we shose.
[19:38] Remi: Anyway, if the module is well written, the logic in the template should be minimal...
[19:38] gwork: chappie, unfortunatly you're right : (
[19:38] carribeiro: And NO templating too - I repeat, NO tool - comes closer to CP in terms of being pythonic, simple and powerful.
[19:39] Remi: Guys, the core CherryPy is not going to change !!!
[19:39] Remi: You'll still be able to use it the way you do now !
[19:39] Remi: *BUT* ...
[19:39] carribeiro: (Ouch. shose? Where did I get that? -> choose!)
[19:39] chappie: carribeiro, no tool is more pythonic than Cheetah?
[19:39] Remi: If you want a web forum on your site, you'll just have to import the module and configure the templates !!
[19:39] carribeiro: Well. I can live with Cheetah. BUT! I would prefer to see more investment on CherryTemplate, and perhaps, xyaptu...
[19:40] Dan_: Can someone paste the chat log to (Link: http://rafb.net/paste)http://rafb.net/paste so I can catch up?
[19:40] carribeiro: chappie: did I say that? I meant, no tool is as pythonic as CP - CherryPy!
[19:40] chappie: carribeiro, I was trying to get clarification.
[19:40] Dan_: (and hello everyone)
[19:40] gwork: remi, that's true, but you'll also have to have a cheetah running. If i want to run it on a handheld.. please....
[19:40] chappie: I'll paste.
[19:40] carribeiro: chappie: sorry!
[19:41] Remi: Yes, you'll have to install SQLObject and Cheetah
[19:41] gwork: And maybe compile Cheetah for a zaurus handheld. please, no , let's not do that.. 
[19:41] carribeiro: Well. For advanced "products" like wikis & blogs, that unavoidable.
[19:41] Remi: But at least, once you have these 2, you can run all the modules u like
[19:41] gwork: keep thngs really pythonic is my opinion
[19:42] gwork: but then any module can have it's own dependencies!
[19:42] carribeiro: gwork: do you intend to run the *server* in a Zaurus? For this kind of product that we are talking about?
[19:42] gwork: (that's fair though)
[19:42] gwork: carlos,  i might need to in about 6 months
[19:42] Remi: Anyway, I have a bit of time on my hands so I'll write the CP/SQLObject/Cheetah boilerplate code and I'll write a small web forum on top of that.
[19:42] gwork: but that's OT
[19:42] carribeiro: The server? Well, you can run plain CP then... 
[19:42] Remi: Then you can see what I meant and we can start from there.
[19:43] chappie: sorry. I can't paste it.  history is not that big.
[19:43] gwork: remi, what is the main goal here.. let's get back to the main discussion
[19:43] Remi: Again, it will be an *addition* to CP that noone has to use if they don't want to
[19:43] carribeiro: Remi: at least the topic was introduced, and everyone will have some time to digest it.
[19:43] gwork: and where will it be stored?
[19:43] Remi: gwork: you can use any DB that SQLObject supports (Mysql, Postgres, SQLite, ...)
[19:43] gwork: i would favour something like cherrypy.products.<productname>
[19:44] gwork: shelve? 
[19:44] gwork: ;)
[19:44] gwork: berkley? 
[19:44] Remi: look it up on sqlobject.org
[19:44] gwork: anyway. .i don't think sqlobject is a problem, but that's not the main issue here
[19:44] chappie: If anything is done that actually creates HTML, I'd propose that it be XHTML/CSS/ECMAScript standards compilant.
[19:44] gwork: we're talking about products, and were talking about product dependancies..
[19:45] Dan_: hey guys, I have been developing a reasonably complex site using SQLObject and Cherrytemplates...
[19:45] gwork: i strongly feel any product, and it's dependancies should be python only. . and all products should be store in the /cherrypy/products/... directory
[19:45] *** deelan has joined #cherrypy.
[19:45] Dan_: and I have to say SQLObjects gets a strong thumbs up
[19:45] Dan_: and cherrytemplates a thumbs dowsn
[19:45] Dan_: debugging with Cheetah is *much* better
[19:45] deelan: hi all
[19:45] Remi: Anyway, let's move on ...
[19:45] Remi: Hi deelan
[19:46] Dan_: so I second Remi's SQLObject and Cheetah selection
[19:46] gwork: remi, please continue on the big picture just a few min more
[19:46] * deelan is playing around with sqlobject :)
[19:46] gwork: hi dan
[19:46] gwork: what about inter product dependancies?
[19:46] Remi: gwork: the goal is just to add high-level "modules" to CP (like web-forum, blog, ...)
[19:47] Remi: And to achieve that we need what I talked about ...
[19:47] carribeiro: In my mind, there should not be dependencies between these products. At least on principle.
[19:47] gwork: i thought you wanted a high level products like blogs/wikis/forums/galeries and lowlevel products like object persistance/databases/session handling/user management etc
[19:47] carribeiro: But! tehre's something that CP can learn from Zope, that is to provide a better acces control model.
[19:47] gwork: a blog and a wiki could both use the same lower products
[19:47] Dan_: gwork:  if one of the sales point of CP2 is that it is pythonic, then it needs to be able to use 3rd party python modules!  So no need to be self contained...
[19:48] chappie: self contained would mean using Gadfly for the database, right?
[19:48] Remi: guys ... we're not making progress ...
[19:48] gwork: remi, do you agree on the lower products?
[19:48] Remi: Just wait for me to write some code and let's talk about this again in one week, OK ?
[19:49] gwork: ok
[19:49] carribeiro: gwork: there's little in common between the wiki and the blog that could be a part of a "product" their internal dependencies will probably be against CP library (cherrypy.lib.cptools) or stndard python modules.
[19:49] Remi: Alright, let's move on to the 2nd topic: the HTTP server and the performance of CP
[19:49] carribeiro: Remi: what about a stnadard access control layer for CP?
[19:49] chappie: remi, are you thinking sqlobject and cheetah, then?
[19:49] Remi: chappie: yes
[19:50] Remi: carlos: yes, that's something I'll have in mind ...
[19:50] gwork: do you have any stats for us to discuss?
[19:50] carribeiro: Remi: can we add this topic for the end of the chat?
[19:50] Dan_: Moving on:  Yes,  Remi about the performance...
[19:50] Remi: carlos: let's discuss it now
[19:51] chappie: I've said before, I'd love to see CP2 doing HTTP 1.1 and HTTPS reliably.
[19:51] Remi: I think a lot of people misunderstand the bottlenecks of web apps ...
[19:51] carribeiro: Remi: what's the topic? it got confusing. Let's talk about performance now, we can talk about the security later...
[19:51] Dan_: yes lets
[19:52] Remi: yeah, I'm talking about performance !
[19:52] chappie: that's where he's going.  Be listening....
[19:52] carribeiro: Sorry. I got it wrong. 
[19:52] chappie: go on about peoples misunderstandings.
[19:52] carribeiro: My take on performance. Measure first.
[19:52] carribeiro: Later, we discuss what to do.
[19:52] Remi: My point is that, in most real-life cases,  the raw performance of the web framework is not as important as you think ! In other words, CherryPy is fast enough !
[19:53] carribeiro: I agree with you. But the lack of a measurement makes people wonder.
[19:53] Dan_: Remi - well, for everything except static pages, you are right...
[19:53] carribeiro: As it is now... it's too easy for both sides to think they are right. 
[19:53] Remi: I gave some measurment before ... For a simple "Hello world" page, I got 500 req/sec
[19:53] Dan_: there should be some way to cache things like images in the static directory...
[19:53] chappie: Remi, what you say may be true but leaving off HTTP1.1, I think HTTPS is a core functionality that needs to be running right in today's Internet environment.
[19:53] carribeiro: We need solid figures for the comparison to be done.
[19:54] chappie: Rather than beefing up CP too much, it may be better to consider what the migration path to Apache looks like in the event that CP can't handle the load.
[19:55] chappie: ... and making this easier so that developers are not deterred from CP initially due to no migration path.
[19:55] gwork: i must agree with chappie. . . 
[19:55] Dan_: hold on guys, back to Remi's speed point, it's true that DB backed pages are pigs because of db and disk access, but some sort of smart way of caching results (internal to CP2 or perhaps via Apache) is needed...
[19:55] gwork: it's a pure 'what if' situation
[19:56] carribeiro: Folks... the reason why I asked for an official measurement is to stop discussion about it.
[19:56] Remi: my point is, in 99% of the real-life cases, the bottleneck will be your actual web app code rather than CherryPy itself
[19:56] Dan_: so the question is "do we just say" if you want to cache, use apache (and CP2 will supply some hooks)?
[19:56] chappie: I think a line needs to be drawn here.  Make CP functional but low traffic (by this I mean make it support HTTPS in addition to what it supports now). Then make it easy for people to migrate to Apache if needed.
[19:56] gwork: What if we would provide better HTTP INFO requests? given the correct data and all for static files?? would this be enough? and let the caching be done on the client side?
[19:57] carribeiro: Remi gave an figure. But I think that this figure need to be backed by more data, like: the server where it was tested, and - is it valid for the current code?
[19:57] *** vi has joined #cherrypy.
[19:57] Dan_: Remi - you are right, but the solution isn't to make the web code faster the solution is to cache, and here CP2 might have something to offer as a frameowkr...
[19:57] Remi: dan: true, but right now we're talking about the HTTP server itself
[19:57] chappie: discussion of pages per second is rather irrelevant at this point.  We don't know what the specifics will be in any given deployment.  This is actually about comfort building in CP at all knowing I have a migration path forward.
[19:57] carribeiro: *IF* people need better performance, by guess is that they should hide CP behind either Apache, or squid. Squid is even simpler IMHO.
[19:58] Dan_: well - if we do caching inside CP2 then it's part of the discussion...
[19:58] Remi: The point I'm trying to make is that improving the HTTP server is not high priority ...
[19:58] gwork: remi, i agree
[19:58] Dan_: I agree.
[19:58] chappie: I think improving it's core functionality, not speed should be a priority.
[19:58] carribeiro: Remi: Agreed. I asked for the measurements to have data to back it.
[19:58] Dan_: Remi - but we need to say something about caching....
[19:59] gwork: chappie, you've got a point there .. 
[19:59] gwork: if i may ... 
[19:59] Remi: chappie: Zope's HTTP server has more features than CherryPy's one... And yet I read that most people run it behind Apache anyway !
[19:59] carribeiro: I've done some work on the cache.
[19:59] carribeiro: There are now docs on the Wiki about the cache filter.
[19:59] carribeiro: It was one of the reasons behind the InternalRedirect request, btw.
[20:00] Remi: No matter how much work we put into it, CherryPy's HTTP server will never be as good as Apache, right ?
[20:00] chappie: Remi: I wouldn't compare to Zope.  I, as a developer, want to stay in Python as much as possible. Apache should not be needed for core functionality.
[20:00] Dan_: Remi - anybody in production will probably want to front with Apache...
[20:00] Dan_: it has nice logs for all the log analysers...
[20:00] carribeiro: Even knowin how much people do love Apache, I prefer Squid to to this web acceleration stuff!
[20:00] *** oool has joined #cherrypy.
[20:01] chappie: Look from the point of view of the developer who wants to make a web site and he doesn't have a good migration path to Apache.  He will not use CP at all in this case!
[20:01] carribeiro: May I try to sum up what I think is a consensus to this point, so we can move on?
[20:01] Dan_: I vote we keep the http server simple where apache can provide functionality..
[20:01] Remi: For any "serious" production website, you'll probably want to run Apache anyway ... And so will your customer ...
[20:02] chappie: I don't agree with you Remi.
[20:02] carribeiro: 1) Speed is not a concern (now, at least)
[20:02] Remi: Ok carlos, go ahead :-)
[20:02] chappie: I think a light weight site with a migration path to Apache would be VERY nice.
[20:02] Dan_: and to work on things where needed (like threading performance - which apache can't help with)
[20:02] gwork: we chose for CP2 for the type of development. . we have a high development speed, and enough freedom to do what we want. If it comes to speed (if it ever comes) it should be a problem pushing as much of the tasks to apache as possible, or some other high speed server.. or use multiple servers.. whatever... If it comes to functionality, we have to look at https and http1.1 . . that's what CP should
[20:02] gwork:  care about, functinality, and have a path so developers can get their site fast enough if it gets loads of traffic.. That's where chappie's heading. . how do i migrate to get the load of my cp2 and let some other applicatino handle it. If we can't some people might not take a look at cp2. 
[20:02] carribeiro: 2) It should be possible to run CP behind Apache. What's missing are better docs on how to do it.
[20:03] carribeiro: I'l resubmit my points, it got lost in the sudden traffic:
[20:03] carribeiro: 1) Speed is not a concern (now, at least)
[20:03] carribeiro: 2) It IS possible to run CP behind Apache. What's missing are better docs on how to do it.
[20:03] chappie: Not just better docs.  The only thing running behind apache gains now is HTTP 1.1 and HTTPS. No real load handling advantage on the backend.
[20:03] carribeiro: Remi: ok?
[20:03] Remi: carlos: ok
[20:03] carribeiro: chappie: can you ellaborate?
[20:03] Dan_: chappie:  load balancing really isn't a cp problem...
[20:04] chappie: If I may....
[20:04] Remi: go ahead, chappie ...
[20:04] chappie: I'm not talking about load balancing.
[20:04] chappie: I'm talking about dynamic page serving.
[20:05] carribeiro: What can Apache do to help CP, and what can be done to improve the integration?
[20:05] chappie: Apache with modPython gives you more than HTTP 1.1 and HTTPS. It give you an embedded python environment.  I need a clear way to migrate from CP to Apache/ModPython so I can get more use of my hardware than a simply Apache Proxy.
[20:05] chappie: s/simply/simple.
[20:05] carribeiro: chappie: are you talking about a mod_cp?
[20:06] chappie: that is an option.
[20:06] Remi: chappie: I suggest u try the following test:
[20:06] Remi: write a simple "Hello world" in CP and benchmark it with Apache's ab
[20:06] chappie: It's not the simple hello world's that are in view here. 
[20:06] Remi: Then what is it ?
[20:06] chappie: Remi, back to what you've been saying.  The backend processing is the bottleneck.
[20:07] carribeiro: chappie: the main benefit of mod_python is that it does have a long running Python process. CP already is such a process... so it already gets part of the benefit.
[20:07] chappie: Migrating to a apache proxy does very little for the back end processing, right?
[20:07] Remi: anyway, let me just finish describing the test ...
[20:07] carribeiro: chappie: in other words: CP is already in the same league of mod_python.
[20:07] Dan_: chappie: dynamic pages take databases etc.  they are the rate limiting case in mod_python or cp2...
[20:07] Remi: Then write the same "Hello world" in mod_python/Apache and benchmark it again. I bet you won't see a big difference ...
[20:07] chappie: go on remi.  I'll reply to dan and carlos in a moment then.
[20:08] carribeiro: I think I can see the point of having a specially customized mod_python version... to run CP.
[20:08] carribeiro: But its something that I can't even begin to figure out how to do :-(
[20:08] Dan_: carrib: I don't see the point...
[20:08] carribeiro: mod_cherrypy, anyonw?
[20:08] Dan_: carrib: why bother?
[20:08] Remi: guys ... I honestly don't understand your concerns about speed ... I suggest this:
[20:09] Dan_: carriib:  you fork the project and gain nothing - do the Remi test...
[20:09] Remi: I'll seriously benchmark CherryPy and mod_python and will publish the results
[20:09] carribeiro: Remi: that's my point, all the time. We don't have enough hard data to justify either our confidence or our fear that CP will not scale.
[20:09] Remi: And then we can discuss ...
[20:09] chappie: I'm talking about something that is not just speed concerns.  Lemme take another go at it.
[20:09] carribeiro: If i had the resources to run such a test, I would do it. But I dont have a good server, and I cant generated the load.
[20:10] Remi: carlos: just use "ab" for the load
[20:10] chappie: I'm talking about migrating my code from CP to Mod Python.  Right now there's only one way to do that.  It's through an apache proxy.
[20:10] chappie: If that proves insufficient, then what do I do.
[20:10] chappie: ?
[20:10] carribeiro: Remi: thanks for the tip. I'll check it.
[20:10] Dan_: Regarding Remi's test:  for really simple pages you might see a difference but add a db query and you will be within 1%...
[20:11] Remi: chappie: If that proves insufficiant, then using mod_python would be insufficient too !!!
[20:11] carribeiro: chappie. If it proves not enough... then probably, you would have to write in C anyway. Seriously.
[20:11] carribeiro: Or distribute the load.
[20:11] carribeiro: I mean, we are talking about serious load here.
[20:11] Remi: carlos: exactly !
[20:11] gwork: ./ ;)
[20:11] carribeiro: For for you to have an idea: A google farm takes *less* than 500 hits per second, that's the performnace quoted by Remi.
[20:11] gwork: woopz. /.
[20:12] Dan_: we are talking trash here, because as we already went over, the delay on dynamic pages is from the *Backend*....
[20:12] chappie: maybe you're right.
[20:12] Remi: Here is what I'll do: I'll write a page explaining how to handle certain loads with CherryPy ... For the first range, you'll have to use CP on its own, then CP behind Apache, then load-balancing ...
[20:12] Remi: dan: thanks !
[20:12] Dan_: (hence  500 hits per second per  google farm...)
[20:12] Remi: Hold on, phone ...
[20:13] chappie: If I give you all this point, then I'd still  like to see HTTPS working in CP2 so that it doesn't ace out consideration of the product.
[20:13] Dan_: chappie:  HTTPS is complicated - let the Apache folks handle it..
[20:13] Dan_: chappie:  we don't have the resources..
[20:13] chappie: It works in CP1 but is flaky.
[20:13] martin: can a simple user ask a hopefully simple question while remi is on the horn ?
[20:13] chappie: I'd like to see it thoroughly debugged if possible.
[20:13] chappie: sure.
[20:14] Dan_: chappie: just hide behind Apache if you need HTTPS...
[20:14] Dan_: shoot martin
[20:14] chappie: Dan_, It will ace CP out of consideration.  I want to see it used by more developers.
[20:14] chappie: go on martin :)
[20:14] martin: I am using csautheticate .. I have one public page .. the login page... if i want to go to a default page after login do I have to override doLogin..or is there another way ?
[20:15] martin: needless to say I am a newbie..both python and CP wise
[20:16] chappie: martin, for a simple situation, you'd send the person to the logged in page after they submit their username and password.
[20:18] martin: I don't get that...what would I do exactly ?
[20:18] Dan_: martin:  if you set the variable fromPage in the login form
[20:18] martin: I did that
[20:18] Dan_: you should end up there after the login is complete...
[20:19] Dan_: did you override checkLoginAndPassword?
[20:19] chappie: martin, you'd redirect the person back to where they were going in the first place after they logged in.
[20:19] martin: I get that if I try to access the protected page..but if I go directly to the login page ?...yes overriding that too
[20:19] Dan_: it should work.
[20:19] Dan_: I also overrode login... 
[20:20] chappie: If you go directly to the login page then there will be no "ReturnTo" page and you'd have to handle that as a special case and send them to a default home page.
[20:20] carribeiro: Just for the curious, and totally OT...
[20:20] Dan_: but I don't know if it is needed...
[20:20] Dan_:     def login(self):
[20:20] Dan_:         redirect('/subscriber/')
[20:20] Dan_:         return ''
[20:20] Dan_:     login.exposed = True
[20:20] Dan_: where subscriber is the place you go after you login from the home page...
[20:21] carribeiro: OT: Google has old numbers that say something about 150 million queries/day. It's something like 2.000 queries per second, average, But that's distributed on several clusters... 16, some sources say. 6, say others.
[20:22] Dan_: martin: did it work?
[20:22] martin: so I would override doLogin to handle the special case where fromPage has not been set ?
[20:23] Dan_: put this in the login form:    <input type=hidden name=fromPage value="/subscriber/">
[20:23] Dan_: where /subscriber/ is the page you want them to end up at...
[20:23] chappie: martin, you might make it so that the use is never given a way to go straight to the login page. You could make it so that each page checks to see if the user's logged in and if not, sends them a login under the same URL they requested, then redirects them to it after they log in.  No special cases then.
[20:25] carribeiro: Folks, in a sense, you have brought the topic that I had proposed.
[20:26] martin: Dan_ but then it souldn't handle the situation where the user does come from another page ? chappie..how would I prevent direct access to the login page...it has to be exposed ?
[20:26] carribeiro: I believe that we should come up with a standard framework for user authentication.
[20:26] carribeiro: And good docs to ship with it.
[20:26] martin: I second that carribeiro
[20:26] gwork: i agree, as it would be nice
[20:26] carribeiro: SOmething reusable, and provided as part of the library, to be as convenient as possible.
[20:26] chappie: martin: I don't think it has to be exposed like you're thinking.
[20:27] martin: ok...how so ? I am sorry for these banal questions
[20:27] carribeiro: My idea is to write a filter, that effectively "wraps" all objects, doing the checks for authentication.
[20:27] gwork: carlos, i think this is exactly a product. . it should not be handled by the core, but the functionality should be present in the distribution
[20:27] chappie: If I request (Link: http://yursite/homepage.html)http://yursite/homepage.html and I'm not logged in, the site would automatically send me the login page, but the URL in the browser would remain unchanged. Nothing to bookmark besides the home page.
[20:27] Dan_: martin:try this as the post:      <form action="/subscriber/doLogin" method="post"> 
[20:27] chappie: When the login was completed, the correct page would be shown.
[20:27] carribeiro: This is not a product, as I devised "products" originally
[20:27] carribeiro: Products, in my mind, are standalone web aplications, ready to run.
[20:28] carribeiro: Authentication is a plug-in that can be applied to many things.
[20:28] carribeiro: But unfortunately, guys, I need to go.
[20:28] carribeiro: Say goodbye to Remi for me.
[20:28] Remi: back
[20:28] Remi: bye carlos
[20:28] Dan_: by carlos
[20:28] chappie: by carlos
[20:28] gwork: bye carlos
[20:28] carribeiro: Hi remi! I was just leaving. Sorry. Have to go now.
[20:28] martin: Dan_... sorry for the pun.... you are the man
[20:29] Remi: carlos: can u send an e-mail with what you propose for authentication ?
[20:29] carribeiro: Good. 
[20:29] martin: carribero...If I can help in any way...say the word
[20:29] carribeiro: I'll do it, I have an idea, I'll write it down.
[20:29] carribeiro: See you later guys!
[20:29] gwork: bye!
[20:30] Remi: OK, so shall we quickly talk about authentication ?
[20:30] chappie: sure.
[20:30] gwork: fine
[20:30] martin: Dan_ and chappie : thanks for the help
[20:31] Remi: too bad Carlos just left, coz I wanted to ask him about the tutorial he said he was writing ...
[20:31] Dan_: martin: did u get it?
[20:31] martin: remi..he isn't going to stay silent for long :-)
[20:31] martin: Dan_ : yep...works beautifully
[20:32] Remi: Apart from a tutorial, do you have anything to suggest for documentation ?
[20:32] Remi: I added a "CherryPy documentation" component in the ticketting system
[20:32] gwork: auth still a topic?
[20:33] martin: I think a small heavyly commented app would be the best documentation...like your forum
[20:33] gwork: or do we wait for carlos to come up with an email?
[20:33] Remi: You can see the documentation tickets here: (Link: http://trac.cherrypy.org/cgi-bin/trac.cgi/report/9)http://trac.cherrypy.org/cgi-bin/trac.cgi/report/9
[20:33] Remi: Gwork: there is one for you :-)
[20:34] gwork: remi, thanks : ) but can you inform me on the discussion topic?
[20:34] Remi: there is a documentation ticket assigned to you 
[20:34] chappie: It would be nice to have the API reference include example snippets and return values.
[20:35] chappie: Great for newbies.
[20:35] Remi: chappie: good idea ... Add a ticket for it :-)
[20:35] Dan_: Have we talked about static files yet?
[20:36] * gwork is losing it.. . 
[20:36] chappie: sure will.
[20:36] Remi: gwork: have a look at this: (Link: http://trac.cherrypy.org/cgi-bin/trac.cgi/ticket/68)http://trac.cherrypy.org/cgi-bin/trac.cgi/ticket/68 it's assigned to you !
[20:36] Remi: dan: no, what about them ?
[20:37] gwork: thank you!! :) i noticed  ; )
[20:37] Dan_: I made a change and want to get a vote:
[20:37] gwork: i will take care of it
[20:37] Dan_: staticdir/xxx?A=yyyy
[20:37] Remi: gwork: oh, OK. So what did you mean by "gwork is losing it" :-)
[20:37] Dan_: should serve a file named: "xxx?A=yyyy" and not "xxx"
[20:38] gwork: i thought we were discussing authentication. . And then, all of a sudden documentation was the topic.. i've lost track of what we're dicussing, right now! 
[20:38] Remi: gwork: we moved on ... Carlos will write an e-mail with what he's proposing for authentication.
[20:39] gwork: remi, thank you, i have a clear vision again :)
[20:39] Remi: dan: true
[20:39] Remi: but it's unlikely that there will be such a file ...
[20:39] Dan_: Remi: there is if you use wget to archive pages and then want server them...
[20:39] Dan_: want to serve them...
[20:40] Remi: true ...
[20:40] Dan_: ok I will commit the change
[20:40] Remi: Did you add a ticket for that ?
[20:40] Remi: oh, ok
[20:40] Remi: Sure, check it in
[20:40] chappie: remi: I made ticket 82 but I goofed and didn't put it under documentation. Can you move it over? 
[20:40] Remi: I need to change that code anyway to it uses a generator to return the file in a streaming way (instead of loading everything in memory)
[20:41] gwork: remi, what dox would you prefer, a heavily documented application, or more like a book. Like cp1 had?
[20:41] chappie: 81. not 82.  I moved it.
[20:41] Remi: chappie: ok
[20:42] Remi: gwork: I'd *love* a book, like the SVN book ! But the topic is too broad, so the book should cover the basics only
[20:42] Remi: Let's wait and see what Carlos comes up with (he's writing a tutorial)
[20:42] Dan_: Ok next small topic: Internal Redirects...
[20:42] Remi: dan: ok
[20:43] Dan_: Redirect ignores port for internal redirects - is this expected?
[20:43] gwork: remi, he's writing a tutorial on authentication isn't he?
[20:43] Remi: gwork: and also an introduction to CherryPy
[20:43] gwork: ah.. thnx
[20:43] Remi: Dan: what do u mean ? Why would u change the port ?
[20:43] Dan_: localhost:8002//foo -> localhost://foo
[20:44] chappie: It's not retaining the port the site is running on.
[20:44] Dan_: from /foo to /foo
[20:44] Dan_: when /foo was served from 8002..
[20:44] gwork: ... http://localhost//foo forces a redirect?
[20:44] Remi: dan: An "InternalRedirect" is for redirecting *within the same CP server* ...
[20:45] Dan_: I guess I missed InternalRedirect....
[20:45] Remi: Maybe u're talking about something else ... What r u trying to achieve ?
[20:47] Dan_: when I run the server on port 8002 and do a redirect the absolute url it redirects is missing the port...
[20:47] gwork: dan_, localhost:9000//foo maps fine with me. . 
[20:47] Remi: dan: oh, I see ...
[20:47] Remi: Maybe the code is buggy ...
[20:47] Dan_: ;)
[20:47] Remi: Let me check ...
[20:47] gwork: dan, how do you perform the redirect?
[20:47] gwork: explicit, or implicit?
[20:48] Dan_: implicit with rediect in httptools.py
[20:48] Dan_: I will make a test case and ticket
[20:48] gwork: so //foo is mapped to /foo ? 
[20:48] gwork: i've tested it here on port 9000, and it works fine
[20:49] Dan_: gwork you did a httptools.redirect('/') and it works?
[20:50] gwork: no, you said an implicit redirect, well, forcing it using httptools seems quite explicit to me :) The explicit indeed fails, it's bug from the beginning in cp2
[20:50] gwork: now i know what you mean ;)
[20:50] gwork: but what happens if i do a redirect while some filters have done jobs already? I think that's why this point made it to the agenda... 
[20:50] Dan_: gwok: ahh, I mean implicit in that I don't give it an absolute url... 
[20:51] Dan_: (one with http://localhost:8002/ )
[20:51] gwork: Dan,  i get it. . communication error :)
[20:51] gwork: but how should the filters handle a redirect, they aren't notified.. . 
[20:52] gwork: remi?
[20:52] Remi: gwork: what do u mean ?
[20:52] Remi: dan: let me check the redirect port thing ...
[20:55] gwork: assume i have _cpFilterList in root.filtered: [filterA,filterB,filterC] and have root.cpFilterList like [filterD,filterE]. . if filterA and FilterB are executed, and the request is remapped to, say root.foo, and not root.filtered.foo, filterA,filterB and filterC will not have the chance to close anything and FilterE and FilterF might expect a certain condition that will never be met, because they 
[20:55] gwork: haven't look at the request before
[20:55] Remi: Dan: the redirect works fine ...
[20:55] Remi: Here is my code:
[20:55] Remi: from cherrypy import cpg 
 from cherrypy.lib import httptools 
  
 class Root: 
         def index(self): 
             res = httptools.redirect('/abcd') 
             print "Location:", cpg.response.headerMap['Location'] 
             return res 
         index.exposed = True 
 cpg.root = Root() 
 cpg.server.start()
[20:56] Remi: "Location" prints as "http://localhost:8080/abcd", as it should ...
[20:56] Remi: gwork: the filters have the option of issuing a real redirect or an "InternalRedirect"
[20:57] Remi: The VirtualHostFilter uses InternalRedirect
[20:57] gwork: and an explicit is with using the error code 303 (if i'm not mistaken)
[20:57] gwork: ?
[20:58] Remi: 302
[20:58] gwork: s/explicit/real
[20:58] gwork: okay. . do we want to have a utility function on these as well, and anser it in the faq?
[20:58] Remi: utility function on what ?
[20:58] gwork: real redirect
[20:59] Remi: there is: httptools.redirect
[20:59] gwork: i thought that was an internal?!?!
[20:59] Remi: no, that's a real one. For internal, u need to do "raise InternalRedirect" in a filter
[21:01] Remi: OK, let's move on to the last topic: the website
[21:01] Remi: Do u have any suggestions for improving it ?
[21:03] martin: I have to leave...thanks again for the help
[21:03] gwork: bye martin
[21:03] Remi: ok, bye martin
[21:03] *** martin has left #cherrypy.
[21:04] gwork: can the right side of the screen be made a bit wider?
[21:04] Remi: how ?
[21:04] gwork: now that's a tricky question... move the left side more to the left?
[21:05] gwork: i see about half an inch free space over there
[21:05] Remi: so, make things tighter, right ?
[21:06] gwork: tighter, as in smaller? no.. fill the screen a a bit more, allowing the right pane to contain more infomation.. 
[21:06] gwork: alowing tickets to be 'back to normal' again.. 
[21:07] Remi: Well, it can't happen unless I remove the left menu for some pages ..
[21:07] gwork: is there no margin set for the left menu?
[21:08] Remi: There's 20px on each side, but that won't make a big difference ...
[21:08] Remi: Anyway, I was looking for more "high-level" suggestions :-)
[21:08] gwork: ok : )
[21:09] Remi: At some point, I'd love to have a "demo" app, but we'll need more features for that ...
[21:09] chappie: selecting the text to the right of the menu section doesn't allow it to print right. It gets truncated. I'd like a printable view of pages.
[21:09] Remi: chappie: just click on the "Download as HTML" link at the bottom
[21:10] chappie: Say, that works!  I'll try some printing from it later and see if it truncates or not.
[21:10] gwork: should (Link: http://trac.cherrypy.org/cgi-bin/trac.cgi/file/trunk/cherrypy/tutorial/05_derived_objects.py)http://trac.cherrypy.org/cgi-bin/trac.cgi/file/trunk/cherrypy/tutorial/05_derived_objects.py provide a draft in the background?
[21:10] gwork: it's not a preview or anything
[21:10] chappie: I don't think you need to spend any time on the site. It appears that there's plenty of things to do on the code with your ideas for modularity.
[21:11] Remi: Alright, so no major suggestions for the site ... That's fine, I like it the way it is :-)
[21:11] gwork: do you still want to use the forum?
[21:12] Remi: Until we have a CP2 one, yes ...
[21:12] Remi: Some people like forums ...
[21:12] gwork: ow . .  ok . .       ; ) 
[21:12] chappie: Can you make the forum mirror the list?
[21:12] gwork: it's an easy to get into contact. . that's true
[21:12] chappie: (not sure that'd be that useful, just an idea.)
[21:13] Remi: chappie: I prefer to keep them separate ...
[21:13] chappie: ok
[21:13] gwork: that's it then?
[21:13] chappie: btw, remi, where's are you located?
[21:14] Remi: london, uk
[21:14] Dan_: Remi - Here is the redirect problem: (Link: http://rafb.net/paste/results/FG5WyH30.html)http://rafb.net/paste/results/FG5WyH30.html
[21:14] chappie: So that's why the time on for the chat was in GMT.
[21:14] chappie: It's your home time zone.
[21:14] Remi: that, plus it's standard :-)
[21:14] Dan_: It is actually BaseUrlFilter that isn't using the port....
[21:15] Remi: dan: are you passing the baseUrl ? what is it ?
[21:16] Dan_: localhost:8002 when you are behind apache....
[21:16] Dan_: (Link: www.foozlebar.com)www.foozlebar.com when you are in front..
[21:16] Dan_: I will fix the default and commit
[21:16] Remi: so how are you creating the BaseUrlFilter ?
[21:17] Dan_: BaseUrlFilter()
[21:17] Remi: Is that behind Apache2 ?
[21:18] Dan_: the default should include localhost:XXX where XXX is the port the cp server running
[21:18] Dan_: yes
[21:18] Remi: dan: no, you need to pass "(Link: http://www.foozlebar.com)http://www.foozlebar.com" as the base url ...
[21:19] Dan_: hmmm, I though baseUrl is for when there is no XForwardedHost...
[21:19] Dan_: here is the offending code in BaeUrlFilter
[21:19] Dan_: def __init__(self, baseUrl = 'http://localhost', useXForwardedHost = True):
[21:19] Dan_:         # New baseUrl
[21:19] Dan_:         self.baseUrl = baseUrl
[21:19] Dan_:         self.useXForwardedHost = useXForwardedHost
[21:20] Dan_: the it just need the default for baseURL to include the current port...
[21:20] Remi: well, in ur case, useXForwardedHost should be True, so it won't use self.baseUrl
[21:20] Dan_: other than that it works with out being explicit about (Link: www.foozlebar.com)www.foozlebar.com
[21:20] gwork: i'll be gone . . thanks all
[21:20] * chappie waves bye
[21:20] Dan_: ahhh, but it is for internal users..
[21:20] Remi: by gwork
[21:21] Dan_: anyway - do you agree the baseUrl default should include the current port?
[21:21] Remi: No !
[21:21] Dan_: (current port that cp is listening to)?
[21:21] Remi: The default is for the case when you run Apache on port 80 and CP behind Apache on port 8080
[21:23] *** vi has signed off IRC (Quit: using sirc version 2.211+KSIRC/1.3.11).
[21:23] Dan_: Right -- so in that case you will need to say
[21:23] Dan_: BaseUrlFilter(baseUrl=
[21:24] Dan_: BaseUrlFilter(baseUrl='localhost:8080') in order for redirects to work when viewing via http://localhost:8080
[21:24] Remi: Let me fix the doc ...
[21:25] Dan_: The apache on 80 will work fine foozlebar.com will work fine in either case...
[21:26] Remi: The doc is fixed ... 
[21:26] Dan_: I thought the point of baseUrl was to have something appropriate for local viewing (pre apache...)
[21:27] Remi: no, it's to generate the right URLs when running your site behind Apache ...
[21:27] Remi: Did u read the last section of this: (Link: http://trac.cherrypy.org/cgi-bin/trac.cgi/wiki/BehindApache)http://trac.cherrypy.org/cgi-bin/trac.cgi/wiki/BehindApache
[21:28] Dan_: no, that is what X-Forwarded-Host is for...
[21:28] Remi: they're both for the same thing ... baseUrl is used for situations where X-Forwarded-Host is not provided (ie: not behind Apache2)
[21:29] Remi: Alright, I have to go as well ...
[21:30] Dan_: ahhh, well, in my case I *am* behind apache2 and want baseUrl for debugging behind apache 2...
[21:30] Remi: Dan: well, you can't access your site both ways ...
[21:30] Dan_: Remi - thanks for your help.  Sure - if you set baseUrl = localhost:8080
[21:30] Dan_: it works great..
[21:31] Dan_: that's why we should change the default...
[21:31] Remi: Oh, true ... I never thought ofusing it for that reason :-)
[21:31] Dan_: it is so elegant!
[21:31] Dan_: so much better than the Zope virtual host monster
[21:31] Remi: Well, that's not the main usage of "baseUrl" so we shouldn't change the default ...
[21:31] Remi: But you could write a recipe about this :-)
[21:32] Remi: "How to abuse the BaseUrlFilter" ;-)
[21:32] Dan_: Well we have designed the default case for apache 1 on port 80... 
[21:32] Dan_: I will write the abuse notes
[21:33] Dan_: but please consider making the default a value add for Apache2...
[21:33] Remi: Make sure this is only a side note ...
[21:33] Dan_: ;^)
[21:33] Dan_: Well, I was going to but it in BOLD at the front... but ok...
[21:34] Remi: LOL ... Alright, I have to go ... Good night everybody. I'll put this session in the wiky

Hosted by WebFaction

Log in as guest/cpguest to create tickets