Google App Engine (GAE/py) の開発環境をつくる

appfy.recipe.gae のサンプル

buildout.cfg:

[buildout]
parts = app_lib gae_sdk gae_tools

[app_lib]
# Sets the library dependencies for the app.
recipe = appfy.recipe.gae:app_lib
lib-directory = app/distlib
use-zipimport = false

# Define the libraries.
eggs =
    tipfy

# Don't copy files that match these glob patterns.
ignore-globs =
    *.c
    *.pyc
    *.pyo
    */test
    */tests
    */testsuite
    */django
    */sqlalchemy

# Don't install these packages or modules.
ignore-packages =
    distribute
    setuptools
    easy_install
    site
    pkg_resources


[gae_sdk]
# Dowloads and extracts the App Engine SDK.
recipe = appfy.recipe.gae:sdk
url = http://googleappengine.googlecode.com/files/google_appengine_1.4.1.zip
destination = ${buildout:parts-directory}
hash-name = false
clear-destination = true


[gae_tools]
# Installs appcfg, dev_appserver and python executables in the bin directory.
recipe = appfy.recipe.gae:tools
sdk-directory = ${gae_sdk:destination}/google_appengine

# Add these paths to sys.path in the generated scripts.
extra-paths =
    app/lib
    app/distlib

実行すると以下のようになります:

$ python bootstrap.py -d init
$ bin/buildout

$ ls bin
bin/appcfg           bin/bulkloader       bin/remote_api_shell
bin/buildout         bin/dev_appserver
bin/bulkload_client  bin/python

アプリのスケルトンを自動生成する設定を追加

buildout.cfg:

[buildout]
parts = prepare app_lib gae_sdk gae_tools

[prepare]
recipe = iw.recipe.cmd:py
on_install = true
cmds =
    >>> files = {}
    >>> files['app.yml'] = """\
    ... application: appname
    ... version: 1
    ... runtime: python
    ... api_version: 1
    ... builtins:
    ... - remote_api: on
    ... - appstats: on
    ... #- datastore_admin: on
    ... handlers:
    ... - url: .*
    ...   script: main.py
    ... """
    >>> files['main.py'] = """\
    ... import sys
    ... sys.path.insert(0, './distlib.zip')
    ... """
    >>> buildout_dir = buildout.get('directory', '.')
    >>> path = os.path.join(buildout_dir, 'app')
    >>> if not os.path.exists(path):
    ...     os.makedirs(os.path.join(buildout_dir, 'app'))
    ...     for name in files:
    ...         open(os.path.join(path, name), 'at').write(files[name])

[app_lib]
# Sets the library dependencies for the app.
recipe = appfy.recipe.gae:app_lib
lib-directory = app/distlib
use-zipimport = true

# Define the libraries.
eggs =
    Flask
    feedparser
    twitter
    BeautifulSoup

# Don't copy files that match these glob patterns.
ignore-globs =
    *.c
    *.pyc
    *.pyo
    */test
    */tests
    */testsuite
    */django
    */sqlalchemy
    simplejson/_speedups.py

# Don't install these packages or modules.
ignore-packages =
    distribute
    setuptools
    easy_install
    site
    pkg_resources


[gae_sdk]
# Dowloads and extracts the App Engine SDK.
recipe = appfy.recipe.gae:sdk
url = http://googleappengine.googlecode.com/files/google_appengine_1.4.1.zip
#destination = ${buildout:parts-directory}
#hash-name = false
clear-destination = true


[gae_tools]
# Installs appcfg, dev_appserver and python executables in the bin directory.
recipe = appfy.recipe.gae:tools
sdk-directory = ${gae_sdk:destination}/google_appengine

# Add these paths to sys.path in the generated scripts.
extra-paths =
    app/lib
    app/distlib.zip

実行すると以下のようになります:

$ bin/buildout

$ ls bin
bin/appcfg           bin/bulkloader       bin/remote_api_shell
bin/buildout         bin/dev_appserver
bin/bulkload_client  bin/python

$ ls app
app.yml     distlib/    distlib.zip main.py

$ bin/dev_appserver app

アプリ名などを設定出来るようにする

buildout.cfg:

[buildout]
parts = prepare app_lib gae_sdk gae_tools

app-dir = app
app-name = appname
eggs =
    Flask
    feedparser
    twitter
    BeautifulSoup

