Disabling images in Python Markdown

Here’s a quick snippet that shows how to disable images (or any extension) in Python Markdown:

import markdown

class MyMarkdownExtension(markdown.Extension):

	def extendMarkdown(self, md, md_globals):
		del md.inlinePatterns['image_link']
		del md.inlinePatterns['image_reference']

my_markdown_extension = MyMarkdownExtension()

raw_text = 'This is a test image: ![Google Logo](http://www.google.com/images/logos/ps_logo2a_cp.png)'

print markdown.markdown(raw_text, [my_markdown_extension], safe_mode = 'escape')

Edit:
Some processing is disabled through md.parser.blockprocessors instead.

Here are the options for each:
md.inlinePatterns:

'backtick'
'escape'
'reference'
'link'
'image_link'
'image_reference'
'short_reference'
'autolink'
'automail'
'linebreak2'
'linebreak'
'html'
'entity'
'not_strong'
'strong_em'
'strong'
'emphasis'
'emphasis2'

md.parser.blockprocessors:

'indent'
'code'
'hashheader'
'setextheader'
'hr'
'olist'
'ulist'
'quote'
'paragraph'

5 Comments

Running a reverse proxy for App Engine on Amazon EC2

Updated Feburary 7th, 2012

1. Create a security group on EC2 that opens ports 22 (SSH) and 80 (HTTP).
2. Start an instance on EC2 using an Ubuntu AMI. Select the security group you just created when launching the instance. I used a micro instance running the “ami-ad7e2ee8″ (32-bit Ubuntu 10.10) image. The best place to find the AMI that you want is http://cloud-images.ubuntu.com/releases/. Everything there is nicely organized by version, release type, CPU architecture, and backing storage. (As opposed to the mess of text in the EC2 classic wizard).
3. Assign an elastic ip to the instance.
4. Go to your domain registrar, and edit your DNS zonefile. Add a CNAME that points www to your “Public DNS” on EC2 (ec2-elasticip.zone.compute.amazonaws.com.). It’s important to use a CNAME record rather than an A record, because your instance will not be accessible to other EC2 instances by public IP address.
5. SSH into your server and install nginx.

If you want the latest version of nginx, you need to add these repositories to apt-get to download from nginx.org. If not, skip this block, and you will get the latest version available from Ubuntu.

cd ~
sudo echo "deb http://nginx.org/packages/ubuntu/ quantal nginx" >> /etc/apt/sources.list
sudo echo "deb-src http://nginx.org/packages/ubuntu/ quantal nginx" >> /etc/apt/sources.list
sudo wget http://nginx.org/keys/nginx_signing.key
sudo apt-key add nginx_signing.key

Now, download and install nginx.

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install nginx
sudo vi /etc/nginx/nginx.conf

6. Now, remove any existing server blocks, and add your own to /etc/nginx/nginx.conf.

server {
        listen 80;

        location / {

        }
}

server {
        listen  80;

        server_name  www.mysite.com;

        location / {
                proxy_pass  http://mysite.appspot.com;
                proxy_set_header  X-Real-IP    $remote_addr;
                proxy_set_header  X-Real-HOST  $host;
        }
}

The first server block is the default, so this blocks requests that are not for the domain you’re trying to proxy.
7. Run nginx:

sudo service nginx start

8. You should be able to access your App Engine site using your own domain. However, in your app engine request handlers, self.request.host will be set to your appspot domain, and self.request.remote_addr will be set to your ec2 ip address. We can fix this by adding some middle ware to app engine, assuming you’re using webapp or webapp2.

class ReverseProxyMiddleware(object):

	def __init__(self, application, debug=False):
		self.application = application

	def __call__(self, environ, start_response):
		real_host = environ.get('HTTP_X_REAL_HOST')
		if real_host:
			environ['HTTP_HOST'] = real_host
			environ['SERVER_NAME'] = real_host
		real_ip = environ.get('HTTP_X_REAL_IP')
		if real_ip:
			environ['REMOTE_ADDR'] = real_ip
		return self.application(environ, start_response)

To use it, wrap your WSGIApplication right after initialization.

application = WSGIApplication([
...
])
application = ReverseProxyMiddleware(application)

9. That’s it! One thing to note is that app engine cron jobs and task queues don’t know anything about your reverse proxy, so in those handlers, self.request.host will still be your appspot domain.

1 Comment

Using a webcam in Molehill

I’ve created a sample project on github that demonstrates how to use a webcam in Molehill. It’s not really any different than using a static texture, except for these lines:

    snapshot.draw(video, snapshotTransform);
    texture.uploadFromBitmapData(snapshot);

The performance is very impressive, and you can see from the code, it was simple to do. Hooray for Molehill.

Edit: Updated to work in Flash Player 11 beta 2.

Leave a Comment

ByteArray compress vs. deflate

I couldn’t find any information on the difference between ByteArray.compress() and ByteArary.deflate(), so I decided to do a quick test.

package
{
	import flash.display.Sprite;
	import flash.utils.ByteArray;
	import flash.utils.getTimer;
	
	public class CompressionTest extends Sprite
	{
		public function CompressionTest()
		{
			var start:uint;
			
			var bytes:ByteArray = new ByteArray();
			
			for(var i:uint = 0; i < 100000; i++)
			{
				bytes.writeShort(0);
				bytes.writeFloat(Math.random());
				bytes.writeFloat(Math.random() * Number.MAX_VALUE);
			}
			
			trace('Uncompressed: '+bytes.length);
			start = getTimer();
			bytes.compress();
			trace('Time spent on compress: '+(getTimer() - start)+'ms');
			trace('Compressed size with compress(): '+bytes.length);
			start = getTimer();
			bytes.uncompress();
			trace('Time spent on uncompress: '+(getTimer() - start)+'ms');
			start = getTimer();
			bytes.deflate();
			trace('Time spent on deflate: '+(getTimer() - start)+'ms');
			trace('Compressed size with deflate(): '+bytes.length);
			start = getTimer();
			bytes.inflate();
			trace('Time spent on inflate: '+(getTimer() - start)+'ms');
		}
	}
}

My results are:

Uncompressed: 1000000
Time spent on compress: 1294ms
Compressed size with compress(): 416142
Time spent on uncompress: 5ms
Time spent on deflate: 1302ms
Compressed size with deflate(): 416136
Time spent on inflate: 5ms

So, it looks like there is absolutely no difference.
According to this StackOverflow post, the only difference is a header and checksum in the compress version.

Leave a Comment

Flash Player molehill is available on Adobe Labs!

Finally, we get a low-level 3D API for flash. The documentation on labs is really bad, the few examples there are don’t work at all. So, I made a simple source code example on github:
https://github.com/magicalhobo/MolehillSimpleExample

,

Leave a Comment

typeof in python

I could not find a good way to get the name of a class from an instance with Python on google. It’s simple (but not obvious):

str(type(var))

1 Comment

Google App Engine “ImportError: DLL load failed with error code 193″

Today I installed PIL, tried to use the images API on the local dev server, then got this message. The problem was I was running a 64-bit version of python, which won’t load PIL correctly. The solution is to install a 32-bit version of python, and make sure you re-install PIL into that copy of python.

Leave a Comment

Follow

Get every new post delivered to your Inbox.