The weblog Industrie Toulouse is now phased out. For now (and probably for quite some time), my new writings can be found at Griddle Noise.
Industrie Toulouse will be archived soon and moved to a different site. I apologize for this. There is a lot that is shifting and changing in regards to the people, places, and servers that have graciously given me free access for the past few years. I thank all of those who have provided this.
Watch this space for notification of archives. And watch the new space for new activity.
The future of this weblog is up in the air right now. I've enjoyed some free hosting from a friend and former coworker for years, but events beyond our control is bringing that to an end. With that in mind, I've been thinking about what to do now. My own site, euc.cx, has a somewhat clouded future right now as well. Presently, I can't really run anything dynamic (server side) on it, which hasn't bothered me as much as I thought it would. The closest it gets to anything dynamic is the subsite DDEC, which is maintained by an old (and modified) version of FTrain Sitekit as a collection of XSLT transforms that are run on my iMac and then uploaded manually. I'm considering using the same method to maintain Industrie Toulouse in the future - hopefully, the near future. I need to dust off my pitiful XSLT skills and transform the Movable Type XML export I cobbled together recently just to make the transform into a Sitekit capable format. From there... who knows?
I'm looking at other options - Blogger, PyBlosxom, etc, but I don't know how far I'll get with any of those. A lot of this is due to euc.cx's future being cloudy. At the office, we talk of making the box that it's on more of an experimental box and giving me more control to work with different technologies, etc, on it. But there's no date tagged onto when that possibility will open up. And even then, there's only so much energy left in my being to monkey with new technologies - as much as I may one to. So at times I dream of a Zope 3 based system, or Subway, or even Rails... And one or more of those may actually happen. But for some reason, the XSLT bug is starting to kick at me again.
I guess that the best message I can give right now is "stay tuned..."
There are still many things that I want to write about, to be sure.
A lot has been going on around these parts lately. Heartache, frustration, disappointment, new hopes, new beginnings, and more. First up is a new living/working space for myself as well as new office space. Thanks to some fancy rapid moves, I'll soon be living in an artist studio in a row of converted warehouses I used to marvel at when younger. As the euc.cx mini-empire grows, this is a huge benefit. I'll be able to return to larger paintings, more spray (and hopefully print) work. I plan on re-learning electronics as well so I can start building my own sound modules. I'll be giving up a wonderful view and my beloved gas stove, but will be surrounded by galleries and studios and a local 'zine. I'll also be near the summer Farmer's Market. And nicest of all, our new offices are just down the block from me. I won't even have to cross a street. At most, I'll have to cross through a gourmet food market where one can find glorious things like Squid-Ink Spaghetti and Kinder Eggs.
On the audio front, there's a new Eucci release, The Mercer, a quiet electro-acoustic composition. aodl has a healthy set of live performances lined up over the next few months, playing before artists international and one state over.
I've been impressed lately with tools like QuickSilver, Ta-da lists, and BaseCamp. I've also been really impressed with paper. Good old fashioned A4 sized legal pads for work, a couple of different notebooks for personal life (I'm excited for the new Moleskine Pocket Reporter Notebooks). It's been interesting to observe a similar excitement for paper going on around the digital world. There's something great about simplicity and manual syncing. I use Ta-da lists to keep tabs on groceries and books to get, and write them down as necessary.
HBO recently announced that The Wire Season 4 will come in 2006. Oh happy day!
Now that a simple skin has been established, it's time to add some views to the todo list. In a style inspired by the article on how to build a todo list in Rails, we're going to present the todo list in two parts on the same page: Incomplete Items, and Completed Items. In the middle will be a form to add a new item. Looking back at the code and interfaces for the basic todo list, you'll notice that there's no real logic here. Just basic 'model' stuff. The list doesn't really care about separating complete and incomplete todo items - that's a detail specific to our browser view.
So one of the first things we need to do is write a Python class that will be a view component for an ITodoList. Its responsibilities will be:
- Listing completed items.
- Listing incomplete items.
- Listing all items (if desired).
- Returning information about the todo items that are interesting to the browser view - such as the items id.
I hear and hear and hear and read and read and read and interpret that there are too many web frameworks for Python. Why does the Python community seem to think this is limited to just them? Yeah, So there's Nevow, Quixote, Zope 2, Zope 3, CherryPy, WebWare, Spyce, bla bla bla. There are just as many different things available for Java, if not more. I can't keep up with Java Server Faces, Struts, Tapestry, J2EE's web parts, JSP, Servlets, on and on and on. I even see Python people look at all of the development and excitement around Ruby On Rails. But on RubyForge's WWW/HTTP - Dynamic Content listing, there are numerous other "web frameworks" and other libraries/toolkits for dynamic content. A similar listing on the Python Package Index (PyPI) is also a fairly big list. The point is - who cares?
There will never be one and only one magnificent web framework. For any language. Ever. Different toolkits have different strengths and play to different audiences. I HATE those who say "there should only be one. Everyone else only has one!" It's just not true.
What I do wish is that people would better explore the unique features of their languages in their web frameworks. I think Ruby On Rails does this expertly in Ruby. Seaside does this well for Smalltalk. I think that Bobo did this well for Python and so did Principia / Zope 1 and 2. Those are unique systems. Yes, Zope 2 has its faults, but it is still wildly successful. Zope and its predecessors were not trying to copy Rails, JSP, PHP, ASP, ColdFusion, CGI.pm or Java Servlets. I see too much of this. Even I was guilty of that, writing my own in the mid nineties inspired too much by NeXT's WebObjects. A model that makes sense for Java does not necessarily make sense for Python.
So, I applaud Quixote, which seems to take some of the concepts of early Bobo/Principia and cleans them up a bit. I applaud Nevow, what little I've seen of it. I've seen even less of CherryPy, which I've seen even less of, but looks to be "pythonic" as well. To a lesser extent, I even applaud Subway. Subway is trying to be a stack similar to Ruby On Rails, but I give it credit for utilizing many pre-written components. So, it's half copy, half original.
I still throw my personal weight and preference behind Zope 3. Zope 3 is simultaneously young and mature. In its released form, it's young. But it's been in development for years and already has some rather successful deployments and projects. I've only barely started working with it myself, but I've liked my experiences. Loose coupling is a magnificent thing. As I'm trying to integrate a well written but monolithic Zope 2 forum product into a more general web site, I realize the benefits of loosely coupled systems written as small components instead of a large monolithic class. I like the way that Zope 3 encourages code structure. More small collaborating objects instead of large massive-inheritance classes.
When it comes down to it, I'd rather have many web frameworks than one way to do it. The chances that any one style will fit everyone in the Python community are slim to nil. Both 'Quixote' and 'CherryPy' claim themselves to be "highly Pythonic." But what does that really mean?
When we last visited the little todo application for Zope X3, we had made some very basic views for the Zope Management Interface (ZMI). At this point, no HTML had been written. No other view/controller code had been written. And we didn't have much of a todo application, but we did have editable Todo objects being stored in a Todo List in the object database. But what it needs now is its own look. To do this, we need to make a skin.
In getting back to showing how to make a Todo List application in Zope X3, I've made a new category covering the simple todo application. Coming up next, I'll show how to write a custom skin for the todo list to give the application its own look, and how to write some new views and adapters to start making the list usable.
But before I continue, I'd like to remind the audience that this is based on How to make a todo list program with Rails 0.9. It's a simple and well written application, and I'm wanting to show Python programmers that they needn't necessarily copy Rails - that there are existing solutions for Python that, in my opinion, fit the Python mindset better. If you want to program in Rails, by all means just learn Ruby and use Rails and enjoy it. But me - I like Python, I have existing applications and libraries in it, and as I start to really explore Zope 3, I'm getting really excited about using it, which hopefully I can do in near-future work related projects.
Using the Rails Todo List example is how I'm finally pushing myself to investigate building a simple but complete Zope 3 application. There may be better ways to accomplish some of what I try here. I'm no Zope 3 expert. I have followed its development and had a hand in some of the concepts early on (many years ago), but have not had the chance to build anything substantial until now. So I thank the authors of the "How to make a todo list program with rails" document for generating some excitement and giving me an idea of something to build, and I hope that they don't mind my usage of what they document as basis for my explorations.
William Rivers Pitt of TruthOut.org has an excellent and personal article about Hunter S. Thompson. Regrettably, I have not read any of Thompson's works. But now I'm even more interested. There seem to be so many parallels between his 1972 writing Fear and Loathing on the Campaign Trail and the recent election cycles.
I think I'd like Thompson for the same reason I love William Burroughs - it's balls out, dirty, raw, and true (or just eerily poignant). And they lived their lives this same way.
From Loud Thinking:
One of the clear goals for Rails from the start was to stay at the infrastructure layer. I didn't want Rails to succumb to the lure of high-level components like login systems, forums, content management, and the likes.
[The case against high-level components]
I agree. But I'd like to add that the case is not against component systems / architecture, it's just against this idea that one-bulletin-board-fits-all is how component architectures should work. Components work best when they're small grained and interchangeable. Yes - being able to nicely integrate a complete bulletin board system into a customers site is a nice thing to have. But in my experience, the work often required to do a good integration in a lot of these systems seems to be about equal to writing one from scratch. This is not always the case - I was able to integrate two very different systems with different histories a few months ago, but there were a couple of advantages there: they were both written in house, and both had put some effort towards just enough customization and control-layer separation that it could work.
I've been using a system that a colleague has been building in house, and it's basically a chain of fine-grained components that operate on data as data flows to and from storage. As a result, we have a system that gives us so much more than most generic form display / validation tools for presenting and working with data and user input, more flexibility than most object-relational mapping systems, and tight granular security. There are parts of the system that require a fair amount of work, most of it in configuration (lots of XML sit-ups, as the Rails community might say). But in my experience so far, once the components are wired together they've proven to be very dependable. Once one part of an application is complete, it rarely needs touching. It's difficult for other things to interfere with it. Built around the concept of "no alarms and no surprises," magic is forbidden. Explicit is better than implicit. And the components are given only enough information to do their specific job - whether it's validating input, presenting data on screen, or preparing data for storage.
I first wrote up how such a system might work a couple of years ago in my post "Component-Relational Mapping?" and that particular system has suited me well in a few projects. This other system is simultaneously a much larger (it stands alone with no requirements on Zope or anything else, and doesn't even place any real requirements on how one stores data) and a much simpler system (the core concepts are really simple). Applications built on it are a good example of applying small, tough, and smart components to get jobs done.
I just added Loud Thinking to my subscriptions list, and hope to have time to actually go through and read it soon. Loud Thinking is the David Heinemeier's weblog. Heinemeier is a big dynamic language advocate and is responsible for Ruby On Rails, a Ruby web application toolkit that's getting considerable buzz lately.
I'm not blown away with Rails. I'm personally more interested in toolkits like Seaside and Wee. Many other pieces of Rails I've seen done in Bobo / Zope to varying degrees. I still believe that Bobo, aka the "Python Object Publisher" is a significant piece of web technology and is still a fundamental part of Zope 2 and 3, wherein an HTTP (or FTP, or other) request is translated into an object call. The Python Object Publisher is an ORB [Object Request Broker] in this sense. Beautifully simple and powerful. Don't let the complexities of the systems built on top of it (Zope 2, etc) fool you.
Anyways, Heinemeier seems to have a lot of interesting ideas and is willing to happily talk about them. Contrary to what you may read in trade rags, the web is not dominated by J2EE. Almost all highly popular and/or innovative web sites are implemented in, or were prototyped in, an agile language such as Python, Ruby, Lisp, or Perl. Movable Type? Perl. LiveJournal? Perl. Google? Prototypes in Python. Yahoo Maps? Python (I don't know if the current version still is, but it was a Python one for a long time). There are some very large news organizations running on Zope (Python). There are a growing number of popular Ruby web applications and sites as well.
There are often grumbles in the Python community about there being "too many Python web frameworks." and wondering what can be done to compete with J2EE. Why compete with J2EE? I know of few who are happy with it. How many Java Web Frameworks have sprouted up in recent years as alternatives or add-ons or extreme enhancements of J2EE's web support? Think Java Server Faces. Think Struts. Think Naked Objects. Think Hibernate. And those are just the names I know of as an extreme outsider. I think it's good that there are different web frameworks and toolkits for Python. Part of being agile, I think, is having a good set of tools to choose from to get a job done. It's far better than a rigid specification that is meant to copy the rigid specifications of a technology that no one seems to really enjoy using.
Although - it would be nice if some toolkits or parts of toolkits were made to be more standalone. I'd love to use Nevow's stan in my Zope and FD4 (an in-house data management framework). Stan is an S-expression like system for generating HTML in Python that actually looks good and one isn't scared to maintain (a simple stan example can be found here). Being able to use stan without the rest of Twisted or Nevow would be nice, just like there are many implementations of the wonderful TAL.
Phil Windley (former CTO of Utah!) writes about Running Code and Regular Releases:
Several interactions I’ve had recently with groups building Web applications have led me a renewed appreciation for the power of running code in a development project. Both of these organizations were some time into a large development project and still didn’t have running code and regular, consistent release cycle. This wisdom gets great lip service, so it surprises me to see people who should know better not following it.This blows my mind. I have never been in a situation on the web where I didn't have running code. Release cycles vary from project to project, but I can not think of a situation where you don't have running code.
Yesterday, I moved my code off of the Zope instance I tend to use for development and into a separate instance (a separate running Zope server). I first moved my core application, along with its two supporting frameworks - one for the data management the application is built on, one for the simple workflow engine the application uses - into the new location. I fired off my unit tests and they all passed in the new location, even without having all of the supporting Zope Products in place yet that were used by the web interface. It was gratifying to see that all my tests succeed and know that the application could, at this point, move just about anywhere. And that I had a reasonable assurance of its success by having so much running code in place already.
Perhaps I've lived too long in the world of dynamic languages like Python where the compilation step is absent. Or perhaps it's that I first started programming on a machine with an omnipresent BASIC interpreter which allowed me to see immediate results. I've never been able to fathom a world of blind design-and-hope development. I could see how large systems with scarce resources were scarce could be built this way, but those should be few and far between now.
There's a pretty good article at ONLamp.com about More Test-Driven Development in Python. It's basic unit test work, showcasing writing tests first and code second. I'm never consistent when it comes to unit testing. On some projects, I use them. On others, I don't. Some projects use code that's been around for years and has no tests. Sometimes, it's just really hard to unit test code meant for Zope 2. And when I say that, I mean underlying Python Product based code, not scripts and forms and other UI related elements. My Zope 2 projects have less and less code managed in the ZODB and more from underlying Python objects.
Zope 3, on the other hand, advocates testing heavily. In the developer documentation for writing a new content object, writing unit tests is step #4, just after preparation, initial design, and writing interfaces. Zope 3 also uses Python's doctest system for writing tests inside of prose. The tests are example code that can be executed in the Python interpreter. Functional Tests are also covered in Zope 3, which are tests that can test a whole application and its UI, whereas unittests and doctests are typically used to cover small components and code outside of their environment. The Zope X3 3.0.0 release itself contains nearly 4000 tests in unit or doctest form. It's great to see testing promoted so heavily in its documentation.
On a recent project, I was reminded (again) of how nice it is to have unit tests. I was running behind schedule and had a few simple tests written to cover some early parts of the system, and I was fast approaching the heart of the application - a complex workflow interaction. I knew that testing it by hand would be menial and terrible, because it would require so much repeat typing and multiple web browsers to be open. But since I was behind schedule and had no UI to show progress with, I kept putting off writing tests. The big turnoff was building the test harness - getting a lot of what would have been repeated manual entry into some setup code. I think that unlike most unit tests, testing workflow or any other state-sensitive system can be a bit more difficult because so much work has to be done to get the system to a particular state where you can test a transition or value. It can be daunting, and daunting items can be easy to put off until another day.
But when I got to the point where I started really having to implement this workflow system, I knew without a doubt that I would be sunk if I didn't have tests to automate the process. So I hunkered down and wrote a Python module in my tests directory called support, and filled it with classes, functions, and dummy objects that could be used in unit tests to build up the system. As I tested each piece of workflow, I could add the successful steps of those tests into the support objects so that other tests wouldn't have to duplicate the work. Getting the test harness and initial tests in place took nearly a full day of development time, but it was worth it. I didn't have anything visual to show anybody yet, but it made everything so much more dependable. And I ended up making my basic deadline anyways.
The moral of the story, which is one I have to be reminded of constantly, is that it's worth it to spend the extra time to make a supporting test harness, even if it appears to be a difficult task. Too often I fall victim to the thoughts of "I just need to get this done, I don't have time to start writing tests" and too often I find myself becoming the victim of "man, I wish I had tests for this!" later down the road when it feels like it's too late.
At the time of this writing, this is the farthest I've gotten with this experiment in Zope 3. What this file,
browser.zcml does is wire up some basic views for the Todo List and Todo items. At this point, we have not written any HTML templates or any view controllers. At this stage, we don't really need to. This is all that is needed to use automatic add and edit forms, complete with code validation. The interfaces we defined go a long way to providing these forms with their display. We also define some
containerViews for the Todo List. Since the TodoList subclasses and sub-interfaces a standard Zope 3 container implementation (think 'Folder', but much simpler. More like a dictionary), it would be nice to reuse the basic container views for the Todo List. This is how we'll get away with adding Todo items:
<configure xmlns="http://namespaces.zope.org/browser"> <!-- Allow adding of the Todo List --> <addMenuItem class="todo.TodoList" title="Todo List" description="A Todo List" permission="zope.ManageContent" /> <!-- Allow basic Zope 3 container views for the Todo List --> <containerViews for=".interfaces.ITodoList" index="zope.View" contents="zope.View" add="zope.ManageContent" /> <!-- And now add / edit forms for the Todo list --> <addform label="Add Todo" name="addtodo.html" schema="todo.interfaces.ITodo" content_factory="todo.Todo" permission="zope.ManageContent" /> <addMenuItem class="todo.Todo" title="Todo" description="A Todo Item" permission="zope.ManageContent" view="addtodo.html" /> <editform schema="todo.interfaces.ITodo" for="todo.interfaces.ITodo" label="Edit Todo" name="edit.html" permission="zope.ManageContent" menu="zmi_views" title="Edit" /> </configure>
There is more that these ZCML declarations can do - filter out specific fields from a Schema definition, wire into custom classes that override widget definitions or provide other help, or use alternate templates than the ones the system uses. This allows the add/edit functionality to be used in custom applications that don't make use of the ZMI but could otherwise benefit by what these editform and addform view controllers provide.
Screen shots of the views generated by these declarations are in the extended entry.
After the basic code and interfaces, comes the trick of wiring the content objects into Zope 3. This is done via ZCML, an extensible configuration language that defines and describes components for use in Zope 3. ZCML may appear to be verbose, and I have not always been its biggest fan, but I have learned that it is almost always better to be explicit than implicit. Zope 2 often made many implicit assumptions. For the most part, this wasn't a problem. But when it was a problem, it was usually something hard to find and debug. When found, it was usually something in the system that was doing something clever and assumptive that the developer didn't expect it to be clever and assumptive about.
So now that our interfaces and content classes are in, it's time to wire them in. Using ZCML, we can define behavior and interfaces for objects outside of code. For example, declaring IAttributeAnnotatable support allows other Zope 3 components to add annotations. Annotations include things like Dublin Core support, which lets Zope 3 track title, description, modified time, etc, without the developer needing to code in support themselves like they did (or inherited) in Zope 2. Much of the security declarations that filled in Zope 2 python based product code is moved to ZCML. Other elements of ZCML might be recognized as similar to the Python code in the Product
<configure xmlns="http://namespaces.zope.org/zope"> <interface interface=".interfaces.ITodoList" type="zope.app.content.interfaces.IContentType" /> <content class="todo.TodoList"> <implements interface="zope.app.annotation.interfaces.IAttributeAnnotatable" /> <implements interface="zope.app.container.interfaces.IContentContainer" /> <factory id="todo.TodoList" description="Todo List"/> <require permission="zope.ManageContent" interface=".interfaces.ITodoList" /> </content> <interface interface=".interfaces.ITodo" type="zope.app.content.interfaces.IContentType" /> <content class="todo.Todo"> <implements interface="zope.app.annotation.interfaces.IAttributeAnnotatable" /> <implements interface="zope.app.container.interfaces.IContentContainer" /> <factory id="todo.Todo" description="Todo"/> <require permission="zope.ManageContent" interface=".interfaces.ITodo" /> <require permission="zope.ManageContent" set_schema=".interfaces.ITodo" /> </content> <include file="browser.zcml"/> </configure>
The last line,
include file="browser.zcml", I'll get to shortly. That is where the web interface is wired in. So far in developing this little project, I've only learned and done the basic add and edit forms, which are really easy in Zope 3. This is where the interface schema items will come into play. Similar, I assume, to how Ruby On Rails has Scaffolding.
But what we've done so far is setup the Model objects and wired them into the basic Zope 3 application. Next - standard views and controllers.
A significant design choice of Zope 3 is that it's interface driven. Interfaces are used not only to document, but to adapt. Interfaces are Zope 3's type system. Unlike class based types, anything can implement them or adapt to them, and all proper code in the Zope 3 system should ask for an interface implementation for a given object.
Interface design has been taken beyond basic method definitions to include object schema and even pre / post conditions. This data can be introspected to build user interfaces, which is how much of the standard Zope 3 management interface gets built. In fact, I'll show how this is done next in the series.
So the basic todo application uses the following interfaces. These are just the basic model objects. The Todo List is just a container that only contains items that implement the ITodo interface. A Todo doesn't do much beyond store some simple data. So here they are, from the file 'interfaces.py' in the package 'todo':
from zope.interface import Interface import zope.schema # These will aid in making a special "todo" container by specifying the # constraint in the interface. from zope.app.container.constraints import ItemTypePrecondition from zope.app.container.interfaces import IContained, IContainer class ITodo(Interface): """ A todo item doesn"t need to do much... """ description = zope.schema.TextLine( title=u"To Do", required=True, ) details = zope.schema.Text( title=u"Details", required=False, ) done = zope.schema.Bool(title=u"Done") class ITodoList(IContainer): """ A todo list contains todo objects. """ def __setitem__(name, object): """ Add an ITodo object. """ __setitem__.precondition = ItemTypePrecondition(ITodo)
The implementation is even simpler. Since this is a small application, I put the implementation in
from zope.interface import implements from zope.app.container.btree import BTreeContainer from persistent import Persistent from interfaces import ITodoList, ITodo class TodoList(BTreeContainer): implements(ITodoList) class Todo(Persistent): implements(ITodo) description = u"" details = u"" done = FalseAnd that's it. Really! Now what needs to be done next is to wire these into Zope 3. But already, one can see that this is much simpler than what one might have to do to write some data objects for Zope 2.
Zope 3 is a skinnable system. It comes with a new "Zope Management Interface", but a nice thing about Zope 3 is that you can write an application that uses Zope 3 that does not use nor care for the ZMI at all. Like in Plone and the CMF, Skins are set up in layers, with the ability to override where you might want.
How to find out what skins are available: Zope 3 provides an excellent API documentation tool, readily available from the Help option in the new ZMI. From the API Documentation tool, I visited Presentations from the top navigation pane. In the bottom navigation pane was a link that said Show Skins and Layers. Clicking on that brought up a page showing all of the skins that are defined in the system, including which one is configured as the default, and the layers that makes up the skin. It also included references to where each skin and layer is defined - down to the file path and line number. On this page was listed StaticTree.
How to change the default skin: Most Zope setups these days run out of an instance home, basically a local set of files and scripts that runs the Zope app server and contains configuration for that particular running, while the bulk of the Zope system resides in a common location on the file system. Zope 3 uses this as well. In an instance home is the etc/ directory containing configuration files. One of these files that is important to customizing your Zope 3 instance is overrides.zcml. The default overrides.zcml is empty, except for a few comments, including a comment on how to set the default skin. Here's what the inner contents, sans comments, of my etc/overrides.zcml file looks like now:
<browser:defaultSkin name="StaticTree" />
After restarting the Zope 3 web server, I can now see the navigation tree in Safari.
I saw a weblog entry from Titus Brown today talking about Python and
It sounds like rewinding the clock by 5 or 10 years and building a leaner, meaner Zope with Python 2.2 would result in the similar advantages for Python: One True App Framework.
In theory, Zope 3 is just that. Without the clock going back five or ten years. Going back ten years, though, you do have just that in Bobo. The Python Object Publisher (ZPublisher in Zope 2, zope.publisher in Zope 3) is at its heart a very simple concept: publishing objects on a URL. I wrote my first Bobo application back in early 1997 and was amazed with how easy it was to take a healthy chunk of existing Python code and put it up on the web. It was much easier than Python CGI programming at the time. There was no grand framework to speak of - just a collection of tools one could mix and match as desired: Bobo for publishing, DTML (a smaller and simpler version of DTML than the one that exists now in Zope) for templating, and BoboPOS for object persistence. In a day, I converted an application that my company had been struggling with from a Java applet front end to a web front end. And half of that day was spent making pretty HTML.
Bobo did a lot of things right that were lacking in almost every other web system of the time, especially plain CGI programming. It's genius was that it was an ORB - an Object Request Broker - that translated HTTP requests and URLs into object calls and traversal. It even included some marshalling features to automatically have values come in as integers, floats, or other value types. My memories of Python CGI programming, which I last did about ten years ago, was that almost all of my time was spent getting data in from the CGI process into the right formats and into an object call, and then back out. I got to spend very little time with my application objects. Bobo turned that around completely. And now in Rails and other application systems like the impressive Seaside and its Ruby equivalient, Wee (which I think is a much more impressive system than Rails), you're seeing similar. But Bobo and BoboPOS did a lot of this stuff back in at least 1996, if not before. And it was on these basic tools that Principia, which became Zope, was built.
So if you rewind the clock ten years, there is a good, powerful, and simple toolkit to build a new system on. Yes - Zope 2 is a complex and strange beast. So what now? Zope 3. Zope 3 right now is actually called Zope X3. It has no backwards compatibility with Zope 2 and is still more of an experimental release. What it is is a complete rewrite of Zope that attempts to deliver the basic tenets of what Bobo offered while also providing a strong application framework that provides even more services. Chief among these services is a strong concept of object adaptation. And, as I wrote up (nearly 2 years ago), aggregation and adaptation is used more than inheritence. Objects aren't expected to know everything. Helper objects can be used or written as needed.
Now, I have not really used Zope 3 very much yet myself. Day to day business work keeps me in Zope 2 land as Zope X3 3.0.0 just barely landed. So after glancing over how to make a simple todo app in Rails, I've decided to try out Zope X3 to do something similar.
First step, installation. I'm running this on my desktop iMac G5, basic Mac OS X 10.3 setup - no MySQL installed or any crap like that. And the nice thing with Zope is that you don't need an RDBMS. Installation required getting an updated Python (the Python in Mac OS X is 2.3.0, and Zope requires 2.3.4), downloading the source release, and then the basic
configure; make; make check; install routine. No further bindings needed. (Of course, Zope X3 can work with MySQL and other RDBMS's, but you don't need to). So installation went pretty smooth.
Also, for this, I'm going off of The Zope 3 Developer Book. Yes, virginia, there is documentation! So far, getting Zope 3 up and running has been pretty easy.
I just had a rather pleasant experience with Apple's iMac Support Site. I had an old CDR with a label on it that wouldn't eject. Part of the disk was bad, as one of the folders wouldn't load in the Finder and the Finder itself had to be relaunched to regain control. I ejected the disk and the system unmounted it, but it did not come out of the drive (nor seemed to make any effort to do so). So I visited Apple's iMac support site and opened up the iMac G5 Troubleshooting Assistant. On the starting page of options was "My CD or DVD drive isn't working properly." On the second page was "My disc won't eject." I clicked on that and it walked me through the basics of ejecting a disc (using the Eject key on the keyboard, ejecting from the Finder) with clear pictures of keyboard keys and on-screen visuals to use and look for. But (as I expected) this didn't do the trick, as the system already suspected the CD as having been ejected. And for what it's worth, the Disk Utility application showed nothing for that drive either. So the next page that came up asked if I was on the computer that was having the problem or on a different machine. I told it I was on the computer in question and it brought up a new window with printable instructions for what to do next.
The instructions dealt with going into Open Firmware, the low level booting firmware used by all modern Macs. I'm unsure how daunting this experience might be to users like my parents, but the instructions were very clear. They included a picture of the Mac keyboard with the special boot keys highlighted (command-option-O-F) and instructions on what will be seen. The commands to type in are fairly simple,
eject cd and then
mac-boot. I tried
eject cd and sure enough, the CDR in question ejected quickly and smoothly. For some quick foolish fun, I poked around Open Firmware briefly, ultimately finding the
words command which shows all of the words defined to control Open Firmware. Then I typed
mac-boot and the startup process resumed as normal.
Overall, it was a very smooth process with no wasted clicks trying to find answers to my question. And if I couldn't find answers, the troubleshooting assistant maintained a "Chat with Apple Support" button at the bottom of the window, and the printable instructions had the URL back to the iMac support site if the open firmware option didn't work.
With the iMac G5, Apple seems to be making strides towards user serviceable machines that still fit their stylistic guidelines for consumer machines, at least, with their high end consumer machines. While the iMac G5 is pretty easy to open up and add RAM to, apparently the new stripped-down Mac mini is not. This makes some sense, as with its price the Mac mini is more of a disposable and replaceable machine if it develops too many problems in its life. Keep the display, buy a new cute and tiny CPU. With the all in ones, there's an expectation for them to last longer, at least in my experience. My iMac DV (G3/400) served me fine for many years, but one of the reasons I held on to it was that I knew that upgrading meant replacing the whole system and I wanted that upgrade to be worth it, and that came true with the iMac G5. With all of the things that can potentially go wrong with a computer, especially an all-in-one unit, over its lifetime, it makes sense for Apple to make the architecture easier for end users to support. It's not the DIY build-your-own-box that many geeks seem to prefer, but it's better than the more rigid architectures demanded by the styling of the iMac G3 and G4 systems (although Apple did a nice job with the iMac G3 DV (slot loading optical drive) systems, making the RAM and Airport card slots fairly accessible).
How this works out in the long run has yet to be seen. But there is a different feel coming from Apple these days. Maybe it's the new strength of the brand, courtesy of the iPod, iTunes, the iBook, and the iMac G5. Maybe it's the communication Apple is getting directly with customers through their successful retail operations. Maybe it's the growing media attention with lines like "hey, I can browse the web on this machine too, and not have to deal with all the viruses currently affecting the Windows world, and it's pretty darn easy to use and good looking too," that's bringing more "switchers" in. Maybe it's that The New Apple (second coming of Steve Jobs Apple) has been around long enough with enough successes and failures (iMac versus Cube) to know what works and what doesn't. Maybe it's just a new sense of pride (part of the strength of the brand) that comes from all of the above. Whatever it is, there is a rather positive feel. Or maybe I'm just feeling a buzz from my pleasant little "oops, how do I get a busted CD out?" support experience. In any case, I'm even happier with this machine and company that I've been a fan of so long. It's experiences like this that enhance brand loyalty, even more than the sexiness of the hardware/software.
Compare and Contrast: Rathergate vs. WMD. A fun filled table comparing the story of nothing and the story of true merit. This is especially fun because now the search for Saddam's Weapons of Mass Destruction has officially ended.
WASHINGTON - The White House acknowledged Wednesday that its hunt for Iraqi weapons of mass destruction — a two-year search costing millions of dollars — has closed down without finding the stockpiles that President Bush cited as a justification for overthrowing Saddam Hussein.So again: the United States rushes to war with one of its main claims based on bad information from questionable sources, and CBS rushes to air with a story about the president based on information from questionable sources. Now - one of these stories told (each based on bad document and sources) has proven to be completely false. And it's not the one that's led to the deaths of over a thousand American servicemen and tens of thousands of innocent Iraqi civilians.
So when do the fired CBS employees get their Presidential Medals of Honor?
Of course it's wonderful to see the human race rallying to the aid of [Asian tsunami] disaster victims, but it's the inconsistency that has me foxed. Nobody is making this sort of fuss about all the people killed in Iraq, and yet it's a human catastrophe of comparable dimensions. (Read more...)
There are a lot of great quotes, notes, and lines in this article. I'm not going to quote them all, as much as I would like to. Iraqi lives are being aggressively and negatively affected by the war in Iraq, whether by insurgents or "coalition" forces. Wars are ruining lives all over the world (especially in Africa), yet they go ignored (especially if they're in Africa) by most of the world. And while it is great to see so much rallying to the aid of natural disaster victims, the treatment of man's worst disaster on man (war) is touched on ever so briefly, and always downplayed in the media. But hey - Jennifer Aniston and Brad Pitt broke up! Where should I go to send Brad some support money and Jen some support cuddling?
Of course, Terry Jones is an actor, director, and member of Monty Python. And British. Being an actor, and a foreign one at that, he should just stay out of politics like all people in Hollywood. Unless those people are Arnold Schwarzenegger, Ronald Reagan, etc.
The funny (and of course overlooked by the cranial-rectal inversion crowd) thing about the CBS/document story is that contrary to the screeching about it, the entire saga is proof that there is no goddamn liberal media. (Read More...)
Excellent post from Atrios concerning the amount of real bullshit that goes on in the media today and in recent years and the comparative actions. From Jayson Blair and Stephen Glass to all of the crap that was Whitewater-era trash journalism. I do not understand how this country keeps itself so easily involved with every little fake crisis that the media or this current administration can come up with while ignoring real issues, or quietly forgetting similar situations that don't shine favorably on The Right.
A boob gets exposed during half time at the Superbowl last year, and we get "nipplegate." CBS rushes a story with cooked documents from questionable sources and we get "Rathergate." George Tenet and the CIA aid a spurious war in Iraq by rushing cooked documents from questionable sources, thousands die, and Tenet gets a presidential medal of freedom and Bush gets re-elected. And where's the *gate on this talk show host that turned himself into a paid advertisement for Bush's No Child Left Behind act? Or is that one going to quietly disappear while this whole Dan Rather thing goes on for eight months, or however long it takes until the Robert Blake murder trial kicks into high gear so we can talk about that non-stop?