Windows 7 – OSX Like Screenshot Command

Strangely, one of the most useful things about OSX was the screenshot capability.

CMD+SHIFT+3 takes the whole screen to the desktop.
CMD+SHIFT+4 takes a selection to the desktop

CTRL+CMD+SHIFT+4 takes a selection to the clipboard.

Well, in windows 7 you can pretty much get most of that functionality by right clicking on the “Snipping Tool”, and assigning a hotkey to it. I made it CTRL+SHIFT+4.

Simple. Done!

It also saves to the clipboard for easy photoshop pasting available via the options dropdown in snipping tool.

Windows remove delay before aero-peek on alt+tab

Aero peek is actually pretty damn useful to tell which program window you’re tabbing into — but the delay is a good few seconds.

I found a SuperUser post that explains how to set this delay.

http://superuser.com/questions/45259/windows-7-alttab-transparent-windows-effect-delay

Set a registry key at:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\AltTab.

In that key, create the following DWORD value: LivePreview_ms and set it to the delay (in milliseconds) of the first live preview.

I set mine to 1 (0 doesn’t work) and it’s instant!

Sublime 2 Windows Hotkey Setup from OSX

Switched to windows environment from OSX.

Most important for me is…

  • Making Ctrl+T the “goto” hotkey
  • Making Ctrl+g the “find next” hokey
  • Making Ctrl+shift+g the “find prev” hotkey
  • Making Ctrl+1~0 the “go to specific tab” hotkey
[
	{ "keys": ["ctrl+t"], "command": "show_overlay", "args": {"overlay": "goto"} },
	{ "keys": ["ctrl+g"], "command": "find_prev" },
	{ "keys": ["ctrl+shift+g"], "command": "find_under" },


    { "keys": ["ctrl+1"], "command": "select_by_index", "args": { "index": 0 } },
    { "keys": ["ctrl+2"], "command": "select_by_index", "args": { "index": 1 } },
    { "keys": ["ctrl+3"], "command": "select_by_index", "args": { "index": 2 } },
    { "keys": ["ctrl+4"], "command": "select_by_index", "args": { "index": 3 } },
    { "keys": ["ctrl+5"], "command": "select_by_index", "args": { "index": 4 } },
    { "keys": ["ctrl+6"], "command": "select_by_index", "args": { "index": 5 } },
    { "keys": ["ctrl+7"], "command": "select_by_index", "args": { "index": 6 } },
    { "keys": ["ctrl+8"], "command": "select_by_index", "args": { "index": 7 } },
    { "keys": ["ctrl+9"], "command": "select_by_index", "args": { "index": 8 } },
    { "keys": ["ctrl+0"], "command": "select_by_index", "args": { "index": 9 } }
]

Git — Undo a hard reset via Reflog

Straight out of this stackoverflow question which I wish I could upvote 50 times.

http://stackoverflow.com/questions/5473/undoing-a-git-reset-hard-head1

I accidentally did a hard reset to a commit too far back and lost some changes. Luckily git reflog shows hashes you can revert to even if its technically not in your repository.

Copy and pasted from the answer at SO, saved for posterity.

$ git init
Initialized empty Git repository in .git/

$ echo "testing reset" > file1
$ git add file1
$ git commit -m 'added file1'
Created initial commit 1a75c1d: added file1
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file1

$ echo "added new file" > file2
$ git add file2
$ git commit -m 'added file2'
Created commit f6e5064: added file2
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 file2

$ git reset --hard HEAD^
HEAD is now at 1a75c1d... added file1

$ cat file2
cat: file2: No such file or directory

$ git reflog
1a75c1d... HEAD@{0}: reset --hard HEAD^: updating HEAD
f6e5064... HEAD@{1}: commit: added file2

$ git reset --hard f6e5064
HEAD is now at f6e5064... added file2

$ cat file2
added new file

Django — Formfield for ForeignKey

I’ve googled formfield_for_foreignkey on many occasions to look up what parameters it accepts, but it always fails me.

I bet you anything posting this blog will make it to the top of the google results and serve as a redirect : )

The docs on formfield for foreignkey:

http://docs.djangoproject.com/en/1.3/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_for_foreignkey

The docs on formfield for manytomany:

http://docs.djangoproject.com/en/1.3/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_for_manytomany

The docs on formfield for choice field:

http://docs.djangoproject.com/en/1.3/ref/contrib/admin/#django.contrib.admin.ModelAdmin.formfield_for_choice_field

Django / Python — Store Dictionary as String

I’d like to store a dictionary as a string on my django model.

It would simply be a few key=value pairs separated by commas. I prefer not to pickle this so that it can easily be edited as a string.