[prepare]
recipe = iw.recipe.cmd:py
on_install = true
cmds =
    >>> files = {}
    >>> files['app.yml'] = """\
    ... application: ${buildout:app-name}
    ... version: 1
    ... runtime: python
    ... api_version: 1
    ... builtins:
    ... - remote_api: on
    ... - appstats: on
    ... #- datastore_admin: on
    ... handlers:
    ... - url: .*
    ...   script: main.py
    ... """
    >>> files['main.py'] = """\
    ... import sys
    ... sys.path.insert(0, './distlib.zip')
    ... """
    >>> buildout_dir = buildout.get('directory', '.')
    >>> path = os.path.join(buildout_dir, '${buildout:app-dir}')
    >>> if not os.path.exists(path):
    ...     os.makedirs(os.path.join(buildout_dir, '${buildout:app-dir}'))
    ...     for name in files:
    ...         open(os.path.join(path, name), 'at').write(files[name])

[app_lib]
# Sets the library dependencies for the app.
recipe = appfy.recipe.gae:app_lib
lib-directory = ${buildout:app-dir}/distlib
use-zipimport = true
eggs = ${buildout:eggs}

# Don't copy files that match these glob patterns.
ignore-globs =
    *.c
    *.pyc
    *.pyo
    */test
    */tests
    */testsuite
    */django
    */sqlalchemy
    simplejson/_speedups.py

# Don't install these packages or modules.
ignore-packages =
    distribute
    setuptools
    easy_install
    site
    pkg_resources


[gae_sdk]
# Dowloads and extracts the App Engine SDK.
recipe = appfy.recipe.gae:sdk
url = http://googleappengine.googlecode.com/files/google_appengine_1.4.1.zip
#destination = ${buildout:parts-directory}
#hash-name = false
clear-destination = true


[gae_tools]
# Installs appcfg, dev_appserver and python executables in the bin directory.
recipe = appfy.recipe.gae:tools
sdk-directory = ${gae_sdk:destination}/google_appengine

# Add these paths to sys.path in the generated scripts.
extra-paths =
    ${buildout:app-dir}/lib
    ${buildout:app-dir}/distlib.zip

デバッグ用の対話コンソール用スクリプトを追加する

buildout.cfg:

[buildout]
parts = prepare debug app_lib gae_sdk gae_tools

app-dir = app
app-name = appname
eggs =
    Flask
    feedparser
    twitter
    BeautifulSoup

[prepare]
recipe = iw.recipe.cmd:py
on_install = true
cmds =
    >>> files = {}
    >>> files['app.yml'] = """\
    ... application: ${buildout:app-name}
    ... version: 1
    ... runtime: python
    ... api_version: 1
    ... builtins:
    ... - remote_api: on
    ... - appstats: on
    ... #- datastore_admin: on
    ... handlers:
    ... - url: .*
    ...   script: main.py
    ... """
    >>> files['main.py'] = """\
    ... import sys
    ... sys.path.insert(0, './distlib.zip')
    ... """
    >>> buildout_dir = buildout.get('directory', '.')
    >>> path = os.path.join(buildout_dir, '${buildout:app-dir}')
    >>> if not os.path.exists(path):
    ...     os.makedirs(os.path.join(buildout_dir, '${buildout:app-dir}'))
    ...     for name in files:
    ...         open(os.path.join(path, name), 'at').write(files[name])

[debug]
recipe = zc.recipe.egg:script
eggs = ipython
extra-paths =
    ${gae_tools:extra-paths}
    ${gae_tools:sdk-directory}/lib/django
    ${gae_tools:sdk-directory}/lib/webob
    ${gae_tools:sdk-directory}/lib/yaml/lib
    ${buildout:directory}/${buildout:app-dir}
interpreter = py

[app_lib]
# Sets the library dependencies for the app.
recipe = appfy.recipe.gae:app_lib
lib-directory = ${buildout:app-dir}/distlib
use-zipimport = true
eggs = ${buildout:eggs}

# Don't copy files that match these glob patterns.
ignore-globs =
    *.c
    *.pyc
    *.pyo
    */test
    */tests
    */testsuite
    */django
    */sqlalchemy
    simplejson/_speedups.py

# Don't install these packages or modules.
ignore-packages =
    distribute
    setuptools
    easy_install
    site
    pkg_resources


