Sunday, November 20, 2011

ANN: straight.plugin 1.2 Released


Erik Youngren contributed the loading of packages as plugin modules, which should be useful to a number of users who have module needs that don't fit in a single .py file. This release also includes .egg packages for Python 2.6, 2.7, and 3.2 versions.


Enjoy!

Or, go straight to the source at http://github.com/ironfroggy/straight.plugin

Thursday, November 03, 2011

NaNoWriMo: Day 3

LONG DAY. Frustrated with the results today, but I am happy that I'm still on track. This is why I got extra words in the first two days!

Daily Goal: 1666

Today: 967

Total: 5005

Remaining: 44995

Remaining Daily: 1606
from my tumblr post

Wednesday, November 02, 2011

NaNoWriMo: Day 2

I love how the story is revealing itself. I am not planning much, but many possibilities are popping into my head as I start to make connections in the story. Partly i wonder if i should avoid them, maybe they are too obvious since i thought of them just from what i’ve written? I don’t know. I’ll probably run with it, I need the material, after all.


What is Roshyn after, anyway?


Daily Goal: 1666


Today: 2028


Total: 4038


Remaining: 45962


Remaining Daily: 1584

from my Tumblr post

Tuesday, November 01, 2011

NaNoWriMo: Day 1

I started my novel. I hate the first thousand words, which were just meandering and going no where. I stumbled on something interesting for the second thousand.
Daily Goal: 1666
Today: 2010
Total: 2010
Remaining: 47,990
Remaining Daily: 1600
Today was a Good Writing Day. Even though I could not write in the morning, and only was able to get 300 words on the bus, I still finished out ahead.
from my Tumblr post

Monday, October 31, 2011

NaNoWriMo: Day 0

I have signed up for NaNoWriMo 2011 with a novel draft I’ll be writing named The Compass and The Leash. I’ll make some notes here each day as I go.
Mirrored from my Tumblr post

Wednesday, September 21, 2011

0x0002 Dev Diaries - JS Privates

A little experiment / toy I have, which I might use to keep some decoupling attempts straight.



Using this, I'll be able to allow the various components to maintain properties on other objects they work with, safely, without interfering with one another.


For example, I have a Draggable behavior that can be enabled in a scene and allows objects in the scene to be, obviously, draggable. During this use, the behavior code may often need to set properties on the objects to track dragging state, but needs to do so without interfering with other behaviors setting properties of their own, even other instances of the same behavior. This simple utility enables this.

privates(this, entity).dragPath = [];
privates(this, entity).dragPath.push(curPos);


...


drawPath(privates(this, entity).dragPath);


The concept this is trying to express is that the first object owns a set of private properties attached to the second object, and this works much like private attributes in many languages but works with delegation and composition, rather than inheritance.


My rendering system will be using this to take the general description of a sprite object and attach to it loaded images, animation state, and flags needed to manage redraw orderings, without mucking in the namespace of the object itself.

Sunday, September 18, 2011

New post on my game development progress.
I've been tinkering on a small Javascript and Canvas engine for the last few weeks, and I'm mostly happy with the results, if not as happy with the progress. Still, it has been steady, so I'll focus on being happy for that part. 
I'm starting to split the codebase into two parts: a javascript utility library, very similar to backbone.js, and the game engine on top of it.
Read the full post

Friday, July 01, 2011

Announcement: JournalApp 2.0 is Live

My Month-Project for June 2011 was the 2.0 release of the JournalApp tool I built during PyCon. I'm going to give a quick overview here, but I really hope anyone with the least bit of interest in what I do will go and look for themselves. I also think you should give it a try, but I don't think its for everyone. I think there are ways to sort your thoughts that work for us and we have different methods that will work best for us. This works best for me. If it works for you, great. If not, I hope you find something for you.

You can try it out now at GoJournalApp.com.

The easiest way for me to summarize it is to just copy-paste the help page right here.
Write. 
Write #awesome things and tag use hashtags to find them later. 
Find things by hashtag by typing only the tags you want to search. 
#likethis 
Have something to do? 
TODO: write todo's in your entries. 
DONE: and click them to check them off. 
ALSO: notice you can use "todo" or any word you want. 
Like searching for tags, you can also search for todo items, or whatever word you used. You can even mix them with hashtags! Here's how I find a list of books i want to read. 
#reading book: 
 Finally, while you are searching, anything you write gets the current hashtags automagically 
 You can use this to create separate notebooks, topics, or any other way you want to organize.

Tuesday, June 28, 2011

Of Auto-Authenticating URLs, Shortlinks, and Danger

The road to hell is paved with good intentions, they say.