I will use this field for arbitrary types of gateway arguments. For example, for the “Gift Card” payment gateway, i’d store a card_id code in this field.

For the CreditCard gateway, I’d store a transaction ID number.

Here’s what I came up with: please, comments and suggestions are welcome.

    @property
    def gateway_arguments(self):
        """
        Dictionary stored as string.
        """
        if not hasattr(self, '_gateway_arguments'):
            try:
                self._gateway_arguments =  dict(
                        (x.strip().split('=') for x in self.gateway_args.split(',') if x)
                    )
            except Exception, e:
                log.critical("Malformed gatway_args on order {id}".format(id=self.id))
               self._gateway_arguments = {}
        return self._gateway_arguments

    
    @gateway_arguments.setter
    def gateway_arguments(self, value):
        self._gateway_arguments = value


    def save(self, *args, **kwargs):
        """ Convert dictionary to string """
        if getattr(self, '_gateway_arguments', None):
            self.gateway_args = ','.join(('{key}={value}'.format(key=key, value=value) for
                key, value in self._gateway_arguments.iteritems() ))
        super(Order, self).save(*args, **kwargs)

Django — django-mailer multi account setup plus throttling

I forked django mailer to support multiple accounts and email queue throttling per day per account.

https://github.com/yuchant/django-mailer

django-mailer by James Tauber http://jtauber.com/
http://code.google.com/p/django-mailer/

A reusable Django app for queuing the sending of email

Forked to support multiple accounts and email throttling.

Forked to allow django-mailer to use multiple email accounts and to impose a daily sending limit per email account.

Specifically made for Google Apps users who have a 500 email a day per user sending limit and are also limited to a from_address that is the actual authenticated account.

If you’d like to use different “from” emails, it’s currently not an option with google apps.

Options

DAILY_SENDING_LIMIT

Specify an optional MAILER_DAILY_SENDING_LIMIT in settings.py to limit the amount of emails per 24 hours.

Throttling is done via emails sent in the last 24 hours, not discrete days.

# settings.py MAILER_DAILY_SENDING_LIMIT = 400 

MULTIPLE ACCOUNTS

send_mail takes an extra keyword argument, account, which is an integer mapped to a specific account in settings.py.

Account 0 is mapped to the default email settings EMAIL_HOST, EMAIL_PORT, etc.

Account 1 is mapped to EMAIL1_HOST, EMAIL1_PORT, etc.

All settings below are required and mailer will complain if it fails to find a setting.

# settings.py
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'foo@example.com'
EMAIL_HOST_PASSWORD = 'password'
EMAIL_USE_TLS = True

EMAIL1_HOST = 'smtp.gmail.com'
EMAIL1_PORT = 587
EMAIL1_HOST_USER = 'bar@example.com'
EMAIL1_HOST_PASSWORD = 'password'
EMAIL1_USE_TLS = True

Usage

from mailer import send_mail

send_mail("Subject", "Body", "from@example.com", ["to@example.com"]) # uses default email settings
send_mail("Subject", "Body", "from@example.com", ["to@example.com"], account=1) # uses EMAIL1_* settings
send_mail("Subject", "Body", "from@example.com", ["to@example.com"], account=2) # uses EMAIL2_* settings

bash $ python manage.py send_mail
# iterates through Messages by account and sends up to DAILY_SENDING_LIMIT per account if specified.

PIP — Install Specific Commit from Git Repository

I’ve switched to an all PIP deployment setup. I used to keep some libraries in my code repository because I needed specific versions or hacked ones.

I’m now in a setup where I don’t have any hacked libraries, so all is good, except I need a dev version of django-mailer that’s not on PIP.

PIP can handle git repos, but what if an unstable change gets introduced?

Well, until now, I didn’t know you could specify a commit hash in your pip install command.

Specify the hash tag with @, and use git:// syntax, not the default https: that the clone bar shows you.

# requirements.txt
git+git://github.com/jtauber/django-mailer.git@840d25bb9db9fbc801b9

# shell
bash $ pip install -r requirements.txt

Django / Python – Fabric Deployment Script and Example

Fabric.

I’d heard about it for at least a year+ but I never got around to it.

I was a little intimidated by it.

The examples seemed so simple, but that was the problem – they seemed too simple, like the examples you run into which look completely uninformative, just a quick blot of code and no explanation.

Well, it turns out fabric really is just that magical.

This is straight life changing!

This is as useful as when I first discovered how much easier it was (for me) to use Git for branching / merging than SVN, or deciding to switch to a linux-like environment for web development.

I’m writing about this today because I was always intimidated by it / thought it would take some time to learn, when there was no reason to be. It’s extremely simple.

Hopefully, it helps somebody out there with the same reservations.

