Radiac's Blog: pythonhttp://radiac.net/blog/python/Posts tagged pythonen-gbSun, 13 Dec 2015 13:34:44 +0000Mara - a Python network service frameworkhttp://radiac.net/blog/2015/12/mara-python-network-service-framework/<p>I've released a new version of <a href="/projects/mara/">Mara</a>, my network service framework written in Python. It aims to make it easy to build TCP/IP services, such as echo servers, flash policy servers, chatrooms, talkers and MUDs.</p> <p>It's event-based; that is to say you write event listener functions which you bind to events that your service raises - like <code>Connect</code>, <code>Receive</code> or <code>Disconnect</code>.</p> <p>Mara is on pypi, so you can <code>pip install mara</code>, then start writing your service. An echo server in Mara looks like this:</p> <pre><code>from mara import Service service = Service() @service.listen(mara.events.Receive) def receive(event): event.client.write(event.data) if __name__ == '__main__': service.run()</code></pre> <p>You can then save it as <code>echo.py</code> and run the service by calling it:</p> <pre><code>python echo.py * Server listening on 127.0.0.1:9000</code></pre> <p>That's a pretty simple example, but Mara can do a bunch more. Its core has support for things like telnet negotiation, timers, a storage system, and seamless restarts (where client connections and storage objects persist, but your code is reloaded cleanly), and it ships with a <code>contrib</code> module which has a lot of optional extras, such as a command manager and dispatcher, basic natural language tools, user accounts and rooms.</p> <p>Although there's a focus on talkers and muds in the contrib modules at the moment, Mara should be a reasonable base for writing any network service. To get a feel for what you can do with it, take a look at the <a href="https://github.com/radiac/mara/tree/master/examples">examples</a>, which include an IRC-style chat server, a simple talker, and the start of a basic mud. There's also fairly comprehensive <a href="/projects/mara/documentation/">documentation</a>.</p> <p>I've always enjoyed writing this sort of thing, so this is a fun side project for me. At its heart Mara is a rewrite of my old perl chat server Cletus, which I wrote in <a href="/personal/diary/2001/10/id-240/">2001</a> - in fact if you dive back a few months through git, you'll see Mara was called Cletus until I realised that name was taken on pypi.</p> <p>It's still missing a few glaringly obvious features at the moment - most notably unicode and python 3 support, an example of using threads through events and timers, and more contrib modules for the mud like items, combat and NPCs. That said, it should make a solid starting point for any network service that you'd want to write, and as always, <a href="/projects/mara/documentation/contributing/">contributions are welcome</a>.</p>Sun, 13 Dec 2015 13:34:44 +0000http://radiac.net/blog/2015/12/mara-python-network-service-framework/Introducing Taguloushttp://radiac.net/blog/2015/10/introducing-tagulous/<p><a href="/projects/django-tagulous/">Tagulous</a> is a tagging library for Django which is based on <code>ManyToManyField</code> and <code>ForeignKey</code> relationships. I've been developing and using it internally for several years, and have recently tidied it up for release; it supports Django 1.4 to 1.9a, on Python 2.7 to 3.5.</p> <p>It started with a simple enough idea - rather than use generic relations like other tagging libraries, use a subclass of <code>ManyToManyField</code> which supports assignment using tag strings, to allow things like this:</p> <pre><code>class Person(models.Model): name = models.CharField(max_length=255) skills = TagField() person = Person.objects.create(name='Bob', skills='run, jump') person.skills = 'run, &quot;kung fu&quot;, jump'</code></pre> <p>And because the underlying relationship is a <code>ManyToManyField</code>, you can build queries exactly as you would expect:</p> <pre><code>runners = Person.objects.filter(skills='run') user_skills = Pet.skills.tag_model.objects.filter(pet__owner=request.user)</code></pre> <p>In this example the related tag model is generated automatically (and accessible on <code>field.tag_model</code>), but you can create custom tag models and share them between fields if you prefer. See the <a href="/projects/django-tagulous/documentation/usage/">usage examples</a> for more examples of how you can use Tagulous.</p> <p>The first version wasn't particularly complex, but as I started using it more it quickly became a more substantial project, with admin support, integrated autocomplete, support for hierarchical trees, and a <code>ForeignKey</code> version - a <code>SingleTagField</code> which essentially operates as a <code>CharField</code> with a list of <code>choices</code> which can be customised by users at runtime.</p> <p>It has a comprehensive set of tests, and has been in use for several years on several projects, so I'm reasonably confident that it's stable and the API won't need to be changed significantly now. That said, I'm releasing it as a beta version until it's been out in the wild for a bit - so please give it a try, and let me know how you get on.</p> <p>Tagulous is available on <a href="https://pypi.python.org/pypi/django-tagulous">pypi</a> and <a href="https://github.com/radiac/django-tagulous/">github</a>, and this site hosts the <a href="/projects/django-tagulous/documentation/">documentation</a> and a <a href="/projects/django-tagulous/demo/">demo</a> of the front-end.</p>Fri, 09 Oct 2015 07:22:53 +0000http://radiac.net/blog/2015/10/introducing-tagulous/