Thanks to funding provided by the Friends of the Vancouver City Archives, we have been able to describe and digitize over one thousand of James Crookall’s images and make them available online.
James Crookall was born November 7, 1887 in Preston, Lancashire, and came to Vancouver as a child. Throughout his life, Crookall was an avid amateur photographer and an enthusiastic outdoorsman. He was an active member of the Vancouver Photographic Society and regularly exhibited his photographs in international salons. He died on July 27, 1960, and his fonds was donated to the Archives by Mrs. Doris Crookall in 1979.
As a young man, Crookall joined the Union Steamship Company of B.C. He served first as a Steward, then as a Clerk and was made Secretary in 1912. His photographs reflect an interest in maritime traffic and activities.
Captain Browne and Williams aboard S.S. Camosun, ~1918. Reference code AM640-: CVA 260-1090.
Man on ship’s gangplank, 1939. Reference code AM640-: CVA 260-1031
In 1907, he joined the 6th Regiment, the Duke of Connaught’s Own Rifles, probably in the reserve unit, as he was still working for the Union Steamship Company. We have been told that he knew Major Matthews, the first City Archivist, and it’s possible he met him as a fellow member of the D.C.O.R.
During World War I, he served for two years with the Royal Flying Corps. Over his lifetime, he took many photographs of both military and civil aircraft at airshows.
Pilot of Aero Club of B.C. biplane (CF-ANN), ~1930. Reference code AM640-: CVA 260-359.
Stunt man with wings, 1937. Reference code AM640-: CVA 260-713.
After the war he resumed his career with Union Steamships. Crookall became Secretary Comptroller and was appointed Secretary-Treasurer in 1949. He retired in 1958 only a few months before Union Steamships ceased operations in 1959.
In addition to photography, Crookall had many recreational interests. He was an avid painter and a keen outdoorsman, regularly cycling or hiking many miles in search of subjects for his easel or his cameras. He was involved with a local group of amateur photographers called the “cycling circus”, which formed during the gas-rationing years of World War II and organized photographic trips by bicycle.
His photographs show an appreciation of geometry, light and shadow.
Architectural details of St. James Church, ca 1936. Reference code AM640-: CVA 260-430.
A metal staircase attached to a tank, 1938. Reference code AM640-: CVA 260-979.
His works also show a keen interest in people at work and play.
Woman at drinking fountain at the beach, 1937. Reference code AM640-: CVA 260-670.
Crookall used a variety of cameras and photographic media. He used glass plate negatives, nitrate film pack negatives and roll film in several formats including 35mm. He tried an unusual and early colour process called Dufaycolor, which was first used for motion pictures in 1932 and then for still photography from the mid-1930s. In this process, the film base was dyed with a fine pattern of red, green and blue lines which acted as filters. The result is a transparent positive image.
Rock Garden of Stanley Park, ~1930s. Reference code AM640-: CVA 260-1803.
Crochet is an MIT-licensed library that makes it easier for threaded applications like Flask or Django to use the Twisted networking framework. Features include:
Runs Twisted's reactor in a thread it manages.
Hooks up Twisted's log system to the Python standard library loggingframework. Unlike Twisted's built-in logging bridge, this includes support for blocking logging.Handler instances.
Provides a blocking API to eventual results (i.e. Deferred instances).
This release includes better documentation and API improvements, as well as better error reporting.
You can see some examples, read the documentation, and download the package at:
For those of you who have seen Crochet before, I'd like to feature a new example. In the following code you can see how Twisted and Crochet allow you download information in the background every few seconds and then cache it, so that the request handler for your web application is not slowed down retrieving the information:
""" An example of scheduling time-based events in the background.
Download the latest EUR/USD exchange rate from Yahoo every 30 seconds in the background; the rendered Flask web page can use the latest value without having to do the request itself.
Note this is example is for demonstration purposes only, and is not actually used in the real world. You should not do this in a real application without reading Yahoo's terms-of-service and following them. """
from flask import Flask
from twisted.internet.task import LoopingCall from twisted.web.client import getPage from twisted.python import log
from crochet import run_in_reactor, setup setup()
class ExchangeRate(object): """ Download an exchange rate from Yahoo Finance using Twisted. """
def __init__(self, name): self._value = None self._name = name
May be None if no value is available. """ return self._value
@run_in_reactor def start(self): """ Start the background process. """ self._lc = LoopingCall(self._download) # Run immediately, and then every 30 seconds: self._lc.start(30, now=True)
def _download(self): """ Do an actual download, runs in Twisted thread. """ print "Downloading!" def parse(result): print("Got %r back from Yahoo." % (result,)) values = result.strip().split(",") self._value = float(values[1]) d = getPage( "http://download.finance.yahoo.com/d/quotes.csv?e=.csv&f=c4l1&s=%s=X" % (self._name,)) d.addCallback(parse) d.addErrback(log.err) return d
This is a short and unsorted collection of personal wisdoms that may help you improving your day and life as a software developer, freelancer, project manager or whatever.
You first, projects second
The first think that counts is you . You and your personal health should have the highest priority. Don't ruin yourself for whatever reason. Your health is your capital.
Don't be reachable at any time
Whatever position you have in a project: you don't have to be reachable at any time for any person. Give your working day a structure. Consider fixed working hours that you do not exceed.
Avoid overtime
Overtime is a bad thing. Yes, things must be done at some point but constant overtime is bad for your health and mood - unless you are a coding maniac.
Don't be a slave of your email client
Reduce to poll time of your email client to one hour or so - being interrupted while programming is a bad thing.
Delay email replies
There are email client add-ons like SendItlater that allow you to answer to an email directly but defer the delivery to a some time in the future. This may slow down email ping-pong between and your customers significantly.
Have separate email clients
For some projects (with lots of email during the day and night) I use a dedicated email client that I can close at any time. I use my standard email client to keep track of my private email and other project email (where I know that there will be only a few mails per day without a big risk of trouble)
Do not respond to all email the same day
If there is some email coming in the late afternoon and you can already smell the trouble by reading the sender or the subject: keep it closed and read it the other day. Do not ruin your last working hour and the rest of the day with trouble emails.
Smell the stress
It takes some experiences to notice when the project stress turns against you. Stress can have various symptoms and they are very individual. Personally I notice upcoming stress situation through problems with my stomach.
Get out of the stress
This is often easier said than doable in reality. But if often helps taking a break for an hour or two and doing sports. First it reduces my aggression level and gives me a more clear thought on some pending problems. Or if you can: take a day off and do something completely different.
Know your limits
Know yourself! You have to know where your personal limits are and how far you can go. While we are all getting older we have to recognize that we can not handle a workload as when we were ten years younger. It does not mean that we are less efficient and effective but we deal with workloads in a different way.
It is you that counts, it is your health that counts. So in order to avoid a burnout: you first, projects and customers second....
Test data generation is always a hot topic when it comes to automated software
testing. One of my first assignments at
4teamwork was to help with the testing. In
the process I was browsing through the test suites of some big projects they are
working on and noticed a lot of similar code related to data creation:
This is very basic object creation code and I’m sure many Plone developers have
written a fair amount of it. While this gets the job done, there is a lot of
noise, that we don’t need to have in every test.
I decided to use a basic implementation of the
Builder Pattern to hide the
noise in specific Builder classes and make our tests shorter and more
expressive at the same time:
Already a big step forward! We have only defined two Builder classes, and we
already notice some duplication among them. Defining a base class gives us a place
to store the shared behavior:
Finally we hide the different Builder implementations and their instantiation
behind a function. This allows us to change the Builders without touching all
the tests that use them:
1234567
defBuilder(name):ifname=="dossier":returnDossierBuilder()elifname=="document":returnDocumentBuilder()else:raiseValueError("No Builder for %s"%name)
And the final code inside the test-cases looks like:
So here's a question for people who remember coming up from beginner: as
you moved from exercises like those in Learn Python the Hard Way, up to
your own self-guided work on small projects, what project were you
working on that made you feel independent and skilled? What program
first felt like your own work rather than an exercise the teacher had
assigned?
I don't want anything too large, but big enough that there's room for
design, and multiple approaches, etc.
If you came to Python from another programming language, then what was
the project that first made you feel competent at programming in
general?
GNU Mailman 3 (the long-awaited revamp of the widely-used, widely-despised
GNU Mailman 2) is on the way, and
Fedora's Aurélien Bompard has been working
on a new frontend for it (here's a before and after screencast showing some of
it off).
I set out to write a fedmsg plugin for mm3 so we
can add it to cool visualizations,
gather more data on non-development contributions to Fedora (which is always
hard to quantify), and to support future fedmsg use cases we haven't yet
thought of.
I searched for documentation, but didn't find anything directly on how to
write plugins. I found Barry's chapter in AOSA to be a really helpful guide
before diving into the mailman3 source itself. This blog post is meant to
relay my findings: two (of many) different ways to write plugins for
mailman3.
Adding a new Handler to the Pipeline
At the end of the day, all we want to do is publish a ØMQ message on a zmq.PUB socket for every
mail that makes its way through mailman.
I learned that at its core mailman is composed of two sequential
processing steps. First, a chain of rules that make moderation
decisions about a message (should it be posted to the list? rejected?
discarded?). Second, a pipeline of handlers that perform manipulation
operations on a message (should special text be added to the end? headers?
should it be archived? added to the digest?).
I came up with this template while trying to figure out how to add another
handler to that second pipeline. It works! (but its not the approach we
ended up using. read further!):
""" An example template for setting up a custom pipeline for Mailman 3.Message processing in mailman 3 is split into two phases, "moderation"and "modification". This pipeline is for the second phase whichwill only be invoked *after* a message has been cleared for delivery.In order to have this module imported and setup by mailman, our ``initialize``function needs to be called. This can be accomplished with the mailman 3``post_hook`` in the config file:: [mailman] post_hook: mm3_custom_handler_template.initializeAfter our ``initialize`` function has been called, the'custom-posting-pipeline' should be available internally to mailman.In mailman 3, each mailing list can have its *own* pipeline; preciselywhich pipeline gets used at runtime is configured in the database --through postorious.:Author: Ralph Bean <rbean@redhat.com>"""from__future__importabsolute_import,print_function,unicode_literalsimportloggingfromzope.interfaceimportimplementerfromzope.interface.verifyimportverifyObjectfrommailman.configimportconfigfrommailman.core.i18nimport_frommailman.core.pipelinesimportPostingPipelinefrommailman.interfaces.handlerimportIHandler__all__=['CustomHandler','CustomPostingPipeline','initialize',]elog=logging.getLogger("mailman.error")@implementer(IHandler)classCustomHandler:""" Do something.. anything with the message. """name='my-custom-handler'description=_('Do something.. anything with the message.')defprocess(self,mlist,msg,msgdata):""" See `IHandler` """elog.error("CUSTOM HANDLER: %r%r%r"%(mlist,msg,msgdata))classCustomPostingPipeline(PostingPipeline):""" A custom posting pipeline that adds our custom handler """name='my-custom-posting-pipeline'description=_('My custom posting pipeline')_default_handlers=PostingPipeline._default_handlers+('my-custom-handler',)definitialize():""" Initialize our custom objects. This should be called as the `config.mailman.post_hook` callable during the third phase of initialization, *after* the other default pipelines have been set up. """# Initialize our handler and make it availablehandler=CustomHandler()verifyObject(IHandler,handler)asserthandler.namenotinconfig.handlers,('Duplicate handler "{0}" found in {1}'.format(handler.name,CustomHandler))config.handlers[handler.name]=handler# Initialize our pipeline and make it availablepipeline=CustomPostingPipeline()config.pipelines[pipeline.name]=pipeline
The above approach works, but it involves a lot of hacking to get mailman
to load our code into the pipeline. We have to occupy the mailman
post_hook and then kind-of hot-patch our pipeline into the list of
existing pipelines.
A benefit of this approach is that we could use postorious
(the DB) to control which mailing lists included our plugin and which
didn't. The site administrator can leave some decisions up to the list
administrators.
I ended up abandoning the above approach and instead landed on...
Adding a second Archiver
One of the Handlers in the default pipeline is the to-archive Handler.
It has a somewhat nicer API for defining multiple destinations for archival.
One of those is typically HyperKitty (or... kittystore)... but you can
add as many as you like.
I wrote this "archiver" (and threw it up on
github,
pypi, and
fedora).
Barring tweaks and modifications, I think its the approach we'll end
up using down the road:
""" Publish notifications about mails to the fedmsg bus.Enable this by adding the following to your mailman.cfg file:: [archiver.fedmsg] # The class implementing the IArchiver interface. class: mailman3_fedmsg_plugin.Archiver enable: yesYou can exclude certain lists from fedmsg publication byadding them to a 'mailman.excluded_lists' list in /etc/fedmsg.d/:: config = { 'mailman.excluded_lists': ['bugzilla', 'commits'], }"""fromzope.interfaceimportimplementsfrommailman.interfaces.archiverimportIArchiverimportsocketimportfedmsgimportfedmsg.configclassArchiver(object):""" A mailman 3 archiver that forwards messages to the fedmsg bus. """implements(IArchiver)name="fedmsg"# This is a list of the headers we're interested in publishing.keys=["archived-at","delivered-to","from","cc","to","in-reply-to","message-id","subject","x-message-id-hash","references","x-mailman-rule-hits","x-mailman-rule-misses",]def__init__(self):""" Just initialize fedmsg. """hostname=socket.gethostname()ifnotgetattr(getattr(fedmsg,'__local',None),'__context',None):fedmsg.init(name="mailman.%s"%hostname)self.config=fedmsg.config.load_config()defarchive_message(self,mlist,msg):"""Send the message to the "archiver". In our case, we just publish it to the fedmsg bus. :param mlist: The IMailingList object. :param msg: The message object. """ifmlist.list_nameinself.config.get('mailman.excluded_lists',[]):returnformat=lambdavalue:valueandunicode(value)msg_metadata=dict([(k,format(msg.get(k)))forkinself.keys])lst_metadata=dict(list_name=mlist.list_name)fedmsg.publish(topic='receive',modname='mailman',msg=dict(msg=msg_metadata,mlist=lst_metadata))deflist_url(self,mlist):""" This doesn't make sense for fedmsg. But we must implement for IArchiver. """returnNonedefpermalink(self,mlist,msg):""" This doesn't make sense for fedmsg. But we must implement for IArchiver. """returnNone
The concepts are so overloaded, so often misused, mistrusted and misunderstood that I feel such introductions are needed indeed.
Feel free to comment it here or there if you’d like to add something to the matter though please note that it’s an intro only and it purposefully leaves out advanced stuff, some of which is listed at the end.
“ITERATION isn’t just for visual design. It also helps you uncover insights. A List Apart found people are often commenting and re-tweeting articles before they read them. They learned this by iterating on where the share and comment links exist on the page.”—LukeW | An Event Apart: 10 Commandments of Web Design.
Skeu It! – and perhaps here is the reason why people went flat with their design styles. :) It’s a parody tumblr collection of some weird looking interfaces with coffee switches, jean pockets and lots of wooden clipboards. The site is now closed off, but definitely proved a point of how ridiculous (or skewed) a UI can get when pushed to the other extreme.
I haven’t written anything on Python here in a good while. But that doesn’t mean I haven’t been busy wrestling with it. I’ll need to take a look at my Perforce changelists over the last months and take stock. In the meantime, I’d like to rant a bit about a most curious peculiarity of Python […]
I have done some improvements in the plugins: python_console_ipython, python_autocomplete, python_utils, js_utils, xml_pretty and django_utils. These plugins I added a month and a half ago (except python_console_ipython) to the kate repository. I have done two improvements and a new feature:
Now they work with Python2 and Python3 (except python_autocomplete, this only works with Python2, due pysmell dependence)
Now they have a configuration page (except python_autocomplete, this should not have configuration parameters)
Page Config Plugins
The new feature is the integration of the python_autocomplete and python_console_ipython plugins with the project plugin. The behaviour of these plugins depends of the loaded project. That is to say, the python_autocomplete plugin autocompletes with our project modules. Currently the kate community is working to add a new python autocomplete using jedi (this will work with Python2 and Python3).
Python Autocomplete (with our modules)
And the python_console_ipython plugin has something that we can name the project console. A ipython shell with the python path of our project and with the environments variables that the project plugin needs.
IPython Console (converted in a django shell)
To use this we need to add in the project file (.kateproject) a new attribute named “python”, with this structure:
I am a django developer, as we say in Django we can come to have a django shell (python manage.py shell) integrated in our editor. But this feature is a generic feature not tied to Django. This feature can be used by other Python developers. I have added only a specific feature to the django developers. If we set in the project file (.kateproject) the attribute projectType with the value Django, the ipython shell automatically loads the models and the settings like a shell_plus does.
or Complete coverage testing or More is Better testing Update 5/22/13: I’ve received several criticisms of this post. Most of them constructive. :) I’d like to take some time to re-read the post, re-read the feedback, and compose a more coherent statement about my thoughts on the matter. I agree with some points of my [...]
Two days, two conferences. The first was a local, business oriented one, Kasvu Open Forum. The second, Djangocon Finland 2012, focused mainly on technology. I gave two talks in the latter one. It was very nice to experience both events and meet some new people and a few old acquaintances.
Kasvu Open Forum
Kasvu Open is a competition of sorts aimed for Finnish growth ventures. This is the second year they are organizing it so things are just about to get rolling. They have two series, one for ideas and one for established companies. Me and my business partner participated in the former one this year with an entry.
We didn't make it to the finals and weren't impressed by the quality of the feedback given. This event totally made up for it. This is definitely something they can improve on the next year. The last thing you want to do is to discourage some potential idea or company. After all Kasvu Open is in the business of creating new business.
You might expect business conferences such as this to be really boring. This wasn't the case here. Each talk given gave some unique view to growth venturing. For instance it was particularly interesting to see how different the mindsets of a venture capitalist and a business angel can be. Former focuses on profit while the latter thinks in more long term and uses a different kind of investment strategy.
I also enjoyed the talk of Jouni Hynynen. He represented The Foundation of Finnish Inventions and explained how immaterial rights relate to business and what is their worth in practice. Even though I'm somewhat categorically opposed to concepts such as software patents, the talk gave some nice insight to the subject.
Overall it seems like there is some positive buzz going on in the Jyväskylä area. It might not be the Silicon Valley and we might be missing the scale benefits. I wouldn't be surprised if something really interesting emerged from the area within the next decades.
Djangocon Finland 2012
This was the first time I visited the Finnish version of Djangocon. I think there were around forty people or so participating the event. The talks were primarily technically oriented. There were a couple of longer talks and several lightning talks.
I actually met a reader of this blog (apparently there are those) at the conference. That was quite a pleasant surprise to be honest. It's small things such as this that make it all worth it.
Thoughts on "Kaleva.fi - how we replaced 10 years of legacy code in one year"
It was particularly interesting to see what Kaleva.fi looks like from "outside" in terms of DevOps. I participated in the project as a software designer during the past year for a period of a few months. So I got to know certain bits of it quite well. I never really looked into the overall infrastructure (too busy staring at my code :) ), though.
There were many interesting tidbits in Markus' talk. Especially the bits on scaling the service were interesting. It's quite different to develop a service used by hundreds of thousands than something that has only a few users. You get a lot of new problems to solve.
Thoughts on other talks
There was this one guy that made Django act like PHP. Django Home Pages is a terrible abomination that simply should not exist. I guess that was kind of the point, though. He created it just in order to see if it can be done.
Leo Honkanen discussed about classy Django applications. I think the main gist here was that with some effort you can provide namespaced url lookups for your templates. Essentially you have to deal with routing using a proxy class that implements urls using a property. The proxy class contains the name of the namespace as a class level attribute. I believe it is possible to implement this as a class method so you can avoid instantiating the whole thing at your url definition.
I'm not entirely sure if one should abuse classes this way. There might be a neater functional solution around to be found. If I ever need to namespace my urls somehow, I'll keep this in mind.
There were a couple of lightning talks as well. The BDD one was semi-interesting. I couldn't see myself writing that amount of code anytime soon, though. There must be some nicer way to describe stories.
bongaus.fi - Spotting Service Powered by Django
My first talk had to do with a service me and my business partner developed during the Spring. We did the development of bongaus.fi in a few distinct phases. The idea of the talk was to give some insight how we created the service and what kind of lessons we learned while doing it. I hope the people got something out of it! You can examine the slides below (probably not visible in RSS):
If there is something you should pick out from the talk I believe it is the importance of developing a Minimum Viable Product (MVP). The only way to know if your product is on the right track is to give it for your users to test. Developing a MVP is an effective way to do this. Besides, it is really fast to get one done since you don't need to get stuck on the details.
In development of bongaus.fi we noticed Pareto principle applies quite well here. It takes only perhaps 20% or so time to get the relevant bits done. The rest is just tweaking and dealing the corner cases. And boy that sure can take time.
Another important thing to pick out is the value of pivots. Even if you are doing something and going to a certain direction, doesn't mean you should be going there indefinitely. It can pay off to adjust the trajectory and try something perhaps a bit different. I believe the willingness to pivot is one of the key attributes of startups that become successful.
Speccer
My second, really brief talk, had to do with Speccer. It is a small testing tool I developed ages ago to make using unittest bearable. To quote myself "unittest provides testing for masochists while Speccer is meant for the rest of us". I hope the slides below give you the gist of it:
Essentially the tool just transforms the light Pythonish syntax (you can mix Python with it) to code using unittest. This means you get to enjoy from the benefits of the both. You get the robust output provided by unittest's test runner while get to use a lighter syntax.
Conclusion
At times I feel like I'm slowly drifting away from a pure development role and more into business. These kind of conferences seem to confirm this. It takes a lot more than just technical skill to make things work in a real world.
Overall it seems like a good idea to be active. You get a lot of new contacts that in turn might prove to be valuable longer term (applies both ways). In addition these sort of events give you a nice extra burst of motivation and helps you to validate some of the work you have done. Sometimes it is a good idea to step out of your role a bit and try something different (ie. a business conf :) ).
In his presentation at An Event Apart in San Diego 2013 Scott Jehl outlined a number of ways to build responsive Web sites that take performance in account. Here's my notes from his talk: Responsive and Responsible.
We need to build Web products to be universally accessible. This includes a lot more than just people with disabilities – it includes slow network connections, less capable devices, and more.
Defensive design and progressive enhancement are a safety net against Murphy's Law. We can't think and code in absolutes.
Responsive design is just part of building a responsible design. We need to consider a number of factors beyond the layout: performance, behavior, accessibility, and costs.
Most of poor performance is our fault: the average page in 2013 weighs 1.4MB. The average load time of a top 2000 site is 6 to 10 seconds.
Good performance is good design. Fast loading Websites make people happy.
Webpagetest.org and Web Inspectors in the browser provide a way for you to measure performance and see what's slowing pages down.
86% of responsive designs send the same assets to all devices.
Content Parity, Optimized Experience
We want to deliver content based on our user’s needs. Only a few years ago we were locked into normalizing things across a number of browsers. Today the diversity of devices makes this idea seem ridiculous. Instead we want to optimize for different devices.
Content parity does not mean every experience is identical. Every browser that comes to our Web site is unique. We need to code in a way that doesn’t presume too much about: viewport size, orientation, font size, settings, preferences, and input modes.
Being responsive from a layout perspective doesn’t preclude being responsive form a performance perspective.
Using em-based breakpoints in your media queries means you are not dependent on device sizes and allow users to adjust font size without breaking layout.
Delivering Content
To load content from a Website, a client makes a request, DNS sends it to the right host, and the host replies with the requested assets. The DNS server finds the right IP address to serve, then goes to a host to get content.
On mobile devices, we go to a cell tower first, then to a DNS, then a host to get content. The connection to the tower takes two seconds and is totally out of our hands. That delay is unique to mobile and only happens once. Then we can send files back and forth after the initial connection is made.
From there we load HTML and any referenced files when all blocking files (that impact rendering) have been received. Be careful of what you include in blocking requests.
After 8 seconds, the carrier will cut off a connection so we want to load as much as possible when that initial connection is open.
Every http request we make is a bit of a gamble -it can fail. So we don’t want to gamble too much with many requests -especially if they are blocking.
Delivering HTML
Tiered delivery: if a piece of content is already accessible somewhere else (through a link on the page), you might consider loading it lazily.
For example: home pages are navigation tools. They mostly include links to other parts of the site.These kinds of pages are prime for deferred loading.
In the initial load, we could just include the critical links in the source then use Javascript to load additional content (like samples of what’s behind that link) after the initial page downloads.
We can enhance the content itself using a technique called Ajax-include. We start with a simple URL and add a data attribute that references an HTML fragment to the link’s mark-up. When Javascript is executed, the link will be replaced with a full set of content using Ajax.
To do this, consider using a data attribute on a link like “data-after”.
You could take this deferred loading further and only show the additional content if a certain media query condition is met.
Delivering CSS
CSS is a blocking element: browsers wait until it is all loaded before displaying a page. This prevents un-styled content from showing up.
Mobile-first media queries: start with CSS that is wide open. Assume no media queries are present. Then adjust using min-width media queries.
Mobile-first media queries deliver a broadly usable default. These initial styles go to all browsers but it sometimes you might want to use a "@media only all" qualifier to target all browsers that support media queries. This is a good way to qualify more advanced styles.
Start with simple design and typography in the basic experience, then enhance upward.
Enhancement qualifiers broaden access and help to simplify QA processes.
But with this approach, we are sending all our CSS files to all browsers even if they’ll never use them.
Every browser downloads every CSS asset today –whether it needs it or not. While we want style sheets to be there when we need them, we don’t necessarily want them to be blocking page rendering.
Webkit does a little better, it loads media queries that apply and renders those on screen and does not block on CSS that is not currently applicable. However it still downloads all CSS files regardless of whether they can be used on the device or not.
The best approach for CSS is still to combine all your CSS in one file. But minify and gzip it. CSS compresses well. GZIP finds repeating segments and reduces CSS file size substantially.
Delivering Images
Images are 66% of file size on Web pages.
Images don’t block page rendering but they can negatively impact page size and data plans.
Background images can be managed with media query cascades to only be loaded when needed. Foreground images are another story.
Compressive images: the quality of a jpg influences its files size more than its pixel dimensions.
Scaling an image doesn't solve all the use cases you might want. Like the art-direction use case.
Responsive images: two proposals have made their way into the standards process: picture and srcset.
The picture element works like the video element in HTML. It has a number of media query-qualified images to load based on what each browser can support and a standard image for fallback when none of those attributes are true.
Srcset is an attribute that you add to an image element. Its very good at managing pixel densities through attributes like 2x, 3x. The browser has the last say on which image to load.
Picturefill is a Javascript polyfill that brings similar support to a DIV-based solution. This prevents pre-fetching images that are not needed.
Should we load retina images for devices that can use them or should we give people a choice of what kind of image they want? After all, serving retina images by default really increases download size.
The picturefill solution can be used to load a standard definition image by default and then give people the option to load a high-resolution image if they choose on their retina device.
Managing images for all the different resolutions is getting harder and harder. Instead of using raster images for icons and background, we could use vector art using SVG.
SVG is text it compresses very well because it is just mark-up. Referencing SVG inline is relatively easy. Browsers that support SVG load it easily but those that don’t can be supported with an onerror attribute to load a fallback image.
You can also specify images as background images or as data URLs that don't require an additional http request.
Grunticon is a tool that listens to a directory of SVG files, updates a CSS file that encodes all those files as data URIs as CSS classes, which can then be concatenated with other CSS files.
Delivering Javascript
Javascript is the second largest part of our pages and it blocks page rendering until loaded.
Start by loading the smallest amount of Javascript you can. Use it to determine what to load next. Initial Javascript: load feature tests, essential polyfills, asset loader, and a script loader.
Yepnope is a very lightweight loader that allows you to determine when to serve Javascript.
If a device is qualified, you can add the Javascript you’ll need everywhere and specific files based on what each device can use. How to determine what Javascript to load: broad qualification, browser features, device/environmental conditions, or template types.
You can load some CSS with Javascript as long as it is not required for default presentation. Additional fonts or background images are good candidates for Javascript loaded CSS.
Third party widgets (to embed on your site) should be loaded asynchronously. But support for async is not perfect as it is only supported in Internet Explorer 10+
Surefire DOM element insertion by Paul Irish is a great article about loading Javascript effectively.
Defend the critical path to loading key content for your pages.
We have the tools to create rich experience without excluding people. But we need to work responsibly to do so.
In his presentation at An Event Apart in San Diego 2013 Jeffrey Zeldman walked through today's web design principles and how they can make our sites better. Here's my notes from his talk: Ten Commandments of Modern Web Design.
Thou Shall Entertain.
We spend lots of time thinking about efficiency and usability but we also need to think about being delightful and entertaining people.
Set a conversational tone with your body copy.
Headlines and visuals play together. Consider how images can add life and clarity to your content pages.
Stock photos might not be the best answer, illustrations and icons naturally come with a unique personality. Stock photos often do not. Part of being entertaining is being different.
Error pages are an opportunity to insert personality. Try to be entertaining but be mindful of people’s mindset when an error occurs. Fun is not appropriate everywhere.
Test Everything
People are using your Web sites on lots of different devices, you need to test on these devices. There is no substitute for using real devices to test. But getting lots of devices can be expensive -so do it strategically. You don't need every device but you need to have representative devices.
Remote Preview is a tool that allows you to preview any URL on large number of mobile devices simultaneously. It's a tiny Javascript-based tool.
Don’t just test your designs and sites, also test your assumptions.
A List Apart made many decisions when redesigning. Then had lots of conversations with readers about what they chose to do. ALA didn’t include an ALT tag on author bios because they felt it was the best decision for accessibility. This goes against convention but it’s important to keep trying different things.
Test your assumptions by publishing your intent and ideas. Encourage discussion about them. Even question the fact that you test assumptions -inception!
Thou Shall Iterate
Iteration is how design happens: “I move stuff around on the page until it looks right” -Milton Glaser. A great designer is the one who keeps moving stuff, even when everyone else leaves the room.
Iteration isn’t just for visual design. It also helps you uncover insights.
A List Apart found people are often commenting and re-tweeting articles before they read them. They learned this by iterating on where the share and comment links exist on the page.
Thou Shalt Ship
Good is the enemy of great. Great is the enemy of shipping.
Not shipping can be soul-crushing. You need to get your designs and ideas into the world. It doesn't matter how good your product is if you don't get it out there.
We're never really done. When you work on the Web, its a process of constant improvement.
Consultants, raise you rates when clients don’t ship. This encourages clients to get the work you do together out and into people’s hands.
Engage Thy Community
The most important asset you have are the people who love and use what you do. Engage with them and treat them well.
Instagram lost a lot of public support when they changed their terms of service without explaining what they were doing and why to the community. Its most passionate users were upset about these changes and caused a big uproar.
Fonts.com added a custom header to their homepage that highlighted the type work of designers.
Big companies care about customers too but they often are less connected to their users than small companies.
Thou Shalt Prioritize
Make sure you are focusing on the most important things at any given time.
Force yourself to make decisions -not everything can be a priority.
If you try to make things without prioritizing, you won’t ship.
Kevin Hoffman has written a series of articles about effective kickoff meetings that highlight the importance of prioritizing work.
Additional Commandments
Love thy user as thyself: treat people well. Do things that you would like to have done to you.
Remember Content & Hold it Holy. Design from the content out instead of based on device breakpoints. Decide where your content requires a change and adapt layout there.
Make sure the content people come to read is free of distractions and front and center. Let people focus on the content.
Make magic, not perfection. Instagram’s success is likely based on how easy they made it to share photos. Many other parts of their experience were incomplete but it didn’t matter. They nailed the workflow of the most critical part of their service.
Thou shalt prioritize: we need to work with decision makers to make sure we are working on the right things.
Github issues, or similar software, can help you set priorities for the changes and features you want to make.
Great design is a product of care and attention applied to areas that matter, resulting in a useful, understandable, and hopefully beautiful user interface. But don’t be fooled into thinking that design is left only for designers.
There is a lot of design in code, and I don’t mean code that builds the user interface—I mean the design of code.
Well-designed code is much easier to maintain, optimize, and extend, making for more efficient developers. That means more focus and energy can be spent on building great things, which makes everyone happy—users, developers, and stakeholders.
There are three high-level, language-agnostic aspects to code design that are particularly important.
System architecture—The basic layout of the codebase. Rules that govern how various components, such as models, views, and controllers, interact with each other.
Maintainability—How well can the code be improved and extended?
Reusability—How reusable are the application’s components? How easily can each implementation of a component be customized?
In looser languages, specifically JavaScript, it takes a bit of discipline to write well-designed code. The JavaScript environment is so forgiving that it’s easy to throw bits and pieces everywhere and still have things work. Establishing system architecture early (and sticking to it!) provides constraints to your codebase, ensuring consistency throughout.
One approach I’m fond of consists of a tried-and-true software design pattern, the module pattern, whose extensible structure lends itself to a solid system architecture and a maintainable codebase. I like building modules within a jQuery plugin, which makes for beautiful reusability, provides robust options, and exposes a well-crafted API.
Below, I’ll walk through how to craft your code into well-organized components that can be reused in projects to come.
The module pattern
There are a lot of design patterns out there, and equally as many resources on them. Addy Osmani wrote an amazing (free!) book on design patterns in JavaScript, which I highly recommend to developers of all levels.
The module pattern is a simple structural foundation that can help keep your code clean and organized. A “module” is just a standard object literal containing methods and properties, and that simplicity is the best thing about this pattern: even someone unfamiliar with traditional software design patterns would be able to look at the code and instantly understand how it works.
In applications that use this pattern, each component gets its own distinct module. For example, to build autocomplete functionality, you’d create a module for the textfield and a module for the results list. These two modules would work together, but the textfield code wouldn’t touch the results list code, and vice versa.
That decoupling of components is why the module pattern is great for building solid system architecture. Relationships within the application are well-defined; anything related to the textfield is managed by the textfield module, not strewn throughout the codebase—resulting in clear code.
Another benefit of module-based organization is that it is inherently maintainable. Modules can be improved and optimized independently without affecting any other part of the application.
I used the module pattern for the basic structure of jPanelMenu, the jQuery plugin I built for off-canvas menu systems. I’ll use that as an example to illustrate the process of building a module.
Building a module
To begin, I define three methods and a property that are used to manage the interactions of the menu system.
The idea is to break down code into the smallest, most reusable bits possible. I could have written just one toggleMenu( ) method, but creating distinct openMenu( ) and closeMenu( ) methods provides more control and reusability within the module.
Notice that calls to module methods and properties from within the module itself (such as the calls to setMenuStyle( )) are prefixed with the this keyword—that’s how modules access their own members.
That’s the basic structure of a module. You can continue to add methods and properties as needed, but it doesn’t get any more complex than that. After the structural foundations are in place, the reusability layer—options and an exposed API—can be built on top.
jQuery plugins
The third aspect of well-designed code is probably the most crucial: reusability. This section comes with a caveat. While there are obviously ways to build and implement reusable components in raw JavaScript (we’re about 90 percent of the way there with our module above), I prefer to build jQuery plugins for more complex things, for a few reasons.
Most importantly, it’s a form of unobtrusive communication. If you used jQuery to build a component, you should make that obvious to those implementing it. Building the component as a jQuery plugin is a great way to say that jQuery is required.
In addition, the implementation code will be consistent with the rest of the jQuery-based project code. That’s good for aesthetic reasons, but it also means (to an extent) that developers can predict how to interact with the plugin without too much research. Just one more way to build a better developer interface.
Before you begin building a jQuery plugin, ensure that the plugin does not conflict with other JavaScript libraries using the $ notation. That’s a lot simpler than it sounds—just wrap your plugin code like so:
(function($) {
// jQuery plugin code here
})(jQuery);
Next, we set up our plugin and drop our previously built module code inside. A plugin is just a method defined on the jQuery ($) object.
All it takes to use the plugin is a call to the function you just created.
var jpm = $.jPanelMenu( );
Options
Options are essential to any truly reusable plugin because they allow for customizations to each implementation. Every project brings with it a slew of design styles, interaction types, and content structures. Customizable options help ensure that you can adapt the plugin to fit within those project constraints.
It’s best practice to provide good default values for your options. The easiest way to do that is to use jQuery’s $.extend( ) method, which accepts (at least) two arguments.
As the first argument of $.extend( ), define an object with all available options and their default values. As the second argument, pass through the passed-in options. This will merge the two objects, overriding the defaults with any passed-in options.
Beyond providing good defaults, options become almost self-documenting—someone can look at the code and see all of the available options immediately.
Expose as many options as is feasible. The customization will help in future implementations, and flexibility never hurts.
API
Options are terrific ways to customize how a plugin works. An API, on the other hand, enables extensions to the plugin’s functionality by exposing methods and properties for the implementation code to take advantage of.
While it’s great to expose as much as possible through an API, the outside world shouldn’t have access to all internal methods and properties. Ideally, you should expose only the elements that will be used.
In our example, the exposed API should include calls to open and close the menu, but nothing else. The internal setMenuStyle( ) method runs when the menu opens and closes, but the public doesn’t need access to it.
To expose an API, return an object with any desired methods and properties at the end of the plugin code. You can even map returned methods and properties to those within the module code—this is where the beautiful organization of the module pattern really shines.
API methods and properties will be available through the object returned from the plugin initialization.
var jpm = $.jPanelMenu({
duration: 1000,
…
});
jpm.open( );
Polishing developer interfaces
With just a few simple constructs and guidelines, we’ve built ourselves a reusable, extensible plugin that will help make our lives easier. Like any part of what we do, experiment with this structure to see if it works for you, your team, and your workflow.
Whenever I find myself building something with a potential for reuse, I break it out into a module-based jQuery plugin. The best part about this approach is that it forces you to use—and test—the code you write. By using something as you build it, you’ll quickly identify strengths, discover shortcomings, and plan changes.
This process leads to battle-tested code ready for open-source contributions, or to be sold and distributed. I’ve released my (mostly) polished plugins as open-source projects on GitHub.
Even if you aren’t building something to be released in the wild, it’s still important to think about the design of your code. Your future self will thank you.
We’ve all been there: that bit of JavaScript functionality that started out as just a handful of lines grows to a dozen, then two dozen, then more. Along the way, a function picks up a few more arguments; a conditional picks up a few more conditions. And then one day, the bug report comes in: something’s broken, and it’s up to us to untangle the mess.
As we ask our client-side code to take on more and more responsibilities—indeed, whole applications are living largely in the browser these days—two things are becoming clear. One, we can’t just point and click our way through testing that things are working as we expect; automated tests are key to having confidence in our code. Two, we’re probably going to have to change how we write our code in order to make it possible to write tests.
Really, we need to change how we code? Yes—because even if we know that automated tests are a good thing, most of us are probably only able to write integration tests right now. Integration tests are valuable because they focus on how the pieces of an application work together, but what they don’t do is tell us whether individual units of functionality are behaving as expected.
That’s where unit testing comes in. And we’ll have a very hard time writing unit tests until we start writing testable JavaScript.
Unit vs. integration: what’s the difference?
Writing integration tests is usually fairly straightforward: we simply write code that describes how a user interacts with our app, and what the user should expect to see as she does. Selenium is a popular tool for automating browsers. Capybara for Ruby makes it easy to talk to Selenium, and there are plenty of tools for other languages, too.
Here’s an integration test for a portion of a search app:
def test_search
fill_in('q', :with => 'cat')
find('.btn').click
assert( find('#results li').has_content?('cat'), 'Search results are shown' )
assert( page.has_no_selector?('#results li.no-results'), 'No results is not shown' )
end
Whereas an integration test is interested in a user’s interaction with an app, a unit test is narrowly focused on a small piece of code:
When I call a function with a certain input, do I receive the expected output?
Apps that are written in a traditional procedural style can be very difficult to unit test—and difficult to maintain, debug, and extend, too. But if we write our code with our future unit testing needs in mind, we will not only find that writing the tests becomes more straightforward than we might have expected, but also that we’ll simply write better code, too.
To see what I’m talking about, let’s take a look at a simple search app:
When a user enters a search term, the app sends an XHR to the server for the corresponding data. When the server responds with the data, formatted as JSON, the app takes that data and displays it on the page, using client-side templating. A user can click on a search result to indicate that he “likes” it; when this happens, the name of the person he liked is added to the “Liked” list on the right-hand side.
A “traditional” JavaScript implementation of this app might look like this:
var tmplCache = {};
function loadTemplate (name) {
if (!tmplCache[name]) {
tmplCache[name] = $.get('/templates/' + name);
}
return tmplCache[name];
}
$(function () {
var resultsList = $('#results');
var liked = $('#liked');
var pending = false;
$('#searchForm').on('submit', function (e) {
e.preventDefault();
if (pending) { return; }
var form = $(this);
var query = $.trim( form.find('input[name="q"]').val() );
if (!query) { return; }
pending = true;
$.ajax('/data/search.json', {
data : { q: query },
dataType : 'json',
success : function (data) {
loadTemplate('people-detailed.tmpl').then(function (t) {
var tmpl = _.template(t);
resultsList.html( tmpl({ people : data.results }) );
pending = false;
});
}
});
$('<li>', {
'class' : 'pending',
html : 'Searching …'
}).appendTo( resultsList.empty() );
});
resultsList.on('click', '.like', function (e) {
e.preventDefault();
var name = $(this).closest('li').find('h2').text();
liked.find('.no-results').remove();
$('<li>', { text: name }).appendTo(liked);
});
});
My friend Adam Sontag calls this Choose Your Own Adventure code—on any given line, we might be dealing with presentation, or data, or user interaction, or application state. Who knows! It’s easy enough to write integration tests for this kind of code, but it’s hard to test individual units of functionality.
What makes it hard? Four things:
A general lack of structure; almost everything happens in a $(document).ready() callback, and then in anonymous functions that can’t be tested because they aren’t exposed.
Complex functions; if a function is more than 10 lines, like the submit handler, it’s highly likely that it’s doing too much.
Hidden or shared state; for example, since pending is in a closure, there’s no way to test whether the pending state is set correctly.
Tight coupling; for example, a $.ajax success handler shouldn’t need direct access to the DOM.
Organizing our code
The first step toward solving this is to take a less tangled approach to our code, breaking it up into a few different areas of responsibility:
Presentation and interaction
Data management and persistence
Overall application state
Setup and glue code to make the pieces work together
In the “traditional” implementation shown above, these four categories are intermingled—on one line we’re dealing with presentation, and two lines later we might be communicating with the server.
While we can absolutely write integration tests for this code—and we should!—writing unit tests for it is pretty difficult. In our functional tests, we can make assertions such as “when a user searches for something, she should see the appropriate results,” but we can’t get much more specific. If something goes wrong, we’ll have to track down exactly where it went wrong, and our functional tests won’t help much with that.
If we rethink how we write our code, though, we can write unit tests that will give us better insight into where things went wrong, and also help us end up with code that’s easier to reuse, maintain, and extend.
Our new code will follow a few guiding principles:
Represent each distinct piece of behavior as a separate object that falls into one of the four areas of responsibility and doesn’t need to know about other objects. This will help us avoid creating tangled code.
Support configurability, rather than hard-coding things. This will prevent us from replicating our entire HTML environment in order to write our tests.
Keep our objects’ methods simple and brief. This will help us keep our tests simple and our code easy to read.
Use constructor functions to create instances of objects. This will make it possible to create “clean” copies of each piece of code for the sake of testing.
To start with, we need to figure out how we’ll break our application into different pieces. We’ll have three pieces dedicated to presentation and interaction: the Search Form, the Search Results, and the Likes Box.
We’ll also have a piece dedicated to fetching data from the server and a piece dedicated to gluing everything together.
Let’s start by looking at one of the simplest pieces of our application: the Likes Box. In the original version of the app, this code was responsible for updating the Likes Box:
var liked = $('#liked');
var resultsList = $('#results');
// ...
resultsList.on('click', '.like', function (e) {
e.preventDefault();
var name = $(this).closest('li').find('h2').text();
liked.find( '.no-results' ).remove();
$('<li>', { text: name }).appendTo(liked);
});
The Search Results piece is completely intertwined with the Likes Box piece and needs to know a lot about its markup. A much better and more testable approach would be to create a Likes Box object that’s responsible for manipulating the DOM related to the Likes Box:
var Likes = function (el) {
this.el = $(el);
return this;
};
Likes.prototype.add = function (name) {
this.el.find('.no-results').remove();
$('<li>', { text: name }).appendTo(this.el);
};
This code provides a constructor function that creates a new instance of a Likes Box. The instance that’s created has an .add() method, which we can use to add new results. We can write a couple of tests to prove that it works:
var ul;
setup(function(){
ul = $('<ul><li class="no-results"></li></ul>');
});
test('constructor', function () {
var l = new Likes(ul);
assert(l);
});
test('adding a name', function () {
var l = new Likes(ul);
l.add('Brendan Eich');
assert.equal(ul.find('li').length, 1);
assert.equal(ul.find('li').first().html(), 'Brendan Eich');
assert.equal(ul.find('li.no-results').length, 0);
});
Not so hard, is it? Here we’re using Mocha as the test framework, and Chai as the assertion library. Mocha provides the test and setup functions; Chai provides assert. There are plenty of other test frameworks and assertion libraries to choose from, but for the sake of an introduction, I find these two work well. You should find the one that works best for you and your project—aside from Mocha, QUnit is popular, and Intern is a new framework that shows a lot of promise.
Our test code starts out by creating an element that we’ll use as the container for our Likes Box. Then, it runs two tests: one is a sanity check to make sure we can make a Likes Box; the other is a test to ensure that our .add() method has the desired effect. With these tests in place, we can safely refactor the code for our Likes Box, and be confident that we’ll know if we break anything.
Our new application code can now look like this:
var liked = new Likes('#liked');
var resultsList = $('#results');
// ...
resultsList.on('click', '.like', function (e) {
e.preventDefault();
var name = $(this).closest('li').find('h2').text();
liked.add(name);
});
The Search Results piece is more complex than the Likes Box, but let’s take a stab at refactoring that, too. Just as we created an .add() method on the Likes Box, we also want to create methods for interacting with the Search Results. We’ll want a way to add new results, as well as a way to “broadcast” to the rest of the app when things happen within the Search Results—for example, when someone likes a result.
var SearchResults = function (el) {
this.el = $(el);
this.el.on( 'click', '.btn.like', _.bind(this._handleClick, this) );
};
SearchResults.prototype.setResults = function (results) {
var templateRequest = $.get('people-detailed.tmpl');
templateRequest.then( _.bind(this._populate, this, results) );
};
SearchResults.prototype._handleClick = function (evt) {
var name = $(evt.target).closest('li.result').attr('data-name');
$(document).trigger('like', [ name ]);
};
SearchResults.prototype._populate = function (results, tmpl) {
var html = _.template(tmpl, { people: results });
this.el.html(html);
};
Now, our old app code for managing the interaction between Search Results and the Likes Box could look like this:
var liked = new Likes('#liked');
var resultsList = new SearchResults('#results');
// ...
$(document).on('like', function (evt, name) {
liked.add(name);
})
It’s much simpler and less entangled, because we’re using the document as a global message bus, and passing messages through it so individual components don’t need to know about each other. (Note that in a real app, we’d use something like Backbone or the RSVP library to manage events. We’re just triggering on document to keep things simple here.) We’re also hiding all the dirty work—such as finding the name of the person who was liked—inside the Search Results object, rather than having it muddy up our application code. The best part: we can now write tests to prove that our Search Results object works as we expect:
var ul;
var data = [ /* fake data here */ ];
setup(function () {
ul = $('<ul><li class="no-results"></li></ul>');
});
test('constructor', function () {
var sr = new SearchResults(ul);
assert(sr);
});
test('display received results', function () {
var sr = new SearchResults(ul);
sr.setResults(data);
assert.equal(ul.find('.no-results').length, 0);
assert.equal(ul.find('li.result').length, data.length);
assert.equal(
ul.find('li.result').first().attr('data-name'),
data[0].name
);
});
test('announce likes', function() {
var sr = new SearchResults(ul);
var flag;
var spy = function () {
flag = [].slice.call(arguments);
};
sr.setResults(data);
$(document).on('like', spy);
ul.find('li').first().find('.like.btn').click();
assert(flag, 'event handler called');
assert.equal(flag[1], data[0].name, 'event handler receives data' );
});
The interaction with the server is another interesting piece to consider. The original code included a direct $.ajax() request, and the callback interacted directly with the DOM:
$.ajax('/data/search.json', {
data : { q: query },
dataType : 'json',
success : function( data ) {
loadTemplate('people-detailed.tmpl').then(function(t) {
var tmpl = _.template( t );
resultsList.html( tmpl({ people : data.results }) );
pending = false;
});
}
});
Again, this is difficult to write a unit test for, because so many different things are happening in just a few lines of code. We can restructure the data portion of our application as an object of its own:
var SearchData = function () { };
SearchData.prototype.fetch = function (query) {
var dfd;
if (!query) {
dfd = $.Deferred();
dfd.resolve([]);
return dfd.promise();
}
return $.ajax( '/data/search.json', {
data : { q: query },
dataType : 'json'
}).pipe(function( resp ) {
return resp.results;
});
};
Now, we can change our code for getting the results onto the page:
var resultsList = new SearchResults('#results');
var searchData = new SearchData();
// ...
searchData.fetch(query).then(resultsList.setResults);
Again, we’ve dramatically simplified our application code, and isolated the complexity within the Search Data object, rather than having it live in our main application code. We’ve also made our search interface testable, though there are a couple caveats to bear in mind when testing code that interacts with the server.
The first is that we don’t want to actually interact with the server—to do so would be to reenter the world of integration tests, and because we’re responsible developers, we already have tests that ensure the server does the right thing, right? Instead, we want to “mock” the interaction with the server, which we can do using the Sinon library. The second caveat is that we should also test non-ideal paths, such as an empty query.
test('constructor', function () {
var sd = new SearchData();
assert(sd);
});
suite('fetch', function () {
var xhr, requests;
setup(function () {
requests = [];
xhr = sinon.useFakeXMLHttpRequest();
xhr.onCreate = function (req) {
requests.push(req);
};
});
teardown(function () {
xhr.restore();
});
test('fetches from correct URL', function () {
var sd = new SearchData();
sd.fetch('cat');
assert.equal(requests[0].url, '/data/search.json?q=cat');
});
test('returns a promise', function () {
var sd = new SearchData();
var req = sd.fetch('cat');
assert.isFunction(req.then);
});
test('no request if no query', function () {
var sd = new SearchData();
var req = sd.fetch();
assert.equal(requests.length, 0);
});
test('return a promise even if no query', function () {
var sd = new SearchData();
var req = sd.fetch();
assert.isFunction( req.then );
});
test('no query promise resolves with empty array', function () {
var sd = new SearchData();
var req = sd.fetch();
var spy = sinon.spy();
req.then(spy);
assert.deepEqual(spy.args[0][0], []);
});
test('returns contents of results property of the response', function () {
var sd = new SearchData();
var req = sd.fetch('cat');
var spy = sinon.spy();
requests[0].respond(
200, { 'Content-type': 'text/json' },
JSON.stringify({ results: [ 1, 2, 3 ] })
);
req.then(spy);
assert.deepEqual(spy.args[0][0], [ 1, 2, 3 ]);
});
});
For the sake of brevity, I’ve left out the refactoring of the Search Form, and also simplified some of the other refactorings and tests, but you can see a finished version of the app here if you’re interested.
When we’re done rewriting our application using testable JavaScript patterns, we end up with something much cleaner than what we started with:
$(function() {
var pending = false;
var searchForm = new SearchForm('#searchForm');
var searchResults = new SearchResults('#results');
var likes = new Likes('#liked');
var searchData = new SearchData();
$(document).on('search', function (event, query) {
if (pending) { return; }
pending = true;
searchData.fetch(query).then(function (results) {
searchResults.setResults(results);
pending = false;
});
searchResults.pending();
});
$(document).on('like', function (evt, name) {
likes.add(name);
});
});
Even more important than our much cleaner application code, though, is the fact that we end up with a codebase that is thoroughly tested. That means we can safely refactor it and add to it without the fear of breaking things. We can even write new tests as we find new issues, and then write the code that makes those tests pass.
Testing makes life easier in the long run
It’s easy to look at all of this and say, “Wait, you want me to write more code to do the same job?”
The thing is, there are a few inescapable facts of life about Making Things On The Internet. You will spend time designing an approach to a problem. You will test your solution, whether by clicking around in a browser, writing automated tests, or—shudder—letting your users do your testing for you in production. You will make changes to your code, and other people will use your code. Finally: there will be bugs, no matter how many tests you write.
The thing about testing is that while it might require a bit more time at the outset, it really does save time in the long run. You’ll be patting yourself on the back the first time a test you wrote catches a bug before it finds its way into production. You’ll be grateful, too, when you have a system in place that can prove that your bug fix really does fix a bug that slips through.
Additional resources
This article just scratches the surface of JavaScript testing, but if you’d like to learn more, check out:
My presentation from the 2012 Full Frontal conference in Brighton, UK.
Grunt, a tool that helps automate the testing process and lots of other things.
Test-Driven JavaScript Development by Christian Johansen, the creator of the Sinon library. It is a dense but informative examination of the practice of testing JavaScript.
Dariusz was a maintainer of PyMQI and also a developer on Spring Python, which is sort of a port of the Java Spring framework to Python.
Zato docs (quite detailed):
https://zato.io/docs/index.html
Part 1 of a basic Zato tutorial:
https://zato.io/docs/tutorial/01.html
I took a look at the tutorial. Broadly, it shows how to install Zato, create a simple Zato service in Python, that talks to PostgreSQL and Redis, and deploy it. Two servers get created, behind a load-balancer, and the service gets hot-deployed to the servers. Then curl is used to access the service. (This tutorial does not create a real client; curl is used to simulate one.)
Zato looks interesting and powerful (and somewhat complex, but that is to be expected for a product like an ESB).
I will check it out more and then report on my findings.
Dexterity is the new content-type development system built into Plone 4.3. It's also usable with Plone 4.1 and 4.2. Lately I've been working on developing a fairly sophisticated content type with Dexterity. It has fieldsets, smart validation and real vocabularies.
All these features were developed through the web. This meant that I was able to show them to project stakeholders — and even do some light usability testing — before ever turning the project into an add-on package. And, when I did convert the project into a Python package, nothing was lost.
Want more? I'll be teaching a class on Developing with Dexterity, June 3-4 at Plone Symposium Midwest.
If you've touched Dexterity at all, you've realized that you may use the TTW field editor to rapidly create a content type with a full set of fields and behaviors. You may be surprised, though, to learn that it's possible to organize the add/edit form into fieldsets, or to wire in validation and vocabularies, without moving the content type to an add-on package.
The trick is that it's possible to edit the XML representation of the field schema all the way through the TTW development process. XML edits show up immediately in your Dexterity type's field display and you may continue to add, move, delete and edit fields there:
If you've followed Dexterity development, you know that this is not really a trick at all: Dexterity was meant to work this way. Dexterity maintains the TTW field list as an XML representation via the supermodel package, which translates back and forth between field schemas and XML. While you're developing TTW, the editable XML representation is stored in the content type's Factory Type Information.
Documentation on how to add fieldsets, validators, vocabularies and permissions via XML is available in the recently created Dexterity XML Reference. To give you a hint of how it works, it's this easy to do a fieldset:
The gotcha is that editing the XML is currently a ZMI step. Go to portal_types, find the type, edit the XML.
The Good News
This is about to get better. The next minor release of Dexterity will have an "Edit XML Model" on the field editor:
Pushing it will use Plone 4.3's new resource editor package (built on the Ace editor) to open an editor. And, not only can you edit, but on save you'll get XML syntax and Dexterity resource checking:
When you're ready to move your project to a Python package, you may keep the XML model you've developed and continue to elaborate your fieldsets by editing that model.
It fixes a crash in the JIT when calling external C functions (with
ctypes/cffi) in a multithreaded context.
What is PyPy?
PyPy is a very compliant Python interpreter, almost a drop-in replacement for
CPython 2.7. It's fast (pypy 2.0 and cpython 2.7.3 performance comparison)
due to its integrated tracing JIT compiler.
This release supports x86 machines running Linux 32/64, Mac OS X 64 or
Windows 32. Support for ARM is progressing but not bug-free yet.
Highlights
This release contains only the fix described above. A crash (or wrong
results) used to occur if all these conditions were true:
your program is multithreaded;
it runs on a single-core machine or a heavily-loaded multi-core one;
it uses ctypes or cffi to issue external calls to C functions.
This was fixed in the branch emit-call-x86 (see the example file
bug1.py).
Metaclasses are a handy feature of Python and Django makes good use of them.
When you create certain kinds of classes in Django, a metaclass will do
something to the class before it is created. For forms, the various attributes of the
class are converted into a base_fields dictionary on the class.
Similarly, a subclass of Model also fires up a metaclass that does some
registering. A foreignkey to another model adds a relation back on that other
model, for instance.
As a recap, a class is something that can be instantiated into an object. It
can have an __init__() method that does something upon
instantiation. type(your_instance) will return the class.
Did you know that you can create classes dynamically? See for yourself:
>>> name = 'ExampleClass'
>>> bases = (object,)
>>> attrs = {'__init__': lambda self: print('Hello from __init__')}
>>> ExampleClass = type(name, bases, attrs)
>>> example = ExampleClass()
Hello From __init__
>>> type(example)
<class '__console__.ExampleClass'>
So... we can actually control how classes are created! You could create a
create_class() method that calls type but that modifies, for instance, the name.
Or we could take all the attributes and add them to a base_fields
dictionary on the instance. Hey, that's what we saw in the first Django form example!
Now, what is type exactly? It is a class that creates classes.
This also means we can subclass it! The most useful thing to override in our
subclass is the __new__() method. The __init__() method creates
instances from the class, the __new__() creates classes. (Update: it
is a little bit different, actually, see Venelin's comment below). So again we can modify the name and/or the
attributes.
How do you use it in practice? Normally you'd set a __metaclass__
attribute on a class. This tells python to use that metaclass for creating the
class. The same for subclasses. This is how our Django form classes use the
metaclass specified in Django's base Form class.
Django uses metaclasses in five places: admin media, models, forms,
formfields, form widgets. Grep for metaclass in your local django
source code once to get a better feel for how Django uses it.
Note on python 3: it uses a slightly different syntax for specifying
metaclasses. So Django 1.5 uses six to
support both ways in a single codebase.
Warning: don't overuse metaclasses. They can make code difficult to debug
and follow. Use Django as a good example of how to use metaclasses. Django
saves you a lot of work by using metaclasses in a few locations.
The last couple of tutorials have been a bit heavy, so this week’s tutorials are going to balance that out by being a little light. We’re having a look at a couple of different aspects of the Python language.
List Comprehensions
The first is comprehensions:
>>> a_list = [1,2,3,4,5]
>>> b_list= [element*2 for element in a_list]
>>> b_list
[2, 4, 6, 8, 10]
In this example, we have automatically generated a new list b_list from an existing list* a_list by using a list comprehension. The structure of the comprehension is, I hope comprehensible. If not, it is a little hard to explain in steps. The comprehension above is equivalent to:
>>> b_list = []
>>> for element in a_list:
... b_list.append(element*2)
...
>>> b_list
[2, 4, 6, 8, 10]
We could call the variableelement anything we liked – it is just another variable:
>>> b_list = [baloney*2 for baloney in a_list]
>>> b_list
[2, 4, 6, 8, 10]
>>>
You can also add conditions. Let’s say you only wanted the even elements in a_list:
>>> b_list = [element for element in a_list if element%2 ==0] #ie remainder is 0 when dividing by two
>>> b_list
[2, 4]
>>>
The condition here is if element%2 ==0, but you can substitute other conditions (as long as they resolve to either True or False). You can have a comprehension which relies on multiple variables (this example is from the Python documentation):
>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
Unwinding this is a little tricky – for each element in [1,2,3] it runs through each element in [3,1,4] (ie 9 comparisons in all) and appends the tuple if the elements are not equal.
List comprehensions provide an easy shorthand for constructing lists. Moreover, they are often more readable than writing out the for loops explicitly.
Tuples
The second topic is tuples.
The other thing we’re going to look at is tuples (pronounced, variously, “tupp-lls”, “two-pls” and, to some people, “tyou-pls” – my preference is tupp-lls, rhymes with couples). Tuples are a little like lists, except that they are immutable. That is, once they are made they cannot be changed. Tuples are made by putting the elements in round braces [actually, adding commas between them and, sometimes, also adding braces]:
Elements of the tuple are referenced in the same way as you’d reference a list but, unlike lists, these elements cannot be changed (tuples are “immutable”):
>>>my_tuple[0]
1
>>>my_tuple[0]=2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
The TypeError is telling us that you can’t change the elements of a tuple. To make a tuple with a single element is a little difficult because the interpreter could just interpret the parentheses as determining order of operation (think (1+2)*3). Instead, we put a comma after the single element to indicate that we are creating a tuple:
>>> my_tuple = (1) # no comma, so Python just thinks it's a number
>>> my_tuple
1
>>> my_tuple[0] # just a number, so has no elements
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'int' object has no attribute '__getitem__'
>>> my_tuple= (1,)
>>> my_tuple
(1,)
>>>my_tuple[0]
1
So, if a tuple does what a list can do, only less, why bother with a tuple? Why not use a list? Well, tuples are easier for the Python interpreter to deal with and therefore might end up being faster. Tuples might also indicate that you have an ordered list where the ordering has some meaning (for example, a date tuple might store year, month and day (in that order) in tuple). The fact that you’re using a tuple then flags that each of the entries has a distinct meaning or use and that their order is significant. Another pragmatic reason to use a tuple is when you have data which you know shouldn’t change (like a constant). So, if you accidentally try to change one of the tuple’s entries, you will have an error thrown.
Finally, since tuples are immutable they can be used as keys in dictionaries, unlike lists:
He's got a love/hate relationship with creativity. The first part of his talk
was impossible to summarize. You'll have to watch the video later on :-)
Artists tell him he's not artistic because he works on developing technical
skills.
Guitarists tell him he's not a real guitarist as he doesn't play in a
band. And 'cause he builds his own guitars he's a programmer, not a Real
Guitarist.
Writers tell him he's not a writer because he writes technical books.
Programmers tell him he's not a programmer because he doesn't work on their
project. And by the way, he's a (technical) writer now, so he's not a
programmer.
He's not creative enough. Or so the others say. Or he's not acceptable. How to
deal with creativity? In a way, you can re-phrase creativity. Programmers are
always making something from nothing, right? Isn't that the pinnacle of
creativity?
Here are four hypothetical persons:
Technique, no imagination: a stereotypical programmer.
Imagination, no technique: stereotypical biz dude.
No imagination, no technique. Probably doesn't exist.
Both imagination and technique. Zed's goal.
Zed's imaginative programmer process. Everyone has a process (if they're
good), here's the one he proposes to help you be more creative:
You start with an idea.
You establish a concept that helps form the idea. It gives your idea
clothes.
Research techniques or tools. Do some research or you'll pay for it later
on.
Refine the concept through composition. So put a box around the vast world
of available possibilities. Just mark which features are inside and outside
the concept.
Explore through prototypes. Throw away code or use paper prototypes for
instance. This saves you so much time later.
You make it real.
We are programmers, so we should iterate this process.
He tried this process with http://projectzorn.com/, going through all the
stages. And he's probably going to work on it during the sprints this weekend,
so join him if you want.
After a very painful porting experience with Jinja2 to Python 3 I
basically left the project idling around for a while because I was too
afraid of breaking Python 3 support. The approach I used was one codebase
that was written in Python 2 and translated with 2to3 to Python 3 on
installation. The unfortunate side-effect of that is that any change you
do requires about a minute of translation which destroys all your
iteration speeds. Thankfully it turns out that if you target the right
versions of Python you can do much better.
Thomas Waldmann from the MoinMoin project started running Jinja2 through
my python-modernize
with the right parameters and ended up with a unified codebase that runs
on 2.6, 2.7 and 3.3. With a bit of cleanup afterwards we were able to
come up with a nice codebase that runs in all versions of Python and also
looks like regular Python code for the most time.
Motivated by the results from this I went through the code a few more
times and also started migrating some other code over to experiment more
with unified codebases.
This is a selection of some tips and tricks I can now share in regards to
accomplishing something similar.
Drop 2.5, 3.1 and 3.2
This is the most important tip. Dropping 2.5 by now is more than possible
since very few people are still on it and dropping 3.1 and 3.2 are no
brainers anyways considering the low adoption of Python 3 so far. But why
would you drop those versions? The basic answer is that 2.6 and 3.3 have
a lot of overlapping syntax and features that allow for code that works
well with both:
Compatible string literals. 2.6 and 3.3 support the same syntax for
strings. You can use 'foo' to refer to a native string (byte
string on 2.x and a Unicode string on 3.x), u'foo' to refer to a
Unicode string and b'foo' to refer to a bytestring or bytes
object.
Compatible print syntax. In case you have a few print statements
sitting around you can from __future__ import print_function and
start using the print function without having to bind it to a
different name or suffering from other inconsistencies.
Compatible exception catching syntax. Python 2.6 introduced except
Exception as e which is also the syntax used on 3.x to catch down
exceptions.
Class decorators are available. They are incredible useful to
automatically correct moved interfaces without leaving a footprint in
the class structure. For instance they can be used to automatically
rename the iteration method from next to __next__ or
__str__ to __unicode__ for Python 2.x.
Builtin next() function to invoke __next__ or next. This
is helpful because they are performing about the same speed as calling
the method directly so you don't pay much of a performance penalty
compared to putting runtime checks into places or making a wrapper
function yourself.
Python 2.6 added the bytearray type which has the same interface
in that version of Python as the one in 3.3. This is useful because
while Python 2.6 lacks the Python 3.3 bytes object it does have
a builtin with that name but that's just another name for str
which has vastly different behavior.
Python 3.3 reintroduces bytes-to-bytes and string-to-string codecs
that were broken in 3.1 and 3.2. Unfortunately the interface for them
is clunkier now and the aliases are missing, but it's much closer to
what we had in 2.x than before.
This is particularly useful if you did stream based encoding and
decoding. That functionality was plain missing between 3.0 up until
3.3.
Yes, the six module can get you quite far, but don't underestimate the
impact of looking at nice code. With the Python 3 port I basically lost
interest in maintaining Jinja2 because the codebase started to frustrate
me. Back then a unified codebase was looking ugly and had a performance
impact (six.b('foo') and six.u('foo') everywhere) or was plagued
under the bad iteration speeds of 2to3. Not having to deal with any of
that brings the joy back. Jinja2's codebase now looks like very clean and
you have to find the Python 2/3 compatibility support. Very few paths in
the code actually do something like if PY2:.
The rest of this article assumes that these are the Python versions you
want to support. Also attempting to support Python 2.5 is a very painful
thing to do and I strongly recommend against it. Supporting 3.2 is
possible if you are willing to wrap all your strings in function calls
which I don't recommend doing for aesthetic and performance reasons.
Skip Six
Six is a pretty neat library and this is where the Jinja2 port started out
with. There however at the end of the day there is not much in six that
actually is required for getting a Python 3 port running and a few things
are missing. Six is definitely required if you want to support Python 2.5
but from 2.6 or later there really is not much of a reason to use six.
Jinja2 ships a _compat module that contains the few helpers required.
Including a few lines of non Python 3 code the whole compatibility module
is less than 80 lines of code.
This saves you from the troubles where users might expect a different
version of six because of another library or pulling in another dependency
into your project.
Start with Modernize
To start with the port the python-modernize library is a good start.
It is a version of 2to3 that produces code that runs in either. While
it's pretty buggy still and the default options are not particularly
great, it can get you quite far with regards to doing the boring parts for
you. You will still need to go over the result and clean up some imports
and ugly results.
Fix your Tests
Before you do anything else walk through your tests and make sure that
they still make sense. A lot of the problems in the Python standard
library in 3.0 and 3.1 came from the fact that the behavior of the
testsuite changed through the conversion to Python 3 in unintended ways.
Write a Compatibility Module
So you're going to skip six, can you live without helpers? The answer is
“no”. You will still need a small compatibility module but that is small
enough that you can just keep it in your package. Here are some basic
examples of what such a compatibility module could look like:
The exact contents of that module will depend on how much actually changed
for you. In case of Jinja2 I put a whole bunch of functions in there.
For instance it contains ifilter, imap and similar itertools functions
that became builtins in 3.x. (I stuck with the Python 2.x functions to
make it clear for the reader of the code that the iterator behavior is
intended and not a bug).
Test for 2.x not 3.x
At one point there will be the requirement to check if you are executing
on 2.x or 3.x. In that cases I would recommend checking for Python 2
first and putting Python 3 into your else branch instead of the other way
round. That way you will have less ugly surprises when a Python 4 comes
around at one point.
The biggest change in Python 3 is without doubt the changes on the Unicode
interface. Unfortunately these changes are very painful in some places
and also inconsistently handled throughout the standard library. The
majority of the time porting will clearly be wasted on this topic. This
topic is a whole article by itself but here is a quick cheat sheet for
porting that Jinja2 and Werkzeug follow:
'foo' always refers to what we call the native string of the
implementation. This is the string used for identifiers, sourcecode,
filenames and other low-level functions. Additionally in 2.x it's
permissible as a literal in Unicode strings for as long as it's
limited to ASCII only characters.
This property is very useful for unified codebases because the general
trend with Python 3 is to introduce Unicode in some interfaces that
previously did not support it, but never the inverse. Since native
string literals “upgrade” to Unicode but still somewhat support
Unicode in 2.x this string literal is very flexible.
For instance the datetime.strftime function strictly does not
support Unicode in Python 2 but is Unicode only in 3.x. Because in
most cases the return value on 2.x however was ASCII only things like
this work really well in 2.x and 3.x:
The string passed to strftime is native (so bytes in 2.x and Unicode
in 3.x). The return value is a native string again and ASCII only.
As such both on 2.x and 3.x it will be a Unicode string once string
formatted.
u'foo' always refers to a Unicode string. Many libraries already
had pretty excellent Unicode support in 2.x so that literal should not
be surprising to many.
b'foo' always refers to something that can hold arbitrary bytes.
Since 2.6 does not actually have a bytes object like Python 3.3
has and Python 3.3 lacks an actual bytestring the usefulness of this
literal is indeed a bit limited. It becomes immediately more useful
when paired with the bytearray object which has the same interface
on 2.x and 3.x:
>>> bytearray(b' foo ').strip()bytearray(b'foo')
Since it's also mutable it's quite efficient at modifying raw bytes
and you can trivially convert it to something more conventional by
wrapping the final result in bytes() again.
In addition to these basic rules I also add text_type, unichr
and string_types variables to my compatibility module as shown above.
With those available the big changes are:
The idea is that you just implement __str__ on both 2.x and 3.x and
let it return Unicode strings (yes, looks a bit odd in 2.x) and the
decorator automatically renames it to __unicode__ for 2.x and adds a
__str__ that invokes __unicode__ and encodes the return value to
utf-8. This pattern has been pretty common in the past with 2.x modules.
For instance Jinja2 and Django use it.
Since Python 3 changed the syntax for defining the metaclass to use in an
incompatible way this makes porting a bit harder than it should be. Six
has a with_metaclass function that can work around this issue but it
generates a dummy class that shows up in the inheritance tree. For Jinja2
I was not happy enough with that solution and modified it a bit. The
external API is the same but the implementation uses a temporary class
to hook in the metaclass. The benefit is that you don't have to pay a
performance penalty for using it and your inheritance tree stays nice.
The code is a bit hard to understand. The basic idea is exploiting the
idea that metaclasses can customize class creation and are picked by by
the parent class. This particular implementation uses a metaclass to
remove its own parent from the inheritance tree on subclassing. The end
result is that the function creates a dummy class with a dummy metaclass.
Once subclassed the dummy classes metaclass is used which has a
constructor that basically instances a new class from the original parent
and the actually intended metaclass. That way the dummy class and dummy
metaclass never show up.
One of the more annoying changes in Python 3 are the changes on the
dictionary iterator protocols. In Python 2 all dictionaries had
keys(), values() and items() that returned lists and
iterkeys(), itervalues() and iteritems() that returned
iterators. In Python 3 none of that exists any more. Instead they were
replaced with new methods that return view objects.
keys() returns a key view which behaves like some sort of read-only
set, values() which returns a read-only container and iterable (not an
iterator!) and items() which returns some sort of read-only set-like
object. Unlike regular sets it however can also point to mutable objects
in which case some methods will fail at runtime.
On the positive side a lot of people missed that views are not iterators
so in many cases you can just ignore that. Werkzeug and Django implement
a bunch of custom dictionary objects and in both cases the decision was
made to just ignore the existence of view objects and let keys() and
friends return iterators.
This is currently the only sensible thing to do due to limitations of the
Python interpreter. There are a few problems with it:
The fact that the views are not iterators by themselves mean that in
the average case you create a temporary object for no good reason.
The set-like behavior of the builtin dictionary views cannot be
replicated in pure Python due to limitations in the interpreter.
Implementing views for 3.x and iterators for 2.x would mean a lot of
code duplication.
This is what the Jinja2 codebase went with for iterating over
dictionaries:
Since iterators changed in general a bit of help is needed to make this
painless. The only change really is the transition from next() to
__next__. Thankfully this is already transparently handled. The only
thing you really need to change is to go from x.next() to next(x)
and the language does the rest.
If you plan on defining iterators a class decorator again becomes helpful:
One of the nice features of the Python 2 encoding protocol was that it was
independent of types. You could register an encoding that would transform
a csv file into a numpy array if you would have preferred that. This
feature however was not well known since the primary exposed interface of
encodings was attached to string objects. Since they got stricter in 3.x
a lot of that functionality was removed in 3.0 but later reintroduced in
3.3 again since it proved useful. Basically all codecs that did not
convert between Unicode and bytes or the other way round were unavailable
until 3.3. Among those codecs are the hex and base64 codec.
There are two use cases for those codecs: operations on strings and
operations on streams. The former is well known as str.encode() in
2.x but now looks different if you want to support 2.x and 3.x due to the
changed string API:
You will also notice that the codecs are missing the aliases in 3.3 which
requires you to write 'base64_codec' instead of 'base64'.
(These codecs are preferable over the functions in the binascii module
because they support operations on streams through the incremental
encoding and decoding support.)
Other Notes
There are still a few places where I don't have nice solutions for yet or
are generally annoying to deal with but they are getting fewer. Some of
them are unfortunately now part of the Python 3 API are hard to discover
until you trigger an edge case.
Filesystem and file IO access continues to be annoying to deal with on
Linux due to it not being based on Unicode. The open() function
and the filesystem layer have dangerous platform specific defaults.
If I SSH into a en_US machine from an de_AT one for instance
Python loves falling back to ASCII encoding for both file system and
file operations.
Generally I noticed the most reliable way to do text on Python 3 that
also works okay on 2.x is just to open files in binary mode and
explicitly decode. Alternatively you can use the codecs.open or
io.open function on 2.x and the builtin open on Python 3 with
an explicit encoding.
URLs in the standard library are represented incorrectly as Unicode
which causes some URLs to not be dealt with correctly on 3.x.
Raising exceptions with a traceback object requires a helper function
since the syntax changed. This is very uncommon in general and easy
enough to wrap. Since the syntax changed this is one of the
situations where you will have to move code into an exec block:
The previous exec trick is useful in general if you have some code
that depends on different syntax. Since exec itself has a different
syntax now you won't be able to use it to execute something against an
arbitrary namespace. This is not a huge deal because eval with
compile can be used as a drop-in that works on both versions.
Alternatively you can bootstrap an exec_ function through exec
itself.
If you have a C module written on top of the Python C API: shoot
yourself. There is no tooling available for that yet from what I know
and so much stuff changed. Take this as an opportunity to ditch the
way you build modules and redo it on top of cffi or ctypes. If
that's not an option because you're something like numpy then you will
just have to accept the pain. Maybe try writing some abomination on
top of the C-preprocessor that makes porting easier.
Use tox for local testing. Being
able to run your tests against all python versions at once is very
helpful and will find you a lot of issues.
Outlook
Unified codebases for 2.x and 3.x are definitely within reach now. The
majority of the porting time will still be spend trying to figure out how
APIs are going to behave with regards to Unicode and interoperability with
other modules that might have changed their API. In any case if you want
to consider porting libraries don't bother with versions outside below
2.5, 3.0-3.2 and it will not hurt as much.
Montréal-Python would like to invite you all to the next Python Project Night, on Thursday, the 30th of May, 2013 at the offices of Caravan.
Like on previous nights, it’s an informal meetup where people work on different projects and generally mess around with Python code. Everyone is welcome, from the grizzled python hacker to the absolute beginner who just finished their first workshop. We will encourage people to help each other and we will also have dedicated helpers to help people get started.
As per usual, beer and pizza are provided, so just bring your laptop computer.
If you have any projects you would like to work on, please post them on the mailing list: montrealpython@googlegroups.com. If you don’t have any ideas, don’t worry, we will find you a project that needs help.
When: Thursday, May 30th 2013 from 7 PM to 9:30 PM
Last year, I illustrated the importance of mobile by highlighting how many devices enter the World each day compared to the number of people born per day on our planet. The ratio was striking. Looking at the same figures today is even more sobering.
The End of 2011
The total of smartphones entering the World per day was about 1.45M devices compared to 371,124 births.
The End of 2012
The total of smartphones entering the World per day was about 3.6M devices again compared to the same 371 thousand births.
In her presentation at An Event Apart in San Diego California 2013 Sarah Parmenter talked about the changes responsive Web design requires of Web designers. Here's my notes from her talk on Responsive Design Workflow:
Any change is accompanied by drawbacks and discomforts. We're going through this transition right now. Responsive design is new and can be hard.
We're used to a fixed canvas when we design but the multi-device Web is filled with many canvases of varying size and shape.
We have to think in terms of designing a puzzle vs. designing a single fixed canvas. We need to work in terms of proportions.
Globally, mobile will continue to grow at a rate of 66% year on year. This forces many designers to adapt. There's no turning back. We can't go back to fixed canvas designs.
We all like order and structure in our lives that's why today feels so overwhelming for many of us.
Experience
Experience: defining, crafting, and honing. To craft the experience, you have to think in terms of emotions: what do you want to convey and to whom?
When your product or service gets an emotional reaction or buy-in, half the battle has been won.
WuFoo, for example, sent hand written notes to customers thanking them for using their service.
Digitally, we can create experiences through white space and aspirational imagery.
There are three questions that can help you define your experience.
What is the single reason someone is coming to my site/store/app? Make sure that experience is great.
What is causing the most friction with my clients/users/visitors?
What is already authentic about your product or service? What makes you unique?
How do you want people to feel when they use your product or service? Accomplishment, empowerment, not just happiness should be up for consideration.
If you define the expectations for experience first, you'll have a way to discuss and decide other choices as you move forward.
What causes the least amount of friction for my users and application? Likely web vs. native discussions will come up. 8 out of 10 times it comes down to budget.
Content
How do we define content structure? Start with content hierarchy: what is most important information in your product? You can learn this through direct observations, click tracking, server logs or more.
You can design with complete content, but not without an understanding of the content structure.
Even if you get content in advance, it may need to be re-written or adjusted for the Web. As a quick fix, consider using a traffic light system: red (remove), yellow (for large screens only?), green (all devices).
If you rewrite content, leave comments on why it was modified.
Aesthetics
When did Photoshop become a dirty word? All of the sudden no one wants to talk about using Photoshop to design but not everyone can design in the browser.
Visual design tools still have their place.
UI pattern sites can help you explore ideas for the design of user interface elements. They catalog various solutions for common design patterns.
44x44px is Apple's guidelines for minimum touch target sizes. To make designs work with touch interfaces.
Cage is a tool that allows you to get approvals from clients more easily.
Getting sign-off on components is also possible. Especially if you treat design as a set of puzzle pieces vs. a single fixed canvas.
A transparent layer of touch target sizes can be overlaid on a comp to make sure all the touch targets are sized appropriately.
Build
For native applications, you need to crop UI elements to be stretchable, which maybe be different than the way you create assets for the Web.
Creating multiple assets for different screen resolutions can be challenging. A scratch file of the UI elements in an interface can isolate all the assets you need to give developers into a single file.
Slicy is a Photoshop supporting application that allows you to name layers or groups with asset names (png, gif, etc) and export all the required assets for a project at once. It’s great with scratch files.
Slicy can automatically export assets when your Photoshop file changes. This can be a big time savings for designers.
Android designs may require more assets for drawable-hdpi drawable-idpi drawable-mdpi and drawable-xhdpi formats.
When making assets for Android, 15% of your 2x image size allows you to create android xhdpi artwork. The nine-patch re-sizer tool can then create the other assets you need.
The iOS app icon template can help you assemble all the image assets you need for iOS icons.
WhatFont is a tool (bookmarklet) for finding what fonts a Web site is using.
CSS Hat is a Photoshop plug-in that shows you the CSS code you need for
Sprite Cow is a free tool from managing CSS sprite images.
Retina.js automatically looks for retina versions and uses those when they are available.
When working with CSS, make sure you use the original size of an image in your code to resize it, not the original code.
There is no science to creativity. It’s about having the right people in place to make the right choices.
In his Billboards & Novels talk at An Event Apart in San Diego, CA 2013 Jon Tan talked about important considerations for font setting and selection on the Web. Here's my notes from his talk:
The Web is reading: how can we give them a better experience doing that?
Language is human communication through the use of written and spoke word in a structured way. Words are gestures that paint pictures in our mind.
A recent study found that “there are important differences between good and poor typography that appear to have little effect on reading speed and comprehension.” People are really good at making sense of even bad writing.
This same study though found that “good typography induces a good mood.” Putting people in a good helps them complete tasks and even underestimate how long the task took them. Basically, time flies when you are having fun. Good typography can help with that. That’s why as designers we should care about good type setting and selection.
The Web is a crude medium for typographers because they have to deal with a wide range of devices: different pixel density and screen sizes.
In addition to huge differences in the quality of screen resolutions, devices can have distinct rendering environments for type: standard smoothing, direct write, clear type, core type + core graphics, etc. This introduces variation in when fonts get anti-aliased (font size) and how they look when smoothed.
Often fonts have to be redrawn several times to work well on many screens.
A typeface is an idea. It will be redrawn for when/how it is used. For fonts that can mean different adjustments for print and for screens. For example, Matthew Carter’s Bell Centennial font was designed for high-speed printing in phone books where ink can bleed. Similarly, Abril and Siri fonts have variations that adjust for screen differences.
Carter also designed Verdana and fonts optimized for the screen.
Fonts for the Screen
Some fonts are optimized for Web. Lean towards those.
Check that the font you want is licensed for Web site use.
Test the smallest screen size first or on the most adverse screens where fonts are likely to have rendering issues.
Confirm language support. If you require certain languages, make sure they are available.
What font variants and features do you need? old style numbers, punctuation, spaces, fractions, small caps, symbols, ornaments, ligatures, etc?
Legibility is taking delight in the smallest things. Because the small details matter.
Letters within a word are recognized simultaneously. We skip along lines in saccades with pauses and fixations that allow use to understand groups of letters before reading on.
It's really important that people can recognize letter forms.
The text “agh! iIl1” is a good way to get a flavor of a font. It helps you see how legible a face is and it’s characteristics.
Kerning and ligatures: text-rendering and optimizeLegibility can be set on Safari and Chrome to enhance font rendering.
Hyphenation styling options are supported in new versions of FireFox, Safari, IE10, and hopefully more browsers soon.
Open Type features are coming soon but you can begin to use them in a progressive enhancement workflow. These elements allow you to turn on/off specific open type features within fonts.
Scan paths are how we move visually through Web pages. Hierarchy can guide people through the elements within a layout. Aim for deliberate interruptions: using position, density, space, hue, luminosity.
Use interruptions for meaning not just artistic flair.
The measure is how long a column should span in order to remain legible. A good average is 40 to 50 characters.
Look for interruptions in the scan path. Squint to see what catches your attention. If everything is calling for your attention, then you can't focus on anything.
There are no rules just good decisions. Remember there’s nuance and subtlety behind design.
Emotional Communication
Sometime there are no words. We recognize faces in 40ms and have an emotional reaction without consciously knowing we’ve seen a face.
Language can be insufficient to explain the things we are seeing and feeling.
There are 4.2 million colors on an advanced display but we don’t have names for all of them.
We communicate something emotional with the font we choose and how we set them. Language is not necessary for emotion.
Fonts are way-finding apps for emotions. Embedded in fonts is an idea that can communicate to people and affect their mood on a visceral level.
We are trying to get people to destinations. To create impact (short form text) or immersive experiences (log form text).
Type shapes our experience. It paints pictures in our mind.
“Details in typefaces are not to be seen but felt.” –Erik Spiekermann
It's all about emotion –use it for doing the right thing with type. “Don’t think. Feel.”
In his The Map Is Not The Territory presentation at An Event Apart San Diego CA 2013, Ethan Marcotte shared his thoughts about the changing definition of the Web and his philosophy for making broadly accessible experiences. Here's my notes from his talk:
Maps capture our understanding of a space. They make us aware of our surroundings and make things feel a little less foreign.
Randal developed a new map for New York. 2 out of every 5 buildings in New York were “mapped over”. This system was designed for use to create regularity. His was a system that became beautiful through use. Randal’s map was attempting to define a new territory: what could a territory be or should be.
We’ve been focused on a relatively small portion of the Web: a few desktops & laptops. We carried over existing ideas (canvas, composition, typography) about design and processes from our knowledge of print.
Mobile reminded us that the control we had over the Web was an illusion. We’re now keenly aware people want to access our content wherever and whenever they want.
We used a number of techniques to make react to an ever changing set of devices on the Web.
The three main ingredients of a responsive design: fluid grid, flexible images, and media queries. This is an attempt to embrace the fluidity of the Web and design across device boundaries. This simple recipe has blossomed into lots of amazing examples.
The movement beyond the desktop is continuing into multi-device experiences. Mobile is driving this new reality forward.
We’re drawing a new map and marking it with new sites both responsive and device specific. But this map is far from complete.
Building A Responsive Application
Editorially is a completely responsive application for collaborative writing.
Fluid grid: target/context = result. Starting from a pixel based layout you can determine the percentages you need to create a flexible design.
Every point in a design allows you to consider whether you want to make major or minor shifts in a design using media query breakpoints. This is a cascading waterfall effect. Start from a baseline small screen experience and enhance as you go wider.
Sometimes it is helpful to step back from the page and instead focus on a system of layout components.
Small screen interfaces force you to simplify elements like navigation menus. To do so, you may sort tasks into logical groupings. This information sort can apply to all screens.
When you move to larger screens, you can reposition elements and even pull some elements out from a menu into the mani navigation. Absolute positioning allows you to do this.
Try to separate priority and layout. In a baseline layout, use the HTML structure to reflect the importance and sequence of content and actions.
Use breakpoints to protect your content.
Toward a New Map
Many sites have been having success with responsive design. The Boston Globe and several e-commerce sites have published statistics about the positive impact responsive redesigns have had.
The Tehan-Lax and Oakley Moto sites are very beautiful designs but very large in terms of file size from 3MB to 85MB.
Responsive design has often been criticized for being too heavy (not performant enough). But the truth is most Websites are much to heavy for today’s reality.
In 2009, the average size of a Web site was 320kb. Today in 2013, it is 1.4MB. In just over two years, we’ve tripled in size. Moore’s law has not kept up with bandwidth.
More people in the world have mobile devices than access to toilets and latrines. In Africa, 60% have mobile devices (700M). That’s more than have access to clean water.
Mobile devices are shared across multiple people in many developing nations. This is slowly changing as smartphones get cheaper.
A number of unique mobile services in Africa are all designed for reach.
What’s happening in these developing areas is emblematic of what’s happening across the World. A large portion of the world is coming online now, on less capable devices and networks than we are used to. Are we ready for this new reality?
Randal developed a new map for New York. 2 out of every 5 buildings in New York were “mapped over”. This system was designed for use to create regularity. His was a system that became beautiful through use.
Randal’s map was attempting to define a new territory: what could a territory be or should be.
We need to move toward a sustainable model for Web design through reduction and reuse.
When Youtube redesigned their player page to be 98KB vs. 1MB, they found the average load time went up. They had accessed markets they couldn’t reach before due to their high load times.
By keeping sites light and accessible we can reach new audiences we may have kept out previously.
A performance budget can help you manage the size of your pages.
Grunticon is a tool that can take a folder of SVG images, create fallback PNGS, and write the CSS code you need to use the SVG images on your site.
We need a new definition of beautiful for the Web: one marked by greater access.
The BBC uses a simple test for “cutting the mustard” allows you to provide an experience to everyone without sacrificing experience for more capable devices.
Editorially does the same thing, checking for the capability of the device to determine if it should load a dynamic editor or not. Browsers that can't load the editor, still load the content so you can read (but not edit).
Let's accept the ebb and flow of things and the fact that we surrender control to our audiences.
Let’s outline a new map that optimizes for each across many people no matter what part of the territory they reside in.
If SharePoint and Facebook had a baby, it would look a lot like Igloo (without the recessive balding or oversharing tendencies). Hosted, managed and with a major release every 90 days, Igloo is a whitelabel content platform built for today’s needs. We also have Sandwich Video.
“We’re at the cusp of understanding the ultimate value of web publishing platforms, particularly ones that work cross-domain.”–Matt Mullenweg of WordPress.
It is a partial crossword solver, because it only helps solve a particular category of crossword clues - those in which the clue (which is usually a sentence or phrase) contains both a "definition" of the answer as well a hint of some kind that leads to the same answer. This solver tries to compute the answer using both the definition and the hint, and checks whether the results match. Ingenious.
I found it interesting because this is a somewhat difficult problem, and yet the author managed to create a solution (involving NLTK and parsing) that works in many, if not all cases.
Also, long ago, in college days, I had written another kind of partial crossword solver (in BASIC); it was much simpler, using a brute force method - what it did was help solve the kind of crossword clues in which the answer is a permutation of a substring of the characters comprising the clue sentence or phrase. The program would generate and display on the screen, all possible permutations of all possible substrings of the sentence, that were of the same length as the answer. Then you had to view those permutations and guess whether any of them was the right answer, based on the clue.
I wrote the permutation-generation code by hand, but saw recently that the Python itertools module has methods to generate permutations (as well as combinations) from sequences:
During Django Con, I was asked how to use Circus to run & monitor a Python
web application. The documentation has no single page step-by-step tutorial
yet, so here goes... this blog post will be integrated into the documentation
for the next release.
Installation
Circus is tested under Mac OS X and Linux, on the latest Python 2.6 and 2.7.
To run a full Circus, you will also need libzmq, libevent &
virtualenv.
This config file tells Circus to bind a socket on port 9999 and run
3 chaussettes workers against it. It also activates the Circus web
dashboard and the statistics module.
Let's use the circusctl shell while the system is running:
$ bin/circusctl
circusctl 0.7.1
circusd-stats: active
circushttpd: active
webapp: active
(circusctl)
You get into an interactive shell. Type help to get all commands:
(circusctl) help
Documented commands (type help <topic>):
========================================
add get list numprocesses quit rm start stop
decr globaloptions listen numwatchers reload set stats
dstats incr listsockets options restart signal status
Undocumented commands:
======================
EOF help
Let's try basic things. Let's list the web workers processes and add a
new one:
(circusctl) list webapp
13712,13713,13714
(circusctl) incr webapp
4
(circusctl) list webapp
13712,13713,13714,13973
Congrats, you've interacted with your Circus! Get off the shell
with Ctrl+D and now run circus-top:
$ bin/circus-top
This is a top-like command to watch all your processes' memory and CPU
usage in real time.
Hit Ctrl+C and now let's quit Circus completely via circus-ctl:
$ bin/circusctl quit
ok
Next steps
You can plug your own WSGI application instead of Chaussette's hello
world simply by pointing the application callable.
Chaussette also comes with many backends like Gevent or Meinheld.
We are excited to announce that Enthought is undertaking a multi-year project to bring the strengths of NumPy to high-performance distributed computing. The goal is to provide a more intuitive and user-friendly interface to both distributed array computing and to high-performance parallel libraries. We will release the project as open source, providing another tool in [...]
So, in relation to the work with Jep ( http://www.nidelven-it.no/weblogs/hosting/blog_entry?id=1368... ) - I've been building a script that can build and setup Jep, Jython and CPython in a directory, and then have a compare.sh script that runs the same code on the 3 different systems.
Here's the output from the generated compare.sh file:
morphex@copyleft-laptop:~/projects/self/jython_jepp_installer6$ ./compare.sh Starting comparison of Jython, Jepp and CPython.. Starting with Jep.. 0.39471411705 0.341079950333 0.333596944809 0.34021282196 0.322955131531 0.322613954544 0.322247982025 0.323844909668 0.319895029068 0.324920892715 Ran in milliseconds: 3878.0 Now Jython.. 1.25800013542 0.579999923706 0.436999797821 0.361000061035 0.43799996376 0.287999868393 0.289000034332 0.910000085831 0.289000034332 0.290999889374 Ran in milliseconds: 7576 Now CPython.. 0.321110010147 0.312225103378 0.312016010284 0.309517145157 0.30745100975 0.313014984131 0.312664985657 0.312491893768 0.311804056168 0.312137126923 Ran in milliseconds: 3165
As you can see, the Jep and CPython scripts are fairly stable in terms of execution speed while Jython varies a bit but gets faster (probably due to the HotSpot technology). If you want to change the test to something else, you can try "./jdk1.7.0_21/bin/java -jar usr/lib/jython-standalone-2.5.3.jar -m compileall -l ." and mytest.py will be recompiled, along with the other .py files.
Now, feel free to use the install.py script as you like, I think it's a good example of how to setup the whole thing in a specific directory.. there was some hair-pulling to get the entire build process setup so that linking and dependencies were setup the right way.
Fun to work with a mix if Python, Java and Bash scripting for a change. I think being able to use Python to script for example prototypes or even production code is a big win in terms of productivity.. weak typing has its place in rapid application development. :)
You may have seen the joke “Enter any 12-digit prime number to continue.” I’ve seen it floating around as the punchline in several contexts.
So what do you do if you need a 12-digit prime? Here’s how to find the smallest one using Python.
>>> from sympy import nextprime
>>> nextprime(10**11)
100000000003L
The function nextprime gives the smallest prime larger than its argument. (Note that the smallest 12-digit number is 1011, not 1012. Great opportunity for an off-by-one mistake.)
Optionally you can provide an addition argument to nextprime to get primes further down the list. For example, this gives the second prime larger than 1011.
>>> nextprime(10**11, 2)
100000000019L
What if you wanted the largest 12-digit prime rather than the smallest?
>>> from sympy import prevprime
>>> prevprime(10**12)
999999999989L
Finally, suppose you want to know how many 12-digit primes there are. SymPy has a function primepi that returns the number of primes less than its argument. Unfortunately, it fails for large arguments. It works for arguments as big as 2**27 but throws a memory error for 2**28.
The number of primes less than n is approximately n / log n, so there are about 32 billion primes between 1011 and 1012. According to Wolfram Alpha, the exact number of 12-digit primes is 33,489,857,205. So if you try 12-digit numbers at random, your chances are about 1 in 30 of getting a prime. If you’re clever enough to just pick odd numbers, your chances go up to 1 in 15.
Obviel is a client-side web framework that supports powerful UI
composition based on an easy to learn core. On top of that Obviel adds
a lot of features, such as templating, i18n support, form generation
and validation, and routing. Obviel stays close to HTML but lets you
build sophisticated components when you need to.
Obviel has come a long way since its beginnings. On top of the core
we've added a template language, an internationalization system that
integrates with JavaScript and templates alike and a routing
library. So it's high time for the One Dot Oh release!
Integrated internationalization (i18n) based on gettext. In a world
with multiple languages we need UIs that can be easily translated to
other languages. I haven't met a client-side web framework yet that
can beat Obviel in this area.
Obviel offers an i18n approach that lets you mark strings in your
JavaScript code in the gettext style:
_("My translatable string")
and also lets you mark translatable strings in templates:
<p data-trans="">My translatable string</p>
Obviel then offers tools to automatically extract these strings into
a .pot file that you can offer to translators in various ways;
gettext has vary extensive tool support.
Routing: path (/foo/bar) to object and object to path with
Traject.
Traject lets you build a nested navigation space on the
client-side. Not only can you route a path to an object, but you can
also generate a path for an object, something that results in
cleaner and more decoupled code.
What's next for Obviel?
We have been transitioning the code from bitbucket to github and from
mercurial to git to make it more accessible to JavaScript hackers who
are more familiar with git. We're still busy updating the docs, but
the transfer has been complete and the code now lives on github.
We've been doing lots of research on using a JavaScript module
system for Obviel so we can better maintain the codebase. I've been
overwhelmed by the options, but soon we'll pick one, I promise! We'll
also introduce various JavaScript codebase maintenance tools such as
the Grunt task runner.
We are still busy working on a configurable transceiver framework for
integrating Obviel with a diversity of backends (HTTP, websockets,
localstorage): Obviel Sync. More on this soon!
As some of you may have noticed, the AdSense bar no longer exists on my blog, this is due to Google recently revoking my AdSense account, I am quite sure it is in regards to mentioning it on a page. Currently users who have an account are able to opt'd out of either being tracked by Analytics or have no ads served to them. I will be removing this feature soon, as I am planning on self-hosting ads from prospect publishers. If you have a Python or Django related project which you would like to adverse on this blog, please contact me. Having a way to fund this website will allow me to publish more quality articles and tutorials. When a new article is posted, this blog receives over 1,000 hits in that single day. These are 1,000 prospect users which use Python and maybe Django who will see your advertisement. These can also be users who are just learning Python, so books and courses are also welcome.
Currently the ad serving system has yet to be implemented, so at this time I am only asking prospect advertisers to provide me with a proposal on how the ads should be served to users and costs they might be willing to pay. For the record this blog has been online for well over a year now and receives many returning users due to the quality of the content which is provided. This website is also much more than a blog, as it has other features which bring users back for more.
I have an art blog over at tumblr where i post my (almost) daily doodles. Usually i post them with the Tumblr UI, but lately i i got annoyed but that way and hacked something together to post images directly from my windows exlorer.
Modify the "Twitter Three-legged OAuth Example" Script from python-oauth2 to use tumblr endpoints and insert your consumer key and secret
Run the script and note the oauth token and secret the script outputs
My actual Poster Script (pretty less coe :-) ), add your keys and blog url here
importpytumblrimportsysclient=pytumblr.TumblrRestClient('<consumer_key>','<consumer_secret>','<oauth_token>','<oauth_secret>',)client.create_photo("your blog url",state="published",data=sys.argv[1])
Add Script to Windows Explorer context menu follwoing this tutorial
It's that time again! Planning for PyCon 2014 is well underway, and we're currently preparing for the launch of our new site. With the launch comes a unique opportunity: Is your organization interested in being a launch day sponsor?
PyCon 2013 launched on July 9, 2012 with 21 sponsors pledging support, leading the charge that drew over 150 organizations to pitch in to the biggest and best Python conference yet. We're planning a similar go-live date for the 2014 site, and we're building up our cadre of supporters for the April 9-17 conference taking place in Montreal, Quebec, Canada.
Your organization's support enables PyCon to do the awesome things that it does. 2013 introduced a number of new events that we've heard great feedback on, so we'd like to keep doing those things and more. For example, the inaugural Young Coders tutorial was such a hit that there are already plans around the world for user groups to replicate it, and we're looking forward to doing a PyCon 2014 rendition. Programs like Financial Aid, which saw its budget increased and then quickly doubled to reach $100,000 USD, are greatly enhanced by the giving of sponsors.
Along with benefiting the community, sponsorship of PyCon brings many benefits to its supporters. We hear it year after year that there is no better place to hire Python developers than at PyCon. We offer sponsors a place on our site to promote their open positions, and we run a job fair on-site that has been a huge success. The Expo Hall is a great place to market your latest projects and to network with 2,000 eager Python developers. The value is unparalleled in the conference scene, especially after considering our flexibility to work with each and every organization. We even offer a 50% discount to organizations under 25 people. See https://us.pycon.org/2013/sponsors/whysponsor/ for more thoughts.
While we're still finalizing the sponsorship prospectus, it will be very similar to the one we used in 2013 at https://us.pycon.org/2013/sponsors/prospectus/. We'll share the details as soon as we complete them, and any questions can be forwarded to our Sponsorship Chair, Jesse Noller.
For 2014, PyCon will have a maximum capacity of 2,000 attendees. We've sold out the last two conferences and we're expecting a third, so mark your calendars for April 9-17, 2014. Other dates to remember are our Call for Proposals in July, and we're looking forward to opening registration in September. We're planning for the conference schedule to be laid out in December, just in time for the holidays.
If you don't have a passport, don't forget that Canada requires one. US residents should see http://travel.state.gov/passport/ for details.
Do you need to display raw Django template code in your Django 1.4 project? Look no further than this script! It's rather crude, but gets the job done. I haven't yet updated a few Django websites to Django 1.5, which has a new template tag to do this for you, so I created this script to use in legacy Django sites, and it works like a charm!
You should Pygments to highlight the syntax like I do on this blog of course. If you are using Django 1.5 or greater, you should use the verbatim template tag over this.
(This is a re-post of what I sent to python-announce@ but with several screenshots attached)
I’m very happy to announce the first release of Zato, the next generation ESB and application server, available under a commercial-friendly open-source LGPL license.
My “speed up pypi installs” PEP438 has been accepted and transition phase 1 is live: as a package maintainer you can speed up the installation for your packages for all your users now, with the click of a button: Login to https://pypi.python.org and then go to urls for each of your packages, and specify that all release files are hosted from pypi.python.org. Or add explicit download urls with an MD5. Tools such as pip or easy_install will thus avoid any slow crawling of third party sites.
Many thanks to Carl Meyer who helped me write the PEP, and Donald Stufft for implementing most of it, and Richard Jones who accepted it today! And thanks also to the distutils-sig discussion participants, in particular Phillip Eby and Marc-Andre Lemburg.
I have completed the migration scripts for deploying the services
currently running on cube. They have been run against our new
machine, dornkirk which is currently running with a snapshot of data.
in /etc/hosts. Please tests it, and verify that things appear to be
working, but be aware that any changes will be lost, when the
transition occurs.
At some point Monday or Tuesday, there will be some downtime for mail
and the mailing lists, as mail-service is migrated to the new
machine. For those that have accounts on cube, your data will be
copied to the new machine at this point.
On Wednesday, at about 10 MDT (16 UTC), there will be downtime of all
twisted services, as live data is transfered over. This may last
up-to a couple of hours.
This work is made possible by the sponsorship of individuals and
organizations which have donated to the Twisted project, part of the
Software Freedom Conservancy, a not-for-profit organization that helps
promote, improve, and develop open source software. Thanks!
ScrollView has been re-factored with new physics calculations. To be exact, the scrollview doesn’t calculate anything now, it just pass the touch position to an Scroll effect. This class calculate the movement’s velocity, and the over-scroll’s distance (means how far you scrolled out of the bounds). Then, we implemented 2 visual effects that use the over-scroll to make the scrollview act as a Damped spring, and/or to fade out the scrollview if you over-scroll too much.
Garden: a separated organization for centralize user’s widgets and addons. You can create garden packages very easily, and import it in the source code with just “kivy.garden.packagename“. Few garden packages are already available!
Finally, I had some time to try it myself, and I managed to make it work pretty well with Robot Framework and Travis-CI:
I try to start from the very beginning, but if you already have Robot Framework tests, or even Travis-CI-integration, you could just skip these initial steps.
Bootstrap Templer
Create buildout directory for Templer installation:
Be careful to answer true for the following question about including Robot test templates:
robot tests (should the default robot test be included) [false]: true
Run buildout:
$ cd example.product $ python bootstrap.py --distribute $ bin/buildout
Update Robot Framework tests to be Selenium grid ready
Using Sauce Labs with Robot Framework (Selenium library) is similar to using robot with your own selenium grid. It mainly requires making the browser opening keyword configurable with a few selected variables.
Plone site [Tags] start Go to ${PLONE_URL} Page should containPlone site
*** Keywords ***
Start browser ${BUILD_INFO} = Set variable ... build:${BUILD_NUMBER},name:${SUITE_NAME} | ${TEST_NAME} Open browser ${PLONE_URL} ${BROWSER} ... remote_url=${REMOTE_URL} ... desired_capabilities=${DESIRED_CAPABILITIES},${BUILD_INFO}
Let me explain what all those variables are about:
ZOPE_HOST should match the host for which ZServer is started during the test setup (ZServer host is configured with ZSERVER_HOST-environment variable. It defaults to localhost.
ZOPE_PORT should match the port number which ZServer is started to listen during the test setup (ZServer pot is configured with ZSERVER_PORT-environment variable. It defaults to 55001, but we reconfigure it later by environment variables with one of the ports currently supported by Sauce Labs.
ZOPE_URL is a convenience variable for accessing Zope application root.
PLONE_SITE_ID is the Plone portal object id (and path name) for the test site. It default to plone, but it can be configured with PLONE_SITE_ID-environment variable. The default should be ok for most cases.
PLONE_URL is a convenience variable for accessing the Plone site front-page.
BROWSER selects the browser to run the tests with. The supported values depend on Selenium Python-package and can also be read from the documentation of Open browser-keyword in Selenium2Library keywordsdocumentation.
REMOTE_URL enables testing with Selenium grid by defining the url of the Selenium hub to use.
DESIRED_CAPABILITIES is used to pass various extra parameters for Selenium hub (e.g. the browser version to use or test metadata).
BUILD_NUMBER is used to identify the Travis-CI build on Sauce Labs.
When robot tests for Plone are run using bin/test, all the variables above can be overridden by defining corresponding ROBOT_-prefixed environment variable (e.g. ROBOT_REMOTE_URL).
Add Travis-CI configuration with Sauce Labs -support
There are a few steps in adding Travis-CI-support into your product.
At first, create travis.cfg to do the required magic for minimizing buildout-time and setting a few required environment variables. Thanks to the great community, we can just extend a public template:
Lines 18-21: Define required environment variables for letting robot to use Sauce Labs.
Lines 22-25: Define build matrix for running the tests with Sauce Labs' default Firefox, Internet Explorer and Mobile Safari. tunnel-identifier-stuff is required for Sauce Labs to allow more than one simultaneous tunnels for the same user account.
Next, define your Sauce Labs username and access key as secret, encrypted, environment variables SAUCE_USERNAME and SAUCE_ACCESS_KEY.
Currently, Sauce Labs offers unlimited free subscription with three simultaneous connections (e.g. running tests for three different browsers at the same time) for Open Source projects. Just make sure to register the account for your project, not yourself. Public repository url is required for the creating the account and it cannot be changed afterwards.
Install Travis gem for Ruby (and install Ruby before that when required):
$ gem install travis # or sudo gem ...
use travis-command to insert encrypted environment variables into the product's .travis.yml:
Make sure to use your own Sauce Labs username and access key, and your product's Github-repository path (with format username/repo).
Finally, enable Travis-CI-tests for you product either at Travis-CI.org or at GitHub.
Done. If I forgot something, I'll update this post.
Behind the basics: Test level status reporting for Sauce Labs
By default, Sauce Labs doesn't really know did the Selenium tests on it pass or fail. To pass that information from our test runner on Travis-CI to Sauce Labs, we need to add some extra code into our test setup.
At first, append the following into the end of src/example/product/testing.py:
This code defines a custom Robot Framework keyword library with a keyword for passing the test status (and other information) back to Sauce Labs.
Next, we update src/example/product/tests/robot_test.txt to store the session id during the setup of every test and send the test result back to Sauce Labs during the teardown of every test:
As you may already know, the main issue in testing Plone add-ons on Travis CI is its strict 15 minute time limit on running your test suite. And as you may also know, 15 minutes is not much time for our dear buildout to gather all the required dependencies of Plone or plone.app.testing, and still run our test after the buildout.
As expected, neither did I get far without having issues with the time limit. And for some reason, I couldn't get the earlier solutions to work for me. Eventually, I found out a new solution, surprisingly, with the help of Plone Unified Installer.
Because Plone Unified Installer comes in a single downloadable package and includes a complete buildout-cache usable also in a test buildout, I realized, that it could speed up my test buildout a lot, and it did. Yet, with Plone 4.3 shipping with Dexterity, I would expect it to speed it up even more.
Update: The method described here is adopted as part of buildout.plonetest, which includes more generic configuration to work with all Plone-versions.
Nothing special here. I expect setup.py of the tested package to include complete extras_require={'test': ... } with all the required dependencies for testing.
So, on a local machine, python bootstrap.py, bin/buildout and bin/test combo should run tests for a freshly cloned package repository just as expected.
travis.cfg
[buildout] extends=buildout.cfg parts= download install test eggs-directory=buildout-cache/eggs download-cache=buildout-cache/downloads
Note, how we need to create a buildout-cache-directory for downloads as defined earlier in travis.cfg. The rest should be easy: we just do the bootstrap and run our tests with sane buildout-options, and... that's all.
I'll show you, how to create your first zope.testrunnercompatible Robot Framework tests for your custom Plone add-on. Also, everything you already know about plone.app.testing, zope.testrunner or Python unittest-library, should apply here.
Update: An up-to-date documentation for writing Robot Framework tests for Plone is available as part of Plone Developer Documentation.
Environment
Here's our dummy Plone add-on package with its testing buildout: