Fun to Program – Python program

Date: 2013/08/14 (initial publish), 2021/08/02 (last update)

Source: en/fun2-00014.md

Previous Post Top Next Post

TOC

This was originally written and created around 2013 and may require to be updated. (2021)

Python program

Python is a vary http://en.wikipedia.org/wiki/High-level_programming_language[high-level programming language] which offers features to support OOP. It is very well documented in the Python documentation web site.

Python frees us from chores of the memory management required by C and allows us to focus on the problem solving. Python module system allows us to organize codes in multiple files nicely and let us divide and conqueror bugs efficiently.

If you are completely new to Python, I found a wiki page at DebianWomen/PythonTutorial to be a very good starting point. (I knew Python basics explained here.)

Let me try to learn slightly advanced Python such as modules and class by going through the following available documentation as the self-teaching session.

Consider the following as my note of the self-teaching session.

TIP: If you are using Python 2.7, replace python3 in the above examples with python.

What is OOP?

An object is a location in memory having a value and referenced by an identifier. An object can be a variable, function, or data structure.

http://en.wikipedia.org/wiki/Object-oriented_programming[Object-oriented programming (OOP)] is a programming paradigm. The “object” for OOP refers to a particular instance of a class. Objects are used to interact with one another to design applications and computer programs. “objects” have

Python2 and Python3

See “Should I use Python 2 or Python 3 for my development activity?”

Currently, Python is available in 2 major versions.

Python2

Python3

The conversion of source files between Python2 and Python3 is done by:

Example to convert Python2 to Python3 using fridge.py in Python inheritance

$ 2to3 -w fridge/fridge.py 2>/dev/null
--- fridge/fridge.py    (original)
+++ fridge/fridge.py    (refactored)
@@ -3,19 +3,19 @@
 class Fridge:
     def __init__(self, name):
         self.beer = 0
-        print name, "bought a new fridge."
+        print(name, "bought a new fridge.")
         self.name = name
     def report_beer(self):
-        print self.name, "has", self.beer, "can(s) of beer in stock."
+        print(self.name, "has", self.beer, "can(s) of beer in stock.")
         return
     def stock_beer(self, cans):
-        print self.name, "stocks", cans, "can(s) of beer."
+        print(self.name, "stocks", cans, "can(s) of beer.")
         self.beer += cans
         return
     def consume_beer(self, cans):
-        print self.name, "tries to consume", cans, "can(s) of beer"
+        print(self.name, "tries to consume", cans, "can(s) of beer")
         if self.beer <= cans:
