- The 'default' feature will be more aligned with the @vocab mechanism of RDFa 1.1 (and JSON-LD)
- Keywords ('reserved') can be redefined. There are preset top-level keys, but that's it. (A parser could parameterize that too of course.)
- No CURIEs - every token is "imported" from a vocabulary.
- Types will be powerful. They'll determine default 'vocab' for a resource description (i.e. JSON object), and you can also import terms locally for a type (so that a Person title is foaf:title although 'title' is globally from 'dc').
- If there are multiple values for a term (i.e. multiple triples with the same subject and predicate), a defined prefix or suffix will be added to the term. This is an experiment to make this nagging problem both explicit and automatic.
- The 'define' will be reduced to a much less needed component. Using 'autocoerce', pattern matching on values will be bravely used to coerce mainly date, dateTime and URI references to their proper types.
- Incoming links can be represented as 'inverseOf' attributes, thus making it possible to frame more of a graph as a tree.
- Named bnodes are out (though they might be snuck in via a "_:" link protocol..). Anonymous bnodes are just fine.
Sunday, July 03, 2011
Resources In Various Frames of JSON
Thursday, November 12, 2009
The Groovy Times
It has been so long since my last post here. I've twittered away like the rest of my peers. I guess I could dish out details from my personal life of the past year now. To examine my interrupt. I won't.
I've been using Groovy a lot in my work on the Swedish Legal Information System. While the things I find interesting in this work deserve many separate posts, I'll just spend this one to drop some nice stuff about groovy.
"Why Groovy", you might ask? Oh dear. For "political" reasons (this is an entire topic of its own), I have to use Java. But the language Java is often so much overwork and ceremony; riddled with convoluted ways to make explicit patterns and formalisms. Dynamic languages are pragmatic. Sure they have flaws, but I find the compromise acceptable. There are probably thousands of articles discussing this, and I prefer to debate it elsewhere (mostly with friends over lunch/dinner/beer).
I must deliver the bulk in Java, and Groovy is impressively close to Java, but with so much more expressive power (ease of use). (More than necessary? My pythonic side says "probably".) I've worked a lot with Jython the last decade, and some with JRuby. Groovy trumps them both (IMHO) when it comes to java library and java culture interoperability. I can spike, explore, and make tests in groovy. Then I add all this horrendous checked exception handling, spinkle some semicolons for the grumpy old compiler, and finally explode-a-pop all the def:s to bulky types when things need to "harden" (to fulfil the contract of delivering .java...; the tests are left in groovy). Not a big deal (especially since I use an editor that makes code editing a breeze). And groovy cross-compiles nicely with traditional cruft.
So what have I used more specifically? Spock. Check it out. Rewrite ten of your JUnit4 tests in it, and if you go back, write ten more. Don't go back. If you're already testing with say JRuby, I won't push you, but I assure you Spock is worth looking at. Specs become liberatingly clear and thin. Data-driving some of them is pure joy. Mocking is dead simple. (Sorry, I won't put code examples here now: look at the spock docs for that. Try them out!)
For building, we do not use Gradle (not yet at least), but that scary beast of mindnumbing declarativity (which I'm usually for), dreadful xml (which I can handle due to prolonged exposure) and conflated purposes (no excuse here) known as Maven 2. It seemed paramount in the surroundings when we started, and won't go away soon. I use it as little as possible (and it is quite impressive when you let it do its thing).
Which leads me to the last thing I want to mention: how to use Groovy's very convenient, builtin Grape system (and its @Grab mechanism) together with my local maven2 artifact repo. That one in <~/.m2>, where all my local packages have been mvn install:ed (along with the umpteen dependencies).
The thing was, when I started, I naively thought things would kind of work at least semi-automagically. I've spent my time in CLASSPATH hell. I wanted groovy to tap into the local m2. Then I was disillusioned again, and attempted to run experimental groovy scripts via GMaven. Didn't fit my use cases at all (that thing is great at compiling, I leave it at that). I shellscripted the path from mvn dependency:build-classpath, then built pathing jars, then just felt quite uneasy (such moves work, but it's not particularly clean).
When Grape appeared I tinkered with the Ivy config in <~/.groovy/grapeConfig.xml>. It surely looks so simple. I couldn't figure it out. Benhard could. Neat.. But alas, that solution copies all the dependencies from the local m2 repo to grape's ivy repo. And I could not get it to grab my new local SNAPSHOT-stuff as they landed either (in spite of eleventy ivy attributes claiming to force all kinds of checks).
Then it appeared, from a combination of fatigue and taking a step back (cue magic "aahh").
Use Groovy's Grape with your Local Maven File Repo
Locate $HOME/.groovy/grapeConfig.xml. If it doesn't exist, see the Grape docs for how the default version should look.
Then add, directly after (xpath) ivysettings/settings, the following directive:
<caches useOrigin="true"/>And, in (xpath) /ivysettings/resolvers/chain, after the first filesystem, add:
<filesystem name="local-maven2" m2compatible="true">
<ivy pattern="${user.home}/.m2/repository/[organisation]/[module]/[revision]/[module]-[revision].pom"/>
<artifact pattern="${user.home}/.m2/repository/[organisation]/[module]/[revision]/[artifact]-[revision](-[classifier]).[ext]"/>
</filesystem>
With that in place (pardon the line width), Grape (and thus @Grab) will happily use anything it finds in your local m2 file repo, without copying the jar:s. (It will still download other stuff to use to the default ~/.groovy/grapes/, which is fine by me.)
That's it for now. There are lot's of cool stuff with Groovy, if you're in a Java environment and want to ackowledge that without giving up modern power.
Three years ago I looked at Scala for the first time, and found it quite interesting. Then I got a bit spooked by the academic machinations of it. Lately that interest has been quite rekindled though, and the future will show what will come of that. I am very happy to have used Groovy so far though, and I would certainly recommend it. Scala may yet be for tomorrow, Groovy is for the Java user of right now.
(Of course, I recommend to continuously look beyond the JVM as well. Simplicity is hard to reach in increments without designing for it from the start. But things will reasonably evolve in most "camps".)
Thursday, November 27, 2008
Labelled Reduction as A Good Thing
from urlparse import urlparse
print urlparse(
"http://localhost:8080/doc/something;en?rev=1")If run with Python 2.5, you get this tuple:('http', 'localhost:8080', '/doc/something',
'en', 'rev=1', ''), whereas in 2.6 it is a namedtuple:ParseResult(
scheme='http', netloc='localhost:8080',
path='/doc/something',
params='en', query='rev=1', fragment='')The last one is unpackable just like a regular tuple, but you can access the parts as attributes as well. This little "data struct" is quite handy, since I don't like to access tuples by index, but quite often pass them around and only access some piece of them at a time.(With these you don't need to create full-fledged classes for every kind of instrumental data. (Sometimes coupling data and functionality in a single paradigm may be a coarse hammer, treating nails and iron chips alike..) Nor resort to the use of dictionaries where you really want a "restricted value lens", if you will.. But this is another rant altogether.)
Of course, there's lots more to enjoy in 2.6 (the enhanced property for decorator use, ABC:s, json, 2to3 etc).
On a related note, do check out Swaroop C H:s excellent and free books on Python (2.x + 3.0(!)): A Byte of Python. And if you're into Vim (you should be, IMHO) his new A Byte of Vim.
Saturday, September 27, 2008
Resources, Manifests, Contexts
While oEmbed is certainly quite neat, I very much agree with the criticism regarding the lack of RESTfulness, and that they have defined a new metadata carrier. I think oEmbed would work very well as an extension element in Atom Entry documents (who already have most of the properties oEmbed (re-)defines). Or by reusing (in such atom entry docs) e.g. Media RSS, as Stephen Weber suggested.
Granted, if (as I do hope) RESTfulness and Atom permeation on the web becomes much more well established (approaching ubiquity), this would be dead easy to define further down the line. (And signs of this adoption continue to pop up, even involving the gargantuans..)
But since it wasn't done right away, oEmbed is to some extent another part of the fragmented web data infrastructure — already in dire need of unification. It's not terrible of course, JSON is very effective — it's just too context-dependent and stripped to work for much more than end-user consumption in "vertical" scenarios. While oEmbed itself is such a scenario, it could very well piggy-back on a more reusable format and thus promote much wider data usability.
A mockup (with unsolicited URI minting in the spaces of others) based on the oEmbed quick example could look like:
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:oembed="http://oembed.com/ns/2008/atom/">
<id>tag:flickr.com,2008:/3123/2341623661_7c99f48bbf_m.jpg</id>
<title>ZB8T0193</title>
<summary></summary>
<content src="http://farm4.static.flickr.com/3123/2341623661_7c99f48bbf_m.jpg"
type="image/jpg"/>
<oembed:photo version="1.0" width="240" height="160"/>
<author>
<name>Bees</name>
<uri>http://www.flickr.com/photos/bees/</uri>
</author>
<source>
<id>tag:flickr.com,2008:/feed</id>
<author>
<name>Flickr</name>
<uri>http://www.flickr.com/</uri>
</author>
</source>
</entry>
The main point, which I have mentioned before, is that Atom Entries work extremely well as manifests of resources. This is something I hope the REST community will pick up in a large way. Atom feeds complement the RESTful infrastructure by defining a standard format for resource collections, and from that it seems quite natural to expose manifests of singular resources as well using the same format.
In case you're wondering: no, I still believe in RDF. It's just easier to sell uniformity one step at a time, and RDF is unfortunately still not well known in the instrumental service shops I've come in contact with (you know, the ones where integration projects pop up ever so often, mainly involves hard technology, and rarely if ever reuse domain knowledge properly). So I choose to support Atom adoption to increase resource orientation and uniformity — we can continue on to RDF if these principles continue to gain momentum (which they will, I'm sure).
Thus I also think we should keep defining the bridge(s) from Atom to RDF for the 3.0 web.. There are some sizzling activities on that respect which can be seen both in the Atom syntax mailing list and the semantic web list. My interest stems from what I currently do at work (and as a hobby it seems). Albeit this is from a very instrumental perspective — and as a complement, rather than an actual bridge.
In part, it's about making Atom entries from RDF, in order for simple RESTful consumers to be able to eat some specific Atom crumbs from the semantic cakes I'm most certainly keeping (the best thing since croutons, no doubt). These entries aren't complete mappings, only selected parts, semantically more coarse-grained and ambiguous. While ambiguity corrupts data (making integration a nightmare), it is used effectively in "lower-case sem-web" things such as tagging and JSON. (Admittedly I suppose it's ontologically and cognitively questionable whether it can ever be fully avoided though.)
We have proper RDF at the core, so this is about meeting "half way" with the gist of keeping things simple without loosing data quality in the process. To reduce and contextualize for common services — that is at the service level, not the resource level. (I called this "RA/SA decoupling" somewhere, for "Resource Application"/"Service Application". Ah well, this will all be clarified when I write down the COURT manifesto ("Crafting Organisation Using Resources over Time"). :D)
Hopefully, this Atom-from-RDF stuff will be reusable enough to be part of my Out of RDF Transmogrifier work. Which (in my private lab) has been expanded beyond Python, currently with a simple Javascript version of the core mapping method ("soonish" to be published). Upon that I'm aiming for a pure js-based "record editor", ported from an (py-)Oort-based prototype from last year. I also hope the service parts of my daytime work may become reusable and open-sourced as well in the coming months. Future will tell.
Tuesday, May 27, 2008
Representation Taxation
Tuesday, May 20, 2008
Memes and Principles, Intent
Wednesday, April 16, 2008
Getting lxml 2 into my gnarly old Tiger; going on ROA
lxml "Symbol not found" _xmlSchematronNewParserCtxt$ sudo port selfupdate$ sudo port uninstall libxml2@2.6.23_0 Activating libxml2 2.6.31_0 failed: Image error: Another version of this port thingy going on.) Then just:$ sudo port install libxml2 libxsltsite-packages) :$ sudo easy_install lxmlBut why?
- CSS selectors
- much improved "bad HTML" support (including BeautifulSoup integration)
- a relaxed comparison mechanism for XML and HTML in doctests!
Set up namespaces:
>>> xmlns("http://www.w3.org/1999/xhtml")
>>> xmlns(a="http://www.w3.org/2005/Atom")
We have a feed:
>>> http_get("/feed",
... xpath("/a:feed/a:link[@rel='next-archive']"))
...
200 OK
Content-Type: application/atom+xml;feed
[XPath 1 matched]
Retrieving a document entry with content-negotiation:
>>> http_get("/publ/sfs/1999:175",
... headers={"Accepts": "application/pdf"},
... follow=True)
...
303 See Other
Location: /publ/sfs/1999:175/pdf,sv
[Following..]
200 OK
Content-Type: application/pdf
Content-Language: sv
[Body]
Tuesday, March 27, 2007
Cutting Edges
On a related note, I've been using RDFLib a lot lately (around the clock as it seems). It's an honor to contribute in an ever so small way to it, and it's great to see it progressing so well (it's been mature for years if that needs to be said). The SPARQL-support is working, and along with Chimezie Ogbuji's FuXi there is now an even stronger Python RDF platform to work with.
Thursday, September 28, 2006
Within the Outer Space
oort.rdfview package. My code was quite illegible and obviously a case of failing to be "clever". A more "properly dressed" class-based approach was (as I honestly felt even when I first stepped off the beaten path) evidently much more easy to maintain. Still, state change is less evident in the flat representation of a class, which doesn't give a structural hint of the intended temporal aspect. Using stuff like IllegalStateException doesn't alleviate this much at all (it's a "formally polite design" though). The impression of "loading" a state and bundling a nice nest of code to unfold at each state change is a quite powerful aspect of closures, I guess.So I thought, let's do that in a somewhat declarative manner.. And thus I (just now) sketched up a way to declare a state change as an hierarchical closure nest which must be unfolded in the proper sequence:
class stateflow(object):
def __init__(self, start_func):
self.start_func = start_func
self.steps = []
self.reset()
def start(self, *args, **kw):
self._started = True
return self.start_func(*args, **kw)
def next(self, step_func):
self.steps.append(step_func)
def __getattr__(self, name):
return self.__dict__.get(name) or self._get_next(name)
def _get_next(self, name):
if not self._started:
raise BadStateError("Not started.")
step_func = self.steps[self._at_step]
if step_func.__name__ != name:
raise BadStateError("Must call %s before %s."
% (step_func.__name__, name))
self._at_step += 1
return step_func
def reset(self):
self._started = False
self._at_step = 0
class BadStateError(LookupError):
pass
#== Let's test it ==
@stateflow
def query(database, subject):
@query.next
def with_query_data(predicate):
@query.next
def run_query(context):
return database[subject][predicate] % context
database = {'s': {'p': "value in %s"}}
query.start(database, 's')
query.with_query_data('p')
assert query.run_query("context") == "value in context"
query.reset()
query.start(database, 's')
try:
query.run_query("context")
except BadStateError, mess:
assert str(mess) == "Must call with_query_data before run_query."
else:
assert False
query.reset()
try:
query.run_query("context")
except BadStateError, mess:
assert str(mess) == "Not started."
else:
assert FalsePretty interesting, I guess. Won't be putting that into my toolkit just yet though (if ever). So, dear closures, it was a nice experience, but I just have to let some of you go. Till next time, keep it simple!
(Oort 0.2 is on the way, by the by. I oort to create an introductory tutorial for it.. And a logo. Yes yes, of course; without a logo, what kind of a toolkit would it be?)
Wednesday, September 13, 2006
Think Outside The Box
- Some years ago, many developers sat in front of humongous 19" CRTs and about 1600x1200 or whatnot.
- Nowadays, most of us sit with sleek notebooks with quite the lesser screen size and resolution.
Thus, it's much more of an annoyance that we have to scroll through rows and rows of boilerplate and wrapped lines of type declaration harnessing. It simply has to go.
(Nevermind productivity or the fact that these new tiny things pack enough CPU power to make DNA sequence processing a BLAST (pardon the pun).)
Tuesday, September 05, 2006
All About the Package
Following is my little list of good starters when doing Python package development.
Most obvious: take a good look at setuptools (especially the concepts and usage of eggs, easy_install and pypi).
For testing, Nose is my one-stop-shop for now. Avoids the articificality of the xUnit-API; uses automatic discovery (with filtering); finds doctests if desired; uses coverage.py if available.
It's probably always wise to follow the practises of the most modern and well-renowned packages. I think Paste is a good example of this.