PageRenderTime 27ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/docs/porting.txt

https://bitbucket.org/ianb/silverlining/
Plain Text | 371 lines | 263 code | 108 blank | 0 comment | 0 complexity | cdd7acfaf384b1e3f9108233e98f4018 MD5 | raw file
Possible License(s): GPL-2.0
  1. Porting An Application To Silver Lining
  2. =======================================
  3. This describes some of the steps of taking an existing application and
  4. "porting" it to Silver Lining.
  5. First steps for a simple Python application
  6. -------------------------------------------
  7. Imagine you've been developing an application for a while, using your
  8. Python framework of choice. It doesn't matter much *what* framework
  9. you used. You might have to do a little cleanup to start:
  10. * Make sure everything runs okay with Python 2.6.
  11. * Make sure you've identified all your requirements.
  12. It's not required to use a ``setup.py`` file or specify your
  13. requirements in ``setup.py`` with ``install_requires``. These files
  14. are good practice, but not necessary.
  15. Clean up your ``site-packages``
  16. -------------------------------
  17. Some people have installed things into their computer as root, e.g.,
  18. by using ``sudo easy_install`` or ``sudo pip install``. This is a bad
  19. idea. This will cause all sorts of weird problems and complications
  20. for you, not just with Silver Lining but with everything.
  21. I recommend deleting as much from ``/usr/lib/python2.6/site-packages``
  22. as you can. I recommend *keeping* some select stable libraries like
  23. PIL, or Database drivers (psycopg, MySQLdb, etc).
  24. Create the file layout
  25. ----------------------
  26. Now you are ready to create a location for storing your application.
  27. With Silver Lining applications all the code and libraries are stored
  28. in a single directory. I usually name this directory ``mything-app``
  29. (where ``mything`` is the name of my application). So run::
  30. $ silver init mything-app
  31. $ cd mything-app
  32. $ source bin/activate
  33. Now you have an activated `virtualenv
  34. <http://virtualenv.openplans.org>`_ with some basic Silver Lining
  35. layout, though no application.
  36. Next, put your application in place::
  37. $ cd src
  38. $ hg/git/svn clone/checkout your-repository mything
  39. If you already have your code checked out into, say, ``~/src/mything``
  40. then unfortunately you'll either have to move it or deal with two
  41. separate checkouts -- the code has to be physically located inside the
  42. ``mything-app`` directory, because only that directory will be
  43. uploaded to the server. Though you can *probably* do something like
  44. this, but I haven't tried it::
  45. $ cd $VIRTUAL_ENV/src
  46. $ ln -s ~/src/mything mything
  47. anyway, you probably want to do this work on a branch or separate
  48. cloned repository.
  49. Next create a new repository for your application's libraries. You
  50. won't install libraries during the regular workflow of developing
  51. applications with Silver Lining, even if you are collaborating with
  52. other developers or using multiple machines -- you'll only install
  53. things when you've actually added, updated, or removed a library that
  54. your application uses. To do that you'll put all your *installed*
  55. libraries in another repository. You can do that like::
  56. $ cd $VIRTUAL_ENV/lib
  57. $ rm -r python
  58. $ hg init python
  59. or use ``git init``, or create a repository and clone/check it out.
  60. This repository will be separate from your main application.
  61. Note that everything gets installed into ``lib/python/``, not into
  62. ``lib/python2.6/site-packages/`` (which exists, but won't be added
  63. to).
  64. Installing Stuff
  65. ----------------
  66. Now you have some files in place, but nothing is really "installed".
  67. If you have a ``setup.py`` file, then run::
  68. $ cd $VIRTUAL_ENV
  69. $ pip install -e src/mything/
  70. This will make the package importable and install any requirements
  71. you've specified.
  72. If you *have not* written a ``setup.py`` file (common for Django
  73. applications) then you'll have to make sure the appropriate directory
  74. is on the path in a more manual fashion. Let's say you want
  75. ``src/mything/`` directly on the path, then you'll do::
  76. $ cd $VIRTUAL_ENV/lib/python/
  77. $ echo ../../src/mything/ > mything.pth
  78. If you need to install some additional things, go ahead now::
  79. $ pip install SomeLibrary
  80. If you are developing a library concurrently with your application
  81. then you should also check that library out into ``src/`` and use
  82. ``pip install -e``.
  83. You should use **pip** specifically and not easy_install, as pip
  84. cleans up after itself, uninstalling libraries and old versions of
  85. libraries.
  86. Non-Python Libraries
  87. --------------------
  88. If you have any libraries that you need that aren't pure-Python, you
  89. should install them system-wide. Ideally you should use your
  90. operating system facilities to install these libraries (e.g.,
  91. ``apt-get install python-lxml``).
  92. Make note of these libraries. Database connection libraries will be
  93. installed automatically, but any other libraries will have to be
  94. explicitly added (more on that later).
  95. Describe your application with ``app.ini``
  96. ------------------------------------------
  97. Now you have to tell Silver Lining how to start up your application,
  98. and possibly some other details. This is done through a configuration
  99. file ``app.ini`` in the root of your app.
  100. There will be an example file in place. You might just want to edit
  101. it, making note of these settings::
  102. [production]
  103. app_name = mything
  104. runner = src/mything/silver-runner.py
  105. Those are really the most important settings. Also if you are using a
  106. database (likely!) then find the appropriate line and uncomment it.
  107. In our example we'll imagine you are using PostgreSQL::
  108. service.postgresql =
  109. Note that you don't need any value there. (Maybe someday there will
  110. be a service that isn't just "enabled" but is actually configured, at
  111. which point it will take some value.)
  112. The most important thing you'll note is that now you have a "runner"
  113. defined in ``src/mything/silver-runner.py``. You better write that!
  114. The specific code you'll use depends on your web framework. This file
  115. will basically look like a mod_wsgi ``.wsgi`` file: it's some Python
  116. code that creates an object ``application``.
  117. You shouldn't need to set up your path in this file. In fact, you
  118. shouldn't need to set up any of your environment, you just find the
  119. application object. You can also use a `Paste Deploy
  120. <http://pythonpaste.org/deploy/>`_ ini file if you want (but even if
  121. you are using a framework such as Pylons, you can if you want import
  122. your ``make_app`` function directly and call it).
  123. Here's an example for Django::
  124. import django.core.handlers.wsgi
  125. application = django.core.handlers.wsgi.WSGIHandler()
  126. Setting Up Your Environment
  127. ---------------------------
  128. One nice thing about Silver Lining is that your environment can
  129. *always* be setup. That means, everything importable all the time,
  130. everything configurable all the time, all data available.
  131. To do this there is a specific file for you to customize (well, a file
  132. for you to create): ``lib/python/silvercustomize.py`` (similar to
  133. ``sitecustomize.py``).
  134. If you are using Django, you should do at least this::
  135. import os
  136. os.environ['DJANGO_SETTINGS_MODULE'] = 'mything.settings'
  137. On other systems you might import or configure other things. It is
  138. preferable to put things here rather than in your runner, as this file
  139. is always loaded, so it will be available in the interactive
  140. interpreter, in tests, in scripts, etc.
  141. Configuration
  142. -------------
  143. Silver Lining uses a different model of configuration than is
  144. typically used. You can, if you want, ignore configuration entirely
  145. -- but this is about *porting* an application, so you certainly
  146. haven't ignored configuration before. So you need to adapt that
  147. configuration.
  148. Silver Lining tells the application about the environment through
  149. `environmental variables <envvariables.html>`_ (``os.environ``).
  150. These variables are *always* set. So if you use a PostgreSQL database
  151. you would look at these:
  152. ``os.environ['CONFIG_PG_DBNAME']``: the name of the database you
  153. should connect to.
  154. ``os.environ['CONFIG_PG_HOST']``: the host of the database (empty
  155. string means localhost).
  156. ``os.environ['CONFIG_PG_PORT']``: the port of the database (empty
  157. string means default port).
  158. ``os.environ['CONFIG_PG_USER']``: the user to connect as.
  159. ``os.environ['CONFIG_PG_PASSWORD']``: the password to use (empty string
  160. means no password).
  161. ``os.environ['CONFIG_PG_SQLALCHEMY']``: creating the SQLAlchemy
  162. connection string from all these pieces is somewhat annoying, so this
  163. does it for you.
  164. These variables will be set both during local development and when
  165. deployed, so you can always rely on them -- you don't need any special
  166. conditionals.
  167. ``bin/``
  168. --------
  169. Yet to be written (it's kind of a pain currently).
  170. Setting Up Your Database
  171. ------------------------
  172. Now you have something that will *run*, but with a blank database.
  173. That's probably not what you want.
  174. You can tell Silver Lining to fetch a URL or call a script every time
  175. an application is updated. It is up to this script to do the right
  176. thing -- to alter tables, to notice tables that already exists, etc.
  177. All Silver Lining handles is fetching this program.
  178. To do this, add a setting to ``app.ini``::
  179. [production]
  180. ...
  181. update_fetch = /update-database
  182. That gets a URL, to call a script::
  183. update_fetch = script:bin/django-admin.py syncdb
  184. You can have multiple entries, one per line (indent subsequent lines).
  185. If you have to poke at a database remotely there's also a way to do
  186. that, with ``silver run``.
  187. These URLs or scripts will also be called everytime you start up the
  188. application locally using ``silver serve``.
  189. Static Files
  190. ------------
  191. If you have static files in your application, they go in ``static/``.
  192. They can (and should) be symlinks. Note that ``static`` doesn't
  193. appear in the URL; so if for example you have a convention that all
  194. your static files go in ``http://example.com/static/`` then you
  195. actually have to get the files into ``static/static/``.
  196. So do something like::
  197. $ cd $VIRTUAL_ENV/static
  198. $ ln -s ../src/mything/mything/media media
  199. For Django you might also symlink things from the admin media into a
  200. location here, like::
  201. $ ln -s ../lib/python/django/contrib/admin/media admin-media
  202. and in ``settings.py``::
  203. ADMIN_MEDIA_PREFIX = '/admin-media/'
  204. Non-Python Libraries
  205. --------------------
  206. Any non-Python libraries have to be installed in production as deb
  207. packages. For instance if you need lxml you'll need the
  208. ``python-lxml`` package installed. You can get this to happen with
  209. this addition to app.ini::
  210. packages =
  211. python-lxml
  212. You can have multiple packages, one on each line. This doesn't
  213. include databases though! (Well, SQLite is fine, as it runs
  214. in-process.)
  215. Testing It Out
  216. --------------
  217. You can run this application locally now, using::
  218. $ silver serve ~/src/mything-app/
  219. This will run any URLs or scripts in ``update_fetch``, and serve up
  220. the application at ``http://localhost:8080``. If you edit any files
  221. the server will restart to get the refreshed files.
  222. Note that when running locally you have to do things like create
  223. databases on your own. You can also `customize the local
  224. configuration <services.html#local-development-configuration>`_ (this
  225. is done *outside* the application).
  226. To test an actual deployment you need a server to deploy to. Silver
  227. Lining can deploy to any dedicated Ubuntu Lucid machine that has been
  228. configured by Silver Lining (using ``silver setup-node``), but the
  229. cloud makes getting a testing server very easy and quite cheap (when
  230. testing, you can allocate a server just for a few hours for testing
  231. before getting rid of it), so you might consider opening an account.
  232. Problems
  233. --------
  234. Here are some problems you might encounter, with ideas for solutions:
  235. I can't see errors
  236. ~~~~~~~~~~~~~~~~~~
  237. Silver Lining doesn't do anything very useful with exceptions on its
  238. own. You should use whatever facilities your web framework has.
  239. Projects like `weberror <http://bitbucket.org/bbangert/weberror/>`_
  240. and `flickzeug <http://dev.pocoo.org/projects/flickzeug/>`_ are a
  241. generic way of wrapping your application, and could be applied in the
  242. runner.
  243. To detect if you are in a production environment, you can use::
  244. from silversupport.env import is_production
  245. application = normal instantiation
  246. if not is_production():
  247. from flickzeug.debug import DebuggedApplication
  248. application = DebuggedApplication(application, evalex=True)
  249. I need custom database setup
  250. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  251. If you want to, you can do things more manually than just using
  252. ``update_fetch``. One way is to use ``silver run``. For instance,
  253. instead of using ``script:bin/django-admin.py syncdb`` you can invoke
  254. this manually on a server like::
  255. $ silver run mything-host.com django-admin.py syncdb
  256. This command can be interactive. There isn't good access directly to
  257. commands like ``psql`` though.
  258. I need a service that isn't supported
  259. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  260. Then write the code! You can fork `the project
  261. <http://bitbucket.org/ianb/silverlining>`_ and add code in
  262. ``silversupport/services/``. It's not very complicated, or at least
  263. not more complicated than using a database properly anyway.