Here’s another example of use:
from dulcinea.spec import any, sequence, require, match
L = [1,2,3,4]
test_is = any(str, sequence(int))
require(L, test_is)
# used like an assert, returns None
match('some string', test_is)
# returns True
require(1234, test_is)
# raises TypeError: iteration over non-sequence
require([1,2,3,'4'], test_is)
# raises
# TypeError:
# Expected: any(str, sequence(int, anything))
# Got: [1, 2, 3, '4']
Read the dulcinea.spec code for more insight – its just over 500 lines and the core is very straightforward
I’ve been only barely following the Python community discussion around static typing (and decorators and other controversial subjects for that matter). I very much like readable Python and tend to shy away from anything that looks, well, obtuse. Perhaps it simply takes a while for me to get my head around things too.
Smalltalk doesn’t appeal to me because you have to teach yourself (I think) a specific way of reading the code in order for it to make sense, while Python just sounds like english as I read it in my head – that and the lack of extraneous punctuation and enforcement of whitespace are among my favorite attributes of the language.
Types I personally can live without, but was reminded about the subject when digging through a helper module of Quixote, the web framework I use.
Recently I left a comment on the Agile testing blog regarding Dulcinea’s “spec” facility, of which I have recently become enamoured.
Examples – here’s a snippet using a “spec” provided by pure python functionality in the the “Dulcinea” compliment to Quixote, a web development tool kit.
subject_is = any(str, sequence(SubjectClass))
Meaning subject is any of “str” or a squence containing SubjectClass. That feels powerful and is much tighter looking than the tests I would normally have littered around in my classes or in module specific functions.
Using this later in some code, in “assert” style:
require(subject, subject_is)
What I like about it is that its simple to read, and write, and lends itself to desiging classes which can serve multiple uses often by overriding just the spec, not entire methods.
class NamedItemFolder:
items_class_is = dict
item_is = NamedItem
name_is = NamedItem.name_is
def init(self):
self.items = self.items_class_is()
def add_item(self, item, name=None):
require(item, self.item_is)
require(name, any(self.name_is, None))
. . . do stuff
What you get are easy to write, visually appealing, useful contraints. What’s more, I don’t have to be an OO uber-programmer in order to find use from this.
http://www.mems-exchange.org/software/dulcinea/ – highly useful, also check out the Quixote web development framework and Durus, an object database, and the other goodies they’ve made available…