[FIX] Set IP checking off for sessions
[cds-indico.git] / setup.py
blobcb739410f5bdf8afb2c382829916192a2764964b
1 # -*- coding: utf-8 -*-
2 ##
3 ##
4 ## This file is part of Indico
5 ## Copyright (C) 2002 - 2012 European Organization for Nuclear Research (CERN)
6 ##
7 ## Indico is free software: you can redistribute it and/or
8 ## modify it under the terms of the GNU General Public License as
9 ## published by the Free Software Foundation, either version 3 of the
10 ## License, or (at your option) any later version.
12 ## Indico is distributed in the hope that it will be useful, but
13 ## WITHOUT ANY WARRANTY; without even the implied warranty of
14 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ## GNU General Public License for more details.
17 ## You should have received a copy of the GNU General Public License
18 ## along with Indico. If not, see <http://www.gnu.org/licenses/>.
20 # Autoinstalls setuptools if the user doesn't have them already
21 import ez_setup
22 ez_setup.use_setuptools()
24 import commands
25 import getopt
26 import os
27 import re
28 import shutil
29 import string
30 import sys
31 import itertools
32 from distutils.sysconfig import get_python_lib, get_python_version
33 from distutils.cmd import Command
34 from distutils.command import bdist
35 from indico.util import i18n
38 import pkg_resources
39 from setuptools.command import develop, install, sdist, bdist_egg, easy_install, test
40 from setuptools import setup, find_packages, findall
43 try:
44 from babel.messages import frontend as babel
45 BABEL_PRESENT = True
46 except ImportError:
47 BABEL_PRESENT = False
50 DEPENDENCY_URLS = ["http://indico-software.org/wiki/Admin/Installation/IndicoExtras",
51 "https://github.com/collective/icalendar/tarball/6f899869d462a23d0ebd3f54fb237e8670242bc4#egg=icalendar-3.0"]
53 DEVELOP_REQUIRES = ['pojson>=0.4', 'termcolor']
55 if sys.platform == 'linux2':
56 import pwd
57 import grp
60 class vars(object):
61 '''Variable holder.'''
62 packageDir = None
63 versionVal = 'None'
64 accessuser = None
65 accessgroup = None
66 dbInstalledBySetupPy = False
67 binDir = None
68 documentationDir = None
69 configurationDir = None
70 htdocsDir = None
72 ### Methods required by setup() ##############################################
74 def _generateDataPaths(x):
76 dataFilesDict = {}
78 for (baseDstDir, srcDir) in x:
79 for f in findall(srcDir):
80 dst_dir = os.path.join(baseDstDir,
81 os.path.relpath(os.path.dirname(f), srcDir))
82 if dst_dir not in dataFilesDict:
83 dataFilesDict[dst_dir] = []
84 dataFilesDict[dst_dir].append(f)
86 dataFiles = []
87 for k, v in dataFilesDict.items():
88 dataFiles.append((k, v))
90 return dataFiles
92 def _getDataFiles(x):
93 """
94 Returns a fully populated data_files ready to be fed to setup()
96 WARNING: when creating a bdist_egg we need to include files inside bin,
97 doc, config & htdocs into the egg therefore we cannot fetch indico.conf
98 values directly because they will not refer to the proper place. We
99 include those files in the egg's root folder.
102 # setup expects a list like this (('foo/bar/baz', 'wiki.py'),
103 # ('a/b/c', 'd.jpg'))
105 # What we do below is transform a list like this:
106 # (('foo', 'bar/baz/wiki.py'),
107 # ('a', 'b/c/d.jpg'))
109 # first into a dict and then into a pallatable form for setuptools.
111 # This re will be used to filter out etc/*.conf files and therefore not overwritting them
112 dataFiles = _generateDataPaths((('bin', 'bin'),
113 ('doc', 'doc'),
114 ('etc', 'etc')))
115 return dataFiles
118 def _getInstallRequires():
119 '''Returns external packages required by Indico
121 These are the ones needed for runtime.'''
123 base = ['ZODB3>=3.8', 'pytz', 'zope.index', 'zope.interface',
124 'lxml', 'cds-indico-extras', 'zc.queue', 'python-dateutil<2.0',
125 'pypdf', 'mako>=0.4.1', 'babel', 'icalendar>=3.0', 'pyatom',
126 'simplejson', 'python-cjson', 'cssmin', 'webassets',
127 'pojson>=0.4', 'requests']
129 #for Python older than 2.7
130 if sys.version_info[0] <= 2 and sys.version_info[1] < 7:
131 base.append('argparse')
133 return base
136 def _versionInit():
137 '''Retrieves the version number from indico/MaKaC/__init__.py and returns it'''
139 from indico.MaKaC import __version__
140 v = __version__
142 print('Indico %s' % v)
144 return v
147 ### Commands ###########################################################
148 class sdist_indico(sdist.sdist):
149 user_options = sdist.sdist.user_options + \
150 [('version=', None, 'version to distribute')]
151 version = 'dev'
153 def run(self):
154 sdist.sdist.run(self)
157 def _bdist_indico(dataFiles):
158 class bdist_indico(bdist.bdist):
159 def run(self):
160 compileAllLanguages(self)
161 bdist.bdist.run(self)
163 bdist_indico.dataFiles = dataFiles
164 return bdist_indico
167 def _bdist_egg_indico(dataFiles):
168 class bdist_egg_indico(bdist_egg.bdist_egg):
169 def run(self):
170 compileAllLanguages(self)
171 bdist_egg.bdist_egg.run(self)
173 bdist_egg_indico.dataFiles = dataFiles
174 return bdist_egg_indico
177 class develop_indico(develop.develop):
178 def run(self):
179 develop.develop.run(self)
181 # create symlink to legacy MaKaC dir
182 # this is so that the ".egg-link" created by the "develop" command works
183 if sys.platform in ["linux2", "darwin"] and not os.path.exists('MaKaC'):
184 os.symlink('indico/MaKaC','MaKaC')
187 class develop_config(develop_indico):
188 description = "prepares the current directory for Indico development"
189 user_options = develop.develop.user_options + [('www-uid=', None, "Set user for cache/log/db (typically apache user)"),
190 ('www-gid=', None, "Set group for cache/log/db (typically apache group)")]
192 www_uid = None
193 www_gid = None
195 def run(self):
196 # dependencies, links, etc...
197 develop_indico.run(self)
199 env = pkg_resources.Environment()
200 easy_install.main(DEVELOP_REQUIRES)
201 env.scan()
203 local = 'etc/indico.conf'
204 if os.path.exists(local):
205 print 'Upgrading existing etc/indico.conf..'
206 upgrade_indico_conf(local, 'etc/indico.conf.sample')
207 else:
208 print 'Creating new etc/indico.conf..'
209 shutil.copy('etc/indico.conf.sample', local)
211 for f in [x for x in ('etc/zdctl.conf', 'etc/zodb.conf', 'etc/logging.conf') if not os.path.exists(x)]:
212 shutil.copy('%s.sample' % f, f)
214 print """\nIndico needs to store some information in the filesystem (database, cache, temporary files, logs...)
215 Please specify the directory where you'd like it to be placed.
216 (Note that putting it outside of your sourcecode tree is recommended)"""
217 prefixDirDefault = os.path.dirname(os.getcwd())
218 prefixDir = raw_input('[%s]: ' % prefixDirDefault).strip()
220 if prefixDir == '':
221 prefixDir = prefixDirDefault
223 directories = dict((d, os.path.join(prefixDir, d)) for d in
224 ['db', 'log', 'tmp', 'cache', 'archive'])
226 print 'Creating directories...',
227 for d in directories.values():
228 if not os.path.exists(d):
229 os.makedirs(d)
230 print 'Done!'
232 directories['htdocs'] = os.path.join(os.getcwd(), 'indico', 'htdocs')
233 directories['bin'] = os.path.join(os.getcwd(), 'bin')
234 directories['etc'] = os.path.join(os.getcwd(), 'etc')
235 directories['doc'] = os.path.join(os.getcwd(), 'doc')
237 self._update_conf_dir_paths(local, directories)
239 directories.pop('htdocs') #avoid modifying the htdocs folder permissions (it brings problems with git)
241 from MaKaC.consoleScripts.installBase import _databaseText, _findApacheUserGroup, _checkDirPermissions, _updateDbConfigFiles, _updateMaKaCEggCache
243 user = ''
245 sourcePath = os.getcwd()
247 # find the apache user/group
248 user, group = _findApacheUserGroup(self.www_uid, self.www_gid)
249 _checkDirPermissions(directories, dbInstalledBySetupPy=directories['db'], accessuser=user, accessgroup=group)
251 _updateDbConfigFiles(directories['db'], directories['log'], os.path.join(sourcePath, 'etc'), directories['tmp'], user)
253 _updateMaKaCEggCache(os.path.join(os.path.dirname(__file__), 'indico', 'MaKaC', '__init__.py'), directories['tmp'])
255 updateIndicoConfPathInsideMaKaCConfig(os.path.join(os.path.dirname(__file__), ''), 'indico/MaKaC/common/MaKaCConfig.py')
256 compileAllLanguages(self)
257 print '''
259 ''' % _databaseText('etc')
261 def _update_conf_dir_paths(self, filePath, dirs):
262 fdata = open(filePath).read()
263 for dir in dirs.items():
264 d = dir[1].replace("\\","/") # For Windows users
265 fdata = re.sub('\/opt\/indico\/%s'%dir[0], d, fdata)
266 open(filePath, 'w').write(fdata)
268 class test_indico(test.test):
270 Test command for Indico
273 description = "Test Suite Framework"
274 user_options = test.test.user_options + [('specify=', None, "Use nosetests style (file.class:testcase)"),
275 ('coverage', None, "Output coverage report in html"),
276 ('unit', None, "Run only Unit tests"),
277 ('functional', None, "Run only Functional tests"),
278 ('pylint', None, "Run python source analysis"),
279 ('jsunit', None, "Run js unit tests"),
280 ('jslint', None, "Run js source analysis"),
281 ('jscoverage', None, "Output coverage report in html for js"),
282 ('jsspecify=', None, "Use js-test-driver style (TestCaseName.testName)"),
283 ('log=', None, "Log to console, using specified level"),
284 ('browser=', None, "Browser to use for functional tests"),
285 ('mode=', None, "Mode to use for functional tests"),
286 ('server-url=', None, "Server URL to use for functional tests"),
287 ('xml', None, "XML output"),
288 ('html', None, "Make an HTML report (when possible)"),
289 ('record', None, "Record tests (for --functional)"),
290 ('silent', None, "Don't output anything in the console, just generate the report"),
291 ('killself', None, "Kill this script right after the tests finished without waiting for db shutdown.")]
292 boolean_options = []
294 specify = None
295 coverage = False
296 unit = False
297 functional = False
298 browser = None
299 pylint = False
300 jsunit = False
301 jslint = False
302 jscoverage = False
303 jsspecify = None
304 silent = False
305 mode = None
306 server_url = None
307 killself = False
308 html = False
309 record = False
310 log = False
311 xml = False
313 def _wrap(self, func, *params):
314 def wrapped():
315 self.res = func(*params)
316 self.with_project_on_sys_path(wrapped)
317 return self.res
319 def finalize_options(self):
320 testsToRun = []
322 allTests = ['unit', 'functional']
324 for testType in allTests:
325 if getattr(self, testType):
326 testsToRun.append(testType)
328 if self.jsspecify and 'jsunit' not in testsToRun:
329 testsToRun.append('jsunit')
331 if testsToRun == []:
332 testsToRun = allTests
333 self.testsToRun = testsToRun
335 def run(self):
337 if self.distribution.install_requires:
338 self.distribution.fetch_build_eggs(self.distribution.install_requires)
339 if self.distribution.tests_require:
340 self.distribution.fetch_build_eggs(self.distribution.tests_require)
342 from indico.tests import TestManager
344 options = {'silent': self.silent,
345 'killself': self.killself,
346 'html': self.html,
347 'browser': self.browser,
348 'mode': self.mode,
349 'specify': self.specify,
350 'coverage': self.coverage,
351 'record': self.record,
352 'server_url': self.server_url,
353 'log': self.log,
354 'xml':self.xml}
356 # get only options that are active
357 options = dict((k,v) for (k,v) in options.iteritems() if v)
359 manager = TestManager()
360 result = self._wrap(manager.main, self.testsToRun, options)
362 sys.exit(result)
364 def download(self, url, path):
365 """Copy the contents of a file from a given URL
366 to a local file.
368 import urllib
369 webFile = urllib.urlopen(url)
370 localFile = open(os.path.join(path, url.split('/')[-1]), 'w')
371 localFile.write(webFile.read())
372 webFile.close()
373 localFile.close()
375 def unzip(self, zipPath, inZipPath, targetFile):
376 """extract the needed file from zip and then delete the zip"""
377 import zipfile
378 try:
379 zfobj = zipfile.ZipFile(zipPath)
380 outfile = open(targetFile, 'wb')
381 outfile.write(zfobj.read(inZipPath))
382 outfile.flush()
383 outfile.close()
385 #delete zip file
386 os.unlink(zipPath)
387 except NameError, e:
388 print e
391 class egg_filename(Command):
392 description = "Get the file name of the generated egg"
393 user_options = []
394 boolean_options = []
396 def initialize_options(self):
397 pass
399 def finalize_options(self):
400 ei_cmd = self.ei_cmd = self.get_finalized_command("egg_info")
401 self.egg_info = ei_cmd.egg_info
403 basename = pkg_resources.Distribution(
404 None, None, ei_cmd.egg_name, ei_cmd.egg_version,
405 get_python_version(),
406 self.distribution.has_ext_modules() and pkg_utils.get_build_platform
407 ).egg_name()
409 print basename
412 def run(self):
413 pass
416 if __name__ == '__main__':
417 # Always load source from the current folder
418 sys.path = [os.path.abspath('indico')] + sys.path
420 #PWD_INDICO_CONF = 'etc/indico.conf'
421 #if not os.path.exists(PWD_INDICO_CONF):
422 # shutil.copy('etc/indico.conf.sample', PWD_INDICO_CONF)
424 from MaKaC.consoleScripts.installBase import *
427 #Dirty trick: For running tests, we need to load all the modules and get rid of unnecessary outputs
428 tempLoggingDir = None
429 if 'test' in sys.argv:
430 import logging
431 import tempfile
432 tempLoggingDir = tempfile.mkdtemp()
433 logging.basicConfig(filename=os.path.join(tempLoggingDir, 'logging'),
434 level=logging.DEBUG)
435 setIndicoInstallMode(False)
436 else:
437 setIndicoInstallMode(True)
439 x = vars()
440 x.packageDir = os.path.join(get_python_lib(), 'MaKaC')
443 x.binDir = 'bin'
444 x.documentationDir = 'doc'
445 x.configurationDir = 'etc'
446 x.htdocsDir = 'htdocs'
448 dataFiles = _getDataFiles(x)
450 foundPackages = list('MaKaC.%s' % pkg for pkg in
451 find_packages(where = 'indico/MaKaC'))
452 foundPackages.append('MaKaC')
453 foundPackages.append('htdocs')
455 # add our namespace package
456 foundPackages += list('indico.%s' % pkg for pkg in
457 find_packages(where = 'indico',
458 exclude = ['htdocs*', 'MaKaC*']))
459 foundPackages.append('indico')
461 cmdclass = {'sdist': sdist_indico,
462 'bdist': _bdist_indico(dataFiles),
463 'bdist_egg': _bdist_egg_indico(dataFiles),
464 'develop_config': develop_config,
465 'develop': develop_indico,
466 'test': test_indico,
467 'egg_filename': egg_filename
470 if BABEL_PRESENT:
471 for cmdname in ['init_catalog', 'extract_messages', 'compile_catalog', 'update_catalog']:
472 cmdclass['%s_js' % cmdname] = getattr(babel, cmdname)
473 cmdclass['compile_catalog_js'] = i18n.generate_messages_js
475 setup(name = "indico",
476 cmdclass = cmdclass,
477 version = _versionInit(),
478 description = "Indico is a full-featured conference lifecycle management and meeting/lecture scheduling tool",
479 author = "Indico Team",
480 author_email = "indico-team@cern.ch",
481 url = "http://indico-software.org",
482 download_url = "http://indico-software.org/wiki/Releases/Indico0.98-rc1",
483 platforms = ["any"],
484 long_description = "Indico allows you to schedule conferences, from single talks to complex meetings with sessions and contributions. It also includes an advanced user delegation mechanism, allows paper reviewing, archival of conference information and electronic proceedings",
485 license = "http://www.gnu.org/licenses/gpl-2.0.txt",
486 entry_points = """
487 [console_scripts]
489 indico_scheduler = indico.modules.scheduler.daemon_script:main
490 indico_initial_setup = MaKaC.consoleScripts.indicoInitialSetup:main
491 indico_ctl = MaKaC.consoleScripts.indicoCtl:main
492 indico_livesync = indico.ext.livesync.console:main
493 indico_shell = indico.util.shell:main
495 [indico.ext_types]
497 statistics = indico.ext.statistics
498 Collaboration = MaKaC.plugins.Collaboration
499 InstantMessaging = MaKaC.plugins.InstantMessaging
500 RoomBooking = MaKaC.plugins.RoomBooking
501 EPayment = MaKaC.plugins.EPayment
502 livesync = indico.ext.livesync
503 importer = indico.ext.importer
505 [indico.ext]
507 statistics.piwik = indico.ext.statistics.piwik
509 Collaboration.EVO = MaKaC.plugins.Collaboration.EVO
510 Collaboration.Vidyo = MaKaC.plugins.Collaboration.Vidyo
511 Collaboration.CERNMCU = MaKaC.plugins.Collaboration.CERNMCU
512 Collaboration.RecordingManager = MaKaC.plugins.Collaboration.RecordingManager
513 Collaboration.RecordingRequest = MaKaC.plugins.Collaboration.RecordingRequest
514 Collaboration.WebcastRequest = MaKaC.plugins.Collaboration.WebcastRequest
516 RoomBooking.CERN = MaKaC.plugins.RoomBooking.CERN
517 RoomBooking.default = MaKaC.plugins.RoomBooking.default
519 EPayment.payPal = MaKaC.plugins.EPayment.payPal
520 EPayment.worldPay = MaKaC.plugins.EPayment.worldPay
521 EPayment.yellowPay = MaKaC.plugins.EPayment.yellowPay
522 EPayment.skipjack = MaKaC.plugins.EPayment.skipjack
524 importer.invenio = indico.ext.importer.invenio
525 importer.dummy = indico.ext.importer.dummy
527 InstantMessaging.XMPP = MaKaC.plugins.InstantMessaging.XMPP
529 livesync.invenio = indico.ext.livesync.invenio
530 livesync.cern_search = indico.ext.livesync.cern_search
532 """,
533 zip_safe = False,
534 packages = foundPackages,
535 package_dir = { 'indico': 'indico',
536 'htdocs': os.path.join('indico', 'htdocs'),
537 'MaKaC' : os.path.join('indico', 'MaKaC')},
538 package_data = {'indico': ['*.*']},
539 include_package_data=True,
540 namespace_packages = ['indico', 'indico.ext'],
541 install_requires = _getInstallRequires(),
542 tests_require = ['nose', 'rednose', 'twill', 'selenium', 'figleaf'],
543 data_files = dataFiles,
544 dependency_links = DEPENDENCY_URLS
547 #delete the temp folder used for logging
548 if 'test' in sys.argv:
549 shutil.rmtree(tempLoggingDir)