Mercurial > libervia-web
comparison setup.py @ 449:981ed669d3b3
/!\ reorganize all the file hierarchy, move the code and launching script to src:
- browser_side --> src/browser
- public --> src/browser_side/public
- libervia.py --> src/browser/libervia_main.py
- libervia_server --> src/server
- libervia_server/libervia.sh --> src/libervia.sh
- twisted --> src/twisted
- new module src/common
- split constants.py in 3 files:
- src/common/constants.py
- src/browser/constants.py
- src/server/constants.py
- output --> html (generated by pyjsbuild during the installation)
- new option/parameter "data_dir" (-d) to indicates the directory containing html and server_css
- setup.py installs libervia to the following paths:
- src/common --> <LIB>/libervia/common
- src/server --> <LIB>/libervia/server
- src/twisted --> <LIB>/twisted
- html --> <SHARE>/libervia/html
- server_side --> <SHARE>libervia/server_side
- LIBERVIA_INSTALL environment variable takes 2 new options with prompt confirmation:
- clean: remove previous installation directories
- purge: remove building and previous installation directories
You may need to update your sat.conf and/or launching script to update the following options/parameters:
- ssl_certificate
- data_dir
author | souliane <souliane@mailoo.org> |
---|---|
date | Tue, 20 May 2014 06:41:16 +0200 |
parents | f94c3caea2ba |
children | 1a0cec9b0f1e |
comparison
equal
deleted
inserted
replaced
448:14c35f7f1ef5 | 449:981ed669d3b3 |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/env python2 |
2 # -*- coding: utf-8 -*- | 2 # -*- coding: utf-8 -*- |
3 | 3 |
4 # Libervia: a Salut à Toi frontend | 4 # Libervia: a Salut à Toi frontend |
5 # Copyright (C) 2011, 2012, 2013, 2014 Jérôme Poisson <goffi@goffi.org> | 5 # Copyright (C) 2011, 2012, 2013, 2014 Jérôme Poisson (goffi@goffi.org) |
6 # Copyright (C) 2013, 2014 Adrien Cossa (souliane@mailoo.org) | |
6 | 7 |
7 # This program is free software: you can redistribute it and/or modify | 8 # This program is free software: you can redistribute it and/or modify |
8 # it under the terms of the GNU Affero General Public License as published by | 9 # it under the terms of the GNU Affero General Public License as published by |
9 # the Free Software Foundation, either version 3 of the License, or | 10 # the Free Software Foundation, either version 3 of the License, or |
10 # (at your option) any later version. | 11 # (at your option) any later version. |
24 from distutils.file_util import copy_file | 25 from distutils.file_util import copy_file |
25 import os | 26 import os |
26 import sys | 27 import sys |
27 import subprocess | 28 import subprocess |
28 from stat import ST_MODE | 29 from stat import ST_MODE |
30 import shutil | |
31 from src.server.constants import Const as C | |
29 | 32 |
30 # seen here: http://stackoverflow.com/questions/7275295 | 33 # seen here: http://stackoverflow.com/questions/7275295 |
31 try: | 34 try: |
32 from setuptools.command import egg_info | 35 from setuptools.command import egg_info |
33 egg_info.write_toplevel_names | 36 egg_info.write_toplevel_names |
50 | 53 |
51 | 54 |
52 NAME = 'libervia' | 55 NAME = 'libervia' |
53 LAUNCH_DAEMON_COMMAND = 'libervia' | 56 LAUNCH_DAEMON_COMMAND = 'libervia' |
54 | 57 |
58 ENV_LIBERVIA_INSTALL = "LIBERVIA_INSTALL" # environment variable to customise installation | |
59 NO_PREINSTALL_OPT = 'nopreinstall' # skip all preinstallation checks | |
60 AUTO_DEB_OPT = 'autodeb' # automaticaly install debs | |
61 CLEAN_OPT = 'clean' # remove previous installation directories | |
62 PURGE_OPT = 'purge' # remove building and previous installation directories | |
63 | |
55 | 64 |
56 class MercurialException(Exception): | 65 class MercurialException(Exception): |
57 pass | 66 pass |
58 | 67 |
59 | 68 |
76 sh_buffer = "" | 85 sh_buffer = "" |
77 run_dir = os.path.dirname(self.sh_script_path) | 86 run_dir = os.path.dirname(self.sh_script_path) |
78 with open(self.sh_script_path, 'r') as sh_file: | 87 with open(self.sh_script_path, 'r') as sh_file: |
79 for ori_line in sh_file: | 88 for ori_line in sh_file: |
80 if ori_line.startswith('DAEMON='): | 89 if ori_line.startswith('DAEMON='): |
81 dest_line = 'DAEMON=""\n' # we want to launch sat as a daemon | 90 dest_line = 'DAEMON=""\n' # we want to launch libervia as a daemon |
82 elif ori_line.startswith('TAP_PATH='): | 91 elif ori_line.startswith('DATA_DIR='): |
83 dest_line = 'TAP_PATH="%s/"\n' % run_dir | 92 dest_line = 'DATA_DIR="%s"\n' % self.install_data_dir |
84 elif ori_line.startswith('PYTHON='): | 93 elif ori_line.startswith('PYTHON='): |
85 dest_line = 'PYTHON="%s"\n' % sys.executable | 94 dest_line = 'PYTHON="%s"\n' % sys.executable |
86 else: | 95 else: |
87 dest_line = ori_line | 96 dest_line = ori_line |
88 sh_buffer += dest_line | 97 sh_buffer += dest_line |
91 sh_file.write(sh_buffer) | 100 sh_file.write(sh_buffer) |
92 | 101 |
93 def custom_create_links(self): | 102 def custom_create_links(self): |
94 """Create symbolic links to executables""" | 103 """Create symbolic links to executables""" |
95 # the script which launch the daemon | 104 # the script which launch the daemon |
96 links = [(self.sh_script_path, LAUNCH_DAEMON_COMMAND)] | 105 for source, dest in self.sh_script_links: |
97 for source, dest in links: | 106 dest = os.path.join(self.install_scripts, dest) |
98 dest_name, copied = copy_file(source, os.path.join(self.install_scripts, dest), link='sym') | 107 if os.path.islink(dest) and os.readlink(dest) != source: |
108 os.remove(dest) # copy_file doesn't force the link update | |
109 dest_name, copied = copy_file(source, dest, link='sym') | |
99 assert (copied) | 110 assert (copied) |
100 # we change the perm in the same way as in the original install_scripts | 111 # we change the perm in the same way as in the original install_scripts |
101 mode = ((os.stat(dest_name)[ST_MODE]) | 0555) & 07777 | 112 mode = ((os.stat(dest_name)[ST_MODE]) | 0555) & 07777 |
102 os.chmod(dest_name, mode) | 113 os.chmod(dest_name, mode) |
103 | 114 |
104 def pyjs_build(self): | 115 def pyjs_build(self): |
105 return subprocess.call('pyjsbuild libervia --no-compile-inplace -m -I %s' % self.install_lib, shell=True) | 116 """Build the browser side JS files from Python source.""" |
117 cwd = os.getcwd() | |
118 os.chdir(os.path.join('src', 'browser')) | |
119 result = subprocess.call('pyjsbuild libervia_main --no-compile-inplace -I %s -o %s' % | |
120 (self.install_lib, self.pyjamas_output_dir), shell=True) | |
121 os.chdir(cwd) | |
122 return result | |
123 | |
124 def copy_data_files(self): | |
125 """To copy the JS files couldn't be done with the data_files parameter | |
126 of setuptools.setup because all the files to be copied must exist before | |
127 the call. Also, we need the value of self.install_lib to build the JS | |
128 files (it's not easily predictable as it may vary from one system to | |
129 another), so we can't call pyjsbuild before setuptools.setup. | |
130 """ | |
131 html = os.path.join(self.install_data_dir, C.HTML_DIR) | |
132 if os.path.isdir(html): | |
133 shutil.rmtree(html, ignore_errors=True) | |
134 shutil.copytree(self.pyjamas_output_dir, html) | |
106 | 135 |
107 def run(self): | 136 def run(self): |
137 self.sh_script_path = os.path.join(self.install_lib, NAME, 'libervia.sh') | |
138 self.sh_script_links = [(self.sh_script_path, LAUNCH_DAEMON_COMMAND)] | |
139 self.install_data_dir = os.path.join(self.install_data, 'share', NAME) | |
140 self.pyjamas_output_dir = os.path.join(os.getcwd(), 'html') | |
108 sys.stdout.write('running pre installation stuff\n') | 141 sys.stdout.write('running pre installation stuff\n') |
109 sys.stdout.flush() | 142 sys.stdout.flush() |
110 build_result = self.pyjs_build() | 143 if PURGE_OPT in install_opt: |
144 self.purge() | |
145 elif CLEAN_OPT in install_opt: | |
146 self.clean() | |
147 install.run(self) | |
148 sys.stdout.write('running post installation stuff\n') | |
149 sys.stdout.flush() | |
150 build_result = self.pyjs_build() # build after libervia.common is accessible | |
111 if build_result == 127: # TODO: remove magic string | 151 if build_result == 127: # TODO: remove magic string |
112 print "pyjsbuild is not installed or not accessible from the PATH of user '%s'" % os.getenv('USERNAME') | 152 print "pyjsbuild is not installed or not accessible from the PATH of user '%s'" % os.getenv('USERNAME') |
113 return | 153 return |
114 if build_result != 0: | 154 if build_result != 0: |
115 print "pyjsbuild failed to build libervia" | 155 print "pyjsbuild failed to build libervia" |
116 return | 156 return |
117 install.run(self) | 157 self.copy_data_files() |
118 sys.stdout.write('running post installation stuff\n') | |
119 sys.stdout.flush() | |
120 self.sh_script_path = os.path.join(self.install_lib, 'libervia_server', 'libervia.sh') | |
121 self.custom_auto_options() | 158 self.custom_auto_options() |
122 self.custom_create_links() | 159 self.custom_create_links() |
123 | 160 |
124 | 161 def confirm(self, message): |
125 def preinstall_check(): | 162 """Ask the user for a confirmation""" |
163 message += 'Proceed' | |
164 while True: | |
165 res = raw_input("%s (y/n)? " % message) | |
166 if res not in ['y', 'Y', 'n', 'N']: | |
167 print "Your response ('%s') was not one of the expected responses: y, n" % res | |
168 message = 'Proceed' | |
169 continue | |
170 if res in ('y', 'Y'): | |
171 return True | |
172 return False | |
173 | |
174 def clean(self, message=None, to_remove=None): | |
175 """Clean previous installation directories | |
176 | |
177 @param message (str): to use a non-default confirmation message | |
178 @param to_remove (str): extra files/directories to remove | |
179 """ | |
180 if message is None: | |
181 message = "Cleaning previous installation directories" | |
182 if to_remove is None: | |
183 to_remove = [] | |
184 to_remove.extend([os.path.join(self.install_lib, NAME), | |
185 self.install_data_dir, | |
186 os.path.join(self.install_data, 'share', 'doc', NAME), | |
187 os.path.join(self.install_lib, "%s-py%s.egg-info" % (self.config_vars['dist_fullname'], self.config_vars['py_version_short'])), | |
188 ]) | |
189 for source, dest in self.sh_script_links: | |
190 dest = os.path.join(self.install_scripts, dest) | |
191 if os.path.islink(dest): | |
192 to_remove.append(dest) | |
193 plugin_file = os.path.join(self.install_lib, 'twisted', 'plugins', NAME) | |
194 if os.path.isfile(plugin_file): | |
195 to_remove.append(plugin_file) | |
196 | |
197 message = "%s:\n%s\n" % (message, "\n".join([" %s" % path for path in to_remove])) | |
198 if not self.confirm(message): | |
199 return | |
200 sys.stdout.write('cleaning previous installation directories...\n') | |
201 sys.stdout.flush() | |
202 for path in to_remove: | |
203 if os.path.isdir(path): | |
204 shutil.rmtree(path, ignore_errors=True) | |
205 else: | |
206 os.remove(path) | |
207 | |
208 def purge(self): | |
209 """Clean building and previous installation directories""" | |
210 message = "Cleaning building and previous installation directories" | |
211 to_remove = [os.path.join(os.getcwd(), 'build'), self.pyjamas_output_dir] | |
212 self.clean(message, to_remove) | |
213 | |
214 | |
215 def preinstall_check(install_opt): | |
126 """Check presence of problematic dependencies, and try to install them with package manager | 216 """Check presence of problematic dependencies, and try to install them with package manager |
127 This ugly stuff is necessary as distributions are not installed correctly with setuptools/distribute | 217 This ugly stuff is necessary as distributions are not installed correctly with setuptools/distribute |
128 Hope to remove this at some point""" | 218 Hope to remove this at some point""" |
129 | 219 |
130 modules_tocheck = [] # if empty this method is dummy | 220 modules_tocheck = [] # if empty this method is dummy |
136 | 226 |
137 sys.stdout.write("Running pre-installation dependencies check\n") | 227 sys.stdout.write("Running pre-installation dependencies check\n") |
138 | 228 |
139 # which modules are not installed ? | 229 # which modules are not installed ? |
140 modules_toinstall = [mod for mod in modules_tocheck if not module_installed(mod)] | 230 modules_toinstall = [mod for mod in modules_tocheck if not module_installed(mod)] |
231 """# is mercurial available ? | |
232 hg_installed = subprocess.call('which hg', stdout=open('/dev/null', 'w'), shell=True) == 0 | |
233 if not hg_installed: | |
234 modules_toinstall.append('mercurial')""" # hg can be installed from pypi | |
141 | 235 |
142 if modules_toinstall: | 236 if modules_toinstall: |
143 # are we on a distribution using apt ? | 237 if AUTO_DEB_OPT in install_opt: # auto debian installation is requested |
144 apt_path = subprocess.Popen('which apt-get', stdout=subprocess.PIPE, shell=True).communicate()[0][:-1] | 238 # are we on a distribution using apt ? |
239 apt_path = subprocess.Popen('which apt-get', stdout=subprocess.PIPE, shell=True).communicate()[0][:-1] | |
240 else: | |
241 apt_path = None | |
242 | |
145 not_installed = set() | 243 not_installed = set() |
146 if apt_path: | 244 if apt_path: |
147 # we have apt, we'll try to use it | 245 # we have apt, we'll try to use it |
148 for module_name in modules_toinstall: | 246 for module_name in modules_toinstall: |
149 package_name = package[module_name] | 247 package_name = package[module_name] |
162 sys.exit(2) | 260 sys.exit(2) |
163 | 261 |
164 | 262 |
165 if sys.argv[1].lower() in ['egg_info', 'install']: | 263 if sys.argv[1].lower() in ['egg_info', 'install']: |
166 # we only check dependencies if egg_info or install is used | 264 # we only check dependencies if egg_info or install is used |
167 install_opt = os.environ.get("LIBERVIA_INSTALL", "") | 265 install_opt = os.environ.get(ENV_LIBERVIA_INSTALL, "").split() |
168 if not "nopreinstall" in install_opt: # user can force preinstall skipping | 266 if not NO_PREINSTALL_OPT in install_opt: # user can force preinstall skipping |
169 preinstall_check() | 267 preinstall_check(install_opt) |
170 | 268 |
171 setup(name=NAME, | 269 setup(name=NAME, |
172 version='0.4.0', | 270 version='0.4.0', |
173 description=u'Web frontend for Salut à Toi', | 271 description=u'Web frontend for Salut à Toi', |
174 long_description=u'Libervia is a web frontend for Salut à Toi (SàT), a multi-frontends and multi-purposes XMPP client.', | 272 long_description=u'Libervia is a web frontend for Salut à Toi (SàT), a multi-frontends and multi-purposes XMPP client.', |
179 'Environment :: Web Environment', | 277 'Environment :: Web Environment', |
180 'Framework :: Twisted', | 278 'Framework :: Twisted', |
181 'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)', | 279 'License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)', |
182 'Operating System :: POSIX :: Linux', | 280 'Operating System :: POSIX :: Linux', |
183 'Topic :: Communications :: Chat'], | 281 'Topic :: Communications :: Chat'], |
184 package_dir={'libervia': '.', 'libervia_server': 'libervia_server'}, | 282 package_dir={'libervia': 'src', 'twisted.plugins': 'src/twisted/plugins'}, |
185 packages=['libervia', 'libervia.output', 'libervia_server', 'twisted.plugins'], | 283 packages=['libervia', 'libervia.common', 'libervia.server', 'twisted.plugins'], |
186 package_data={'libervia': ['libervia.py'], 'libervia.output': ['**/*.*'], 'libervia_server': ['libervia.sh']}, | 284 package_data={'libervia': ['libervia.sh']}, |
187 data_files=[('share/doc/%s' % NAME, ['COPYING', 'README'])], | 285 data_files=[(os.path.join('share', 'doc', NAME), ['COPYING', 'README', 'INSTALL']), |
286 (os.path.join('share', NAME, C.SERVER_CSS_DIR), [os.path.join(C.SERVER_CSS_DIR, filename) for filename in os.listdir(C.SERVER_CSS_DIR)]), | |
287 ], | |
188 scripts=[], | 288 scripts=[], |
189 zip_safe=False, | 289 zip_safe=False, |
190 dependency_links=['http://www.blarg.net/%7Esteveha/pyfeed-0.7.4.tar.gz', 'http://www.blarg.net/%7Esteveha/xe-0.7.4.tar.gz'], | 290 dependency_links=['http://www.blarg.net/%7Esteveha/pyfeed-0.7.4.tar.gz', 'http://www.blarg.net/%7Esteveha/xe-0.7.4.tar.gz'], |
191 install_requires=['sat', 'twisted', 'pyfeed', 'xe', 'txJSON-RPC', 'zope.interface', 'pyopenssl'], | 291 install_requires=['sat', 'twisted', 'pyfeed', 'xe', 'txJSON-RPC', 'zope.interface', 'pyopenssl'], |
192 cmdclass={'install': CustomInstall}, | 292 cmdclass={'install': CustomInstall}, |
193 ) | 293 ) |
194 |