Monday, June 25, 2012

Setting up CherryPy using mod_wsgi on Mac OS X Snow Leopard

Getting CherryPy 3.2 setup on Snow Leopard with mod_wsgi is relatively easy. Here is a step-by-step guide.

A word of caution:

This tutorial requires you to modify sensitive system files on your computer. If you are uncomfortable doing this or unaware of the repercussions, take some time and do your due-diligence to understand the repercussions before following these steps or do not follow the steps outlined in this tutorial.


Step 1 (optional) - Download and install Python 2.7.3  

Python is installed on SnowLeopard by default, but it's an older version 2.6. If you want to use that, you can skip this section.

  • Download Python 2.7.3 from the Python standard releases page
  • Browse to the downloaded python-2.7.3-macosx10.6.dmg file in Finder
  • Double-click on it and follow the installation instruction

The Python standard release of 2.7.3 installs the python executable to the following location on your Mac by default:
        /Library/Frameworks/Python.framework/Versions/2.7/bin

Add the above location to your $PATH environment variable.

Python 2.7.3 should now be up-and-running. To test this, open a terminal and type:
        python -V

The following text should show up (If not, you may have your $PATH environment variable set incorrectly).:
        Python 2.7.3

Step 2 - Download and install mod_wsgi

There are a few ways to do this. If you are sticking with Python 2.6 that comes pre-installed on Snow Leopard, you can download and install the Snow Leopard binary. If you have macports or homebrew you can use one of those if you prefer. Here, I will demonstrate how to compile it from source. It's quick, easy and puts the resulting mod_wsgi.so file in the same place as all of the other Apache mods.

To download and compile from source, open up a terminal and type the following commands (Hit the [return] key after each command, you will see output from some of them. Also, the terminal may ask for your password at some point):
cd ~/Downloads/
wget http://modwsgi.googlecode.com/files/mod_wsgi-3.3.tar.gz
tar -zxvf mod_wsgi-3.3.tar.gz
cd mod_wsgi-3.3
sudo ./configure
sudo make
sudo make install
Now, you should have mod_wsgi.so installed with your other Apache modules in /usr/libexec/apache2. To confirm this, keep the terminal open and type the command: ls /usr/libexec/apache2/mod_wsgi.so The terminal should print back the file path (if not, something went awry, try again): /usr/libexec/apache2/mod_wsgi.so

Step 3 - Test mod_wsgi on Apache

You have downloaded mod_wsgi, now let's get Apache to load it.

First, you need to edit some of the Apache configuration files. FYI, you will need to make hidden files and folders visible if they aren't already.
  •  Tell Apache to load the mod_wsgi.so file that you installed. Open the following file in your favorite text editor:Macintosh HD/private/etc/apache2/httpd.conf
  • Find the big list of lines that begin with LoadModule. After the last LoadModule line, add the following line and save the file. You will be prompted for your password when saving. (Note, if you used macports or homebrew to install mod_wsgi, the location of mod_wsgi.so will be different):LoadModule wsgi_module  libexec/apache2/mod_wsgi.so
  • Now, create a VirtualHost in Apache. Open up the following file in your favorite text editor: Macintosh HD/private/etc/apache2/extra/httpd-vhosts.conf  
  • Add the following lines to the bottom of the file and save it: <VirtualHost *:80>
        ServerAdmin me@test-cherry-py
        ServerName test-cherrypy

        DocumentRoot "/Library/WebServer/test-cherrypy/documents"
       
        <Directory "/Library/WebServer/test-cherrypy/documents">
            Options Indexes FollowSymLinks Includes
            AllowOverride All
            Order allow,deny
            Allow from all
        </Directory>

        WSGIScriptAlias / /Library/WebServer/test-cherrypy/wsgi-scripts/test-cherrypy.py

        <Directory "/Library/WebServer/test-cherrypy/wsgi-scripts">
            Order allow,deny
            Allow from all
        </Directory>
    </VirtualHost>
