[IMP]: improvement in trigger server action
[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
38 has_py2exe = False
39 if os.name == 'nt':
40     import py2exe
41     has_py2exe = True
42
43 sys.path.append(join(os.path.abspath(os.path.dirname(__file__)), "bin"))
44
45 execfile(join('bin', 'release.py'))
46
47 if sys.argv[1] == 'bdist_rpm':
48     version = version.split('-')[0]
49
50 # get python short version
51 py_short_version = '%s.%s' % sys.version_info[:2]
52
53 required_modules = [
54     ('lxml', 'lxml module: pythonic libxml2 and libxslt bindings'),
55     ('mako', 'Mako template engine'),
56     ('dateutil', "Extensions to the standard datetime module"),
57     ('psycopg2', 'PostgreSQL module'),
58     ('pychart', 'pychart module'),
59     ('pydot', 'pydot module'),
60     ('pytz', 'Timezone handling library for Python'),
61     ('reportlab', 'reportlab module'),
62     ('yaml', 'YAML parser and emitter for Python'),
63 ]
64
65 def check_modules():
66     errors = []
67     for modname, desc in required_modules:
68         try:
69             imp.find_module(modname)
70         except ImportError:
71             errors.append(
72                 'Error: python module %s (%s) is required' % (modname, desc))
73
74     if errors:
75         print '\n'.join(errors)
76         sys.exit(1)
77
78 def find_addons():
79     for root, _, names in os.walk(join('bin', 'addons')):
80         if '__terp__.py' in names:
81             yield basename(root), root
82     #look for extra modules
83     try:
84         empath = os.getenv('EXTRA_MODULES_PATH', '../addons/')
85         for mname in open(join(empath, 'server_modules.list')):
86             mname = mname.strip()
87             if not mname:
88                 continue
89             if os.path.exists(join(empath, mname, '__terp__.py')):
90                 yield mname, join(empath, mname)
91             else:
92                 print "Module %s specified, but no valid path." % mname
93     except:
94         pass
95
96 def data_files():
97     '''Build list of data files to be installed'''
98     files = []
99     if os.name == 'nt':
100         for root, _, names in os.walk(join('bin','addons')):
101             files.append((root, [join(root, name) for name in names]))
102         for root, _, names in os.walk('doc'):
103             files.append((root, [join(root, name) for name in names]))
104         files.append(('.', [join('bin', 'import_xml.rng'),
105                             join('bin', 'server.pkey'),
106                             join('bin', 'server.cert')]))
107     else:
108         man_directory = join('share', 'man')
109         files.append((join(man_directory, 'man1'), ['man/openerp-server.1']))
110         files.append((join(man_directory, 'man5'), ['man/openerp_serverrc.5']))
111
112         doc_directory = join('share', 'doc', 'openerp-server-%s' % version)
113         files.append((doc_directory, filter(isfile, glob.glob('doc/*'))))
114         files.append((join(doc_directory, 'migrate', '3.3.0-3.4.0'),
115                       filter(isfile, glob.glob('doc/migrate/3.3.0-3.4.0/*'))))
116         files.append((join(doc_directory, 'migrate', '3.4.0-4.0.0'),
117                       filter(isfile, glob.glob('doc/migrate/3.4.0-4.0.0/*'))))
118
119         openerp_site_packages = join('lib', 'python%s' % py_short_version, 'site-packages', 'openerp-server')
120
121         files.append((openerp_site_packages, [join('bin', 'import_xml.rng'),
122                                               join('bin', 'server.pkey'),
123                                               join('bin', 'server.cert')]))
124
125         if sys.version_info[0:2] == (2,5):
126             files.append((openerp_site_packages, [ join('python25-compat','BaseHTTPServer.py'),
127                                                    join('python25-compat','SimpleXMLRPCServer.py'),
128                                                    join('python25-compat','SocketServer.py')]))
129
130         for addonname, add_path in find_addons():
131             addon_path = join('lib', 'python%s' % py_short_version, 'site-packages', 'openerp-server','addons', addonname)
132             for root, dirs, innerfiles in os.walk(add_path):
133                 innerfiles = filter(lambda fil: os.path.splitext(fil)[1] not in ('.pyc', '.pyd', '.pyo'), innerfiles)
134                 if innerfiles:
135                     res = os.path.normpath(join(addon_path, root.replace(join(add_path), '.')))
136                     files.extend(((res, map(lambda fil: join(root, fil),
137                                             innerfiles)),))
138
139     return files
140
141 if not os.getenv('NO_CHECK_MODULES') :
142     check_modules()
143
144 f = file('openerp-server','w')
145 f.write("""#!/bin/sh
146 echo "Error: the content of this file should have been replaced during "
147 echo "installation\n"
148 exit 1
149 """)
150 f.close()
151
152 def find_package_dirs():
153     package_dirs = {'openerp-server': 'bin'}
154     for mod, path in find_addons():
155         package_dirs['openerp-server.addons.' + mod] = path
156     return package_dirs
157
158 class openerp_server_install(install):
159     def run(self):
160         # create startup script
161         start_script = "#!/bin/sh\ncd %s\nexec %s ./openerp-server.py $@\n"\
162             % (join(self.install_libbase, "openerp-server"), sys.executable)
163         # write script
164         f = open('openerp-server', 'w')
165         f.write(start_script)
166         f.close()
167         install.run(self)
168
169 options = {
170     "py2exe": {
171         "compressed": 1,
172         "optimize": 2,
173         "dist_dir": 'dist',
174         "packages": ["lxml", "lxml.builder", "lxml._elementpath", "lxml.etree",
175                      "lxml.objectify", "decimal", "xml", "encodings",
176                      "dateutil", "wizard", "pychart", "PIL", "pyparsing",
177                      "pydot", "asyncore","asynchat", "reportlab", "vobject",
178                      "HTMLParser", "select", "yaml"],
179         "excludes" : ["Tkconstants","Tkinter","tcl"],
180     }
181 }
182
183 setup(name             = name,
184       version          = version,
185       description      = description,
186       long_description = long_desc,
187       url              = url,
188       author           = author,
189       author_email     = author_email,
190       classifiers      = filter(None, classifiers.split("\n")),
191       license          = license,
192       data_files       = data_files(),
193       cmdclass         = {
194             'install' : openerp_server_install,
195       },
196       scripts          = ['openerp-server'],
197       packages         = ['openerp-server',
198                           'openerp-server.addons',
199                           'openerp-server.ir',
200                           'openerp-server.osv',
201                           'openerp-server.pychart',
202                           'openerp-server.pychart.afm',
203                           'openerp-server.report',
204                           'openerp-server.report.printscreen',
205                           'openerp-server.report.pyPdf',
206                           'openerp-server.report.render',
207                           'openerp-server.report.render.html2html',
208                           'openerp-server.report.render.makohtml2html',
209                           'openerp-server.report.render.odt2odt',
210                           'openerp-server.report.render.rml2html',
211                           'openerp-server.report.render.rml2pdf',
212                           'openerp-server.report.render.rml2txt',
213                           'openerp-server.service',
214                           'openerp-server.tools',
215                           'openerp-server.wizard',
216                           'openerp-server.workflow'] + \
217                           [('openerp-server.addons.' + name)
218                            for name, _ in find_addons()],
219       package_dir      = find_package_dirs(),
220       console = [{"script": join("bin", "openerp-server.py"),
221                   "icon_resources": [(1,join("pixmaps","openerp-icon.ico"))]
222                   }],
223       options = options,
224       )
225
226 if has_py2exe:
227   # Sometime between pytz-2008a and pytz-2008i common_timezones started to
228   # include only names of zones with a corresponding data file in zoneinfo.
229   # pytz installs the zoneinfo directory tree in the same directory
230   # as the pytz/__init__.py file. These data files are loaded using
231   # pkg_resources.resource_stream. py2exe does not copy this to library.zip so
232   # resource_stream can't find the files and common_timezones is empty when
233   # read in the py2exe executable.
234   # This manually copies zoneinfo into the zip. See also
235   # http://code.google.com/p/googletransitdatafeed/issues/detail?id=121
236   import pytz
237   import zipfile
238   # Make sure the layout of pytz hasn't changed
239   assert (pytz.__file__.endswith('__init__.pyc') or
240           pytz.__file__.endswith('__init__.py')), pytz.__file__
241   zoneinfo_dir = join(os.path.dirname(pytz.__file__), 'zoneinfo')
242   # '..\\Lib\\pytz\\__init__.py' -> '..\\Lib'
243   disk_basedir = os.path.dirname(os.path.dirname(pytz.__file__))
244   zipfile_path = join(options['py2exe']['dist_dir'], 'library.zip')
245   z = zipfile.ZipFile(zipfile_path, 'a')
246   for absdir, directories, filenames in os.walk(zoneinfo_dir):
247     assert absdir.startswith(disk_basedir), (absdir, disk_basedir)
248     zip_dir = absdir[len(disk_basedir):]
249     for f in filenames:
250       z.write(join(absdir, f), join(zip_dir, f))
251   z.close()
252