[gae_sdk]
# Dowloads and extracts the App Engine SDK.
recipe = appfy.recipe.gae:sdk
url = http://googleappengine.googlecode.com/files/google_appengine_1.4.1.zip
#destination = ${buildout:parts-directory}
#hash-name = false
clear-destination = true


[gae_tools]
# Installs appcfg, dev_appserver and python executables in the bin directory.
recipe = appfy.recipe.gae:tools
sdk-directory = ${gae_sdk:destination}/google_appengine

# Add these paths to sys.path in the generated scripts.
extra-paths =
    ${buildout:app-dir}/lib
    ${buildout:app-dir}/distlib.zip

NoseとNoseGAEを使って自動テストの設定を追加する

buildout.cfg:

[buildout]
parts = prepare debug app_lib gae_sdk gae_tools test

app-dir = app
app-name = appname
eggs =
    Flask
    feedparser
    twitter
    BeautifulSoup

[prepare]
recipe = iw.recipe.cmd:py
on_install = true
cmds =
    >>> files = {}
    >>> files['app.yml'] = """\
    ... application: ${buildout:app-name}
    ... version: 1
    ... runtime: python
    ... api_version: 1
    ... builtins:
    ... - remote_api: on
    ... - appstats: on
    ... #- datastore_admin: on
    ... handlers:
    ... - url: .*
    ...   script: main.py
    ... """
    >>> files['main.py'] = """\
    ... import sys
    ... sys.path.insert(0, './distlib.zip')
    ... """
    >>> buildout_dir = buildout.get('directory', '.')
    >>> path = os.path.join(buildout_dir, '${buildout:app-dir}')
    >>> if not os.path.exists(path):
    ...     os.makedirs(os.path.join(buildout_dir, '${buildout:app-dir}'))
    ...     for name in files:
    ...         open(os.path.join(path, name), 'at').write(files[name])

[debug]
recipe = zc.recipe.egg:script
eggs = ipython
extra-paths =
    ${gae_tools:extra-paths}
    ${gae_tools:sdk-directory}
    ${gae_tools:sdk-directory}/lib/django
    ${gae_tools:sdk-directory}/lib/webob
    ${gae_tools:sdk-directory}/lib/yaml/lib
    ${buildout:directory}/${buildout:app-dir}
interpreter = py

[app_lib]
# Sets the library dependencies for the app.
recipe = appfy.recipe.gae:app_lib
lib-directory = ${buildout:app-dir}/distlib
use-zipimport = true
eggs = ${buildout:eggs}

# Don't copy files that match these glob patterns.
ignore-globs =
    *.c
    *.pyc
    *.pyo
    */test
    */tests
    */testsuite
    */django
    */sqlalchemy
    simplejson/_speedups.py

# Don't install these packages or modules.
ignore-packages =
    distribute
    setuptools
    easy_install
    site
    pkg_resources


[gae_sdk]
# Dowloads and extracts the App Engine SDK.
recipe = appfy.recipe.gae:sdk
url = http://googleappengine.googlecode.com/files/google_appengine_1.4.1.zip
#destination = ${buildout:parts-directory}
#hash-name = false
clear-destination = true


[gae_tools]
# Installs appcfg, dev_appserver and python executables in the bin directory.
recipe = appfy.recipe.gae:tools
sdk-directory = ${gae_sdk:destination}/google_appengine

# Add these paths to sys.path in the generated scripts.
extra-paths =
    ${buildout:app-dir}/lib
    ${buildout:app-dir}/distlib.zip

[test]
recipe = pbp.recipe.noserunner
eggs =
    ${app_lib:eggs}
    nose
    nosegae
extra-paths = ${debug:extra-paths}
environment = nose-environment
working-directory = ${buildout:directory}/${buildout:app-dir}
defaults = --without-sandbox

[nose-environment]
NOSE_WITH_DOCTEST = true
NOSE_WITH_GAE = true
NOSE_WHERE = ${buildout:directory}/${buildout:app-dir}

実行すると以下のようになります:

$ bin/buildout

$ ls bin
bin/appcfg           bin/ipcontroller     bin/pycolor
bin/buildout         bin/ipengine         bin/python
bin/bulkload_client  bin/iptest           bin/remote_api_shell
bin/bulkloader       bin/ipython          bin/test
bin/dev_appserver    bin/ipythonx         bin/twitter
bin/ipcluster        bin/py               bin/twitterbot

$ bin/test
----------------------------------------------------------------------
Ran 0 tests in 0.005s