So, it was a good intention when someone (not me) decided to install a link shortener and send password reset links through it, before producing the printed newsletters that would be sent out to individual members. They would need to type the URLs in by hand, so a shorter URL was a good idea. At least, it must have seemed like it, at the time.

Today I took a look at this system, which I was asked to clean up before it gets used again after several months of being ignored. I admit it didn't click in my mind immediately, but after producing some newsletter content in our staging system and verifying the shortlinks were being recorded properly, it suddenly jumped out of the screen and bit me on the nose:

The shortener was producing sequential links for a bunch of password reset links.

What this meant in practical terms is that two newsletters sent out with password reset links for two different users would send them URLs like http://foo.com/z1 and http://foo.com/z2 and while these were very short for the user to type in they were not easy to type in, if you require "correctly" as part of the measurement of how easy it is. They are so short and the space so condensed that mistyping won't get you a 404, but someone else's entirely valid password reset link. This is terrible. There is a reason password resets give you links with long randomized sequences of characters, and all of those reasons were being thrown out the window.

Turns out, a shortened URL can be too short.

Monday, June 27, 2011

A tale of three TODO products

I'm the kind of guy that hates the amount of time he spends considering, evaluating, and test driving new productivity software. Recently I had yet another surge of uncertainty over my use of Remember The Milk, and I tried a few other things. I gave a spin on Nozbe and Todo.txt, and I've come to a conclusion.

For now...

I have been a big fan of Remember The Milk, and I pay for a professional account. Even still, I'm not above admitting I might be wrong, so when a few things started to annoy me I sought out something new. I had heard Todo.txt talked up a lot on This Week in Google, given that the author is a host on the show. I had also tried Nozbe in the past, but new it had several large updates since then and wanted to give it another try.

Remember The Milk

I really was happy with RTM, so I want to make clear the things I do like about it! I really have been happy with the Android app, and with the use of smart lists to create filters that match different contexts I want to work in. Here is the corner stone of my smart lists, which I combine with several others:

(dueBefore:"tomorrow midnight" OR (due:never AND tag:next) ) OR (dueWithin:"1 month of today" AND tag:bill) OR (tag:writing AND dueWithin:"1 week of today") OR (tag:sticky)

This means "Everything with a due date that is today or already passed, or without a due date marked to be done next, or due within the next month and is a bill, or is something i need to write within the next week, or is tagged 'sticky'" and I can update this as need be, and other lists that use it adjust themselves. What this lets me do is set due dates in the future and hide the items until they become important, so it works great for setting my todo list for work and to see a condensed set of things I should focus on each day.

So, what was getting on my nerves? What I haven't gotten to feel right is a small and loose set of tasks that I want to do in order, and so only one is relevant at a time. Good example is a book series. I need to maintain next tags on items right now, and that isn't terrible, but automation is great. What I feel would be nice is a tool where lists were super light and throw-away and only the top item on the list was included in the main view, as a "Next Action". Yes, that is a GTD thing.

Todo.txt

I can't say the idea of keeping everything in a file I own isn't appealing, it is. I was able to customize the sorting command and some filtering options so I could kind of do a thing like the next actions I talked about before, and I could see the first thing in each context I've defined when I list my tasks. But, that flexibility kind of vanishes when I use the android app, so while it is very cool that it just syncs my local file via Dropbox, it also means that I can only customize half my experience, which kind of just makes the android half feel worse. At least my smart lists work in RTM's android app.

Nozbe

The most appealing feature here is an actual support for next actions. With any list, anything marked as a next action is easily accessible and the main view will show me only one next action for each list and will show me the next one when I complete the current. That's great. However, lists are not cheap. As in, I need to pay to get more than 5, and it costs more than RTM. I did not feel that I can create them willy nilly, which meant I felt confined. Nice app, and an integration with evernote that I will never use, even though I am an evernote user. Better luck next time.

Conclusion

I've returned to Remember The Milk. I should focus on doing, more than what to be doing.

Freelance Freedom #213: Getting Things Done


Relearning Twisted.web

I want to use Twisted.web for some projects, and I haven't used it in years. I'm relearning and I feel like a novice all over again, as I should, given the years that have passed since I have seriously looked at any twisted code. I miss it, very much. Want to relearn or learn for the first time? I can't stress enough the excellence of a quick pass through the examples of Twisted.web in 60 Seconds. Go through those immediately. Afterwards, I read up on the new twisted.web.template, which is based on the Nevow templates I worked with so long-feeling ago, and I'm pretty happy with what I see there. I'm wondering how well it will produce HTML5 compliant markup, not that it is very strict, but it looks pretty clear.

My brain still thinks in asynchronous operations and I constantly have to unravel those thoughts and figure out how to express them, non-ideally, in a synchronous workflow. This is becoming tiring, and while I don't plan on leaving Django, I do plan on giving my brain a rest. Maybe I'll find a way to combine my two interests in the near future...

