From Fedora Project Wiki
(fedmsg)
(pylint, pyflakes, pep8)
Line 2: Line 2:


=== Coding style ===                                                                                                                                                                     
=== Coding style ===                                                                                                                                                                     
* Python code should be [http://www.python.org/dev/peps/pep-0008/ PEP8 compliant]  
* Python code should be [http://www.python.org/dev/peps/pep-0008/ PEP8 compliant]
                                                                                                                                                                       
 
You can run pylint over your code once in a while to help catch PEP8 violations.  pyflakes and pep8 (the program) are fast enough that you could  setup your editor to [http://lewk.org/blog/python-vim-pyflakes run them whenever you save] a python file (but they don't catch nearly as many things as pylint does).
 
=== Centralized logging ===
=== Centralized logging ===
                                                                                                                                                                            
                                                                                                                                                                            

Revision as of 20:07, 24 January 2013

Best Practices for Fedora Infrastructure Apps

Coding style

You can run pylint over your code once in a while to help catch PEP8 violations. pyflakes and pep8 (the program) are fast enough that you could setup your editor to run them whenever you save a python file (but they don't catch nearly as many things as pylint does).

Centralized logging

Most of our apps use the standard Python logging module, which usually ends up logging to /var/log/httpd/error_log on the app server.

To have your app logs shipped to our central logging server, you can configure the SysLogHandler to do so.

For config-file based logging setups, you can do something like the following:

[logging]                                                                                                                                                             
                                                                                                                                                                          
[[handlers]]                                                                                                                                                          
                                                                                                                                                                         
[[[syslog_out]]]                                                                                                                                                      
class='handlers.SysLogHandler'                                                                                                                                        
args="('/dev/log', handlers.SysLogHandler.LOG_LOCAL4,)"                                                                                                               
formatter='full_content'                                                                                                                                              
                                                                                                                                                                          
[[loggers]]                                                                                                                                                           
                                                                                                                                                                          
[[[bodhi]]]                                                                                                                                                           
level='DEBUG'                                                                                                                                                         
qualname='bodhi'                                                                                                                                                      
handlers=['syslog_out']                                                                                                                                               
propagate=0                                                                                                                                                           

Here is an example of doing it in pure Python:

import logging
import logging.handlers

syslogger = logging.getLogger('bodhi')
syslogger.setLevel(logging.DEBUG)
handler = logging.handlers.SysLogHandler(address='/dev/log', facility=logging.handlers.SysLogHandler.LOG_LOCAL4)
syslogger.addHandler(handler)
syslogger.info('Hello SysLog!')

The app logs will then appear in /var/log/hosts/<HOST>/<YEAR>/<MONTH>/<DAY>/apps.log as well as the merged log /var/log/merged/apps.log on our central rsyslog server.

Translations

Use transifex to manage translations and add the projects to the Fedora Project Team so the Fedora i18n team can translate.

Do not mark Exception messages for translation. We want those to remain untranslated for several reasons:

  1. It's easier to do a web search for the exceptions if the messages aren't translated.
  2. Translators don't know what all the technical information in exception messages are so the translations aren't always accurate.
  3. The exception messages aren't intended for end users -- they're to help with debugging or other coders. So it's not very useful to translate them.

Web Frameworks

Use one of Flask, Pyramid, or TurboGears2. Limiting the number of web frameworks we're responsible for will greatly help with our long term maintenance burden.

Use git flow

First, yum install gitflow.

Quick cheatsheet for getting started. You can also read:

# First thing when you initially clone a repo
$ git flow init

# Always work on the 'devel' or 'develop' branch if just doing small maintenance

# Working on a major feature
# git flow creates feature branches that are prefixed with feature/
$ git flow feature start my-new-feature
$ # make edits, commit

# Share that feature with others for review
$ git flow feature publish my-new-feature

# When you're done.. you can merge it on github with a click, or if you'd like to do so from the CLI
$ git flow feature finish my-new-feature

# Working on a release
# Releases end up on the master branch
$ git flow release start 0.3.32
$ # make some edits, bump version numbers, commit, release to pypi.
$ git flow release finish 0.3.32
$ git push --all
$ git push --tags

This quick overview and a more in depth article on using it.

If you're more comfortable using vanilla git without the gitflow addon, the things to be aware of are:

  • new commits should go to the devel branch (the default on the repos we set up on github).
  • master is used to make releases from and should reflect what's in production (or in an rpm, ready to be pushed to production) at any given time.
  • hotfixes have their own branches that need to be merged into both master (for release) and devel.
hotfix recipe
Add a hotfix recipe in the cheatsheet

fedmsg

Think about how to add fedmsg hooks into every event that changes data. However, also make it so that fedmsg is optional (ie: the app doesn't fail if fedmsg is not available/installed). This makes it easier to test apps outside of infrastructure and makes us more robust in case fedmsg starts failing sometime.