Update debian changelog
[pysam.git] / setup.py
1 #!/usr/bin/python
2 '''
3
4 pysam
5 *****
6
7 '''
8
9 import os, sys, glob, shutil, hashlib, re, fnmatch
10 import platform
11
12 name = "pysam"
13
14 # collect pysam version
15 sys.path.insert( 0, "pysam")
16 import version
17
18 version = version.__version__
19
20 samtools_exclude = ( "bamtk.c", "razip.c", "bgzip.c", 
21                      "main.c", "calDepth.c", "bam2bed.c",
22                      "wgsim.c", "md5fa.c", "maq2sam.c",)
23 samtools_dest = os.path.abspath( "samtools" )
24 tabix_exclude = ( "main.c", )
25 tabix_dest = os.path.abspath( "tabix" )
26
27 def locate(pattern, root=os.curdir):
28     '''Locate all files matching supplied filename pattern in and below
29     supplied root directory.'''
30     for path, dirs, files in os.walk(os.path.abspath(root)):
31        for filename in fnmatch.filter(files, pattern):
32           yield os.path.join(path, filename)
33
34 def _update_pysam_files(cf, destdir):
35     '''update pysam files applying redirection of ouput'''
36     for filename in cf:
37         if not filename: continue
38         dest = filename + ".pysam.c"
39         with open( filename ) as infile:
40             with open( dest, "w" ) as outfile:
41                 outfile.write( '#include "pysam.h"\n\n' )
42                 outfile.write( re.sub( "stderr", "pysamerr", "".join(infile.readlines()) ) )
43             with open( os.path.join( destdir, "pysam.h" ), "w" )as outfile:
44                 outfile.write ("""#ifndef PYSAM_H
45 #define PYSAM_H
46 #include "stdio.h"
47 extern FILE * pysamerr;
48 #endif
49 """)
50
51 # copy samtools source
52 if len(sys.argv) >= 2 and sys.argv[1] == "import":
53    if len(sys.argv) < 3: raise ValueError("missing PATH to samtools source directory")
54    if len(sys.argv) < 4: raise ValueError("missing PATH to tabix source directory")
55
56    for destdir, srcdir, exclude in zip( 
57       (samtools_dest, tabix_dest), 
58       sys.argv[2:4],
59       (samtools_exclude, tabix_exclude)):
60
61       srcdir = os.path.abspath( srcdir )
62       if not os.path.exists( srcdir ): raise IOError( "samtools src dir `%s` does not exist." % srcdir )
63
64       cfiles = locate( "*.c", srcdir )
65       hfiles = locate( "*.h", srcdir )
66       ncopied = 0
67       
68       def _compareAndCopy( src, srcdir, destdir, exclude ):
69
70          d, f = os.path.split(src)
71          if f in exclude: return None
72          common_prefix = os.path.commonprefix( (d, srcdir ) )
73          subdir = re.sub( common_prefix, "", d )[1:]
74          targetdir = os.path.join( destdir, subdir )
75          if not os.path.exists( targetdir ):
76             os.makedirs( targetdir )
77          old_file = os.path.join( targetdir, f )
78          if os.path.exists( old_file ):
79             md5_old = hashlib.md5("".join(open(old_file,"r").readlines())).digest()
80             md5_new = hashlib.md5("".join(open(src,"r").readlines())).digest()
81             if md5_old != md5_new:
82                raise ValueError( "incompatible files for %s and %s" % (old_file, src ))
83
84          shutil.copy( src, targetdir )
85          return old_file
86
87       for src_file in hfiles:
88          _compareAndCopy( src_file, srcdir,destdir, exclude )
89          ncopied += 1
90
91       cf = []
92       for src_file in cfiles:
93          cf.append( _compareAndCopy( src_file, srcdir, destdir, exclude ) )
94          ncopied += 1
95          
96       sys.stdout.write("installed latest source code from %s: %i files copied" % (srcdir, ncopied))
97       # redirect stderr to pysamerr and replace bam.h with a stub.
98       sys.stdout.write("applying stderr redirection")
99      
100       _update_pysam_files(cf, destdir)
101       
102
103    sys.exit(0)
104
105 if len(sys.argv) >= 2 and sys.argv[1] == "refresh":
106     sys.stdout.write("refreshing latest source code from .c to .pysam.c")
107 # redirect stderr to pysamerr and replace bam.h with a stub.
108     sys.stdout.write("applying stderr redirection")
109     for destdir in ('samtools', 'tabix'):
110         pysamcfiles = locate( "*.pysam.c", destdir )
111         for f in pysamcfiles: os.remove(f)
112         cfiles = locate( "*.c", destdir )
113         _update_pysam_files(cfiles, destdir)
114
115     sys.exit(0)
116
117
118
119 from distribute_setup import use_setuptools
120 use_setuptools()
121
122 from setuptools import Extension, setup
123 from Cython.Distutils import build_ext
124
125 classifiers = """
126 Development Status :: 2 - Alpha
127 Operating System :: MacOS :: MacOS X
128 Operating System :: Microsoft :: Windows :: Windows NT/2000
129 Operating System :: OS Independent
130 Operating System :: POSIX
131 Operating System :: POSIX :: Linux
132 Operating System :: Unix
133 Programming Language :: Python
134 Topic :: Scientific/Engineering
135 Topic :: Scientific/Engineering :: Bioinformatics
136 """
137
138 if platform.system()=='Windows':
139     include_os = ['win32']
140     os_c_files = ['win32/getopt.c']
141 else:
142     include_os = []
143     os_c_files = []
144
145 samtools = Extension(
146     "csamtools",                   # name of extension
147     [ "pysam/csamtools.pyx" ]  +\
148         [ "pysam/%s" % x for x in (
149                 "pysam_util.c", )] +\
150         glob.glob( os.path.join( "samtools", "*.pysam.c" )) +\
151         os_c_files + \
152         glob.glob( os.path.join( "samtools", "*", "*.pysam.c" ) ),
153     library_dirs=[],
154     include_dirs=[ "samtools", "pysam" ] + include_os,
155     libraries=[ "z", ],
156     language="c",
157     define_macros = [('_FILE_OFFSET_BITS','64'),
158                      ('_USE_KNETFILE','')], 
159     )
160
161 tabix = Extension(
162     "ctabix",                   # name of extension
163     [ "pysam/ctabix.pyx", ]  +\
164        [ "pysam/%s" % x for x in ( "tabix_util.c", )] +\
165         os_c_files + \
166        glob.glob( os.path.join( "tabix", "*.pysam.c" ) ),
167     library_dirs=[],
168     include_dirs=[ "tabix", "pysam" ] + include_os,
169     libraries=[ "z", ],
170     language="c",
171     define_macros = [('_FILE_OFFSET_BITS','64'),
172                      ('_USE_KNETFILE','')], 
173     )
174
175 tabproxies = Extension(
176     "TabProxies",                   # name of extension
177     [ "pysam/TabProxies.pyx", ] + os_c_files,
178     library_dirs=[],
179     include_dirs= include_os,
180     libraries=[ "z", ],
181     language="c",
182     )
183
184 cvcf = Extension(
185     "cvcf",                   # name of extension
186     [ "pysam/cvcf.pyx", ] + os_c_files,
187     library_dirs=[],
188     include_dirs= ["tabix",] + include_os,
189     libraries=[ "z", ],
190     language="c",
191     )
192
193 metadata = {
194     'name': name,
195     'version': version,
196     'description': "pysam", 
197     'long_description': __doc__,
198     'author': "Andreas Heger",
199     'author_email': "andreas.heger@gmail.com",
200     'license': "MIT",
201     'platforms': "ALL",
202     'url': "http://code.google.com/p/pysam/",
203     'py_modules': [
204       "pysam/__init__", 
205       "pysam/Pileup", 
206       "pysam/version" ],
207     # cython larger that 0.16 for yield support
208     'requires' : ['cython (>=0.16)'],
209     'ext_modules': [samtools, tabix, tabproxies, cvcf ],
210     'cmdclass' : {'build_ext': build_ext},
211     'install_requires' : ['cython>=0.12.1',], 
212     # do not pack in order to permit linking to csamtools.so
213     'zip_safe' :False,
214     'use_2to3': True,
215     }
216
217 if sys.version_info[0] < 3:
218     metadata['py_modules'].append("pysam/namedtuple")
219
220 if __name__=='__main__':
221    dist = setup(**metadata)