This is the result of the hour I spent relearning last night.

import time


from twisted.web.server import Site, NOT_DONE_YET
from twisted.web.static import File
from twisted.web.resource import Resource

from twisted.internet import reactor
from twisted.internet.defer import Deferred

class ClockPage(Resource):
    isLeaf = True
    def render_GET(self, request):
        d = Deferred()
        @d.addCallback
        def _(r):
            request.write("<html><body>%s</body></html>" % (r,))
            request.finish()

        def get_time(r):
            d.callback(time.ctime())

        reactor.callLater(2, get_time, None)
        return NOT_DONE_YET

resource = ClockPage()
factory = Site(resource)
reactor.listenTCP(8888, factory)

reactor.run()

Monday, June 13, 2011

Windows 8, HTML5 Applications, and Bitching, Moaning, Whiny Developers

I have a great idea, Windows developers: stop being a big bag of whiny bullshit. Oh my god, you have yet another optional API in your toolbox, if you want to use it. Oh no! It's based on scary web thingies you haven't used before! Guess what? COM was new and scary, and so was Win32, and so was .Net and WFC and DirectX and everything else Redmond is spat at your feet to walk on our praise, at your discretion, for the last several decades. You're making a big whiny fuss because you have one more optional API to use, for a novelty new feature that has obvious merits, but is so obviously not the entire picture of Windows 8 that your overt and public cry-fest would be laughable if it was even remotely believable. I refuse to accept that the host of Windows developers is really buying into the bullshit story that everything in the history of Windows is getting swept under the rug and replaced by this, that everything is immediately an old, festering legacy API with legacy applications waiting to collect dust on Balmer's bookshelf. Not a god damn chance. They didn't rewrite Word on top of .Net, and they aren't going to rewrite it for HTML5, either. They're going to integrate a lot of things the Internet Explorer 9 platform provides into the new Operating System and they're going to do some fun looking features and make a great effort. Hell, it might even be a Decent Product! But you know what it isn't going to be? It isn't going to be made from scratch biscuits from grandma's secret recipe. No. This is going to be hamburger helper with some basil tossed in, so the cook feels fancy. Learn a little Javascript, because you've got so many things under your belt already that one more language isn't going to make much of a difference, so live a little and see what its all about. Make a fun little touch-based windows 8 application and impress your friends, and then get back to your job where you'll write version 17 of whatever corporate tax audit tool you've been maintainer for the last twenty years. When someone suggests rewriting it for Windows 8, giggle with your friends while one of the managers mentions that most the customers are still migrating off Windows XP and IE6, and move on to getting some real work done.

Sunday, May 29, 2011

ANNOUNCE: Hashtrack.js 0.2

Hashtrack.js 0.2 includes a number of bug fixes and enhancements, and I'd like to start doing official releases that really show off what the tool is capable of. I've been using this for a few years in projects both personal and professional, and I always merge improvements back into it. Hopefully, I can start making an effort to polish it up better, because in this day and age we all are finding ourselves in need of stateful web applications, and we need to handle this gracefully.

Take a look at the github repo for hashtrack if you like the sample code below, or take a look at the very sparse but informative docs.

 hashtrack.onhashvarchange("background", function (value) {
     $('body').css('background', value);
 }, true);

 -----

 <a href="#?background=green">Make the background green</a>

Sunday, May 01, 2011

ANNOUNCE: straight.plugin - A simple plugin loader for Python 2.7 - 3.2

Tonight I uploaded straight.plugin 1.1 to the Python Package Index. This release includes a new loader, straight.plugin.loaders.ClassLoader and adds an subclasses parameter to the simple load() API to invoke class loading, opposed to the default module loading. The classes are filtered by type and are looked up in the same modules that would be loaded by the ModuleLoader available in straight.plugin 1.0. This release has been testing on Python 2.7 and 3.2.

You can check out the source at github or the packages at PyPI.

Monday, March 07, 2011

How To Attend Pycon 2011

Short announcement:

I will be at Pycon this year. Also, that Saturday, March 12, is my birthday.

See you there!

Saturday, February 12, 2011

Django: How to hook in after multiple M2M have been processed

This situation comes up, from time to time, when we need to get something to happen after a many-to-many field is changed. The novice will connect a post_save signal and scratch his head when it doesn't fire on the addition or removal of items in the ManyToManyField. We all learn that it takes a slightly more complicated signal, the m2m_changed signal, and its many actions, which tell us exactly what has changed in the particular field sending it (the signal comes from the field's through table, to be exact).