First, let me point you to the official fabric docs where you can find the tutorial and more.

Install fabric.

First, pip install fabric on each machine you need to use fabric on.

 pip install fabric 

Create the fab file that contains functions

Create a blank file called fabfile.py in the directory you’d like to use the fabric commands from.

For my django project, that’s the directory that contains settings.py and manage.py. My “home base”, or where you’ll find me in an average terminal window.

Create your first fabric command

In just a few lines of code, let’s set up a fabric script that asks the server to pull from the git repository and restart apache.

 
    # import fabrics API functions - self-explanatory once you see 
    from fabric.api import * 
    def pushpull():
        local('git push') # runs the command on the local environment
        run('cd /path/to/project/; git pull') # runs the command on the remote environment 
    

Let’s try running that in bash.

 bash$ fab pushpull 

It will ask you for a server to connect to that’s running fabric. You will want to enter in your username@host:port here.

Obviously, typing the full URL every time defeats the purpose of an automation script – let’s add it into our fabric file.

Add remote server commands

Let’s add the remote server information to our fabric file. We need to add our server information to our fabric script via the env.hosts parameter.

 from fabric.api import * 
 env.hosts = ['me@example.com:22']
 def pushpull(): 
    local('git push') # runs the command on the local environment 
    run('git pull') # runs the command on the remote environment 

env is a dictionary containing various settings, one of which is ‘hosts’ – a list of hosts that all commands will run through.

Now, if we run fab pushpull, we won’t need to type in the server name. If you have SSH keys set up, you won’t need a password.

Add more server setup commands

Next, I want support for working on a development server or production.
Adding this information via a separate function ensures our commands are not tied to specific environments. For example, I use the same functions chained with “dev” or “prod” to determine which environment I am applying the command towards.

Okay, our first roadblock; it turns out that you can not dynamically set env.hosts within a function – it will not register.

 def pushpull(host=None):
    env.hosts = [host] # this will fail
 bash$ fab pushpull:me@example.com # fails 
 

You need to define it in a separate function. Here’s what I’ve done.

I’ve set up a “dev” and “prod” function that sets up the environment prior to running another fab command. For good measure, I also created an “all” command.

 dev_sever = 'me@dev.example.com:22'
 prod_server = 'me@example.com:22'
 
 def dev(): 
    """ Use development server settings """
    env.hosts = [dev_server] # this is the place to add other setup, such as if the django project is in a different directory 
    # reference this variable later 
    env['dir'] = '/path/' 
    
    
 def prod():
    """ Use production server settings """ 
    env.hosts = [prod_server] 
    
    
 def all(): 
    """ Use all serves """
    env.hosts = [dev_server, prod_server]

Now, we can run the command.

 bash$ fab dev pushpull bash$ fab prod pushpull bash$ fab all pushpull 

Wow, amazing. The possibilities already are limitless!

Some tips – reuse functions.

I’ve found that writing many small functions helps since I’m not always using fabric.

For example, I have a large, full deployment function that…

  • commits local changes
  • pushes the changes
  • pulls the changes on the remote machine
  • syncdbs the remote machine
  • migrates the remote machine
  • restarts apache and other servers

Now, each one of these functions is actually another separate function, since who knows, I might have committed my changes myself and even pushed changes and now I only need a server restart – for me that’s “fab prod deploy”

Passing arguments to fabric functions.

Functions can accept arguments, and are passed to the python functions from the shell via a colon

 bash$ fab dev some_func:arg1,arg2,keyword=kwarg 

Preventing errors from blowing up

Any non success exit code will stop your function. Use the settings function from the api to allow them to silently pass.

For example, git commit -a will fail if there’s nothing to add.

 
    def foo():
        with settings(warn_only=True):
            local('git commit -a') # fabric will no longer abort 

Keep functions open-ended via *args

There are tons of special case scenarios with django-south and its commands, so I’ve made a migrate fabric command that accepts an arbitrary number of arguments, to support say migrate myapp 0001 —fake

 
    def migrate(*args):
        with cd(env['mypath']): # every command will now be run in the path specified 
            run('python manage.py migrate ' + ' '.join(args)) 
 bash$ fab dev migrate:--all,--fake,0001 

Define a way to revert a mistake

Make sure you have a way out of an operation that kills your site.

In my case, I have set up a git revert command as “revert”

    def revert():
        """ Revert git via reset --hard @{1} """
        with cd(env['dir']):
            run('git reset --hard @{1}')
            arestart() # restarts server 
            

This command would undo the last pull to the working state the server should have been in before we forced a pull.

Use docstrings

The first line of your docstring appears when you list your fab functions via fab –list

One final note:

Check the docs. There are functions such as sudo(‘myfunc’) that will run as root. Very useful.