If you haven't read Part 1 and/or Part 2 of this series, I recommend you do that before continuing with this article. In Part 2, we looked at how to configure a Pyramid application using Declarative Configuration and Imperative Configuration.
This article will cover the application project structure. By taking a closer look at the project structure, this will help us to know where important files are located along with where to put our own files that will comprise the application.
Project Structure
In Part 1 of this series, we generated an example application using the scaffolding for a project called MyProject. This section will use that example to outline a project structure. The main application directory, MyProject, contains the following files that come with every project:
- Changes.txt. This file contains the changes for your application. It's not a file to document code changes, but rather a high-level overview of changes. The standard format is to document changes by version, as in the following example:
1.0 (unreleased) ---------------------- - Initial version - Drop support for Python 2.5This file helps other programmers to identify high-level changes that have taken place in the application.
- Readme.txt. Describes the overall summary of what the application does, as in this example:
This application is a web spider that traverses links on a web site that is provided as starting point. A collection of the hyper-links is stored to a database.
- development.ini. This file holds the configuration for connecting to your web server. It uses development configuration settings, as opposed to production settings. This file will be covered in detail later in this series.
- production.ini. This file has the configuration for connecting to the web server. It uses production configuration settings, as opposed to development settings. production.ini is basically the same as development.ini, but turns off debugging options that slow page rendering.
- MANIFEST.in. This configuration file includes references to files that are not Python files, but should be distributed with the application. Think of it as a JEE Java project Manifest file for Java. The Java Manifest file is similar to a Python Manifest file in that it references .jar files and the class path to their location. Once the app is archived and then decompressed, Manifest creates a roadmap to place the application source files. The following line could appear in a Manifest file:
include *.txt *.js *.css
- setup.py. This is a multipurpose command-line file used for testing, packaging, and distributing an application. When distributing an app, this file looks at the MANIFEST.in file to determine what should be included in the app. Look at this example setup.py file:
import os from setuptools import setup, find_packages here = os.path.abspath(os.path.dirname(__file__)) README = open(os.path.join(here, 'README.txt')).read() CHANGES = open(os.path.join(here, 'CHANGES.txt')).read() requires = [ 'pyramid', 'pyramid_debugtoolbar', 'waitress', ] setup(name='MyProject', version='0.0', description='MyProject', long_description=README + '\n\n' + CHANGES, classifiers=[ "Programming Language :: Python", "Framework :: Pyramid", "Topic :: Internet :: WWW/HTTP", "Topic :: Internet :: WWW/HTTP :: WSGI :: Application", ], author='', author_email='', url='', keywords='web pyramid pylons', packages=find_packages(), include_package_data=True, zip_safe=False, install_requires=requires, tests_require=requires, test_suite="myproject", entry_points=""" [paste.app_factory] main = myproject:main """, )A lot of this file's contents are application metadata. Running this file from the command line creates an application tarball file that you can send to other people to run the application. This is an example command:
$ python setup.py sdist
- setup.cfg. This file contains settings that allow testing and internationalization of your application to work smoothly. The default settings suffice most of the time.
The project structure contains a series of folders called packages. These packages include the Python files that run your application. The __init__.py file that's in a package folder tells Python the folder is a package. A distribution is a collection of packages. The top of the project folder hierarchy is referred to as the distribution root.
- myproject folder. This folder is the main package for your application. Like all packages, it contains an entry point into the package. In this case, it's the application. A typical __init.py__ file to initialize the application is shown below:
from pyramid.config import Configurator def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ config = Configurator(settings=settings) config.add_static_view('static', 'static', cache_max_age=3600) config.add_route('home', '/') config.scan() return config.make_wsgi_app()This file creates an application server instance and connects it to the web server, allowing the app to take HTTP requests. In terms of functionality, it's similar to a Java Servlet. In this example, the home view is added to the routing configuration, telling the app that nothing after the domain name (or IP/port number) will show this view by default.
- myproject\views.py. This file contains view configurations, also known as view callables. I covered views in detail in Part 2 of this series. View callables are used in Declarative Configurations. An example views.py file appears below:
from pyramid.view import view_config @view_config(route_name='home', renderer='templates/mytemplate.pt') def my_view(request): return {'project': 'MyProject'}The config.scan command in the __setyp.py__ file seeks out these view declarations by looking for the @view_config decorator to get the view details. The function maps a route to a path and returns a Response object by the my_view function that can be used by the application.
- myproject\static. The static subdirectory holds all the applications static files, such as .css, .html, and images.
- myproject\templates\mytemplate.pt. Template files end with a .pt extension. This is the default template file displayed by the my_view callable defined earlier. Templates are often used by views. You can think of views as the presentation layer to your application.
- myproject\tests.py. This module is used for unit-testing the application. It's generated by default with a single unit test. Unit tests often test view requests. Following is an example module:
import unittest from pyramid import testing class ViewTests(unittest.TestCase): def setUp(self): self.config = testing.setUp() def tearDown(self): testing.tearDown() def test_my_view(self): from .views import my_view request = testing.DummyRequest() info = my_view(request) self.assertEqual(info['project'], 'MyProject')
Conclusion
In this article, you learned the basics of a Python project structure. The structure is easy to follow and should be used as a means of communicating with other Python developers. The structure is used by several Python frameworks. It's important to understand which file types can be used by the structure, along with their locations. This understanding makes adding custom code much easier. One quick way to set up a Python project structure is by using a scaffolding template application. This type of application can serve as a good starting point for your project requirements.
In Part 4 of this series, I'll cover the application startup process and take a closer look at the development.ini configuration file, which has numerous settings.