[DEL] Remove obsolete presentation/Ui/Draw/*.js
[cds-indico.git] / setup.py
blob3404b23863fe33bd7d1faebcd8d59645636b34a3
1 # -*- coding: utf-8 -*-
2 ##
3 ##
4 ## This file is part of CDS Indico.
5 ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN.
6 ##
7 ## CDS 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 2 of the
10 ## License, or (at your option) any later version.
12 ## CDS 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 GNU
15 ## General Public License for more details.
17 ## You should have received a copy of the GNU General Public License
18 ## along with CDS Indico; if not, write to the Free Software Foundation, Inc.,
19 ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21 # Autoinstalls setuptools if the user doesn't have them already
22 import ez_setup
23 ez_setup.use_setuptools()
25 import commands
26 import getopt
27 import os
28 import re
29 import shutil
30 import string
31 import sys
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
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 EXTRA_RESOURCES_URL = "http://indico-software.org/wiki/Admin/Installation/IndicoExtras"
52 if sys.platform == 'linux2':
53 import pwd
54 import grp
57 class vars(object):
58 '''Variable holder.'''
59 packageDir = None
60 versionVal = 'None'
61 accessuser = None
62 accessgroup = None
63 dbInstalledBySetupPy = False
64 binDir = None
65 documentationDir = None
66 configurationDir = None
67 htdocsDir = None
69 ### Methods required by setup() ##############################################
71 def _generateDataPaths(x):
73 dataFilesDict = {}
75 for (baseDstDir, srcDir) in x:
76 for f in findall(srcDir):
77 dst_dir = os.path.join(baseDstDir,
78 os.path.relpath(os.path.dirname(f), srcDir))
79 if dst_dir not in dataFilesDict:
80 dataFilesDict[dst_dir] = []
81 dataFilesDict[dst_dir].append(f)
83 dataFiles = []
84 for k, v in dataFilesDict.items():
85 dataFiles.append((k, v))
87 return dataFiles
89 def _getDataFiles(x):
90 """
91 Returns a fully populated data_files ready to be fed to setup()
93 WARNING: when creating a bdist_egg we need to include files inside bin,
94 doc, config & htdocs into the egg therefore we cannot fetch indico.conf
95 values directly because they will not refer to the proper place. We
96 include those files in the egg's root folder.
97 """
99 # setup expects a list like this (('foo/bar/baz', 'wiki.py'),
100 # ('a/b/c', 'd.jpg'))
102 # What we do below is transform a list like this:
103 # (('foo', 'bar/baz/wiki.py'),
104 # ('a', 'b/c/d.jpg'))
106 # first into a dict and then into a pallatable form for setuptools.
108 # This re will be used to filter out etc/*.conf files and therefore not overwritting them
109 dataFiles = _generateDataPaths((('bin', 'bin'),
110 ('doc', 'doc'),
111 ('etc', 'etc')))
112 return dataFiles
115 def _getInstallRequires():
116 '''Returns external packages required by Indico
118 These are the ones needed for runtime.'''
120 base = ['ZODB3>=3.8', 'pytz', 'zope.index', 'zope.interface',
121 'lxml', 'cds-indico-extras', 'zc.queue', 'python-dateutil<2.0',
122 'pypdf', 'mako>=0.4.1', 'babel', 'icalendar', 'pyatom',
123 'simplejson']
125 #for Python older than 2.7
126 if sys.version_info[0] <= 2 and sys.version_info[1] < 7:
127 base.append('argparse')
129 return base
132 def _versionInit():
133 '''Retrieves the version number from indico/MaKaC/__init__.py and returns it'''
135 from indico.MaKaC import __version__
136 v = __version__
138 print('Indico %s' % v)
140 return v
142 ### Commands ###########################################################
143 class sdist_indico(sdist.sdist):
144 user_options = sdist.sdist.user_options + \
145 [('version=', None, 'version to distribute')]
146 version = 'dev'
148 def run(self):
149 global x
150 sdist.sdist.run(self)
153 class jsdist_indico:
154 def jsCompress(self):
155 from MaKaC.consoleScripts.installBase import jsCompress
156 jsCompress()
159 def _bdist_indico(dataFiles):
160 class bdist_indico(bdist.bdist, jsdist_indico):
161 def run(self):
162 self.jsCompress()
163 compileAllLanguages(self)
164 bdist.bdist.run(self)
166 bdist_indico.dataFiles = dataFiles
167 return bdist_indico
170 def _bdist_egg_indico(dataFiles):
171 class bdist_egg_indico(bdist_egg.bdist_egg, jsdist_indico):
172 def run(self):
173 self.jsCompress()
174 compileAllLanguages(self)
175 bdist_egg.bdist_egg.run(self)
177 bdist_egg_indico.dataFiles = dataFiles
178 return bdist_egg_indico
181 class jsbuild(Command):
182 description = "minifies and packs javascript files"
183 user_options = []
184 boolean_options = []
186 def initialize_options(self):
187 pass
189 def finalize_options(self):
190 pass
192 def run(self):
193 from MaKaC.consoleScripts.installBase import jsCompress
194 jsCompress()
196 class fetchdeps:
197 def run(self):
198 print "Checking if dependencies need to be installed..."
200 wset = pkg_resources.working_set
202 wset.resolve(map(pkg_resources.Requirement.parse,
203 filter(lambda x: x != None, _getInstallRequires())),
204 installer=self._installMissing)
206 print "Done!"
209 def _installMissing(self, dist):
210 env = pkg_resources.Environment()
211 print dist, EXTRA_RESOURCES_URL
212 easy_install.main(["-f", EXTRA_RESOURCES_URL, "-U", str(dist)])
213 env.scan()
215 if env[str(dist)]:
216 return env[str(dist)][0]
217 else:
218 return None
221 class fetchdeps_indico(fetchdeps, Command):
222 description = "fetch all the dependencies needed to run Indico"
223 user_options = []
224 boolean_options = []
226 def initialize_options(self):
227 pass
229 def finalize_options(self):
230 pass
233 class develop_indico(Command):
234 description = "prepares the current directory for Indico development"
235 user_options = [('www-uid=', None, "Set user for cache/log/db (typically apache user)"),
236 ('www-gid=', None, "Set group for cache/log/db (typically apache group)")]
237 boolean_options = []
239 www_uid = None
240 www_gid = None
242 def initialize_options(self):
243 pass
245 def finalize_options(self):
246 pass
248 def run(self):
250 fetchdeps().run()
252 local = 'etc/indico.conf'
253 if os.path.exists(local):
254 print 'Upgrading existing etc/indico.conf..'
255 upgrade_indico_conf(local, 'etc/indico.conf.sample')
256 else:
257 print 'Creating new etc/indico.conf..'
258 shutil.copy('etc/indico.conf.sample', local)
260 for f in [x for x in ('etc/zdctl.conf', 'etc/zodb.conf', 'etc/logging.conf') if not os.path.exists(x)]:
261 shutil.copy('%s.sample' % f, f)
263 print """\nIndico needs to store some information in the filesystem (database, cache, temporary files, logs...)
264 Please specify the directory where you'd like it to be placed.
265 (Note that putting it outside of your sourcecode tree is recommended)"""
266 prefixDirDefault = os.path.dirname(os.getcwd())
267 prefixDir = raw_input('[%s]: ' % prefixDirDefault).strip()
269 if prefixDir == '':
270 prefixDir = prefixDirDefault
272 directories = dict((d, os.path.join(prefixDir, d)) for d in
273 ['db', 'log', 'tmp', 'cache', 'archive'])
275 print 'Creating directories...',
276 for d in directories.values():
277 if not os.path.exists(d):
278 os.makedirs(d)
279 print 'Done!'
281 directories['htdocs'] = os.path.join(os.getcwd(), 'indico', 'htdocs')
282 directories['bin'] = os.path.join(os.getcwd(), 'bin')
283 directories['etc'] = os.path.join(os.getcwd(), 'etc')
284 directories['doc'] = os.path.join(os.getcwd(), 'doc')
286 self._update_conf_dir_paths(local, directories)
288 directories.pop('htdocs') #avoid modifying the htdocs folder permissions (it brings problems with git)
290 from MaKaC.consoleScripts.installBase import _databaseText, _findApacheUserGroup, _checkDirPermissions, _updateDbConfigFiles, _updateMaKaCEggCache
292 user = ''
294 sourcePath = os.getcwd()
296 # find the apache user/group
297 user, group = _findApacheUserGroup(self.www_uid, self.www_gid)
298 _checkDirPermissions(directories, dbInstalledBySetupPy=directories['db'], accessuser=user, accessgroup=group)
300 _updateDbConfigFiles(directories['db'], directories['log'], os.path.join(sourcePath, 'etc'), directories['tmp'], user)
302 _updateMaKaCEggCache(os.path.join(os.path.dirname(__file__), 'indico', 'MaKaC', '__init__.py'), directories['tmp'])
304 updateIndicoConfPathInsideMaKaCConfig(os.path.join(os.path.dirname(__file__), ''), 'indico/MaKaC/common/MaKaCConfig.py')
305 compileAllLanguages(self)
306 print '''
308 ''' % _databaseText('etc')
310 if sys.platform == "linux2":
311 # create symlink to legacy MaKaC dir
312 # this is so that the ".egg-link" created by the "develop" command works
313 os.symlink('indico/MaKaC','MaKaC')
315 def _update_conf_dir_paths(self, filePath, dirs):
316 fdata = open(filePath).read()
317 for dir in dirs.items():
318 d = dir[1].replace("\\","/") # For Windows users
319 fdata = re.sub('\/opt\/indico\/%s'%dir[0], d, fdata)
320 open(filePath, 'w').write(fdata)
322 class test_indico(Command):
324 Test command for Indico
327 description = "Test Suite Framework"
328 user_options = [('specify=', None, "Use nosetests style (file.class:testcase)"),
329 ('coverage', None, "Output coverage report in html"),
330 ('unit', None, "Run only Unit tests"),
331 ('functional', None, "Run only Functional tests"),
332 ('pylint', None, "Run python source analysis"),
333 ('jsunit', None, "Run js unit tests"),
334 ('jslint', None, "Run js source analysis"),
335 ('jscoverage', None, "Output coverage report in html for js"),
336 ('jsspecify=', None, "Use js-test-driver style (TestCaseName.testName)"),
337 ('log=', None, "Log to console, using specified level"),
338 ('grid', None, "Use Selenium Grid"),
339 ('xml', None, "XML output"),
340 ('html', None, "Make an HTML report (when possible)"),
341 ('record', None, "Record tests (for --functional)"),
342 ('parallel', None, "Parallel test execution using Selenium Grid (for --functional)"),
343 ('threads=', None, "Parallel test execution with several threads (for --functional)"),
344 ('repeat=', None, "Number of repetitions (for --functional)"),
345 ('silent', None, "Don't output anything in the console, just generate the report"),
346 ('killself', None, "Kill this script right after the tests finished without waiting for db shutdown.")]
347 boolean_options = []
349 specify = None
350 coverage = False
351 unit = False
352 functional = False
353 pylint = False
354 jsunit = False
355 jslint = False
356 jscoverage = False
357 jsspecify = None
358 grid = None
359 silent = False
360 killself = False
361 html = False
362 record = False
363 parallel = False
364 threads = False
365 repeat = False
366 log = False
367 xml = False
369 def initialize_options(self):
370 pass
372 def finalize_options(self):
373 pass
375 def run(self):
377 if not self.checkTestPackages():
378 print "Please install those missing packages before launching the tests again"
379 sys.exit(-1)
381 #missing jars will be downloaded automatically
382 if not self.checkTestJars():
383 print "Some jars could not be downloaded. Please download the missing jars manually"
384 sys.exit(-1)
386 from indico.tests import TestManager, TEST_RUNNERS
387 testsToRun = []
389 allTests = TEST_RUNNERS.keys()
391 for testType in allTests:
392 if getattr(self, testType):
393 testsToRun.append(testType)
395 if self.jsspecify and 'jsunit' not in testsToRun:
396 testsToRun.append('jsunit')
398 if testsToRun == []:
399 testsToRun = allTests
402 options = {'silent': self.silent,
403 'killself': self.killself,
404 'html': self.html,
405 'specify': self.specify,
406 'coverage': self.coverage,
407 'record': self.record,
408 'parallel': self.parallel,
409 'threads': self.threads,
410 'repeat': self.repeat,
411 'log': self.log,
412 'xml':self.xml}
414 # get only options that are active
415 options = dict((k,v) for (k,v) in options.iteritems() if v)
417 manager = TestManager()
419 result = manager.main(testsToRun, options)
421 sys.exit(result)
423 def checkTestPackages(self):
424 packagesList = ['figleaf',
425 'nose>=0.11',
426 'rednose',
427 'selenium',
428 'twill']
429 validPackages = True
431 for package in packagesList:
432 try:
433 pkg_resources.require(package)
434 except pkg_resources.DistributionNotFound:
435 print """
436 %s not found! Please install it.
437 i.e. try 'easy_install %s'""" % (package, package)
438 validPackages = False
439 return validPackages
441 def checkTestJars(self):
443 check if needed jars are here, if not,
444 dowload them and unzip the file if necessary
447 from indico.tests import TestConfig
449 jarsList = {}
450 currentFilePath = os.path.dirname(__file__)
451 testModPath = os.path.join(currentFilePath, 'indico', 'tests')
453 try:
454 jarsList['jsunit'] = {'path': os.path.join(testModPath,
455 'javascript',
456 'unit'),
457 'url': TestConfig.getInstance().getJSUnitURL(),
458 'filename': TestConfig.getInstance().getJSUnitFilename()}
460 jarsList['jscoverage'] = {'path': os.path.join(testModPath,
461 'javascript',
462 'unit',
463 'plugins'),
464 'url': TestConfig.getInstance().getJSCoverageURL(),
465 'filename': TestConfig.getInstance().getJSCoverageFilename()}
467 jarsList['selenium'] = {'path': os.path.join(testModPath,
468 'python',
469 'functional'),
470 'url': TestConfig.getInstance().getSeleniumURL(),
471 'filename': TestConfig.getInstance().getSeleniumFilename()}
472 except KeyError, key:
473 print "[ERR] Please specify a value for %s in tests.conf" % key
474 sys.exit(1)
476 validJars = True
478 for name in jarsList:
479 jar = jarsList[name]
480 #check if jar is already here
481 if not os.path.exists(os.path.join(jar['path'], jar['filename'])):
482 print "Downloading %s to %s..." % (jar['url'], jar['path'])
483 try:
484 self.download(jar['url'], jar['path'])
485 except IOError, e:
486 validJars = validJars and False
487 print 'Could not download %s from %s (%s)' % (jar['filename'], jar['url'], e)
489 return validJars
491 def download(self, url, path):
492 """Copy the contents of a file from a given URL
493 to a local file.
495 import urllib
496 webFile = urllib.urlopen(url)
497 localFile = open(os.path.join(path, url.split('/')[-1]), 'w')
498 localFile.write(webFile.read())
499 webFile.close()
500 localFile.close()
502 def unzip(self, zipPath, inZipPath, targetFile):
503 """extract the needed file from zip and then delete the zip"""
504 import zipfile
505 try:
506 zfobj = zipfile.ZipFile(zipPath)
507 outfile = open(targetFile, 'wb')
508 outfile.write(zfobj.read(inZipPath))
509 outfile.flush()
510 outfile.close()
512 #delete zip file
513 os.unlink(zipPath)
514 except NameError, e:
515 print e
518 class egg_filename(Command):
519 description = "Get the file name of the generated egg"
520 user_options = []
521 boolean_options = []
523 def initialize_options(self):
524 pass
526 def finalize_options(self):
527 ei_cmd = self.ei_cmd = self.get_finalized_command("egg_info")
528 self.egg_info = ei_cmd.egg_info
530 basename = pkg_resources.Distribution(
531 None, None, ei_cmd.egg_name, ei_cmd.egg_version,
532 get_python_version(),
533 self.distribution.has_ext_modules() and pkg_utils.get_build_platform
534 ).egg_name()
536 print basename
539 def run(self):
540 pass
543 if __name__ == '__main__':
544 # Always load source from the current folder
545 sys.path = [os.path.abspath('indico')] + sys.path
547 #PWD_INDICO_CONF = 'etc/indico.conf'
548 #if not os.path.exists(PWD_INDICO_CONF):
549 # shutil.copy('etc/indico.conf.sample', PWD_INDICO_CONF)
551 from MaKaC.consoleScripts.installBase import *
554 #Dirty trick: For running tests, we need to load all the modules and get rid of unnecessary outputs
555 tempLoggingDir = None
556 if 'test' in sys.argv:
557 import logging
558 import tempfile
559 tempLoggingDir = tempfile.mkdtemp()
560 logging.basicConfig(filename=os.path.join(tempLoggingDir, 'logging'),
561 level=logging.DEBUG)
562 setIndicoInstallMode(False)
563 else:
564 setIndicoInstallMode(True)
566 x = vars()
567 x.packageDir = os.path.join(get_python_lib(), 'MaKaC')
570 x.binDir = 'bin'
571 x.documentationDir = 'doc'
572 x.configurationDir = 'etc'
573 x.htdocsDir = 'htdocs'
575 dataFiles = _getDataFiles(x)
577 foundPackages = list('MaKaC.%s' % pkg for pkg in
578 find_packages(where = 'indico/MaKaC'))
579 foundPackages.append('MaKaC')
580 foundPackages.append('htdocs')
582 # add our namespace package
583 foundPackages += list('indico.%s' % pkg for pkg in
584 find_packages(where = 'indico',
585 exclude = ['htdocs*', 'MaKaC*']))
586 foundPackages.append('indico')
588 cmdclass = {'sdist': sdist_indico,
589 'bdist': _bdist_indico(dataFiles),
590 'bdist_egg': _bdist_egg_indico(dataFiles),
591 'jsbuild': jsbuild,
592 'fetchdeps': fetchdeps_indico,
593 'develop_config': develop_indico,
594 'test': test_indico,
595 'egg_filename': egg_filename
598 if BABEL_PRESENT:
599 for cmdname in ['init_catalog', 'extract_messages', 'compile_catalog', 'update_catalog']:
600 cmdclass['%s_js' % cmdname] = getattr(babel, cmdname)
601 cmdclass['compile_catalog_js'] = i18n.generate_messages_js
603 setup(name = "indico",
604 cmdclass = cmdclass,
605 version = _versionInit(),
606 description = "Indico is a full-featured conference lifecycle management and meeting/lecture scheduling tool",
607 author = "Indico Team",
608 author_email = "indico-team@cern.ch",
609 url = "http://indico-software.org",
610 download_url = "http://indico-software.org/wiki/Releases/Indico0.97.0",
611 platforms = ["any"],
612 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",
613 license = "http://www.gnu.org/licenses/gpl-2.0.txt",
614 entry_points = """
615 [console_scripts]
617 indico_scheduler = indico.modules.scheduler.daemon_script:main
618 indico_initial_setup = MaKaC.consoleScripts.indicoInitialSetup:main
619 indico_ctl = MaKaC.consoleScripts.indicoCtl:main
620 indico_livesync = indico.ext.livesync.console:main
621 indico_shell = indico.util.shell:main
623 [indico.ext_types]
625 Collaboration = MaKaC.plugins.Collaboration
626 InstantMessaging = MaKaC.plugins.InstantMessaging
627 RoomBooking = MaKaC.plugins.RoomBooking
628 EPayment = MaKaC.plugins.EPayment
629 livesync = indico.ext.livesync
630 importer = indico.ext.importer
633 [indico.ext]
635 Collaboration.EVO = MaKaC.plugins.Collaboration.EVO
636 Collaboration.Vidyo = MaKaC.plugins.Collaboration.Vidyo
637 Collaboration.CERNMCU = MaKaC.plugins.Collaboration.CERNMCU
638 Collaboration.RecordingManager = MaKaC.plugins.Collaboration.RecordingManager
639 Collaboration.RecordingRequest = MaKaC.plugins.Collaboration.RecordingRequest
640 Collaboration.WebcastRequest = MaKaC.plugins.Collaboration.WebcastRequest
642 RoomBooking.CERN = MaKaC.plugins.RoomBooking.CERN
643 RoomBooking.default = MaKaC.plugins.RoomBooking.default
645 EPayment.payPal = MaKaC.plugins.EPayment.payPal
646 EPayment.worldPay = MaKaC.plugins.EPayment.worldPay
647 EPayment.yellowPay = MaKaC.plugins.EPayment.yellowPay
648 EPayment.skipjack = MaKaC.plugins.EPayment.skipjack
650 importer.invenio = indico.ext.importer.invenio
651 importer.dummy = indico.ext.importer.dummy
653 InstantMessaging.XMPP = MaKaC.plugins.InstantMessaging.XMPP
655 livesync.invenio = indico.ext.livesync.invenio
656 livesync.cern_search = indico.ext.livesync.cern_search
658 """,
659 zip_safe = False,
660 packages = foundPackages,
661 package_dir = { 'indico': 'indico',
662 'htdocs': os.path.join('indico', 'htdocs'),
663 'MaKaC' : os.path.join('indico', 'MaKaC')},
664 package_data = {'indico': ['*.*']},
665 include_package_data=True,
666 namespace_packages = ['indico', 'indico.ext'],
667 install_requires = _getInstallRequires(),
668 data_files = dataFiles,
669 dependency_links = [
670 EXTRA_RESOURCES_URL
674 #delete the temp folder used for logging
675 if 'test' in sys.argv:
676 shutil.rmtree(tempLoggingDir)