Writing simple python setup commands

 
Thread Tools Search this Thread
Operating Systems Linux Red Hat Writing simple python setup commands
# 1  
Old 04-30-2009
Writing simple python setup commands

Building software in most languages is a pain. Remember ant build.xml, maven2 pom files, and multi-level makefiles?

Python has a simple solution for building modules, applications, and extensions called distutils. Disutils comes as part of the Python distribution so there are no other packages required.

Pull down just about any python source code and you’re more than likely going to find a setup.py script that helps make building and installing a snap. Most engineers don’t add functionality when using distutils, instead opting to use the default commands.

In some cases, developers might provide secondary scripts to do other tasks for building and testing outside of the setup script, but I believe that can lead to unnecessary complication of common tasks.

For those who are not familiar with setup scripts, Figure 1 shows a simple example.

#!/usr/bin/env python"""Setup script."""from distutils.core import setupsetup(name = "myapp", version = "1.0.0", description = "My simple application", long_description = "My simple application that doesn't do anything.", author = "Me", author_email = 'me@example.dom', url = "http://example.dom/myapp/", download_url = "http://example.dom/myapp/download/", platforms = ['any'], license = "GPLv3+", package_dir = {'myapp': 'src/myapp'}, packages = ['myapp'], classifiers = [ 'License :: OSI Approved :: GNU General Public License (GPL)', 'Development Status :: 5 - Production/Stable', 'Topic :: Software Development :: Libraries :: Python Modules', 'Programming Language :: Python'],)Figure 1.
This setup script lists the metadata, maps to a package directory, and provides the general commands expected from distutils setup. This is great, but as I’ve said, it may not do everything you need it to.

What if, for example, we want to be able to see all the TODO tags in the codebase on any platform? In other words, grep won’t cut it.

Let’s start by writing a function that searches for TODO tags in files and prints them back to the screen in a nice format like:

src/myapp/__init__.py (11): TODO: remove me

def report_todo(): """ Prints out TODO's in the code. """ import os import re # The format of the string to print: file_path (line_no): %s line_str format_str = "%s (%i): %s" # regex to remove whitespace in front of TODO's remove_front_whitespace = re.compile("^[ ]*(.*)$") # Look at all non pyc files from current directory down for rootdir in ['src/', 'bin/']: # walk down each root directory for root, dirs, files in os.walk(rootdir): # for each single file in the files for afile in files: # if the file doesn't end with .pyc if not afile.endswith('.pyc'): full_path = os.path.join(root, afile) fobj = open(full_path, 'r') line_no = 0 # look at each line for TODO's for line in fobj.readlines(): if 'todo' in line.lower(): nice_line = remove_front_whitespace.match( line).group(1) # print the info if we have a TODO print(format_str % ( full_path, line_no, nice_line)) line_no += 1Figure 2.
The report_todo function is self-contained and quite simple, if a bit clunky by itself. Who wants to install and use a ‘report-todo’ command on machines just to look for TODO tags?

We want to turn this into a setup command so that we can ship it with our application ‘myapp’ to be used by developers via setup.py. We will probably add more setup commands in the future, so let’s create a class to subclass our commands from. We do this because most of our commands will probably be simple and won’t need to override the *_option methods (though they can if they need to).

import osfrom distutils.core import setup, Commandclass SetupBuildCommand(Command): """ Master setup build command to subclass from. """ user_options = [] def initialize_options(self): """ Setup the current dir. """ self._dir = os.getcwd() def finalize_options(self): """ Set final values for all the options that this command supports. """ passFigure 3.
The SetupBuildCommand defines a few methods that are required for all setup commands. As I stated before, most of our commands will probably not deviate from these defaults, so defining them higher in the object hierarchy means simpler code in the commands themselves. If we do want to add arguments to to any of our commands, we can override initialize_options() and finalize_options() to handle the arguments properly.

Now that we have the SetupBuildCommand to subclass from we can merge our report_todo function into a SetupBuildCommand class. To do this, we create a class that subclasses SetupBuildCommand, and then add a description variable and a run method (which is what is executed when the command runs).

class TODOCommand(SetupBuildCommand): """ Quick command to show code TODO's. """ description = "prints out TODO's in the code" def run(self): """ Prints out TODO's in the code. """ import re # The format of the string to print: file_path (line_no): %s line_str format_str = "%s (%i): %s" # regex to remove whitespace in front of TODO's remove_front_whitespace = re.compile("^[ ]*(.*)$") # Look at all non pyc files in src/ and bin/ for rootdir in ['src/', 'bin/']: # walk down each root directory for root, dirs, files in os.walk(rootdir): # for each single file in the files for afile in files: # if the file doesn't end with .pyc if not afile.endswith('.pyc'): full_path = os.path.join(root, afile) fobj = open(full_path, 'r') line_no = 0 # look at each line for TODO's for line in fobj.readlines(): if 'todo' in line.lower(): nice_line = remove_front_whitespace.match( line).group(1) # print the info if we have a TODO print(format_str % ( full_path, line_no, nice_line)) line_no += 1Figure 4.
The run method in this example is the same as report_todo but in a method format (with self) and renamed to run.

