Launchpad automatic translations update.
[odoo/odoo.git] / setup.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 ##############################################################################
4 #
5 #    OpenERP, Open Source Management Solution
6 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
7 #
8 #    This program is free software: you can redistribute it and/or modify
9 #    it under the terms of the GNU Affero General Public License as
10 #    published by the Free Software Foundation, either version 3 of the
11 #    License, or (at your option) any later version.
12 #
13 #    This program is distributed in the hope that it will be useful,
14 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 #    GNU Affero General Public License for more details.
17 #
18 #    You should have received a copy of the GNU Affero General Public License
19 #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 #
21 ##############################################################################
22
23 # setup from TinERP
24 #   taken from straw http://www.nongnu.org/straw/index.html
25 #   taken from gnomolicious http://www.nongnu.org/gnomolicious/
26 #   adapted by Nicolas Évrard <nicoe@altern.org>
27 #
28
29 import imp
30 import sys
31 import os
32 from os.path import join, isfile, basename
33 import glob
34
35 from distutils.core import setup, Command
36 from distutils.command.install import install
37 from distutils.sysconfig import get_python_lib
38
39 has_py2exe = False
40 if os.name == 'nt':
41     import py2exe
42     has_py2exe = True
43
44 sys.path.append(join(os.path.abspath(os.path.dirname(__file__)), "bin"))
45
46 execfile(join('bin', 'release.py'))
47
48 if 'bdist_rpm' in sys.argv:
49     version = version.split('-')[0]
50
51 # get python short version
52 py_short_version = '%s.%s' % sys.version_info[:2]
53
54 required_modules = [
55     ('lxml', 'lxml module: pythonic libxml2 and libxslt bindings'),
56     ('mako', 'Mako template engine'),
57     ('dateutil', "Extensions to the standard datetime module"),
58     ('psycopg2', 'PostgreSQL module'),
59     ('pychart', 'pychart module'),
60     ('pydot', 'pydot module'),
61     ('pytz', 'Timezone handling library for Python'),
62     ('reportlab', 'reportlab module'),
63     ('yaml', 'YAML parser and emitter for Python'),
64     ('pywebdav', 'PyWebDAV is a standards compliant WebDAV server and library written in Python'),
65 ]
66
67 def check_modules():
68     errors = []
69     for modname, desc in required_modules:
70         try:
71             imp.find_module(modname)
72         except ImportError:
73             errors.append(
74                 'Error: python module %s (%s) is required' % (modname, desc))
75
76     if errors:
77         print '\n'.join(errors)
78         sys.exit(1)
79
80 def find_addons():
81     for root, _, names in os.walk(join('bin', 'addons')):
82         if '__openerp__.py' in names or '__terp__.py' in names:
83             yield basename(root), root
84     #look for extra modules
85     try:
86         empath = os.getenv('EXTRA_MODULES_PATH', '../addons/')
87         for mname in open(join(empath, 'server_modules.list')):
88             mname = mname.strip()
89             if not mname:
90                 continue
91
92             terp = join(empath, mname, '__openerp__.py')
93             if not os.path.exists(terp):
94                 terp = join(empath, mname, '__terp__.py')
95
96             if os.path.exists(terp):
97                 yield mname, join(empath, mname)
98             else:
99                 print "Module %s specified, but no valid path." % mname
100     except:
101         pass
102
103 def data_files():
104     '''Build list of data files to be installed'''
105     files = []
106     if os.name == 'nt':
107         for root, _, names in os.walk(join('bin','addons')):
108             files.append((root, [join(root, name) for name in names]))
109         for root, _, names in os.walk('doc'):
110             files.append((root, [join(root, name) for name in names]))
111         files.append(('.', [join('bin', 'import_xml.rng'),
112                             join('bin', 'server.pkey'),
113                             join('bin', 'server.cert')]))
114     else:
115         man_directory = join('share', 'man')
116         files.append((join(man_directory, 'man1'), ['man/openerp-server.1']))
117         files.append((join(man_directory, 'man5'), ['man/openerp_serverrc.5']))
118
119         doc_directory = join('share', 'doc', 'openerp-server-%s' % version)
120         files.append((doc_directory, filter(isfile, glob.glob('doc/*'))))
121         files.append((join(doc_directory, 'migrate', '3.3.0-3.4.0'),
122                       filter(isfile, glob.glob('doc/migrate/3.3.0-3.4.0/*'))))
123         files.append((join(doc_directory, 'migrate', '3.4.0-4.0.0'),
124                       filter(isfile, glob.glob('doc/migrate/3.4.0-4.0.0/*'))))
125
126         openerp_site_packages = join(get_python_lib(prefix=''), 'openerp-server')
127
128         files.append((openerp_site_packages, [join('bin', 'import_xml.rng'),
129                                               join('bin', 'server.pkey'),
130                                               join('bin', 'server.cert')]))
131
132         if sys.version_info[0:2] == (2,5):
133             files.append((openerp_site_packages, [ join('python25-compat','BaseHTTPServer.py'),
134                                                    join('python25-compat','SimpleXMLRPCServer.py'),
135                                                    join('python25-compat','SocketServer.py')]))
136
137         for addonname, add_path in find_addons():
138             addon_path = join(get_python_lib(prefix=''), 'openerp-server','addons', addonname)
139             for root, dirs, innerfiles in os.walk(add_path):
140                 innerfiles = filter(lambda fil: os.path.splitext(fil)[1] not in ('.pyc', '.pyd', '.pyo'), innerfiles)
141                 if innerfiles:
142                     res = os.path.normpath(join(addon_path, root.replace(join(add_path), '.')))
143                     files.extend(((res, map(lambda fil: join(root, fil),
144                                             innerfiles)),))
145
146     return files
147
148 if not os.getenv('NO_CHECK_MODULES') :
149     check_modules()
150
151 f = file('openerp-server','w')
152 f.write("""#!/bin/sh
153 echo "Error: the content of this file should have been replaced during "
154 echo "installation\n"
155 exit 1
156 """)
157 f.close()
158
159 def find_package_dirs():
160     package_dirs = {'openerp-server': 'bin'}
161     for mod, path in find_addons():
162         package_dirs['openerp-server.addons.' + mod] = path
163     return package_dirs
164
165 class openerp_server_install(install):
166     def run(self):
167         # create startup script
168         start_script = "#!/bin/sh\ncd %s\nexec %s ./openerp-server.py $@\n"\
169             % (join(self.install_libbase, "openerp-server"), sys.executable)
170         # write script
171         f = open('openerp-server', 'w')
172         f.write(start_script)
173         f.close()
174         install.run(self)
175
176 options = {
177     "py2exe": {
178         "compressed": 1,
179         "optimize": 2,
180         "dist_dir": 'dist',
181         "packages": [
182                  "lxml", "lxml.builder", "lxml._elementpath", "lxml.etree",
183                  "lxml.objectify", "decimal", "xml", "xml", "xml.dom", "xml.xpath",
184                  "encodings", "dateutil", "wizard", "pychart", "PIL", "pyparsing",
185                  "pydot", "asyncore","asynchat", "reportlab", "vobject",
186                  "HTMLParser", "select", "mako", "poplib",
187                  "imaplib", "smtplib", "email", "yaml","pywebdav",
188                  ],
189         "excludes" : ["Tkconstants","Tkinter","tcl"],
190     }
191 }
192
193 setup(name             = name,
194       version          = version,
195       description      = description,
196       long_description = long_desc,
197       url              = url,
198       author           = author,
199       author_email     = author_email,
200       classifiers      = filter(None, classifiers.split("\n")),
201       license          = license,
202       data_files       = data_files(),
203       cmdclass         = {
204             'install' : openerp_server_install,
205       },
206       scripts          = ['openerp-server'],
207       packages         = ['openerp-server',
208                           'openerp-server.addons',
209                           'openerp-server.ir',
210                           'openerp-server.osv',
211                           'openerp-server.pychart',
212                           'openerp-server.pychart.afm',
213                           'openerp-server.report',
214                           'openerp-server.report.printscreen',
215                           'openerp-server.report.pyPdf',
216                           'openerp-server.report.render',
217                           'openerp-server.report.render.html2html',
218                           'openerp-server.report.render.makohtml2html',
219                           'openerp-server.report.render.odt2odt',
220                           'openerp-server.report.render.rml2html',
221                           'openerp-server.report.render.rml2pdf',
222                           'openerp-server.report.render.rml2txt',
223                           'openerp-server.service',
224                           'openerp-server.tools',
225                           'openerp-server.wizard',
226                           'openerp-server.workflow'] + \
227                           [('openerp-server.addons.' + name)
228                            for name, _ in find_addons()],
229       package_dir      = find_package_dirs(),
230       console = [{"script": join("bin", "openerp-server.py"),
231                   "icon_resources": [(1,join("pixmaps","openerp-icon.ico"))]
232                   }],
233       options = options,
234       )
235
236 if has_py2exe:
237   # Sometime between pytz-2008a and pytz-2008i common_timezones started to
238   # include only names of zones with a corresponding data file in zoneinfo.
239   # pytz installs the zoneinfo directory tree in the same directory
240   # as the pytz/__init__.py file. These data files are loaded using
241   # pkg_resources.resource_stream. py2exe does not copy this to library.zip so
242   # resource_stream can't find the files and common_timezones is empty when
243   # read in the py2exe executable.
244   # This manually copies zoneinfo into the zip. See also
245   # http://code.google.com/p/googletransitdatafeed/issues/detail?id=121
246   import pytz
247   import zipfile
248   # Make sure the layout of pytz hasn't changed
249   assert (pytz.__file__.endswith('__init__.pyc') or
250           pytz.__file__.endswith('__init__.py')), pytz.__file__
251   zoneinfo_dir = join(os.path.dirname(pytz.__file__), 'zoneinfo')
252   # '..\\Lib\\pytz\\__init__.py' -> '..\\Lib'
253   disk_basedir = os.path.dirname(os.path.dirname(pytz.__file__))
254   zipfile_path = join(options['py2exe']['dist_dir'], 'library.zip')
255   z = zipfile.ZipFile(zipfile_path, 'a')
256   for absdir, directories, filenames in os.walk(zoneinfo_dir):
257     assert absdir.startswith(disk_basedir), (absdir, disk_basedir)
258     zip_dir = absdir[len(disk_basedir):]
259     for f in filenames:
260       z.write(join(absdir, f), join(zip_dir, f))
261   z.close()
262