In the above VirtualHost code-block, you told Apache to answer to the domain name test-cherrypy, and to look for files and folders that probably don't exist on your machine yet. Let's get your machine set up so that Apache can find these files, directories and the domain name.

  • Fake the domain name. In Finder, open up the file Macintosh HD/etc/hosts in your favorite text editor and add the following line to the end of the file:127.0.0.1     test-cherrypy
  • Create the directories and files that your VirtualHost directive above refers to. Go to the terminal and type the following commands (hit [return] after each command):
    cd /Library/Webserver
    sudo mkdir test-cherrypy
    sudo mkdir test-cherrypy/documents
    sudo mkdir test-cherrypy/wsgi-scripts
    sudo touch test-cherrypy/wsgi-scripts/test-cherrypy.py
  • In Finder, open up the following file in your favorite text editor: Macintosh HD/Library/Webserver/test-cherrypy/wsgi-scripts/test-cherrypy.py
  • It should be empty. Add the following lines of code to the file and save it: def application(environ, start_response):
        status = '200 OK'
        output = 'Hello, from mod_wsgi!'

        response_headers = [('Content-type', 'text/plain'),
                            ('Content-Length', str(len(output)))]
        start_response(status, response_headers)

        return [output]
Now, go to the Apple menu and open up System Preferences > Sharing  and uncheck and re-check the Web Sharing checkbox. This will restart Apache. Alternatively, you could type the following in the terminal:sudo apachectl restart
Open up your favorite browser and go to http://test-cherrypy. You should be greeted with the following text:
Hello, from mod_wsgi!

Thursday, June 14, 2012

Sublime Text 2 Plugin Authoring Resources

I recently found myself authoring a Sublime Text 2 plugin for use at work. When it was all said and done, the process was fairly straight-forward. Plugins are written in python and follow simple conventions. If you too are interested in creating your own Sublime Text 2 plugins, here are some of the resources that I found useful:




Also, just take a look through the Sublim packages directory at the installed packages, almost anything you need to learn can be found in the code that is in there.

Customizing ColdFusion Highlighting in Sublime Text 2


This post assumes that you have Package Control installed in Sublime Text 2. If not, find out more about it here:  http://wbond.net/sublime_packages/package_control

If you haven't already installed the ColdFusion package in Sublime Text 2, you will need to do so before continuing. To install the ColdFusion package through Package Control:

  • In Sublime, type [ctrl]+[shift]+p (Win/Lin) or [cmd]+[shift]+p (Mac) to open the Command Pallette
  • Choose "Package Control: Install Package" from the list
  • Type ColdFusion in the text box
  • Select the ColdFusion package from the list
Once the ColdFusion package is installed, take it for a spin and give it time to sink in that you won't have to rely on the bloated clunkiness of ColdFusion Builder any longer. WIN!


For me, one thing I needed to change was the color scheme for ColdFusion versus HTML tags, since by default they both have the same color scheme. To highlight ColdFusion tags in a different color from the html tags:
  • In Sublime Text 2 open up Preferences -> Browse Packages and then go to the Color Scheme - Default directory
  • Open the theme file for the theme you are using. For instance, I am using the Monokai theme, so I opened the Monokai.tmTheme file
  • Add the following code before the final </array> tag in this file
<!-- BEGIN ColdFusion specific coloring -->
<dict>
    <key>name</key>
    <string>CF tag name</string>
    <key>scope</key>
    <string>entity.name.tag.conditional.cfml, entity.name.tag.declaration.cfml, entity.name.tag.other, entity.name.tag.cf, entity.name.tag.inline.other.cfml</string>
    <key>settings</key>
    <dict>
         <key>fontStyle</key>
         <string>bold</string>
         <key>foreground</key>
         <string>#A9BBDB</string>
    </dict>