Now it’s time to bring all this together. If we add Figure 1 and Figure 2 to the setup script (Figure 1), then all that is left is to map the setup command with a command name. Do this via the cmdclass argument, and in the form:

cmdclass = {'name': CommandClass}

Figure 5 shows it all together in an abbreviated form.

#!/usr/bin/env python"""Setup script."""import osfrom distutils.core import setup, Commandclass SetupBuildCommand(Command): """ Master setup build command to subclass from. """ # See Figure 3class TODOCommand(SetupBuildCommand): """ Quick command to show code TODO's. """ # See Figure 4setup(name = "myapp", version = "1.0.0", description = "My simple application", long_description = "My simple application that doesn't do anything.", author = "Me", author_email = 'me@example.dom', url = "http://example.dom/myapp/", download_url = "http://example.dom/myapp/download/", platforms = ['any'], license = "GPLv3+", package_dir = {'myapp': 'src/myapp'}, packages = ['myapp'], classifiers = [ 'License :: OSI Approved :: GNU General Public License (GPL)', 'Development Status :: 5 - Production/Stable', 'Topic :: Software Development :: Libraries :: Python Modules', 'Programming Language :: Python'], cmdclass = {'todo': TODOCommand},)Figure 5.
You’ll notice that `python setup.py –help-commands` now shows ‘Extra commands’ with our TODO command listed.

Give it a go and see what you have left to do in your code!

Image Image Image Image Image Image
Image

More...
Login or Register to Ask a Question

Previous Thread | Next Thread

10 More Discussions You Might Find Interesting

1. Shell Programming and Scripting

Python DictWriter header - not writing in first line of existing file

Hello I am facing a very unique problem and not able to understand why. I have written a function which will check header of the file. If header is present good else it will write the header on top def writeHeaderOutputCSV(fileName): # See if the file exist already try: ... (0 Replies)
Discussion started by: radioactive9
0 Replies

2. Linux

Unable to access CentOS setup Network Configuration after attempting Python update

I attempted to update Python on my CentOS 5.6 VM and have encountered some issues after then. Initially yum wouldn't work, but I have resolved that. However, now I am unable to access the Network Configuration section under setup. When I do select this option I see this at the command line: ... (2 Replies)
Discussion started by: crmpicco
2 Replies

3. Programming

Simple encryption in python

Hi, i have the below script: ###############################SimpleEncryption################################ #Simple encryption implemented in python #Author:pandeeswaran ############################################################################### def Encrypt(input): res='' ... (13 Replies)
Discussion started by: pandeesh
13 Replies

4. Shell Programming and Scripting

Help with writing simple bash script

I want to write a bash script to: 1. Send an email from localhost to an external gmail account. (gmail then automatically forwards the message back to a pop account on the same server. 2. Script waits 3 minutes then checks to see if the email arrived, and if not, it sends an email to... (9 Replies)
Discussion started by: sallyanne
9 Replies

5. UNIX for Dummies Questions & Answers

writing commands?

how to write a command line that displays the long listing of just the directories in the current working directory? (1 Reply)
Discussion started by: jorogon0099
1 Replies

6. Shell Programming and Scripting

Writing a simple loop in perl

Dear all, I am a complete newbie to (perl) programming and I am completely stuck in a project. I have the following arrays @array_1 @array_2 @array_A @array_B @array_C Each element pair of array_1 and array_2 is linked to all elements of a third array (e.g. array_A, array_B or... (3 Replies)
Discussion started by: docdudetheman
3 Replies

7. Programming

Writing a shell in Python

Hi all, For one of my projects I'm required to write a python shell which takes in the usual shell commands such as changing directory, clearing the screen and quitting the shell. I've found plenty of resources on doing it in C, but nothing on Python yet. Could anyone point me in the right... (1 Reply)
Discussion started by: sadistik_exec
1 Replies

8. UNIX for Dummies Questions & Answers

HELP! writing simple shell script

how would i write a shell script to show the number of lines in which int variable appears in a c++ program. (3 Replies)
Discussion started by: deadleg
3 Replies

9. UNIX for Dummies Questions & Answers

simple modem setup question from new comer

How do you adjust the volume on a modem internally. I know there is a setting to turn off the speaker during handshake and leave it on while dialing. Could someone help me please? (2 Replies)
Discussion started by: agentrambo
2 Replies

10. UNIX for Dummies Questions & Answers

Need help writing simple script

I'm trying to write a simple unix script that will delete files after 30 days of being created. I've never done this before but conceptually it sounds easy. Here is what I'm trying to do: Get System Date Get File Date If (sysdate-filedate>30days) rm file All of these files are contained... (1 Reply)
Discussion started by: tamdoankc
1 Replies
Login or Register to Ask a Question