[06:45] <LPCIBot> Project windmill-devel build #151: STILL FAILING in 1 hr 8 min: https://lpci.wedontsleep.org/job/windmill-devel/151/
[09:07] <magcius> how did you guys hack apart zope so that you wouldn't have to use ZODB^W pickle?
[09:08] <wgrant> magcius: It basically just needs a custom publication class.
[09:09] <wgrant> I tried a similar thing in 2007 or so, and basically ended up copying the base publication and deleting ZODBish bits, and it worked fine.
[09:09] <wgrant> It wasn't practical to inherit much of it.
[09:09] <wgrant> Because ZODB is so ingrained.
[09:09] <wgrant> But it didn't end up that big, and that was the only thing to which I had to make significant changes, IIRC.
[09:09] <wgrant> I
[09:09] <wgrant> I may still have a copy of it around somewhere.
[09:09] <magcius> zope hacker I'm talking to says that must "wreak havoc on security"
[09:09] <wgrant> ... why?
[09:10] <wgrant> The security machinery doesn't depend on ZODB :/
[09:10] <wgrant> That would be very Zope, but it's not true :)
[09:10] <magcius> "because the ZODB allows per object access control"
[09:10] <wgrant> That's got very little to do with ZODB.
[09:11] <wgrant> Security proxies work on Python objects.
[09:11] <wgrant> Not in the ZODB.
[09:11] <magcius> wgrant, can you point me to this code somewhere in LP?
[09:12] <wgrant> It'll be in lib/canonical/launchpad/webapp somewhere.
[09:12] <wgrant> canonical.launchpad.webapp.publication has our very custom publication.
[09:15] <wgrant> May also need custom RequestPublicationFactories.
[09:15] <wgrant> I forget where they live.
[09:15]  * wgrant greps.
[09:19] <wgrant> Possibly not.
[09:19] <wgrant> Anyway, the critical bit is getApplication on the publication.
[09:19] <wgrant> You can see here it gets the ILaunchpadRoot utility.
[09:19] <wgrant> Rather than taking the root from a ZODB.
[09:20] <wgrant> There's also lovely.zetup which does ZODB and ZConfig removal, IIRC>
[09:21] <wgrant> But it's been a while :)
[10:13] <lifeless> wgrant: magcius: the problem is that zopes entire programming model is based around aozdb
[10:13] <lifeless> wgrant: magcius: so we're *still* paying for this hack in terms of performance
[10:13] <magcius> heh
[10:14] <magcius> if you could "do it again" today, what would you do
[10:15] <lifeless> well
[10:15] <lifeless> https://dev.launchpad.net/ArchitectureGuide/Services
[10:15] <lifeless> we are doing it again :)
[10:17] <lifeless> magcius: your zope hacker is right, it wreaks havoc
[10:17] <lifeless> magcius: it works, but its terribly terribly slow unless we're careful to preload things
[10:19] <lifeless> magcius: in terms of choosing an application stack, if we were setting out to do LP from scratch, I couldn't really say.
[10:19] <magcius> OK.
[10:19] <magcius> I'm getting into the scary world of web development here, and all the existing frameworks suck :(
[10:20] <wgrant> I don't like Django for this sort of thing.
[10:20] <wgrant> Zope sucks, but it is semi-appropriate for what LP is.
[10:20] <wgrant> Django is less appropriate IMO.
[10:20] <lifeless> I'd like to do something with http://liftweb.net/
[10:27] <magcius> Here's what I like about Zope: the security/auth system is a bit neato, and I do like the interface and adapter system
[10:27] <lifeless> mmm
[10:27] <magcius> everything else? ZODB? meh.
[10:27] <wgrant> The security stuff is awesome, but is really slow with SQL.
[10:28] <lifeless> so I don't value those at all
[10:28] <magcius> lifeless, I like that you have to define users and roles and what can access what.
[10:28] <magcius> so that we don't get another diaspora :D
[10:28] <lifeless> they don't really fit in a hugely dynamic language like python
[10:28] <magcius> do you mean the auth system or z.i?
[10:29] <lifeless> z.i.
[10:29] <magcius> I assume you've read glyph's infamous post?
[10:29] <lifeless> ignoring some of the fugly globals based implementation details
[10:30] <lifeless> magcius: I think I have
[10:30] <magcius> I just treat z.i as a better isinstance right now
[10:30] <magcius> but not __subclasshook__. Because __subclasshook__ is all about trickery and deceit.
[11:22] <magcius> lifeless, http://glyph.twistedmatrix.com/2009/02/explaining-why-interfaces-are-great.html
[11:37] <lifeless> magcius: yes, that one
[11:38] <lifeless> magcius: basically, I think in python you want to embrace the duck
[11:38] <magcius> of course
[11:38] <magcius> z.i doesn't disallow or try to prevent that
[11:39] <magcius> but there are sometimes when you have an A, and you want a B
[11:39] <lifeless> I argue that using z.i. shows a failure to embrace the duck.
[11:39] <magcius> adaptation is perfect for that
[11:39] <lifeless> its *a* solution.
[11:39] <magcius> other solutions are isinstance
[11:39] <magcius> but isinstance is a bit closed... you have to modify the method if you want to add new types...
[11:39] <lifeless> isinstance, delegation, multimethods, type factories
[11:40] <magcius> etc etc.
[11:40] <lifeless> offhand
[11:40] <lifeless> there are probably other approaches too.
[11:40] <magcius> never heard of any of the latter
[11:40] <magcius> to make isinstance extensible, they added ABCs and __subclasshook__
[11:40] <lifeless> yes
[11:40] <lifeless> this was a bit myopic.
[11:41] <magcius> which allows you to lie: you can say you're a B, even though you just look almost like a B
[11:41] <magcius> to me, that's the wrong way of doing it
[11:41] <lifeless> having a problem with isinstance, they made it worse :)
[11:41] <magcius> with z.i, you define what things you need in an interface, and then adaptation allows you to turn anything into what you need
[11:41] <magcius> instead of lying
[11:42] <lifeless> sure, if you don't mind the costs
[11:42] <lifeless> and the inflexability
[11:42] <lifeless> I dislike the costs and find the inflexability more a burden than a benefit, most of the time.
[11:42] <magcius> what costs do you see?
[11:43] <lifeless> its a global registry
[11:43] <lifeless> you run more code when importing your app
[11:43] <lifeless> You have to double-define everything
[11:43] <magcius> double-define?
[11:43] <lifeless> class IFoo(Interface): def foo():pass
[11:44] <magcius> you don't have to do that, although you should for documentation.
[11:44] <lifeless> class Foo(object): implements(IFoo); def foo(self): do stuff.
[11:44] <magcius> z.i won't check to make sure you're implementing everything
[11:44] <magcius> you can just do class IFoo(Interface): pass if you want
[11:44] <lifeless> magcius: you asked what the costs are.
[11:44] <lifeless> if you are writing in this style, this is something you do: its a cost.
[11:44] <magcius> OK, sure.
[11:45] <lifeless> magcius: we use interfaces very extensively in LP; I'm quite familiar with the system.
[11:45] <magcius> Right.
[11:45] <lifeless> I'm not arguing against it from a position of ignorance :)
[11:45] <magcius> I wish there was something that provided adaptation as a language feature.
[11:46] <lifeless> Oh, and I should add confusing-code to the list.
[11:46] <magcius> z.i code is extremely messy, z.c more so
[11:46] <lifeless> adaption is a poor way to write code, IMNSHO.
[11:46] <lifeless> i don't mean the implementation of z.i. is confusing : I mean that adaption centric code is confusing for readers.
[11:46] <magcius> if it was a Python language feature instead of ABCs, I would cheer.
[11:47] <magcius> but yeah
[11:47] <magcius> additionally, having to define roles and explicitly say "this is public" I like
[11:47] <lifeless> If IFloat and IString existed, when would you use "%3.4f" % foo and when would you use IString(foo), if foo is a float ?
[11:48] <magcius> those are dumb, though
[11:48] <magcius> IString isn't an interface.
[11:48] <magcius> what does it allow?
[11:49] <magcius> it would be ISequence or IMapping
[11:49] <lifeless> well, it would extend ISequence,
[11:49] <magcius> what does IString add on top of ISequence?
[11:49] <lifeless> actually IImmutableSequence
[11:50] <lifeless> magcius: replace, format, for starters
[11:50] <lifeless> magcius: join
[11:51] <magcius> I would expect IString(float(foo)) to be implemented in terms of a simple adapter:
[11:51] <magcius> def float_to_str(value): return str(value)
[11:52] <lifeless> this demonstrates the point.
[11:52] <lifeless> Thats approximately never the right way to convert a float to a string
[11:52] <magcius> well sure
[11:52] <lifeless> so having an adapter is bogus
[11:52] <magcius> str(float(value)) is as useless, though
[11:52] <lifeless> of course it is
[11:52]  * magcius kicks XChat
[11:53] <magcius> ^W in XChat is "close tab"
[11:53] <magcius> I have no idea why...
[11:54] <magcius> If you're saying IString(foo) is stupid because str(foo) is stupid...
[11:54] <magcius> I don't see how this is an argument *against* interfaces or adaptation.
[11:55] <magcius> we already do the same thing with duck typing -- we don't care what it is, we just want a string out of it
[11:55] <magcius> str(foo) is the easy way to do this
[11:55] <lifeless> cast-based adaption is only useful when there is one and only one right way to get from A to B
[11:56] <magcius> of course.
[11:56] <magcius> for most types, there usually is only one way
[11:57] <lifeless> I disagree there.
[11:57] <lifeless> Perhaps 50%. Perhaps.
[11:57] <magcius> if there's a difference, you need to define a new interface IMHO
[11:57] <lifeless> I need to sleep
[11:58] <lifeless> I'll think more about how to articulate this.
[11:58] <magcius> if you have an IUser and you want an IAuthToken, going through an intermediate IPotato shouldn't effect the result.
[11:58] <lifeless> uhm
[11:59] <lifeless> I think you're talking about something different.
[12:00] <magcius> you go to bed. I will too.
[12:00] <lifeless> Noddy example.
[12:00] <lifeless> say you have ICar and IPassenger
[12:00] <lifeless> and a Car instance with 3 Passengers.
[12:00] <lifeless> Whats the behaviour of IPassenger(car)
[12:00] <magcius> it throws an error
[12:00] <magcius> or raises
[12:01] <lifeless> if there is an adapter present it won't.
[12:01] <lifeless> that doesn't make it useful.
[12:01] <magcius> the adapter throws an error
[12:01] <magcius> if there's more than one passenger :)
[12:01] <lifeless> if you do that, then you have code that will sometimes work and sometimes not.
[12:01] <magcius> realistically, this is the wrong use of adaptation
[12:02] <lifeless> See - when I see a right use of it, I will be happy.
[12:02] <magcius> in my code, all my use of interfaces is bascially 'isinstance' on steroids.
[12:02] <lifeless> I have *honestly* not seen a problem in python made simpler by using interfaces.
[12:02] <magcius> It's extremely, uh, method-based.
[12:02] <lifeless> magcius: using isinstance is a design problem in the first place.
[12:02] <magcius> lifeless, there are certain extreme cases where it is necessary.
[12:03] <lifeless> !cite
[12:03] <lifeless>  :)
[12:03] <lifeless> I'm going to crash. Feel free to pick this up another time if you like.
[12:04] <magcius> OK
[12:08] <magcius> lifeless, http://paste.pound-python.org/show/TrBZVgWsMKEHo5EtQv8c/
[12:09] <magcius> lifeless, you may say that's extreme edgecase... but this is what 90% of what my usage of z.i is
[12:10] <magcius> I would have to subclass if I wanted to add something else, and it quickly became messy.
[12:10] <magcius> so, I left a "hook".
[12:14] <lifeless> http://paste.pound-python.org/show/7357/
[12:14] <lifeless> very quick-n-dirty
[12:14] <magcius> ... and it's failing to load
[12:14] <magcius> great
[12:14]  * magcius shoots _habnabit in the face.
[12:14] <lifeless> I wouldn't normally do that, but am working on the assumption you can't fix your types ;)
[12:19] <lifeless> do you want me to paste it somewhere else?
[12:19] <lifeless> say so now cause *yawn*
[12:21]  * lifeless waves gnight
[17:14] <LPCIBot> Project windmill-db-devel build #339: STILL FAILING in 1 hr 8 min: https://lpci.wedontsleep.org/job/windmill-db-devel/339/
[20:50] <LPCIBot> Yippie, build fixed!
[20:50] <LPCIBot> Project db-devel build #593: FIXED in 4 hr 55 min: https://lpci.wedontsleep.org/job/db-devel/593/
[23:58] <LPCIBot> Project windmill-db-devel build #340: STILL FAILING in 1 hr 7 min: https://lpci.wedontsleep.org/job/windmill-db-devel/340/