Well, a slightly more complicated case arose in a design today and I was scratching my head and feeling like a novice all over again. You see, I needed to know when new things had been adding to such a field, but I had more than one. In fact, I had four of them. I needed a specific function called on the instance when all of these fields were finished being cleared or added to or subtracted from. This was in a form in the Django admin.

Thankfully I had an assumption I could make this easier with: the fields in question would only be set from the admin interface. With this knowledge in hand, I hopped into the app's admin.py and I added these methods:


    def response_change(self, request, obj):
        response = super(MyAdmin, self).response_change(request, obj)

        obj.do_thing()

        return response

    def response_add(self, request, obj, *args, **kwargs):
        response = super(MyAdmin, self).response_add(request, obj, *args, **kwargs)

        obj.do_thing()

        return response

These get called when the admin interface is used to edit and create a new object, respectively. It happens after both the model instance itself and all of the many-to-many fields have been saved, which is exactly what we need. It works, but I wish I could find a better solution.

Tuesday, January 11, 2011

How To Speed Up Django Tests on Postgresql

I had a problem with a Django project that took forever to run its unit tests. The test database took an enormous amount of time to run, upwards of ten to fifteen minutes each. I didn't have a lot of ways around this, because I had to use a base Model that pulled in lots of cascading requirements and I couldn't avoid the dozens of applications it needed to build tables for. This was really hindering my ability to develop, as I rely heavily on constantly running tests in my own pathetic attempt at Continuous Integration.

After some poking around the PG forums, I eventually worked out this script, which I now run on startup.


#!/usr/bin/env bash
service postgresql stop
mount -t tmpfs -o size=500m tmpfs /mnt/pg_data_mem/
cp -R /var/lib/postgresql/8.4/main/ /mnt/pg_data_mem/
mount --bind /var/lib/postgresql/8.4/main/pg_xlog /mnt/pg_data_mem/main/pg_xlog
chown -R postgres:postgres /mnt/pg_data_mem/
sudo -u postgres /usr/lib/postgresql/8.4/bin/pg_resetxlog -f /mnt/pg_data_mem/main/service postgresql start

I also set data_directory = '/mnt/pg_data_mem/main' in postgresql.conf.

This works in development, where I don't need my DB to persist between reboots. If I did want to keep it around, I could just copy from /mnt/pg_data_mem/main/ to /var/lib/postgresql/8.4/main/ and keep it on disc. For now, my one-way solution works.

Sunday, January 02, 2011

Soft Announcement: Trapdoor Prototype

Previously I made a little preview of something I'm announcing today, but it is a soft announcement as I've had it on github for some time, but I haven't done anything with the project.

This is just a prototype, an experiment, and it is called Trapdoor. I don't remember why I named it Trapdoor.

Trapdoor has a simple concept, along the lines of Mozilla Prism. I wanted to take things I use to build web applications and test how they could be applied to building desktop applications. This meant two things:

1) I need to wrap up a web application in something that can be run locally.

2) I need some way to extend a web application in ways that normally only desktop applications can provide.

This has been done in the simplest way I could find, at the time, and is available on github.

extensions:
 - calculator.Calculator
js:
 - calculator.js
plugins:
 - trapdoor.contrib.windowmanager

Applications are configured through this simply manifest, where they are given extensions, plugins, and javascript. Honestly, extensions and plugins can probably be merged. They are both defined by a Python class and the object exposes methods to the Javascript, which gets loaded and initialized by the runtime. The current version includes two plugins:

trapdoor.contrib.windowmanager

This is a basic plugin that provides a simple createWindow method, through which the Javascript can create new windows with (in the future) more control than the standard Javascript APIs would otherwise provide. One thing I'll be adding to this is a fullscreen API and other properties to control the window appearance, such as borders and which controls are visible.

trapdoor.contrib.nodes

This is my favorite of the two standard plugins. Each Node is an isolated Javascript runtime, in its own global space. The application is loaded in the first node, but it can create and initialize others, allowing it to run untrusted Javascript safely. If I continue development, I hope to use this to test ways to allow community additions to software without worrying about what they are running. This is similar to how extensions and user scripts work in Firefox and Chrome.

Now, I don't know if more will come of this. I think, if it does, it should probably be evaluated if I should rewrite it based on Chromium and V8, rather than Qt and whatever Javascript engine it is running on. It is also lacking a solid use case, for me, that I can use to drive my desire to improve it. However, I had fun writing it for the thought experiment, and I do hope to do more with it in the near future.

Please, fork it and tell me what you think.
I write here about programming, how to program better, things I think are neat and are related to programming. I might write other things at my personal website.

I am happily employed by the excellent Caktus Group, located in beautiful and friendly Carrboro, NC, where I work with Python, Django, and Javascript.

Blog Archive