Radiac's Blog: pythonhttp://radiac.net/blog/python/Posts tagged pythonen-gbFri, 13 Sep 2019 16:04:16 +0000Syntactic Sugar vs Maintainabilityhttp://radiac.net/blog/2019/09/syntactic-sugar-vs-maintainability/<p>I've just given a talk at PyCon UK, called <a href="/pycon2019/">Syntactic Sugar vs Maintainability</a>, looking at balancing helping your users at the cost of your sanity.</p> <p>The synopsis was:</p> <blockquote> <p>Is it ever worth committing coding sins for the greater good? We'll look at techniques which can make your code easier to use at the cost of being harder to maintain, and when the effort is worth the reward.</p> <p>There are plenty of ways in which you can use and abuse the power of python to make your library code easier for your users to work with. I'm going to talk you through some techniques to design clean and simple library interfaces for your users, and explain how they can make things both easier and harder at the same time.</p> <p>Using real world examples we'll touch on topics such as automatic registration using metaclasses; changing base classes at runtime to save your users a line of code; and the joys and pitfalls of monkey patching things which should probably never be monkey patched.</p> <p>By the end of the talk you'll know why doing these things is usually a bad idea, and why I think it's worth doing them anyway.</p> </blockquote> <p>I've also uploaded the <a href="/pycon2019/">slides and links to resources</a> - if you came to listen, thanks very much! And if you didn't, the video should be up soon.</p>Fri, 13 Sep 2019 16:04:16 +0000http://radiac.net/blog/2019/09/syntactic-sugar-vs-maintainability/Mara - 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/