-            print ("No more beer after drinking %i can(s) of beer!" % self.beer)...
+            print(("No more beer after drinking %i can(s) of beer!" % self.beer)...
             self.beer = 0
         else:
             self.beer -= cans
@@ -25,12 +25,12 @@
 class NormalFridge(Fridge):
     def __init__(self, name, min_beer):
         Fridge.__init__(self, name)
-        print name, "wishes to have", min_beer, "cans of beer"
+        print(name, "wishes to have", min_beer, "cans of beer")
         self.min_beer = min_beer
     def check_beer(self):
         if self.beer < self.min_beer:
-            print ("%i extra can(s) of beer needed for good stocking." %
-                    (self.min_beer - self.beer))
+            print(("%i extra can(s) of beer needed for good stocking." %
+                    (self.min_beer - self.beer)))
         return
     def consume_beer(self, cans):
         Fridge.consume_beer(self, cans)

References:

Python modules

See “The Python Tutorial: Modules”.

The Python module is a block of reusable code which can be imported to some Python code.

Types of modules:

Names defined by the Python module:

Python module search path:

Let’s check it with the printpath2 script for Python 2.*.

Program to check sys.path for Python 2.*

#!/usr/bin/python
import sys
print "dir() =", dir()
print "dir(sys) =", dir(sys)
print "sys.path =", sys.path

The console output is:

sys.path for Python 2.*

$ ./printpath2
dir() = ['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'sys'
]
dir(sys) = ['__displayhook__', '__doc__', '__excepthook__', '__name__', '__packa
ge__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache', '_current_f
rames', '_getframe', '_mercurial', '_multiarch', 'api_version', 'argv', 'builtin
_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayh
ook', 'dont_write_bytecode', 'exc_clear', 'exc_info', 'exc_type', 'excepthook', 
'exec_prefix', 'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 
'getcheckinterval', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencodi
ng', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'gettrace', 
'hexversion', 'long_info', 'maxint', 'maxsize', 'maxunicode', 'meta_path', 'modu
les', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'py3kwa
rning', 'pydebug', 'setcheckinterval', 'setdlopenflags', 'setprofile', 'setrecur
sionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'v
ersion_info', 'warnoptions']
sys.path = ['/path/to/path', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_
64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/usr/lib/python2.7/lib-old', '/usr/
lib/python2.7/lib-dynload', '/home/osamu/.local/lib/python2.7/site-packages', '/
usr/local/lib/python2.7/dist-packages', '/usr/lib/python2.7/dist-packages', '/us
r/lib/python2.7/dist-packages/PIL', '/usr/lib/python2.7/dist-packages/gst-0.10',
 '/usr/lib/python2.7/dist-packages/gtk-2.0', '/usr/lib/pymodules/python2.7', '/u
sr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode']

Let’s check it with the printpath3 script for Python 3.*.

Program to check sys.path for Python 3.*

#!/usr/bin/python3
import sys
print("dir() =", dir())
print("dir(sys) =", dir(sys))
print("sys.path =", sys.path)

The console output is:

sys.path for Python 3.*

$ ./printpath3
dir() = ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__n
ame__', '__package__', 'sys']
dir(sys) = ['__displayhook__', '__doc__', '__excepthook__', '__loader__', '__nam
e__', '__package__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache
', '_current_frames', '_debugmallocstats', '_getframe', '_home', '_mercurial', '
_xoptions', 'abiflags', 'api_version', 'argv', 'base_exec_prefix', 'base_prefix'
, 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright',
 'displayhook', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', 
'executable', 'exit', 'flags', 'float_info', 'float_repr_style', 'getcheckinterv
al', 'getdefaultencoding', 'getdlopenflags', 'getfilesystemencoding', 'getprofil
e', 'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval', 'gettr
ace', 'hash_info', 'hexversion', 'implementation', 'int_info', 'intern', 'maxsiz
e', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_c
ache', 'platform', 'prefix', 'setcheckinterval', 'setdlopenflags', 'setprofile',
 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr', 'stdin', 'stdou
t', 'thread_info', 'version', 'version_info', 'warnoptions']
sys.path = ['/path/to/path', '/usr/lib/python3.3', '/usr/lib/python3.3/plat-x86_
64-linux-gnu', '/usr/lib/python3.3/lib-dynload', '/home/osamu/.local/lib/python3
.3/site-packages', '/usr/local/lib/python3.3/dist-packages', '/usr/lib/python3/d
ist-packages']

The Python module search path is set as follows:

TIP: The additional Python module search path including dist-packages are for modules provided by the Debian system.

The sys.path value consists of only existing directory path on the system. (I.e., /home/<user_name>/.local/lib/python3.2/site-packages should exist to see it in the above example.)

References:

Python module package

See “The Python Tutorial: Python module package.”

Python module files may be organized in multi-level directories. For example on Unix-like environments, a Python module package foo may contain directories and files as follows:

foo/
    __init__.py
    bar.py
    baz/
        __init__.py
        qux.py

Python scope

See “The Python Tutorial: Python Scopes and Namespaces.”

A scope is a textual region of a Python program where a namespace is directly accessible by the unqualified reference to a name. It is determined textually no matter from where or by what alias the function is called.

The name searching order is the following:

The name binding scope can be manipulated.

Here is an example of code to show scopes and namespaces: test_scope.

#!/usr/bin/python3
# vi:se ts=4 sts=4 et:
import sys
#######################################################################
def test_spam(context):
    try:
        print(context, "EXT Valid:", spam)
    except:
        print(context, "EXT Error:", sys.exc_info()[1])
#######################################################################
def scope_test():
    def do_local():
        spam = "local spam"
    def do_nonlocal():
        nonlocal spam
        spam = "nonlocal spam"
    def do_del_nonlocal():
        nonlocal spam
        del spam
    def do_global():
        global spam
        spam = "global spam"
    def test_spam_in(context):
        try:
            print(context, "IN Valid:", spam)
        except:
            print(context, "IN Error", sys.exc_info()[1])
#----------------------------------------------------------------------
### Check spam status before scope_test() INSIDE ###
    try:
        print("Scope", "Valid:", spam)
    except:
        print("Scope", "Error:", sys.exc_info()[1])
### Make assignment INSIDE ###
    spam = "scope_test spam"
### Check spam status after assignment INSIDE ###
    try:
        print("Assign", "Valid:", spam)
    except:
        print("Assign", "Error:", sys.exc_info()[1])
### Make local assignment INSIDE ###
    do_local()
### Check spam status after do_local INSIDE ###
    try:
        print("local", "Valid:", spam)
    except:
        print("local", "Error:", sys.exc_info()[1])
### Check spam status after do_local INT ###
    test_spam_in("local")
### Check spam status after do_local EXT ###
    test_spam("local")
### Make nonlocal assignment INSIDE ###
    do_nonlocal()
### Check spam status after do_nonlocal INSIDE ###
    try:
        print("nonlocal", "Valid:", spam)
    except:
        print("nonlocal", "Error:", sys.exc_info()[1])
### Check spam status after do_nonlocal INT ###
    test_spam_in("nonlocal")
### Check spam status after do_nonlocal EXT ###
    test_spam("nonlocal")
### Make nonlocal del INSIDE ###
    do_del_nonlocal()
### Check spam status after do_nonlocal INSIDE ###
    try:
        print("nonlocal after del", "Valid:", spam)
    except:
        print("nonlocal after del", "Error:", sys.exc_info()[1])
### Check spam status after do_local INT ###
    test_spam_in("nonlocal after del")
### Make global assignment INSIDE ###
    do_global()
### Check spam status after do_global INSIDE ###
    try:
        print("Global ", "Valid:", spam)
    except:
        print("Global ", "Error:", sys.exc_info()[1])
#######################################################################
### Check spam status before scope_test() OUTSIDE ###
try:
    print("Start ", "Valid:", spam)
except:
    print("Start ", "Error:", sys.exc_info()[1])
### Call scope_test() ###
scope_test()
### Check spam status after scope_test() OUTSIDE ###
try:
    print("End   ", "Valid:", spam)
except:
    print("End   ", "Error:", sys.exc_info()[1])

This is a bit more complicated than the example found on Python Tutorial since this handles exceptions caused by the errors.

Let’s execute this.

$ ./test_scope|fold
Start  Error: global name 'spam' is not defined
Scope Error: local variable 'spam' referenced before assignment
Assign Valid: scope_test spam
local Valid: scope_test spam
local IN Valid: scope_test spam
local EXT Error: global name 'spam' is not defined
nonlocal Valid: nonlocal spam
nonlocal IN Valid: nonlocal spam
nonlocal EXT Error: global name 'spam' is not defined
nonlocal after del Error: local variable 'spam' referenced before assignment
nonlocal after del IN Error free variable 'spam' referenced before assignment in
 enclosing scope
Global  Error: local variable 'spam' referenced before assignment
End    Valid: global spam

Python class

See “The Python Tutorial: A First Look at Classes.”

When a class definition is left normally (via the end), a class object is created. Class object for MyClass has attributes such as foo and bar globally referenced as MyClass.foo and MyClass.bar.

By the assignment of a class object, a new instance object such as x is created. Instance objects can have 2 types of valid attributes: data attribute and method attribute. They may be referenced as x.foo and x.bar.

The data attribute in Python is equivalent of instance variables in Smalltalk and data members in http://en.wikipedia.org/wiki/C++[C++].

Data attributes override method attributes and may cause confusion. There are some naming conventions to prevent this confusion.

The first argument of a method is called self by convention.

An object has class (also called its type) which is stored as object.__class__.

The instantiation method is defined by def __init__(self): etc.

Python inheritance

See “The Python Tutorial: Inheritance.”

The syntax for the derived class definition starts with:

Derived classes may override methods of their base classes. (I.e., All methods in Python are effectively virtual methods in http://en.wikipedia.org/wiki/C++[C++] sense.)

A base class accessible as BaseClassName may be extended by calling its method directly as BaseClassName.methodname(self, arguments).

Python has two built-in functions that work with inheritance:

Python supports a form of multiple inheritance as well. A class definition with multiple base classes looks like this:

The syntax for the multiple inheritance starts with:

The attributes inherited from a parent class is searched basically as:

Thus, the search order is:

In practice, slightly more complex method resolution order like the call-next-method of CLOS is supported via cooperative calls to the super built-in function. (This is out-of-scope for me now.)

Here is an example of code fridge/fridge.py in Python2 to show how class and inheritance can be used.

#!/usr/bin/python
# vi:se ts=4 sts=4 et:
class Fridge:
    def __init__(self, name):
        self.beer = 0
        print name, "bought a new fridge."
        self.name = name
    def report_beer(self):
        print self.name, "has", self.beer, "can(s) of beer in stock."
        return
    def stock_beer(self, cans):
        print self.name, "stocks", cans, "can(s) of beer."
        self.beer += cans
        return
    def consume_beer(self, cans):
        print self.name, "tries to consume", cans, "can(s) of beer"
        if self.beer <= cans:
            print ("No more beer after drinking %i can(s) of beer!" % self.beer)
            self.beer = 0
        else:
            self.beer -= cans
        self.report_beer()
        return

class NormalFridge(Fridge):
    def __init__(self, name, min_beer):
        Fridge.__init__(self, name)
        print name, "wishes to have", min_beer, "cans of beer"
        self.min_beer = min_beer
    def check_beer(self):
        if self.beer < self.min_beer:
            print ("%i extra can(s) of beer needed for good stocking." % 
                    (self.min_beer - self.beer))
        return
    def consume_beer(self, cans):
        Fridge.consume_beer(self, cans)
        self.check_beer()
        return

def test(name = "Tom", minimum = 6):
    tom_fridge = NormalFridge(name, minimum)
    tom_fridge.stock_beer(12)
    tom_fridge.consume_beer(5)
    tom_fridge.consume_beer(5)
    tom_fridge.consume_beer(5)
    tom_fridge.stock_beer(8)
    tom_fridge.consume_beer(3)
    exit(0)

if __name__ == '__main__':
    test()

Let’s execute this.

$ python fridge/fridge.py
Tom bought a new fridge.
Tom wishes to have 6 cans of beer
Tom stocks 12 can(s) of beer.
Tom tries to consume 5 can(s) of beer
Tom has 7 can(s) of beer in stock.
Tom tries to consume 5 can(s) of beer
Tom has 2 can(s) of beer in stock.
4 extra can(s) of beer needed for good stocking.
Tom tries to consume 5 can(s) of beer
No more beer after drinking 2 can(s) of beer!
Tom has 0 can(s) of beer in stock.
6 extra can(s) of beer needed for good stocking.
Tom stocks 8 can(s) of beer.
Tom tries to consume 3 can(s) of beer
Tom has 5 can(s) of beer in stock.
1 extra can(s) of beer needed for good stocking.

Here is an example of code fridge/fridge.py in Python3 converted from the above example by 2to3 as described in Python2 and Python3.

#!/usr/bin/python
# vi:se ts=4 sts=4 et:
class Fridge:
    def __init__(self, name):
        self.beer = 0
        print(name, "bought a new fridge.")
        self.name = name
    def report_beer(self):
        print(self.name, "has", self.beer, "can(s) of beer in stock.")
        return
    def stock_beer(self, cans):
        print(self.name, "stocks", cans, "can(s) of beer.")
        self.beer += cans
        return
    def consume_beer(self, cans):
        print(self.name, "tries to consume", cans, "can(s) of beer")
        if self.beer <= cans:
            print(("No more beer after drinking %i can(s) of beer!" % self.beer))
            self.beer = 0
        else:
            self.beer -= cans
        self.report_beer()
        return

class NormalFridge(Fridge):
    def __init__(self, name, min_beer):
        Fridge.__init__(self, name)
        print(name, "wishes to have", min_beer, "cans of beer")
        self.min_beer = min_beer
    def check_beer(self):
        if self.beer < self.min_beer:
            print(("%i extra can(s) of beer needed for good stocking." % 
                    (self.min_beer - self.beer)))
        return
    def consume_beer(self, cans):
        Fridge.consume_beer(self, cans)
        self.check_beer()
        return

def test(name = "Tom", minimum = 6):
    tom_fridge = NormalFridge(name, minimum)
    tom_fridge.stock_beer(12)
    tom_fridge.consume_beer(5)
    tom_fridge.consume_beer(5)
    tom_fridge.consume_beer(5)
    tom_fridge.stock_beer(8)
    tom_fridge.consume_beer(3)
    exit(0)

if __name__ == '__main__':
    test()

Let’s execute this.

$ python3 fridge/fridge.py
Tom bought a new fridge.
Tom wishes to have 6 cans of beer
Tom stocks 12 can(s) of beer.
Tom tries to consume 5 can(s) of beer
Tom has 7 can(s) of beer in stock.
Tom tries to consume 5 can(s) of beer
Tom has 2 can(s) of beer in stock.
4 extra can(s) of beer needed for good stocking.
Tom tries to consume 5 can(s) of beer
No more beer after drinking 2 can(s) of beer!
Tom has 0 can(s) of beer in stock.
6 extra can(s) of beer needed for good stocking.
Tom stocks 8 can(s) of beer.
Tom tries to consume 3 can(s) of beer
Tom has 5 can(s) of beer in stock.
1 extra can(s) of beer needed for good stocking.

Python private variables

See “The Python Tutorial: Private Variables.”

Private instance variables that should be treated as a non-public part of the API normally use names prefixed with an underscore (e.g. _spam) by convention.

The name mangling mechanism to support class-private members:

Install Python source distribution

See http://docs.python.org/3/install/["The Python Tutorial: Installing Python Modules"] to learn distutils from user’s perspective.

Python programs are normally distributed as a tar ball containing Python module package and script files. These are managed by the cross-platform distribution utility, distutils. The Python source distribution tar ball can be untared as:

setup.py
foo/
    __init__.py
    bar.py
    baz/
        __init__.py
        qux.py
scripts/
    command_line_command

The setup.py script of distutils installs Python module package foo in this Python source distribution to the lib/pythonX.Y/site-packages subdirectory with:

Basic install (system wide to /usr/local)

$ sudo python3 setup.py install

Alternate install (per user to ~/.local)

$ pythone setup.py install --user

Alternate install (per user to ~/)

$ python3 setup.py install --home

Alternate install (custom to /path/to)

$ python3 setup.py install --prefix=/path/to

Each execution of setup.py script in the above examples also installs files in the scripts to the corresponding bin subdirectory.

Generate Python source distribution

See The Python Tutorial: Distributing Python Modules to learn distutils from developer’s perspective.

The setup.py script of distutils can generate Python source distribution from the source tree containing Python modules and script files.

Generate Python source distribution

$ python3 setup.py sdist

This creates a dist/foo-1.0.tar.gz tar ball file for the Python source distribution.

Example #1 of Python source distribution

Let’s populate the fridge directory with a few files to make Python source distribution.

Let’s make a source tree for Python module fridge.

$ ls -lR fridge
fridge:
total 20
-rw-r--r-- 1 osamu osamu 1586 Aug 17 23:43 fridge.py
-rw-r--r-- 1 osamu osamu 1579 Aug 17 23:43 fridge.py.bak
-rw-rw-r-- 1 osamu osamu   31 Mar 28 22:17 README
drwxrwxr-x 2 osamu osamu 4096 Apr  6 18:14 scripts
-rwxr-xr-x 1 osamu osamu  362 Apr  5 23:58 setup.py

fridge/scripts:
total 12
-rw-r--r-- 1 osamu osamu 124 Apr  6 18:14 jane
-rw-r--r-- 1 osamu osamu  93 Mar 28 20:18 joe
-rw-r--r-- 1 osamu osamu  81 Mar 28 20:19 tom
$
$ cat fridge/setup.py
#!/usr/bin/python3
# vi:se ts=4 sts=4 et si:
from distutils.core import setup
setup(name='fridge',
    version='1.0',
    description='Python Distutils practice',
    author='Osamu Aoki',
    author_email='osamu@debian.org',
    url='http://people.debian.org/~osamu/',
    py_modules=['fridge'],
    scripts=['scripts/jane', 'scripts/joe', 'scripts/tom'],
    )
$
$ cat fridge/README
python source package practice
$
$ cat fridge/scripts/jane
#!/usr/bin/python3
import fridge
import sys

if __name__ == '__main__':
    print(sys.path)
    fridge.test(name = "Jane")
$
$ cat fridge/scripts/joe
#!/usr/bin/python3
import fridge

if __name__ == '__main__':
    fridge.test(name = "Joe")
$
$ cat fridge/scripts/tom
#!/usr/bin/python3
import fridge

if __name__ == '__main__':
    fridge.test()

Please note “py_modules=['fridge'],” in setup.py which tells to use the fridge.py file as the fridge module.

Let’s execute setup.py and generate Python source distribution

$ cd fridge; python3 setup.py sdist; cd -
/path/to/package2/fridge
running sdist
running check
warning: sdist: manifest template 'MANIFEST.in' does not exist (using default fil...

writing manifest file 'MANIFEST'
creating fridge-1.0
creating fridge-1.0/scripts
making hard links in fridge-1.0...
hard linking README -> fridge-1.0
hard linking fridge.py -> fridge-1.0
hard linking setup.py -> fridge-1.0
hard linking scripts/jane -> fridge-1.0/scripts
hard linking scripts/joe -> fridge-1.0/scripts
hard linking scripts/tom -> fridge-1.0/scripts
creating dist
Creating tar archive
removing 'fridge-1.0' (and everything under it)
/path/to/package2

Let’s see the updated source tree for fridge

$ ls -lR fridge
fridge:
total 28
drwxrwxr-x 2 osamu osamu 4096 Aug 17 23:43 dist
-rw-r--r-- 1 osamu osamu 1586 Aug 17 23:43 fridge.py
-rw-r--r-- 1 osamu osamu 1579 Aug 17 23:43 fridge.py.bak
-rw-rw-r-- 1 osamu osamu  106 Aug 17 23:43 MANIFEST
-rw-rw-r-- 1 osamu osamu   31 Mar 28 22:17 README
drwxrwxr-x 2 osamu osamu 4096 Apr  6 18:14 scripts
-rwxr-xr-x 1 osamu osamu  362 Apr  5 23:58 setup.py

fridge/dist:
total 4
-rw-rw-r-- 1 osamu osamu 1230 Aug 17 23:43 fridge-1.0.tar.gz

fridge/scripts:
total 12
-rw-r--r-- 1 osamu osamu 124 Apr  6 18:14 jane
-rw-r--r-- 1 osamu osamu  93 Mar 28 20:18 joe
-rw-r--r-- 1 osamu osamu  81 Mar 28 20:19 tom
$
$ tar -tvzf fridge/dist/fridge-1.0.tar.gz
drwxrwxr-x osamu/osamu       0 2013-08-17 23:43 fridge-1.0/
drwxrwxr-x osamu/osamu       0 2013-08-17 23:43 fridge-1.0/scripts/
-rw-r--r-- osamu/osamu     124 2013-04-06 18:14 fridge-1.0/scripts/jane
-rw-r--r-- osamu/osamu      93 2013-03-28 20:18 fridge-1.0/scripts/joe
-rw-r--r-- osamu/osamu      81 2013-03-28 20:19 fridge-1.0/scripts/tom
-rw-r--r-- osamu/osamu    1586 2013-08-17 23:43 fridge-1.0/fridge.py
-rw-rw-r-- osamu/osamu     233 2013-08-17 23:43 fridge-1.0/PKG-INFO
-rwxr-xr-x osamu/osamu     362 2013-04-05 23:58 fridge-1.0/setup.py
-rw-rw-r-- osamu/osamu      31 2013-03-28 22:17 fridge-1.0/README
$
$ tar -xvzOf fridge/dist/fridge-1.0.tar.gz fridge-1.0/PKG-INFO
fridge-1.0/PKG-INFO
Metadata-Version: 1.0
Name: fridge
Version: 1.0
Summary: Python Distutils practice
Home-page: http://people.debian.org/~osamu/
Author: Osamu Aoki
Author-email: osamu@debian.org
License: UNKNOWN
Description: UNKNOWN
Platform: UNKNOWN

You see few files generated.

Let’s untar Python source distribution package and install as user.

$ tar -xvzf fridge/dist/fridge-1.0.tar.gz -C dist
fridge-1.0/
fridge-1.0/scripts/
fridge-1.0/scripts/jane
fridge-1.0/scripts/joe
fridge-1.0/scripts/tom
fridge-1.0/fridge.py
fridge-1.0/PKG-INFO
fridge-1.0/setup.py
fridge-1.0/README
$ cd dist/fridge-1.0; python3 setup.py install --user;cd -
/path/to/package2/dist/fridge-1.0
running install
running build
running build_py
creating build
creating build/lib
copying fridge.py -> build/lib
running build_scripts
creating build/scripts-3.3
copying and adjusting scripts/jane -> build/scripts-3.3
copying and adjusting scripts/joe -> build/scripts-3.3
copying and adjusting scripts/tom -> build/scripts-3.3
changing mode of build/scripts-3.3/jane from 664 to 775
changing mode of build/scripts-3.3/joe from 664 to 775
changing mode of build/scripts-3.3/tom from 664 to 775
running install_lib
copying build/lib/fridge.py -> /home/osamu/.local/lib/python3.3/site-packages
byte-compiling /home/osamu/.local/lib/python3.3/site-packages/fridge.py to fridge...
running install_scripts
copying build/scripts-3.3/jane -> /home/osamu/.local/bin
copying build/scripts-3.3/joe -> /home/osamu/.local/bin
copying build/scripts-3.3/tom -> /home/osamu/.local/bin
changing mode of /home/osamu/.local/bin/jane to 775
changing mode of /home/osamu/.local/bin/joe to 775
changing mode of /home/osamu/.local/bin/tom to 775
running install_egg_info
Removing /home/osamu/.local/lib/python3.3/site-packages/fridge-1.0.egg-info
Writing /home/osamu/.local/lib/python3.3/site-packages/fridge-1.0.egg-info
/path/to/package2
$ jane|fold
['/home/osamu/.local/bin', '/usr/lib/python3.3', '/usr/lib/python3.3/plat-x86_64
-linux-gnu', '/usr/lib/python3.3/lib-dynload', '/home/osamu/.local/lib/python3.3
/site-packages', '/usr/local/lib/python3.3/dist-packages', '/usr/lib/python3/dis
t-packages']
Jane bought a new fridge.
Jane wishes to have 6 cans of beer
Jane stocks 12 can(s) of beer.
Jane tries to consume 5 can(s) of beer
Jane has 7 can(s) of beer in stock.
Jane tries to consume 5 can(s) of beer
Jane has 2 can(s) of beer in stock.
4 extra can(s) of beer needed for good stocking.
Jane tries to consume 5 can(s) of beer
No more beer after drinking 2 can(s) of beer!
Jane has 0 can(s) of beer in stock.
6 extra can(s) of beer needed for good stocking.
Jane stocks 8 can(s) of beer.
Jane tries to consume 3 can(s) of beer
Jane has 5 can(s) of beer in stock.
1 extra can(s) of beer needed for good stocking.

Unfortunately, distutils as of now does not offer uninstall. We need to remove files manually to uninstall them.

Let’s uninstall Python source distribution manually.

$ rm -rf dist
$ rm -r ~/.local/bin/jane ~/.local/bin/joe ~/.local/bin/tom
$ rm -r ~/.local/lib/python3.2/site-packages/fridge.py
rm: cannot remove ‘/home/osamu/.local/lib/python3.2/site-packages/fridge.py’: No ...
$ rm -r ~/.local/lib/python3.2/site-packages/fridge-1.0.egg-info
rm: cannot remove ‘/home/osamu/.local/lib/python3.2/site-packages/fridge-1.0.egg-...
$ rm -rf ~/.local/lib/python3.2/site-packages/__pycache__

Example #2 of Python source distribution

Let’s try an alternative Python source distribution with Python module package.

Basically, move fridge/fridge.py in Example #1 to fridge/src/fridge/__init__.py.

Let’s execute this.

$ python3 fridge/src/fridge/__init__.py
Tom bought a new fridge.
Tom wishes to have 6 cans of beer
Tom stocks 12 can(s) of beer.
Tom tries to consume 5 can(s) of beer
Tom has 7 can(s) of beer in stock.
Tom tries to consume 5 can(s) of beer
Tom has 2 can(s) of beer in stock.
4 extra can(s) of beer needed for good stocking.
Tom tries to consume 5 can(s) of beer
No more beer after drinking 2 can(s) of beer!
Tom has 0 can(s) of beer in stock.
6 extra can(s) of beer needed for good stocking.
Tom stocks 8 can(s) of beer.
Tom tries to consume 3 can(s) of beer
Tom has 5 can(s) of beer in stock.
1 extra can(s) of beer needed for good stocking.

Let’s populate the fridge directory with mostly the same files except:

Let’s make a source tree for Python module fridge.

$ ls -lR fridge
fridge:
total 16
-rw-rw-r-- 1 osamu osamu   31 Mar 28 22:17 README
drwxrwxr-x 2 osamu osamu 4096 Apr  6 18:14 scripts
-rwxr-xr-x 1 osamu osamu  402 Apr  5 23:59 setup.py
drwxrwxr-x 3 osamu osamu 4096 Mar 29 00:01 src

fridge/scripts:
total 12
-rw-r--r-- 1 osamu osamu 124 Apr  6 18:14 jane
-rw-r--r-- 1 osamu osamu  93 Mar 28 20:18 joe
-rw-r--r-- 1 osamu osamu  81 Mar 28 20:19 tom

fridge/src:
total 4
drwxrwxr-x 2 osamu osamu 4096 Apr  6 18:35 fridge

fridge/src/fridge:
total 4
-rw-r--r-- 1 osamu osamu 1583 Mar 28 20:10 __init__.py
$
$ cat fridge/setup.py
#!/usr/bin/python3
# vi:se ts=4 sts=4 et si:
from distutils.core import setup
setup(name='fridge',
    version='1.0',
    description='Python Distutils practice',
    author='Osamu Aoki',
    author_email='osamu@debian.org',
    url='http://people.debian.org/~osamu/',
    packages=['fridge'],
    package_dir={'fridge': 'src/fridge'},
    scripts=['scripts/jane', 'scripts/joe', 'scripts/tom'],
    )

Please note “package_dir={'fridge': 'src/fridge'},” in setup.py which tells to use files in the src/fridge directory as the fridge module package.

Let’s execute setup.py and generate Python source distribution

$ cd fridge; python3 setup.py sdist; cd -
/path/to/package3/fridge
running sdist
running check
warning: sdist: manifest template 'MANIFEST.in' does not exist (using default fil...

writing manifest file 'MANIFEST'
creating fridge-1.0
creating fridge-1.0/scripts
creating fridge-1.0/src
creating fridge-1.0/src/fridge
making hard links in fridge-1.0...
hard linking README -> fridge-1.0
hard linking setup.py -> fridge-1.0
hard linking scripts/jane -> fridge-1.0/scripts
hard linking scripts/joe -> fridge-1.0/scripts
hard linking scripts/tom -> fridge-1.0/scripts
hard linking src/fridge/__init__.py -> fridge-1.0/src/fridge
creating dist
Creating tar archive
removing 'fridge-1.0' (and everything under it)
/path/to/package3

Let’s see the updated source tree for fridge

$ ls -lR fridge
fridge:
total 24
drwxrwxr-x 2 osamu osamu 4096 Aug 17 23:43 dist
-rw-rw-r-- 1 osamu osamu  119 Aug 17 23:43 MANIFEST
-rw-rw-r-- 1 osamu osamu   31 Mar 28 22:17 README
drwxrwxr-x 2 osamu osamu 4096 Apr  6 18:14 scripts
-rwxr-xr-x 1 osamu osamu  402 Apr  5 23:59 setup.py
drwxrwxr-x 3 osamu osamu 4096 Mar 29 00:01 src

fridge/dist:
total 4
-rw-rw-r-- 1 osamu osamu 1268 Aug 17 23:43 fridge-1.0.tar.gz

fridge/scripts:
total 12
-rw-r--r-- 1 osamu osamu 124 Apr  6 18:14 jane
-rw-r--r-- 1 osamu osamu  93 Mar 28 20:18 joe
-rw-r--r-- 1 osamu osamu  81 Mar 28 20:19 tom

fridge/src:
total 4
drwxrwxr-x 2 osamu osamu 4096 Apr  6 18:35 fridge

fridge/src/fridge:
total 4
-rw-r--r-- 1 osamu osamu 1583 Mar 28 20:10 __init__.py
$
$ tar -tvzf fridge/dist/fridge-1.0.tar.gz
drwxrwxr-x osamu/osamu       0 2013-08-17 23:43 fridge-1.0/
drwxrwxr-x osamu/osamu       0 2013-08-17 23:43 fridge-1.0/scripts/
-rw-r--r-- osamu/osamu     124 2013-04-06 18:14 fridge-1.0/scripts/jane
-rw-r--r-- osamu/osamu      93 2013-03-28 20:18 fridge-1.0/scripts/joe
-rw-r--r-- osamu/osamu      81 2013-03-28 20:19 fridge-1.0/scripts/tom
drwxrwxr-x osamu/osamu       0 2013-08-17 23:43 fridge-1.0/src/
drwxrwxr-x osamu/osamu       0 2013-08-17 23:43 fridge-1.0/src/fridge/
-rw-r--r-- osamu/osamu    1583 2013-03-28 20:10 fridge-1.0/src/fridge/__init__.py...
-rw-rw-r-- osamu/osamu     233 2013-08-17 23:43 fridge-1.0/PKG-INFO
-rwxr-xr-x osamu/osamu     402 2013-04-05 23:59 fridge-1.0/setup.py
-rw-rw-r-- osamu/osamu      31 2013-03-28 22:17 fridge-1.0/README

You see few files generated.

Let’s untar Python source distribution package and install as user.

$ tar -xvzf fridge/dist/fridge-1.0.tar.gz -C dist
fridge-1.0/
fridge-1.0/scripts/
fridge-1.0/scripts/jane
fridge-1.0/scripts/joe
fridge-1.0/scripts/tom
fridge-1.0/fridge.py
fridge-1.0/PKG-INFO
fridge-1.0/setup.py
fridge-1.0/README
$ cd dist/fridge-1.0; python3 setup.py install --user;cd -
/path/to/package2/dist/fridge-1.0
running install
running build
running build_py
creating build
creating build/lib
copying fridge.py -> build/lib
running build_scripts
creating build/scripts-3.3
copying and adjusting scripts/jane -> build/scripts-3.3
copying and adjusting scripts/joe -> build/scripts-3.3
copying and adjusting scripts/tom -> build/scripts-3.3
changing mode of build/scripts-3.3/jane from 664 to 775
changing mode of build/scripts-3.3/joe from 664 to 775
changing mode of build/scripts-3.3/tom from 664 to 775
running install_lib
copying build/lib/fridge.py -> /home/osamu/.local/lib/python3.3/site-packages
byte-compiling /home/osamu/.local/lib/python3.3/site-packages/fridge.py to fridge...
running install_scripts
copying build/scripts-3.3/jane -> /home/osamu/.local/bin
copying build/scripts-3.3/joe -> /home/osamu/.local/bin
copying build/scripts-3.3/tom -> /home/osamu/.local/bin
changing mode of /home/osamu/.local/bin/jane to 775
changing mode of /home/osamu/.local/bin/joe to 775
changing mode of /home/osamu/.local/bin/tom to 775
running install_egg_info
Removing /home/osamu/.local/lib/python3.3/site-packages/fridge-1.0.egg-info
Writing /home/osamu/.local/lib/python3.3/site-packages/fridge-1.0.egg-info
/path/to/package2
$ jane|fold
['/home/osamu/.local/bin', '/usr/lib/python3.3', '/usr/lib/python3.3/plat-x86_64
-linux-gnu', '/usr/lib/python3.3/lib-dynload', '/home/osamu/.local/lib/python3.3
/site-packages', '/usr/local/lib/python3.3/dist-packages', '/usr/lib/python3/dis
t-packages']
Jane bought a new fridge.
Jane wishes to have 6 cans of beer
Jane stocks 12 can(s) of beer.
Jane tries to consume 5 can(s) of beer
Jane has 7 can(s) of beer in stock.
Jane tries to consume 5 can(s) of beer
Jane has 2 can(s) of beer in stock.
4 extra can(s) of beer needed for good stocking.
Jane tries to consume 5 can(s) of beer
No more beer after drinking 2 can(s) of beer!
Jane has 0 can(s) of beer in stock.
6 extra can(s) of beer needed for good stocking.
Jane stocks 8 can(s) of beer.
Jane tries to consume 3 can(s) of beer
Jane has 5 can(s) of beer in stock.
1 extra can(s) of beer needed for good stocking.

Unfortunately, distutils as of now does not offer uninstall. We need to remove files manually to uninstall them.

Let’s uninstall Python source distribution manually.

$ rm -rf dist
$ rm -r ~/.local/bin/jane ~/.local/bin/joe ~/.local/bin/tom
$ rm -r ~/.local/lib/python3.2/site-packages/fridge.py
rm: cannot remove ‘/home/osamu/.local/lib/python3.2/site-packages/fridge.py’: No ...
$ rm -r ~/.local/lib/python3.2/site-packages/fridge-1.0.egg-info
rm: cannot remove ‘/home/osamu/.local/lib/python3.2/site-packages/fridge-1.0.egg-...
$ rm -rf ~/.local/lib/python3.2/site-packages/__pycache__

Debian package from Python2 source distribution (dh_make)

The dh_make is handy for making a Debian package. I will be very sloppy for now. (More work is needed to make package suitable for Debian.)

Let’s make Debian source package.

$ tar -xvzf fridge/dist/fridge-1.0.tar.gz -C deb
fridge-1.0/
fridge-1.0/scripts/
fridge-1.0/scripts/jane
fridge-1.0/scripts/joe
fridge-1.0/scripts/tom
fridge-1.0/fridge.py
fridge-1.0/PKG-INFO
fridge-1.0/setup.py
fridge-1.0/README
$ cd deb/fridge-1.0; dh_make -s --createorig --yes; cd -
/path/to/package1/deb/fridge-1.0
Maintainer name  : Osamu Aoki
Email-Address    : osamu@debian.org
Date             : Sat, 17 Aug 2013 23:43:26 +0900
Package Name     : fridge
Version          : 1.0
License          : blank
Type of Package  : Single
Currently there is no top level Makefile. This may require additional tuning.
Done. Please edit the files in the debian/ subdirectory now. You should also
check that the fridge Makefiles install into $DESTDIR and not in / .
/path/to/package1
$ ls -lR deb
deb:
total 8
drwxrwxr-x 4 osamu osamu 4096 Aug 17 23:43 fridge-1.0
-rw-rw-r-- 1 osamu osamu 1212 Aug 17 23:43 fridge_1.0.orig.tar.xz

deb/fridge-1.0:
total 24
drwxr-xr-x 3 osamu osamu 4096 Aug 17 23:43 debian
-rw-r--r-- 1 osamu osamu 1579 Apr  8 21:16 fridge.py
-rw-rw-r-- 1 osamu osamu  233 Aug 17 23:43 PKG-INFO
-rw-rw-r-- 1 osamu osamu   31 Mar 28 22:17 README
drwxrwxr-x 2 osamu osamu 4096 Aug 17 23:43 scripts
-rwxr-xr-x 1 osamu osamu  361 Apr  8 21:13 setup.py

deb/fridge-1.0/debian:
total 104
-rw-rw-r-- 1 osamu osamu   180 Aug 17 23:43 changelog
-rw-rw-r-- 1 osamu osamu     2 Aug 17 23:43 compat
-rw-rw-r-- 1 osamu osamu   505 Aug 17 23:43 control
-rw-rw-r-- 1 osamu osamu  1668 Aug 17 23:43 copyright
-rw-rw-r-- 1 osamu osamu     7 Aug 17 23:43 docs
-rw-rw-r-- 1 osamu osamu   128 Aug 17 23:43 fridge.cron.d.ex
-rw-rw-r-- 1 osamu osamu   232 Aug 17 23:43 fridge.default.ex
-rw-rw-r-- 1 osamu osamu   504 Aug 17 23:43 fridge.doc-base.EX
-rw-rw-r-- 1 osamu osamu  4675 Aug 17 23:43 init.d.ex
-rw-rw-r-- 1 osamu osamu  1625 Aug 17 23:43 manpage.1.ex
-rw-rw-r-- 1 osamu osamu  4648 Aug 17 23:43 manpage.sgml.ex
-rw-rw-r-- 1 osamu osamu 11003 Aug 17 23:43 manpage.xml.ex
-rw-rw-r-- 1 osamu osamu   123 Aug 17 23:43 menu.ex
-rw-rw-r-- 1 osamu osamu   956 Aug 17 23:43 postinst.ex
-rw-rw-r-- 1 osamu osamu   929 Aug 17 23:43 postrm.ex
-rw-rw-r-- 1 osamu osamu   689 Aug 17 23:43 preinst.ex
-rw-rw-r-- 1 osamu osamu   876 Aug 17 23:43 prerm.ex
-rw-rw-r-- 1 osamu osamu   173 Aug 17 23:43 README.Debian
-rw-rw-r-- 1 osamu osamu   191 Aug 17 23:43 README.source
-rwxr-xr-x 1 osamu osamu   442 Aug 17 23:43 rules
drwxr-xr-x 2 osamu osamu  4096 Aug 17 23:43 source
-rw-rw-r-- 1 osamu osamu   775 Aug 17 23:43 watch.ex

deb/fridge-1.0/debian/source:
total 4
-rw-rw-r-- 1 osamu osamu 12 Aug 17 23:43 format

deb/fridge-1.0/scripts:
total 12
-rw-r--r-- 1 osamu osamu 124 Apr  6 18:14 jane
-rw-r--r-- 1 osamu osamu  93 Mar 28 20:18 joe
-rw-r--r-- 1 osamu osamu  81 Mar 28 20:19 tom
$

  ... update debian/control
  ... update debian/rules
  ... touch up template files
  ... remove unused template files

$ ls -l deb/fridge-1.0/debian
total 32
-rw-rw-r-- 1 osamu osamu  180 Apr  6 22:36 changelog
-rw-rw-r-- 1 osamu osamu    2 Apr  6 22:36 compat
-rw-rw-r-- 1 osamu osamu  554 Apr  8 21:18 control
-rw-rw-r-- 1 osamu osamu 1668 Apr  6 22:36 copyright
-rw-rw-r-- 1 osamu osamu  440 Apr  6 23:03 manpage.1
-rw-rw-r-- 1 osamu osamu  120 Apr  6 23:03 README.Debian
-rwxr-xr-x 1 osamu osamu   67 Apr  9 20:33 rules
drwxr-xr-x 2 osamu osamu 4096 Apr  6 22:36 source
$ cat deb/fridge-1.0/debian/control
Source: fridge
Section: unknown
Priority: extra
Maintainer: Osamu Aoki <osamu@debian.org>
Build-Depends: debhelper (>= 8.0.0), python-minimal, python
Standards-Version: 3.9.3
X-Python-Version: >= 2.6
Homepage: <insert the upstream URL, if relevant>
#Vcs-Git: git://git.debian.org/collab-maint/fridge.git
#Vcs-Browser: http://git.debian.org/?p=collab-maint/fridge.git;a=summary

Package: fridge
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: <insert up to 60 chars description>
 <insert long description, indented with spaces>
$ cat deb/fridge-1.0/debian/rules
#!/usr/bin/make -f
#export DH_VERBOSE=1

%:
    dh $@ --with python2

Here, I add the package dependency etc. to debian/control.

Let’s make Debian binary package.

$ cd deb/fridge-1.0; debuild -us -uc; cd -
/path/to/package1/deb/fridge-1.0
 dpkg-buildpackage -rfakeroot -D -us -uc -I -i
dpkg-buildpackage: source package fridge
dpkg-buildpackage: source version 1.0-1
dpkg-buildpackage: source distribution unstable
dpkg-buildpackage: source changed by Osamu Aoki <osamu@debian.org>
 dpkg-source -I -i --before-build fridge-1.0
dpkg-buildpackage: host architecture amd64
 fakeroot debian/rules clean
dh clean --with python2
   dh_testdir
   dh_auto_clean
running clean
'build/lib.linux-x86_64-2.7' does not exist -- can't clean it
'build/bdist.linux-x86_64' does not exist -- can't clean it
'build/scripts-2.7' does not exist -- can't clean it
   dh_clean
 dpkg-source -I -i -b fridge-1.0
dpkg-source: info: using source format `3.0 (quilt)'
dpkg-source: info: building fridge using existing ./fridge_1.0.orig.tar.xz
dpkg-source: info: building fridge in fridge_1.0-1.debian.tar.gz
dpkg-source: info: building fridge in fridge_1.0-1.dsc
 debian/rules build
dh build --with python2
   dh_testdir
   dh_auto_configure
   dh_auto_build
running build
running build_py
creating build
creating build/lib.linux-x86_64-2.7
copying fridge.py -> build/lib.linux-x86_64-2.7
running build_scripts
creating build/scripts-2.7
copying and adjusting scripts/jane -> build/scripts-2.7
copying and adjusting scripts/joe -> build/scripts-2.7
copying and adjusting scripts/tom -> build/scripts-2.7
changing mode of build/scripts-2.7/jane from 644 to 755
changing mode of build/scripts-2.7/joe from 644 to 755
changing mode of build/scripts-2.7/tom from 644 to 755
   dh_auto_test
 fakeroot debian/rules binary
dh binary --with python2
   dh_testroot
   dh_prep
   dh_auto_install
running install
running build
running build_py
running build_scripts
running install_lib
creating /path/to/package1/deb/fridge-1.0/debian/fridge/usr
creating /path/to/package1/deb/fridge-1.0/debian/fridge/usr/lib
creating /path/to/package1/deb/fridge-1.0/debian/fridge/usr/lib/python2.7
creating /path/to/package1/deb/fridge-1.0/debian/fridge/usr/lib/python2.7/dist-pa...
copying build/lib.linux-x86_64-2.7/fridge.py -> /path/to/package1/deb/fridge-1.0/...
running install_scripts
creating /path/to/package1/deb/fridge-1.0/debian/fridge/usr/bin
copying build/scripts-2.7/jane -> /path/to/package1/deb/fridge-1.0/debian/fridge/...
copying build/scripts-2.7/joe -> /path/to/package1/deb/fridge-1.0/debian/fridge/u...
copying build/scripts-2.7/tom -> /path/to/package1/deb/fridge-1.0/debian/fridge/u...
changing mode of /path/to/package1/deb/fridge-1.0/debian/fridge/usr/bin/jane to 7...
changing mode of /path/to/package1/deb/fridge-1.0/debian/fridge/usr/bin/joe to 75...
changing mode of /path/to/package1/deb/fridge-1.0/debian/fridge/usr/bin/tom to 75...
running install_egg_info
Writing /path/to/package1/deb/fridge-1.0/debian/fridge/usr/lib/python2.7/dist-pac...
   dh_installdocs
   dh_installchangelogs
   dh_python2
   dh_perl
   dh_link
   dh_compress
   dh_fixperms
   dh_installdeb
   dh_gencontrol
dpkg-gencontrol: warning: Depends field of package fridge: unknown substitution v...
dpkg-gencontrol: warning: package fridge: unused substitution variable ${python:V...
dpkg-gencontrol: warning: package fridge: unused substitution variable ${python:D...
   dh_md5sums
   dh_builddeb
dpkg-deb: building package `fridge' in `../fridge_1.0-1_all.deb'.
 dpkg-genchanges  >../fridge_1.0-1_amd64.changes
dpkg-genchanges: including full source code in upload
 dpkg-source -I -i --after-build fridge-1.0
dpkg-buildpackage: full upload (original source is included)
Now running lintian...
W: fridge source: superfluous-clutter-in-homepage <insert the upstream URL, if re...
N:
N:    The "Homepage:" field in this package's control file contains
N:    superfluous markup around the URL, like enclosing < and >. This is
N:    unnecessary and needlessly complicates using this information.
N:
N:    Refer to Debian Policy Manual section 5.6.23 (Homepage) for details.
N:
N:    Severity: normal, Certainty: certain
N:
N:    Check: fields, Type: binary, udeb, source
N:
W: fridge source: bad-homepage <insert the upstream URL, if relevant>
N:
N:    The "Homepage:" field in this package's control file does not contain a
N:    valid absolute URL. Most probably you forgot to specify the scheme (e.g.
N:    http).
N:
N:    This tag is also triggered if the scheme is not known by Lintian.
N:
N:    Please file a bug against Lintian, if this tag is triggered for a valid
N:    homepage URL.
N:
N:    Severity: normal, Certainty: certain
N:
N:    Check: fields, Type: binary, udeb, source
N:
W: fridge source: out-of-date-standards-version 3.9.3 (current is 3.9.4)
N:
N:    The source package refers to a Standards-Version older than the one that
N:    was current at the time the package was created (according to the
N:    timestamp of the latest debian/changelog entry). Please consider
N:    updating the package to current Policy and setting this control field
N:    appropriately.
N:
N:    If the package is already compliant with the current standards, you
N:    don't have to re-upload the package just to adjust the Standards-Version
N:    control field. However, please remember to update this field next time
N:    you upload the package.
N:
N:    See /usr/share/doc/debian-policy/upgrading-checklist.txt.gz in the
N:    debian-policy package for a summary of changes in newer versions of
N:    Policy.
N:
N:    Refer to http://www.debian.org/doc/debian-policy/upgrading-checklist for
N:    details.
N:
N:    Severity: normal, Certainty: certain
N:
N:    Check: standards-version, Type: source
N:
W: fridge: wrong-bug-number-in-closes l3:#nnnn
N:
N:    Bug numbers can only contain digits.
N:
N:    Refer to Debian Policy Manual section 4.4 (Debian changelog:
N:    debian/changelog) for details.
N:
N:    Severity: normal, Certainty: certain
N:
N:    Check: changelog-file, Type: binary
N:
W: fridge: new-package-should-close-itp-bug
N:
N:    This package appears to be the first packaging of a new upstream
N:    software package (there is only one changelog entry and the Debian
N:    revision is 1), but it does not close any bugs. The initial upload of a
N:    new package should close the corresponding ITP bug for that package.
N:
N:    This warning can be ignored if the package is not intended for Debian or
N:    if it is a split of an existing Debian package.
N:
N:    Refer to Debian Developer's Reference section 5.1 (New packages) for
N:    details.
N:
N:    Severity: normal, Certainty: certain
N:
N:    Check: changelog-file, Type: binary
N:
E: fridge: helper-templates-in-copyright
N:
N:    The /usr/share/doc/<pkg>/copyright file still contains template markers
N:    from a packaging helper. Please fill in the actual license, upstream
N:    copyright holders, and download information about the package and remove
N:    any remaining templates generated by the packaging helper.
N:
N:    Severity: important, Certainty: certain
N:
N:    Check: copyright-file, Type: binary
N:
W: fridge: copyright-has-url-from-dh_make-boilerplate
N:
N:    There is "url://example.com" in your copyright file. This was most
N:    likely a remnant from the dh_make template.
N:
N:    Make sure you include the real location where you obtained the upstream
N:    sources (if any).
N:
N:    Refer to Debian Policy Manual section 12.5 (Copyright information) for
N:    details.
N:
N:    Severity: normal, Certainty: certain
N:
N:    Check: copyright-file, Type: binary
N:
E: fridge: copyright-contains-dh_make-todo-boilerplate
N:
N:    The string "Please also look if..." appears in the copyright file, which
N:    indicates that you either didn't check the whole source to find
N:    additional copyright/license, or that you didn't remove that paragraph
N:    after having done so.
N:
N:    Refer to Debian Policy Manual section 12.5 (Copyright information) for
N:    details.
N:
N:    Severity: serious, Certainty: possible
N:
N:    Check: copyright-file, Type: binary
N:
E: fridge: description-is-dh_make-template
N:
N:    The synopsis or the extended description has not been changed from the
N:    template provided by dh_make.
N:
N:    Severity: serious, Certainty: certain
N:
N:    Check: description, Type: binary, udeb
N:
E: fridge: section-is-dh_make-template
N:
N:    The "Section:" field in this package's control file is set to unknown.
N:    This is not a valid section, and usually means a dh_make template
N:    control file was used and never modified to set the correct section.
N:
N:    Refer to Debian Policy Manual section 2.4 (Sections) for details.
N:
N:    Severity: serious, Certainty: certain
N:
N:    Check: fields, Type: binary, udeb, source
N:
W: fridge: superfluous-clutter-in-homepage <insert the upstream URL, if relevant>...
W: fridge: bad-homepage <insert the upstream URL, if relevant>
W: fridge: binary-without-manpage usr/bin/jane
N:
N:    Each binary in /usr/bin, /usr/sbin, /bin, /sbin or /usr/games should
N:    have a manual page
N:
N:    Note that though the man program has the capability to check for several
N:    program names in the NAMES section, each of these programs should have
N:    its own manual page (a symbolic link to the appropriate manual page is
N:    sufficient) because other manual page viewers such as xman or tkman
N:    don't support this.
N:
N:    If the name of the man page differs from the binary by case, man may be
N:    able to find it anyway; however, it is still best practice to make the
N:    case of the man page match the case of the binary.
N:
N:    If the man pages are provided by another package on which this package
N:    depends, lintian may not be able to determine that man pages are
N:    available. In this case, after confirming that all binaries do have man
N:    pages after this package and its dependencies are installed, please add
N:    a lintian override.
N:
N:    Refer to Debian Policy Manual section 12.1 (Manual pages) for details.
N:
N:    Severity: normal, Certainty: possible
N:
N:    Check: manpages, Type: binary
N:
W: fridge: binary-without-manpage usr/bin/joe
W: fridge: binary-without-manpage usr/bin/tom
E: fridge: python-script-but-no-python-dep usr/bin/jane
N:
N:    Packages with Python scripts should depend on the package python. Those
N:    with scripts that specify a specific version of Python must depend on
N:    that version of Python (exactly).
N:
N:    For example, if a script in the package uses #!/usr/bin/python, the
N:    package needs a dependency on python. If a script uses
N:    #!/usr/bin/python2.6, the package needs a dependency on python2.6. A
N:    dependency on python (>= 2.6) is not correct, since later versions of
N:    Python may not provide the /usr/bin/python2.6 binary.
N:
N:    If you are using debhelper, adding ${python:Depends} to the Depends
N:    field and ensuring dh_pysupport or dh_pycentral are run during the build
N:    should take care of adding the correct dependency.
N:
N:    In some cases a weaker relationship, such as Suggests or Recommends,
N:    will be more appropriate.
N:
N:    Severity: important, Certainty: certain
N:
N:    Check: scripts, Type: binary
N:
E: fridge: python-script-but-no-python-dep usr/bin/joe
E: fridge: python-script-but-no-python-dep usr/bin/tom
Finished running lintian.
/path/to/package1
$ ls -l deb
total 36
drwxrwxr-x 5 osamu osamu  4096 Aug 17 23:43 fridge-1.0
-rw-r--r-- 1 osamu osamu  3364 Aug 17 23:43 fridge_1.0-1_all.deb
-rw-r--r-- 1 osamu osamu 11908 Aug 17 23:43 fridge_1.0-1_amd64.build
-rw-r--r-- 1 osamu osamu  1419 Aug 17 23:43 fridge_1.0-1_amd64.changes
-rw-r--r-- 1 osamu osamu  1993 Aug 17 23:43 fridge_1.0-1.debian.tar.gz
-rw-r--r-- 1 osamu osamu   808 Aug 17 23:43 fridge_1.0-1.dsc
-rw-rw-r-- 1 osamu osamu  1212 Aug 17 23:43 fridge_1.0.orig.tar.xz
$ dpkg -c deb/fridge_1.0-1_all.deb
drwxr-xr-x root/root         0 2013-08-17 23:43 ./
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/lib/
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/lib/python2.7/
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/lib/python2.7/dist-packages...
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/bin/
-rwxr-xr-x root/root       124 2013-08-17 23:43 ./usr/bin/jane
-rwxr-xr-x root/root        93 2013-08-17 23:43 ./usr/bin/joe
-rwxr-xr-x root/root        81 2013-08-17 23:43 ./usr/bin/tom
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/share/
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/share/doc/
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/share/doc/fridge/
-rw-r--r-- root/root      1668 2013-04-06 22:36 ./usr/share/doc/fridge/copyright
-rw-r--r-- root/root       120 2013-04-06 23:03 ./usr/share/doc/fridge/README.Deb...
-rw-r--r-- root/root       172 2013-04-06 22:36 ./usr/share/doc/fridge/changelog....
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/share/pyshared/
-rw-r--r-- root/root       233 2013-08-17 23:43 ./usr/share/pyshared/fridge-1.0.e...
-rw-r--r-- root/root      1579 2013-04-08 21:16 ./usr/share/pyshared/fridge.py
lrwxrwxrwx root/root         0 2013-08-17 23:43 ./usr/lib/python2.7/dist-packages...
lrwxrwxrwx root/root         0 2013-08-17 23:43 ./usr/lib/python2.7/dist-packages...

Now we have Debian package fridge_1.0-1_all.deb which can be installed and removed easily.

Debian package from Python3 source distribution (dh_make)

Let’s do the same for Python3.

Let’s make Debian source package.

$ tar -xvzf fridge/dist/fridge-1.0.tar.gz -C deb
fridge-1.0/
fridge-1.0/scripts/
fridge-1.0/scripts/jane
fridge-1.0/scripts/joe
fridge-1.0/scripts/tom
fridge-1.0/fridge.py
fridge-1.0/PKG-INFO
fridge-1.0/setup.py
fridge-1.0/README
$ cd deb/fridge-1.0; dh_make -s --createorig --yes; cd -
/path/to/package2/deb/fridge-1.0
Maintainer name  : Osamu Aoki
Email-Address    : osamu@debian.org
Date             : Sat, 17 Aug 2013 23:43:32 +0900
Package Name     : fridge
Version          : 1.0
License          : blank
Type of Package  : Single
Currently there is no top level Makefile. This may require additional tuning.
Done. Please edit the files in the debian/ subdirectory now. You should also
check that the fridge Makefiles install into $DESTDIR and not in / .
/path/to/package2
$ ls -lR deb
deb:
total 8
drwxrwxr-x 4 osamu osamu 4096 Aug 17 23:43 fridge-1.0
-rw-rw-r-- 1 osamu osamu 1212 Aug 17 23:43 fridge_1.0.orig.tar.xz

deb/fridge-1.0:
total 24
drwxr-xr-x 3 osamu osamu 4096 Aug 17 23:43 debian
-rw-r--r-- 1 osamu osamu 1586 Aug 17 23:43 fridge.py
-rw-rw-r-- 1 osamu osamu  233 Aug 17 23:43 PKG-INFO
-rw-rw-r-- 1 osamu osamu   31 Mar 28 22:17 README
drwxrwxr-x 2 osamu osamu 4096 Aug 17 23:43 scripts
-rwxr-xr-x 1 osamu osamu  362 Apr  5 23:58 setup.py

deb/fridge-1.0/debian:
total 104
-rw-rw-r-- 1 osamu osamu   180 Aug 17 23:43 changelog
-rw-rw-r-- 1 osamu osamu     2 Aug 17 23:43 compat
-rw-rw-r-- 1 osamu osamu   505 Aug 17 23:43 control
-rw-rw-r-- 1 osamu osamu  1668 Aug 17 23:43 copyright
-rw-rw-r-- 1 osamu osamu     7 Aug 17 23:43 docs
-rw-rw-r-- 1 osamu osamu   128 Aug 17 23:43 fridge.cron.d.ex
-rw-rw-r-- 1 osamu osamu   232 Aug 17 23:43 fridge.default.ex
-rw-rw-r-- 1 osamu osamu   504 Aug 17 23:43 fridge.doc-base.EX
-rw-rw-r-- 1 osamu osamu  4675 Aug 17 23:43 init.d.ex
-rw-rw-r-- 1 osamu osamu  1625 Aug 17 23:43 manpage.1.ex
-rw-rw-r-- 1 osamu osamu  4648 Aug 17 23:43 manpage.sgml.ex
-rw-rw-r-- 1 osamu osamu 11003 Aug 17 23:43 manpage.xml.ex
-rw-rw-r-- 1 osamu osamu   123 Aug 17 23:43 menu.ex
-rw-rw-r-- 1 osamu osamu   956 Aug 17 23:43 postinst.ex
-rw-rw-r-- 1 osamu osamu   929 Aug 17 23:43 postrm.ex
-rw-rw-r-- 1 osamu osamu   689 Aug 17 23:43 preinst.ex
-rw-rw-r-- 1 osamu osamu   876 Aug 17 23:43 prerm.ex
-rw-rw-r-- 1 osamu osamu   173 Aug 17 23:43 README.Debian
-rw-rw-r-- 1 osamu osamu   191 Aug 17 23:43 README.source
-rwxr-xr-x 1 osamu osamu   442 Aug 17 23:43 rules
drwxr-xr-x 2 osamu osamu  4096 Aug 17 23:43 source
-rw-rw-r-- 1 osamu osamu   775 Aug 17 23:43 watch.ex

deb/fridge-1.0/debian/source:
total 4
-rw-rw-r-- 1 osamu osamu 12 Aug 17 23:43 format

deb/fridge-1.0/scripts:
total 12
-rw-r--r-- 1 osamu osamu 124 Apr  6 18:14 jane
-rw-r--r-- 1 osamu osamu  93 Mar 28 20:18 joe
-rw-r--r-- 1 osamu osamu  81 Mar 28 20:19 tom
$

  ... update debian/control
  ... update debian/rules
  ... touch up template files
  ... remove unused template files

$ ls -l deb/fridge-1.0/debian
total 32
-rw-rw-r-- 1 osamu osamu  180 Apr  6 22:36 changelog
-rw-rw-r-- 1 osamu osamu    2 Apr  6 22:36 compat
-rw-rw-r-- 1 osamu osamu  557 Apr  8 22:54 control
-rw-rw-r-- 1 osamu osamu 1668 Apr  6 22:36 copyright
-rw-rw-r-- 1 osamu osamu  440 Apr  6 23:03 manpage.1
-rw-rw-r-- 1 osamu osamu  120 Apr  6 23:03 README.Debian
-rwxr-xr-x 1 osamu osamu  663 Apr  9 20:44 rules
drwxr-xr-x 2 osamu osamu 4096 Apr  6 22:36 source
$ cat deb/fridge-1.0/debian/control
Source: fridge
Section: unknown
Priority: extra
Maintainer: Osamu Aoki <osamu@debian.org>
Build-Depends: debhelper (>= 8.0.0), python3-minimal, python3
Standards-Version: 3.9.3
X-Python3-Version: >= 3.1
Homepage: <insert the upstream URL, if relevant>
#Vcs-Git: git://git.debian.org/collab-maint/fridge.git
#Vcs-Browser: http://git.debian.org/?p=collab-maint/fridge.git;a=summary

Package: fridge
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: <insert up to 60 chars description>
 <insert long description, indented with spaces>
$ cat deb/fridge-1.0/debian/rules
#!/usr/bin/make -f
#export DH_VERBOSE=1
ifeq ($(DH_VERBOSE),1)
    DH_VERBOSE_OPT = -ex
else
    DH_VERBOSE_OPT = -e
endif
PY3REQUESTED := $(shell py3versions -r)
PY3DEFAULT := $(shell py3versions -d)
PYTHON3 := $(filter-out $(PY3DEFAULT),$(PY3REQUESTED)) python3

%:
    dh $@ --with python3

override_dh_auto_clean:
    rm -rf build

override_dh_auto_build:
    set $(DH_VERBOSE_OPT); for python in $(PYTHON3); do \
        $$python setup.py build; \
    done

# use fridge instead of tmp since it is single binary package
override_dh_auto_install:
    set $(DH_VERBOSE_OPT); for python in $(PYTHON3); do \
        $$python setup.py install --root=debian/fridge --install-layout=deb; \
    done

Here, I am working around lack of Python3 support (#538978 and #597105 bugs) by debhelper using the customized build script debian/rules following http://developer.ubuntu.com/packaging/html/python-packaging.html[Ubuntu documentation on “Packaging Python modules and applications”]

Let’s make Debian binary package.

$ cd deb/fridge-1.0; debuild -us -uc; cd -
/path/to/package2/deb/fridge-1.0
 dpkg-buildpackage -rfakeroot -D -us -uc -I -i
dpkg-buildpackage: source package fridge
dpkg-buildpackage: source version 1.0-1
dpkg-buildpackage: source distribution unstable
dpkg-buildpackage: source changed by Osamu Aoki <osamu@debian.org>
 dpkg-source -I -i --before-build fridge-1.0
dpkg-buildpackage: host architecture amd64
 fakeroot debian/rules clean
dh clean --with python3
   dh_testdir
   debian/rules override_dh_auto_clean
make[1]: Entering directory `/path/to/package2/deb/fridge-1.0'
rm -rf build
make[1]: Leaving directory `/path/to/package2/deb/fridge-1.0'
   dh_clean
 dpkg-source -I -i -b fridge-1.0
dpkg-source: info: using source format `3.0 (quilt)'
dpkg-source: info: building fridge using existing ./fridge_1.0.orig.tar.xz
dpkg-source: info: building fridge in fridge_1.0-1.debian.tar.gz
dpkg-source: info: building fridge in fridge_1.0-1.dsc
 debian/rules build
dh build --with python3
   dh_testdir
   dh_auto_configure
   debian/rules override_dh_auto_build
make[1]: Entering directory `/path/to/package2/deb/fridge-1.0'
set -e; for python in  python3; do \
        $python setup.py build; \
    done
running build
running build_py
creating build
creating build/lib
copying fridge.py -> build/lib
running build_scripts
creating build/scripts-3.3
copying and adjusting scripts/jane -> build/scripts-3.3
copying and adjusting scripts/joe -> build/scripts-3.3
copying and adjusting scripts/tom -> build/scripts-3.3
changing mode of build/scripts-3.3/jane from 644 to 755
changing mode of build/scripts-3.3/joe from 644 to 755
changing mode of build/scripts-3.3/tom from 644 to 755
make[1]: Leaving directory `/path/to/package2/deb/fridge-1.0'
   dh_auto_test
 fakeroot debian/rules binary
dh binary --with python3
   dh_testroot
   dh_prep
   debian/rules override_dh_auto_install
make[1]: Entering directory `/path/to/package2/deb/fridge-1.0'
set -e; for python in  python3; do \
        $python setup.py install --root=debian/fridge --install-layout=deb; \
    done
running install
running build
running build_py
running build_scripts
running install_lib
creating debian/fridge
creating debian/fridge/usr
creating debian/fridge/usr/lib
creating debian/fridge/usr/lib/python3
creating debian/fridge/usr/lib/python3/dist-packages
copying build/lib/fridge.py -> debian/fridge/usr/lib/python3/dist-packages
byte-compiling debian/fridge/usr/lib/python3/dist-packages/fridge.py to fridge.cp...
running install_scripts
creating debian/fridge/usr/bin
copying build/scripts-3.3/jane -> debian/fridge/usr/bin
copying build/scripts-3.3/joe -> debian/fridge/usr/bin
copying build/scripts-3.3/tom -> debian/fridge/usr/bin
changing mode of debian/fridge/usr/bin/jane to 755
changing mode of debian/fridge/usr/bin/joe to 755
changing mode of debian/fridge/usr/bin/tom to 755
running install_egg_info
Writing debian/fridge/usr/lib/python3/dist-packages/fridge-1.0.egg-info
make[1]: Leaving directory `/path/to/package2/deb/fridge-1.0'
   dh_installdocs
   dh_installchangelogs
   dh_pysupport
dh_pysupport: This program is deprecated, you should use dh_python2 instead. Migr...
   dh_python3
   dh_perl
   dh_link
   dh_compress
   dh_fixperms
   dh_installdeb
   dh_gencontrol
dpkg-gencontrol: warning: Depends field of package fridge: unknown substitution v...
dpkg-gencontrol: warning: package fridge: unused substitution variable ${python3:...
   dh_md5sums
   dh_builddeb
dpkg-deb: building package `fridge' in `../fridge_1.0-1_all.deb'.
 dpkg-genchanges  >../fridge_1.0-1_amd64.changes
dpkg-genchanges: including full source code in upload
 dpkg-source -I -i --after-build fridge-1.0
dpkg-buildpackage: full upload (original source is included)
Now running lintian...
W: fridge source: superfluous-clutter-in-homepage <insert the upstream URL, if re...
N:
N:    The "Homepage:" field in this package's control file contains
N:    superfluous markup around the URL, like enclosing < and >. This is
N:    unnecessary and needlessly complicates using this information.
N:
N:    Refer to Debian Policy Manual section 5.6.23 (Homepage) for details.
N:
N:    Severity: normal, Certainty: certain
N:
N:    Check: fields, Type: binary, udeb, source
N:
W: fridge source: bad-homepage <insert the upstream URL, if relevant>
N:
N:    The "Homepage:" field in this package's control file does not contain a
N:    valid absolute URL. Most probably you forgot to specify the scheme (e.g.
N:    http).
N:
N:    This tag is also triggered if the scheme is not known by Lintian.
N:
N:    Please file a bug against Lintian, if this tag is triggered for a valid
N:    homepage URL.
N:
N:    Severity: normal, Certainty: certain
N:
N:    Check: fields, Type: binary, udeb, source
N:
W: fridge source: out-of-date-standards-version 3.9.3 (current is 3.9.4)
N:
N:    The source package refers to a Standards-Version older than the one that
N:    was current at the time the package was created (according to the
N:    timestamp of the latest debian/changelog entry). Please consider
N:    updating the package to current Policy and setting this control field
N:    appropriately.
N:
N:    If the package is already compliant with the current standards, you
N:    don't have to re-upload the package just to adjust the Standards-Version
N:    control field. However, please remember to update this field next time
N:    you upload the package.
N:
N:    See /usr/share/doc/debian-policy/upgrading-checklist.txt.gz in the
N:    debian-policy package for a summary of changes in newer versions of
N:    Policy.
N:
N:    Refer to http://www.debian.org/doc/debian-policy/upgrading-checklist for
N:    details.
N:
N:    Severity: normal, Certainty: certain
N:
N:    Check: standards-version, Type: source
N:
W: fridge: wrong-bug-number-in-closes l3:#nnnn
N:
N:    Bug numbers can only contain digits.
N:
N:    Refer to Debian Policy Manual section 4.4 (Debian changelog:
N:    debian/changelog) for details.
N:
N:    Severity: normal, Certainty: certain
N:
N:    Check: changelog-file, Type: binary
N:
W: fridge: new-package-should-close-itp-bug
N:
N:    This package appears to be the first packaging of a new upstream
N:    software package (there is only one changelog entry and the Debian
N:    revision is 1), but it does not close any bugs. The initial upload of a
N:    new package should close the corresponding ITP bug for that package.
N:
N:    This warning can be ignored if the package is not intended for Debian or
N:    if it is a split of an existing Debian package.
N:
N:    Refer to Debian Developer's Reference section 5.1 (New packages) for
N:    details.
N:
N:    Severity: normal, Certainty: certain
N:
N:    Check: changelog-file, Type: binary
N:
E: fridge: helper-templates-in-copyright
N:
N:    The /usr/share/doc/<pkg>/copyright file still contains template markers
N:    from a packaging helper. Please fill in the actual license, upstream
N:    copyright holders, and download information about the package and remove
N:    any remaining templates generated by the packaging helper.
N:
N:    Severity: important, Certainty: certain
N:
N:    Check: copyright-file, Type: binary
N:
W: fridge: copyright-has-url-from-dh_make-boilerplate
N:
N:    There is "url://example.com" in your copyright file. This was most
N:    likely a remnant from the dh_make template.
N:
N:    Make sure you include the real location where you obtained the upstream
N:    sources (if any).
N:
N:    Refer to Debian Policy Manual section 12.5 (Copyright information) for
N:    details.
N:
N:    Severity: normal, Certainty: certain
N:
N:    Check: copyright-file, Type: binary
N:
E: fridge: copyright-contains-dh_make-todo-boilerplate
N:
N:    The string "Please also look if..." appears in the copyright file, which
N:    indicates that you either didn't check the whole source to find
N:    additional copyright/license, or that you didn't remove that paragraph
N:    after having done so.
N:
N:    Refer to Debian Policy Manual section 12.5 (Copyright information) for
N:    details.
N:
N:    Severity: serious, Certainty: possible
N:
N:    Check: copyright-file, Type: binary
N:
E: fridge: description-is-dh_make-template
N:
N:    The synopsis or the extended description has not been changed from the
N:    template provided by dh_make.
N:
N:    Severity: serious, Certainty: certain
N:
N:    Check: description, Type: binary, udeb
N:
E: fridge: section-is-dh_make-template
N:
N:    The "Section:" field in this package's control file is set to unknown.
N:    This is not a valid section, and usually means a dh_make template
N:    control file was used and never modified to set the correct section.
N:
N:    Refer to Debian Policy Manual section 2.4 (Sections) for details.
N:
N:    Severity: serious, Certainty: certain
N:
N:    Check: fields, Type: binary, udeb, source
N:
W: fridge: superfluous-clutter-in-homepage <insert the upstream URL, if relevant>...
W: fridge: bad-homepage <insert the upstream URL, if relevant>
W: fridge: binary-without-manpage usr/bin/jane
N:
N:    Each binary in /usr/bin, /usr/sbin, /bin, /sbin or /usr/games should
N:    have a manual page
N:
N:    Note that though the man program has the capability to check for several
N:    program names in the NAMES section, each of these programs should have
N:    its own manual page (a symbolic link to the appropriate manual page is
N:    sufficient) because other manual page viewers such as xman or tkman
N:    don't support this.
N:
N:    If the name of the man page differs from the binary by case, man may be
N:    able to find it anyway; however, it is still best practice to make the
N:    case of the man page match the case of the binary.
N:
N:    If the man pages are provided by another package on which this package
N:    depends, lintian may not be able to determine that man pages are
N:    available. In this case, after confirming that all binaries do have man
N:    pages after this package and its dependencies are installed, please add
N:    a lintian override.
N:
N:    Refer to Debian Policy Manual section 12.1 (Manual pages) for details.
N:
N:    Severity: normal, Certainty: possible
N:
N:    Check: manpages, Type: binary
N:
W: fridge: binary-without-manpage usr/bin/joe
W: fridge: binary-without-manpage usr/bin/tom
E: fridge: python-script-but-no-python-dep usr/bin/jane
N:
N:    Packages with Python scripts should depend on the package python. Those
N:    with scripts that specify a specific version of Python must depend on
N:    that version of Python (exactly).
N:
N:    For example, if a script in the package uses #!/usr/bin/python, the
N:    package needs a dependency on python. If a script uses
N:    #!/usr/bin/python2.6, the package needs a dependency on python2.6. A
N:    dependency on python (>= 2.6) is not correct, since later versions of
N:    Python may not provide the /usr/bin/python2.6 binary.
N:
N:    If you are using debhelper, adding ${python:Depends} to the Depends
N:    field and ensuring dh_pysupport or dh_pycentral are run during the build
N:    should take care of adding the correct dependency.
N:
N:    In some cases a weaker relationship, such as Suggests or Recommends,
N:    will be more appropriate.
N:
N:    Severity: important, Certainty: certain
N:
N:    Check: scripts, Type: binary
N:
E: fridge: python-script-but-no-python-dep usr/bin/joe
E: fridge: python-script-but-no-python-dep usr/bin/tom
Finished running lintian.
/path/to/package2
$ ls -l deb
total 36
drwxrwxr-x 5 osamu osamu  4096 Aug 17 23:43 fridge-1.0
-rw-r--r-- 1 osamu osamu  3254 Aug 17 23:43 fridge_1.0-1_all.deb
-rw-r--r-- 1 osamu osamu 11805 Aug 17 23:43 fridge_1.0-1_amd64.build
-rw-r--r-- 1 osamu osamu  1419 Aug 17 23:43 fridge_1.0-1_amd64.changes
-rw-r--r-- 1 osamu osamu  2265 Aug 17 23:43 fridge_1.0-1.debian.tar.gz
-rw-r--r-- 1 osamu osamu   810 Aug 17 23:43 fridge_1.0-1.dsc
-rw-rw-r-- 1 osamu osamu  1212 Aug 17 23:43 fridge_1.0.orig.tar.xz
$ dpkg -c deb/fridge_1.0-1_all.deb
drwxr-xr-x root/root         0 2013-08-17 23:43 ./
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/lib/
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/lib/python3/
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/lib/python3/dist-packages/
-rw-r--r-- root/root       233 2013-08-17 23:43 ./usr/lib/python3/dist-packages/f...
-rw-r--r-- root/root      1586 2013-08-17 23:43 ./usr/lib/python3/dist-packages/f...
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/bin/
-rwxr-xr-x root/root       124 2013-08-17 23:43 ./usr/bin/jane
-rwxr-xr-x root/root        93 2013-08-17 23:43 ./usr/bin/joe
-rwxr-xr-x root/root        81 2013-08-17 23:43 ./usr/bin/tom
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/share/
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/share/doc/
drwxr-xr-x root/root         0 2013-08-17 23:43 ./usr/share/doc/fridge/
-rw-r--r-- root/root      1668 2013-04-06 22:36 ./usr/share/doc/fridge/copyright
-rw-r--r-- root/root       120 2013-04-06 23:03 ./usr/share/doc/fridge/README.Deb...
-rw-r--r-- root/root       172 2013-04-06 22:36 ./usr/share/doc/fridge/changelog....

Now we have Debian package fridge_1.0-1_all.deb which can be installed and removed easily.

Debian package from Python2 source distribution (debmake)

The debmake is even more handier for making a Debian package. I will be very sloppy for now as well. (More work is needed to make package suitable for Debian.)

Let’s make Debian source package.

$ cd fridge; debmake -d -u 1.0 -b :python; cd -
/path/to/package1/fridge
running sdist
running check
warning: sdist: manifest template 'MANIFEST.in' does not exist (using default fil...

writing manifest file 'MANIFEST'
creating fridge-1.0
creating fridge-1.0/scripts
making hard links in fridge-1.0...
hard linking README -> fridge-1.0
hard linking fridge.py -> fridge-1.0
hard linking setup.py -> fridge-1.0
hard linking scripts/jane -> fridge-1.0/scripts
hard linking scripts/joe -> fridge-1.0/scripts
hard linking scripts/tom -> fridge-1.0/scripts
Creating tar archive
removing 'fridge-1.0' (and everything under it)
fridge-1.0/
fridge-1.0/scripts/
fridge-1.0/scripts/jane
fridge-1.0/scripts/joe
fridge-1.0/scripts/tom
fridge-1.0/fridge.py
fridge-1.0/PKG-INFO
fridge-1.0/setup.py
fridge-1.0/README
I: sanity check of parameters
I: process "make dist" equivalent
I: pwd = /path/to/package1/fridge
I: setup.py (Python): sdist
I:  tar-ball made
I: pwd = /path/to/package1
I: create symlink at /path/to/package1/fridge_1.0.orig.tar.gz pointing to fridge/...
I: process untar
I: run "tar -xvzf fridge_1.0.orig.tar.gz".
I: untared.
I: pwd = /path/to/package1/fridge-1.0
I: analyze source
I: generate debian/*
I: File written: debian/source/format
I: File written: debian/source/local-options
I: File written: debian/patches/series
I: File written: debian/compat
I: File written: debian/rules
I: File written: debian/README.Debian
I: File written: debian/changelog
I: File written: debian/copyright
I: File written: debian/control
I: File written: debian/fridge.install
I: run "debmake -x" to get more template files
I: upon return to the shell, current directory becomes /path/to/package1/fridge
I: please execute "cd /path/to/package1/fridge-1.0"
I: before building binary package with dpkg-buildpackage (or debuild, pdebuild, s...
/path/to/package1
$ ls -lR fridge-1.0
fridge-1.0:
total 24
drwxrwxr-x 4 osamu osamu 4096 Aug 17 23:43 debian
-rw-r--r-- 1 osamu osamu 1579 Apr  8 21:16 fridge.py
-rw-rw-r-- 1 osamu osamu  233 Aug 17 23:43 PKG-INFO
-rw-rw-r-- 1 osamu osamu   31 Mar 28 22:17 README
drwxrwxr-x 2 osamu osamu 4096 Aug 17 23:43 scripts
-rwxr-xr-x 1 osamu osamu  361 Apr  8 21:13 setup.py

fridge-1.0/debian:
total 36
-rw-rw-r-- 1 osamu osamu  185 Aug 17 23:43 changelog
-rw-rw-r-- 1 osamu osamu    2 Aug 17 23:43 compat
-rw-rw-r-- 1 osamu osamu  737 Aug 17 23:43 control
-rw-rw-r-- 1 osamu osamu 1025 Aug 17 23:43 copyright
-rw-rw-r-- 1 osamu osamu    1 Aug 17 23:43 fridge.install
drwxrwxr-x 2 osamu osamu 4096 Aug 17 23:43 patches
-rw-rw-r-- 1 osamu osamu  255 Aug 17 23:43 README.Debian
-rwxr-xr-x 1 osamu osamu  219 Aug 17 23:43 rules
drwxrwxr-x 2 osamu osamu 4096 Aug 17 23:43 source

fridge-1.0/debian/patches:
total 4
-rw-rw-r-- 1 osamu osamu 211 Aug 17 23:43 series

fridge-1.0/debian/source:
total 8
-rw-rw-r-- 1 osamu osamu  12 Aug 17 23:43 format
-rw-rw-r-- 1 osamu osamu 123 Aug 17 23:43 local-options

fridge-1.0/scripts:
total 12
-rw-r--r-- 1 osamu osamu 124 Apr  6 18:14 jane
-rw-r--r-- 1 osamu osamu  93 Mar 28 20:18 joe
-rw-r--r-- 1 osamu osamu  81 Mar 28 20:19 tom
$ cat fridge-1.0/debian/control
Source: fridge
Section: unknown
Priority: extra
Maintainer: Osamu Aoki <osamu@debian.org>
Build-Depends: python-all,
    debhelper (>=9)
Standards-Version: 3.9.4
Homepage: <insert the upstream URL, if relevant>
Vcs-Git: git://git.debian.org/collab-maint/fridge.git
Vcs-Browser: http://git.debian.org/?p=collab-maint/fridge.git
X-Python-Version: >= 2.6

Package: fridge
Architecture: all
Multi-Arch: foreign
Pre-Depends: ${misc:Pre-Depends}
Depends: ${misc:Depends},
    ${python:Depends}
Description: <insert up to 60 chars description>
 <insert long description, indented with spaces>
 <continued long description lines ...>
 .
 <continued long description line after a line break indicated by " .">
 <continued long description lines ...>


$ cat fridge-1.0/debian/rules
#!/usr/bin/make -f
# uncomment to enable verbose mode for debhelper
#DH_VERBOSE = 1
# uncomment to exclude VCS paths
#DH_ALWAYS_EXCLUDE=CVS:.svn:.git

%:
    dh $@ --with "python2"

# Customize by adding override scripts

Now we have Debian package fridge_1.0-1_all.deb which can be installed and removed easily.

Debian package from Python3 source distribution (debmake)

Let’s do the same for Python3 (The debmake does hard work for you).

Let’s make Debian source package.

$ cd fridge; debmake -d -u 1.0 -b :python; cd -
/path/to/package2/fridge
running sdist
running check
warning: sdist: manifest template 'MANIFEST.in' does not exist (using default fil...

writing manifest file 'MANIFEST'
creating fridge-1.0
creating fridge-1.0/scripts
making hard links in fridge-1.0...
hard linking README -> fridge-1.0
hard linking fridge.py -> fridge-1.0
hard linking setup.py -> fridge-1.0
hard linking scripts/jane -> fridge-1.0/scripts
hard linking scripts/joe -> fridge-1.0/scripts
hard linking scripts/tom -> fridge-1.0/scripts
Creating tar archive
removing 'fridge-1.0' (and everything under it)
fridge-1.0/
fridge-1.0/scripts/
fridge-1.0/scripts/jane
fridge-1.0/scripts/joe
fridge-1.0/scripts/tom
fridge-1.0/fridge.py
fridge-1.0/PKG-INFO
fridge-1.0/setup.py
fridge-1.0/README
I: sanity check of parameters
I: process "make dist" equivalent
I: pwd = /path/to/package2/fridge
I: setup.py (Python3): sdist
I:  tar-ball made
I: pwd = /path/to/package2
I: create symlink at /path/to/package2/fridge_1.0.orig.tar.gz pointing to fridge/...
I: process untar
I: run "tar -xvzf fridge_1.0.orig.tar.gz".
I: untared.
I: pwd = /path/to/package2/fridge-1.0
I: analyze source
I: generate debian/*
I: File written: debian/source/format
I: File written: debian/source/local-options
I: File written: debian/patches/series
I: File written: debian/compat
I: File written: debian/rules
I: File written: debian/README.Debian
I: File written: debian/changelog
I: File written: debian/copyright
I: File written: debian/control
I: File written: debian/fridge.install
I: run "debmake -x" to get more template files
I: upon return to the shell, current directory becomes /path/to/package2/fridge
I: please execute "cd /path/to/package2/fridge-1.0"
I: before building binary package with dpkg-buildpackage (or debuild, pdebuild, s...
/path/to/package2
$ ls -lR fridge-1.0
fridge-1.0:
total 24
drwxrwxr-x 4 osamu osamu 4096 Aug 17 23:43 debian
-rw-r--r-- 1 osamu osamu 1586 Aug 17 23:43 fridge.py
-rw-rw-r-- 1 osamu osamu  233 Aug 17 23:43 PKG-INFO
-rw-rw-r-- 1 osamu osamu   31 Mar 28 22:17 README
drwxrwxr-x 2 osamu osamu 4096 Aug 17 23:43 scripts
-rwxr-xr-x 1 osamu osamu  362 Apr  5 23:58 setup.py

fridge-1.0/debian:
total 36
-rw-rw-r-- 1 osamu osamu  185 Aug 17 23:43 changelog
-rw-rw-r-- 1 osamu osamu    2 Aug 17 23:43 compat
-rw-rw-r-- 1 osamu osamu  764 Aug 17 23:43 control
-rw-rw-r-- 1 osamu osamu 1025 Aug 17 23:43 copyright
-rw-rw-r-- 1 osamu osamu    1 Aug 17 23:43 fridge.install
drwxrwxr-x 2 osamu osamu 4096 Aug 17 23:43 patches
-rw-rw-r-- 1 osamu osamu  255 Aug 17 23:43 README.Debian
-rwxr-xr-x 1 osamu osamu  763 Aug 17 23:43 rules
drwxrwxr-x 2 osamu osamu 4096 Aug 17 23:43 source

fridge-1.0/debian/patches:
total 4
-rw-rw-r-- 1 osamu osamu 211 Aug 17 23:43 series

fridge-1.0/debian/source:
total 8
-rw-rw-r-- 1 osamu osamu  12 Aug 17 23:43 format
-rw-rw-r-- 1 osamu osamu 123 Aug 17 23:43 local-options

fridge-1.0/scripts:
total 12
-rw-r--r-- 1 osamu osamu 124 Apr  6 18:14 jane
-rw-r--r-- 1 osamu osamu  93 Mar 28 20:18 joe
-rw-r--r-- 1 osamu osamu  81 Mar 28 20:19 tom
$ cat fridge-1.0/debian/control
Source: fridge
Section: unknown
Priority: extra
Maintainer: Osamu Aoki <osamu@debian.org>
Build-Depends: debhelper (>=9),
    python3-all
Standards-Version: 3.9.4
Homepage: <insert the upstream URL, if relevant>
Vcs-Git: git://git.debian.org/collab-maint/fridge.git
Vcs-Browser: http://git.debian.org/?p=collab-maint/fridge.git
X-Python-Version: >= 2.6
X-Python3-Version: >= 3.2

Package: fridge
Architecture: all
Multi-Arch: foreign
Pre-Depends: ${misc:Pre-Depends}
Depends: ${misc:Depends},
    ${python:Depends}
Description: <insert up to 60 chars description>
 <insert long description, indented with spaces>
 <continued long description lines ...>
 .
 <continued long description line after a line break indicated by " .">
 <continued long description lines ...>


$ cat fridge-1.0/debian/rules
#!/usr/bin/make -f
# uncomment to enable verbose mode for debhelper
#DH_VERBOSE = 1
# uncomment to exclude VCS paths
#DH_ALWAYS_EXCLUDE=CVS:.svn:.git

%:
    dh $@ --with "python2,python3"

# special work around for python3 (#538978 and #597105 bugs)
PY3REQUESTED := $(shell py3versions -r)
PY3DEFAULT := $(shell py3versions -d)
PYTHON3 := $(filter-out $(PY3DEFAULT),$(PY3REQUESTED)) python3

override_dh_auto_clean:
    -rm -rf build

override_dh_auto_build:
    set -ex; for python in $(PYTHON3); do \
        $$python setup.py build; \
    done

override_dh_auto_install:
    set -ex; for python in $(PYTHON3); do \
        $$python setup.py install \
            --root=debian/fridge\
            --force\
            --install-layout=deb; \
    done

# Customize by adding override scripts

Now we have Debian package fridge_1.0-1_all.deb which can be installed and removed easily.

Python + C

For non-trivial tasks, it is good idea to write major parts of the program in some high level programing language such as Python using modules, with some mission-critical small parts of the program as Python modules written in C (or in any compiled languages) for speed.

There are several approaches to mix Python and C/C++ code.

Previous Post Top Next Post