</dict>
<dict>
    <key>name</key>
    <string>CF tag brackets</string>
    <key>scope</key>
    <string>punctuation.definition.tag.begin.cfml, punctuation.definition.tag.end.cfml, punctuation.definition.tag.begin.ctml, punctuation.definition.tag.end.ctml, punctuation.definition.tag.start.cfml</string>
    <key>settings</key>
    <dict>
         <key>fontStyle</key>
         <string></string>
         <key>foreground</key>
         <string>#A9BBDB</string>
    </dict>
</dict>
<dict>
    <key>name</key>
    <string>CF tag attribute</string>
    <key>scope</key>
    <string>meta.tag.block.other.cfml, entity.other.attribute-name.cfml, entity.other.attribute-name.name.cfml</string>
    <key>settings</key>
    <dict>
         <key>fontStyle</key>
         <string></string>
         <key>foreground</key>
         <string>#CF99D1</string>
    </dict>
</dict>
<dict>
    <key>name</key>
    <string>CF tag attribute quotes</string>
    <key>scope</key>
    <string>punctuation.definition.string.begin.cfml, punctuation.definition.string.end.cfml</string>
    <key>settings</key>
    <dict>
         <key>fontStyle</key>
         <string></string>
         <key>foreground</key>
         <string>#A9BBDB</string>
    </dict>
</dict>
<dict>
    <key>name</key>
    <string>CF tag attribute values</string>
    <key>scope</key>
    <string>string.quoted.double.cfml</string>
    <key>settings</key>
    <dict>
         <key>fontStyle</key>
         <string></string>
         <key>foreground</key>
         <string>#CCCCCC</string>
    </dict>
</dict>
<dict>
    <key>name</key>
    <string>CF tag equals signs</string>
    <key>scope</key>
    <string>meta.tag.inline.cfml, punctuation.separator.key-value.cfml</string>
    <key>settings</key>
    <dict>
         <key>fontStyle</key>
         <string></string>
         <key>foreground</key>
         <string>#CF99D1</string>
    </dict>
</dict>
<dict>
    <key>name</key>
    <string>CF tag variables</string>
    <key>scope</key>
    <string>meta.tag.inline.cfml variable.other.cfscript, meta.tag.block.conditional.cfml variable.other.cfscript</string>
    <key>settings</key>
    <dict>
         <key>fontStyle</key>
         <string></string>
         <key>foreground</key>
         <string>#FFFFFF</string>
    </dict>
</dict>
<dict>
    <key>name</key>
    <string>CF comments</string>
    <key>scope</key>
    <string>comment.block.cfml, comment.line.cfml, comment.line.double-slash.cfscript, comment.block.cfscript</string>
    <key>settings</key>
    <dict>
         <key>fontStyle</key>
         <string></string>
         <key>foreground</key>
         <string>#000000</string>
         <key>background</key>
         <string>#999999</string>
    </dict>
</dict>
<!-- END ColdFusion specific coloring -->
  • Save the file and then open up a ColdFusion page, your CF tags should be a different color
  • To change the color of the CF tags, adjust the hexadecimal colors in the new code block

More info:

Sublime text uses selectors to identify parts of the code for coloring. You will see that the outer <dict></dict> code blocks contain a <key>scope</key> section followed by a <string></string> section. You put the selectors in this <string></string> section.

You can get the selector names to identify different parts of your code by going to one of your code pages and highlighting the code you want to color. Then hit [ctrl]+[alt]+[shift]+p (Win/Lin) or [cmd]+[opt]+p (Mac) to display the selector in the status bar at the bottom. To copy the selectors to the clipboard hit [ctrl]+` (Win/Lin) or [cmd]+`(Mac) to open the console and paste the following code into it: sublime.set_clipboard(view.syntax_name(view.sel()[0].b)) If you find a good resource for altering/creating themes post it here! The basis for the information on this page can be found at: http://stackoverflow.com/questions/9345222/syntax-specific-highlighting-with-sublime-text-2