There IS a simple solution to work conveniently in git-svn with repository that has svn:externals set. You can clone all repositories to seperate trees, and instead of watching svn:externals, make hard links to the trees you need (remember to ignore them in git). The problem is you can't have hard links to directories... unless you're using OS X Leopard (they implemented it in order to get Time Machine to work).
This ability isn't exposed to the command line (ln makes an explicit check to prevent you from doing that), but the code to have it working(scroll down to listing 4) is trivial.
Update: When working with hard-linked directories, remember to be careful when unlinking them: rm wouldn't unlink the directory unless provided with "-r" option, which deletes everything recursively, leaving other hard links to that directory empty.
Wednesday, 8 October 2008
Getting svn:externals to work with git-svn and... Leopard
Autor:
Konrad
o
00:04
0
komentarze
Tuesday, 23 September 2008
Harness the power of wget
I finally invested enough time in reading wget's man page to be able to download file hierarchies exposed through http file server. The magic command is:wget -r -np -nH --cut-dirs=2 http://example.com/some/nested/directory
The switches mean:
- -r
- turns of recursive download
- -np
- no-parent - only links to files below in the hierarchy are followed
- -nH
- no-host - doesn't dump the files into directory named after host name
- --cut-dirs=2
- in addition to skipping host name skips also 2 topmost directories. In the example instead of some/nestes/directory the files are put straight into directory
Autor:
Konrad
o
01:36
0
komentarze
Wednesday, 21 May 2008
Getting fresh datastore while testing GAE apps
If you want to find out how to test you GAE apps, check out these two URLs first:
http://groups.google.com/group/google-appengine/msg/9132b44026040498
http://farmdev.com/thoughts/45/testing-google-app-engine-sites/
I want to show you how to clear the datastore quickly (yep, only that :>):
from google.appengine.api import apiproxy_stub_map
def clear_datastore():
datastore = apiproxy_stub_map.apiproxy.GetStub('datastore_v3')
datastore.Clear()
Autor:
Konrad
o
10:42
1 komentarze
Etykiety: gae, google app engine, testing
Tuesday, 29 April 2008
Outputting pdfs with google app engine
It's child easy, but not googleable yet. I used reportlab - a handy, pure-python pdf library. Here are the steps:
- Checkout reportlab into your app directory
svn co http://www.reportlab.co.uk/svn/public/reportlab/trunk \
reportlab - Write some pdf-generation code, like
The key is the canvas instantiation. The constructor takes a file-like object and writes into it. You might have noticed that the code is heavily inspired by this tutorial. The only difference is the creation of canvas.import wsgiref.handlers
from google.appengine.ext import webapp
from reportlab.pdfgen import canvas
class MainPage(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'application/pdf'
p = canvas.Canvas(self.response.out)
p.drawString(100, 750, "Hey, it's easy!.")
p.showPage()
p.save()
def main():
application = webapp.WSGIApplication([('/', MainPage)], debug=True)
wsgiref.handlers.CGIHandler().run(application)
if __name__ == "__main__":
main() - That's it. See? I said it was easy. You can run the dev_appserver or upload it to Google in order to see the results.
Autor:
Konrad
o
05:40
8
komentarze
Etykiety: google app engine, pdf, pdf generation, python
Thursday, 13 March 2008
Saturday, 16 February 2008
Brand new blog engine without a single line of code
Having investigated the new Google D&S forms feature, I decided to create a proof-of-concept blog application (OK - calling it an application is a *bit* an overstatement). It has some basic features, like form for entering entries and a feed. I doesn't have a site and is pretty much crippled. Still, quite good for 0 lines of code.
Here's the feed
And here's the new entry form. Feel free to post.
Autor:
Konrad
o
11:27
1 komentarze
Sunday, 3 February 2008
Implementing Arc's function-negation operator in Python
Hey look! This guy implemented Arc's function-negation operator in Chicken. And he claims to be a Pythoneer, traitor ;-) !
I just investigated the possibilities of doing more or less the same thing in Python. Of course: you can't change the syntax, and you can't change default function's behaviour (which is not having "~" operator implemented). Or can't you?
Let's start with something more explicit for a moment. Nothing prevents us from creating a callable decorator that implements __invert__ something like this:
class invertible:
def __init__(self, foo):
self.foo = foo
def __call__(self, *args, **kwargs):
return self.foo(*args, **kwargs)
def __invert__(self):
def wrapper(*args, **kwargs):
return not self.foo(*args, **kwargs)
return wrapper
Implementing __init__ enables us to call invertible() with an argument, and implementing __call__ makes the instances of our class callable. These two work together in a way that an ordinary decorator works: It's a callable, that takes a callable and returns another callable - easy, huh?Implementing __invert__ lets us use the "~" operator on the instances of our class, like this:
truth = invertible(lambda: True)
not_truth = ~truth
assert truth()
assert not not_truth()This implementation, even though it's easy, is not finished yet. The inverted value is a regular function, which means, that we couldn't invert it again. The easy solution to that is decorating the wrapper:class invertible:
# ...
def __invert__(self):
@invertible
def wrapper(*args, **kwargs):
return not self.foo(*args, **kwargs)
return wrapperBut this would cause the wrappers to accumulate on inverting. We can also check explicitly if we get an invertible on input and set a switch on each instanceclass invertible:
def __init__(self, foo):
self.foo = foo
self.inverted = False
def __call__(self, *args, **kwargs):
if self.inverted:
return not self.foo(*args, **kwargs)
else:
return self.foo(*args, **kwargs)
def __invert__(self):
ret = invertible(self.foo)
ret.inverted = (not self.inverted)
return retNow, with the decorator ready, you can do some *evil* magic with frames and namespaces in order to decorate everything in scope, but I'm leaving it as an exercise to readers ;P
Autor:
Konrad
o
05:00
5
komentarze
