1 # This file is part of Indico.
2 # Copyright (C) 2002 - 2015 European Organization for Nuclear Research (CERN).
4 # Indico is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License as
6 # published by the Free Software Foundation; either version 3 of the
7 # License, or (at your option) any later version.
9 # Indico is distributed in the hope that it will be useful, but
10 # WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 # General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with Indico; if not, see <http://www.gnu.org/licenses/>.
17 # Autoinstalls setuptools if the user doesn't have them already
19 ez_setup
.use_setuptools()
26 from distutils
.sysconfig
import get_python_lib
, get_python_version
27 from distutils
.cmd
import Command
28 from distutils
.command
import bdist
32 from setuptools
.command
import develop
, sdist
, bdist_egg
, easy_install
, test
33 from setuptools
import setup
, find_packages
, findall
36 DEPENDENCY_URLS
= ["http://indico-software.org/wiki/Admin/Installation/IndicoExtras"]
40 '''Variable holder.'''
45 dbInstalledBySetupPy
= False
47 documentationDir
= None
48 configurationDir
= None
52 def compile_languages(cmd
):
54 Compile all language files
55 Needed to generate binary distro
57 from babel
.messages
import frontend
59 compile_cmd
= frontend
.compile_catalog(cmd
.distribution
)
60 cmd
.distribution
._set
_command
_options
(compile_cmd
)
61 compile_cmd
.finalize_options()
65 def read_requirements_file(fname
):
66 with
open(fname
, 'r') as f
:
67 return [dep
.strip() for dep
in f
.readlines() if not (dep
.startswith('-') or '://' in dep
)]
70 def _generateDataPaths(x
):
74 for (baseDstDir
, srcDir
) in x
:
75 for f
in findall(srcDir
):
76 dst_dir
= os
.path
.join(baseDstDir
,
77 os
.path
.relpath(os
.path
.dirname(f
), srcDir
))
78 if dst_dir
not in dataFilesDict
:
79 dataFilesDict
[dst_dir
] = []
80 dataFilesDict
[dst_dir
].append(f
)
83 for k
, v
in dataFilesDict
.items():
84 dataFiles
.append((k
, v
))
89 def _getInstallRequires():
90 """Returns external packages required by Indico
92 These are the ones needed for runtime."""
94 return read_requirements_file(os
.path
.join(os
.path
.dirname(__file__
), 'requirements.txt'))
98 """Retrieves the version number from indico/MaKaC/__init__.py and returns it"""
100 from indico
.MaKaC
import __version__
103 print 'Indico %s' % v
109 class sdist_indico(sdist
.sdist
):
110 user_options
= (sdist
.sdist
.user_options
+
111 [('version=', None, 'version to distribute')])
115 sdist
.sdist
.run(self
)
118 def _bdist_indico(dataFiles
):
119 class bdist_indico(bdist
.bdist
):
121 compile_languages(self
)
122 bdist
.bdist
.run(self
)
124 bdist_indico
.dataFiles
= dataFiles
128 def _bdist_egg_indico(dataFiles
):
129 class bdist_egg_indico(bdist_egg
.bdist_egg
):
131 compile_languages(self
)
132 bdist_egg
.bdist_egg
.run(self
)
134 bdist_egg_indico
.dataFiles
= dataFiles
135 return bdist_egg_indico
138 class develop_indico(develop
.develop
):
140 develop
.develop
.run(self
)
142 # create symlink to legacy MaKaC dir
143 # this is so that the ".egg-link" created by the "develop" command works
144 if sys
.platform
in ["linux2", "darwin"] and not os
.path
.exists('MaKaC'):
145 os
.symlink('indico/MaKaC', 'MaKaC')
147 # install dev dependencies
148 env
= pkg_resources
.Environment()
149 easy_install
.main(read_requirements_file(os
.path
.join(os
.path
.dirname(__file__
), 'requirements.dev.txt')))
153 class develop_config(develop_indico
):
154 description
= "prepares the current directory for Indico development"
155 user_options
= (develop
.develop
.user_options
+
156 [('www-uid=', None, "Set user for cache/log/db (typically apache user)"),
157 ('www-gid=', None, "Set group for cache/log/db (typically apache group)"),
158 ('http-port=', None, "Set port used by HTTP server"),
159 ('https-port=', None, "Set port used by HTTP server in HTTPS mode"),
160 ('zodb-port=', None, "Set port used by ZODB"),
161 ('smtp-port=', None, "Set port used for SMTP (e-mail sending)"),
162 ('use-apache', None, "Use apache (will chmod directories accordingly)")])
173 # dependencies, links, etc...
174 develop_indico
.run(self
)
176 local
= 'etc/indico.conf'
177 if os
.path
.exists(local
):
178 print 'Upgrading existing etc/indico.conf...'
180 print 'Creating new etc/indico.conf..'
181 shutil
.copy('etc/indico.conf.sample', local
)
183 upgrade_indico_conf(local
, 'etc/indico.conf.sample', {
184 'BaseURL': 'http://localhost:{0}'.format(self
.http_port
),
185 'BaseSecureURL': 'https://localhost:{0}'.format(self
.https_port
),
186 'DBConnectionParams': ("localhost", int(self
.zodb_port
)),
187 'SmtpServer': ("localhost", int(self
.smtp_port
))
190 for f
in [x
for x
in ('etc/zdctl.conf', 'etc/zodb.conf', 'etc/logging.conf') if not os
.path
.exists(x
)]:
191 shutil
.copy('%s.sample' % f
, f
)
193 print """\nIndico needs to store some information in the filesystem (database, cache, temporary files, logs...)
194 Please specify the directory where you'd like it to be placed.
195 (Note that putting it outside of your sourcecode tree is recommended)"""
196 prefixDirDefault
= os
.path
.dirname(os
.getcwd())
197 prefixDir
= raw_input('Full path [%s]: ' % prefixDirDefault
).strip()
200 prefixDir
= prefixDirDefault
202 directories
= dict((d
, os
.path
.join(prefixDir
, d
)) for d
in
203 ['db', 'log', 'tmp', 'cache', 'archive'])
205 print 'Creating directories...',
206 for d
in directories
.values():
207 if not os
.path
.exists(d
):
212 directories
.update(dict((d
, os
.path
.join(os
.getcwd(), 'indico', d
)) for d
in ['htdocs', 'bin', 'etc', 'doc']))
214 self
._update
_conf
_dir
_paths
(local
, directories
)
216 # avoid modifying the htdocs folder permissions (it brings problems with git)
217 directories
.pop('htdocs')
219 from MaKaC
.consoleScripts
.installBase
import _databaseText
, _findApacheUserGroup
, _checkDirPermissions
, \
220 _updateDbConfigFiles
, _updateMaKaCEggCache
222 user
= getpass
.getuser()
223 sourcePath
= os
.getcwd()
226 # find the apache user/group
227 user
, group
= _findApacheUserGroup(self
.www_uid
, self
.www_gid
)
228 _checkDirPermissions(directories
, dbInstalledBySetupPy
=directories
['db'], accessuser
=user
, accessgroup
=group
)
230 _updateDbConfigFiles(os
.path
.join(sourcePath
, 'etc'),
231 db
=directories
['db'],
232 log
=directories
['log'],
233 tmp
=directories
['tmp'],
237 _updateMaKaCEggCache(os
.path
.join(os
.path
.dirname(__file__
), 'indico', 'MaKaC', '__init__.py'),
240 compile_languages(self
)
243 ''' % _databaseText('etc')
245 def _update_conf_dir_paths(self
, filePath
, dirs
):
246 fdata
= open(filePath
).read()
247 for dir in dirs
.items():
248 d
= dir[1].replace("\\", "/") # For Windows users
249 fdata
= re
.sub('\/opt\/indico\/%s' % dir[0], d
, fdata
)
250 open(filePath
, 'w').write(fdata
)
253 class test_indico(test
.test
):
255 Test command for Indico
258 description
= "Test Suite Framework"
259 user_options
= (test
.test
.user_options
+ [('specify=', None, "Use nosetests style (file.class:testcase)"),
260 ('coverage', None, "Output coverage report in html"),
261 ('unit', None, "Run only Unit tests"),
262 ('functional', None, "Run only Functional tests"),
263 ('pylint', None, "Run python source analysis"),
264 ('jsunit', None, "Run js unit tests"),
265 ('jslint', None, "Run js source analysis"),
266 ('jscoverage', None, "Output coverage report in html for js"),
267 ('jsspecify=', None, "Use js-test-driver style (TestCaseName.testName)"),
268 ('log=', None, "Log to console, using specified level"),
269 ('browser=', None, "Browser to use for functional tests"),
270 ('mode=', None, "Mode to use for functional tests"),
271 ('server-url=', None, "Server URL to use for functional tests"),
272 ('xml', None, "XML output"),
273 ('html', None, "Make an HTML report (when possible)"),
274 ('record', None, "Record tests (for --functional)"),
275 ('silent', None, "Don't output anything in the console, just generate the report"),
276 ('clean-shutdown', None,
277 "Do not kill this script right after the tests finished without waiting for db shutdown.")])
293 clean_shutdown
= False
299 def _wrap(self
, func
, *params
):
301 self
.res
= func(*params
)
302 self
.with_project_on_sys_path(wrapped
)
305 def finalize_options(self
):
308 allTests
= ['unit', 'functional']
310 for testType
in allTests
:
311 if getattr(self
, testType
):
312 testsToRun
.append(testType
)
314 if self
.jsspecify
and 'jsunit' not in testsToRun
:
315 testsToRun
.append('jsunit')
318 testsToRun
= allTests
319 self
.testsToRun
= testsToRun
323 if self
.distribution
.install_requires
:
324 self
.distribution
.fetch_build_eggs(self
.distribution
.install_requires
)
325 if self
.distribution
.tests_require
:
326 self
.distribution
.fetch_build_eggs(self
.distribution
.tests_require
)
328 from indico
.tests
import TestManager
330 options
= {'silent': self
.silent
,
331 'killself': not self
.clean_shutdown
,
333 'browser': self
.browser
,
335 'specify': self
.specify
,
336 'coverage': self
.coverage
,
337 'record': self
.record
,
338 'server_url': self
.server_url
,
342 # get only options that are active
343 options
= dict((k
, v
) for (k
, v
) in options
.iteritems() if v
)
345 manager
= TestManager()
346 result
= self
._wrap
(manager
.main
, self
.testsToRun
, options
)
350 def download(self
, url
, path
):
351 """Copy the contents of a file from a given URL
355 webFile
= urllib
.urlopen(url
)
356 localFile
= open(os
.path
.join(path
, url
.split('/')[-1]), 'w')
357 localFile
.write(webFile
.read())
361 def unzip(self
, zipPath
, inZipPath
, targetFile
):
362 """extract the needed file from zip and then delete the zip"""
365 zfobj
= zipfile
.ZipFile(zipPath
)
366 outfile
= open(targetFile
, 'wb')
367 outfile
.write(zfobj
.read(inZipPath
))
377 class egg_filename(Command
):
378 description
= "Get the file name of the generated egg"
382 def initialize_options(self
):
385 def finalize_options(self
):
386 ei_cmd
= self
.ei_cmd
= self
.get_finalized_command("egg_info")
387 self
.egg_info
= ei_cmd
.egg_info
389 basename
= pkg_resources
.Distribution(
390 None, None, ei_cmd
.egg_name
, ei_cmd
.egg_version
,
391 get_python_version(),
392 self
.distribution
.has_ext_modules() and pkg_utils
.get_build_platform
).egg_name()
400 if __name__
== '__main__':
401 # Always load source from the current folder
402 sys
.path
= [os
.path
.abspath('indico')] + sys
.path
404 #PWD_INDICO_CONF = 'etc/indico.conf'
405 #if not os.path.exists(PWD_INDICO_CONF):
406 # shutil.copy('etc/indico.conf.sample', PWD_INDICO_CONF)
408 from MaKaC
.consoleScripts
.installBase
import setIndicoInstallMode
, upgrade_indico_conf
410 #Dirty trick: For running tests, we need to load all the modules and get rid of unnecessary outputs
411 tempLoggingDir
= None
412 if 'test' in sys
.argv
:
415 tempLoggingDir
= tempfile
.mkdtemp()
416 logging
.basicConfig(filename
=os
.path
.join(tempLoggingDir
, 'logging'),
418 setIndicoInstallMode(False)
420 setIndicoInstallMode(True)
423 x
.packageDir
= os
.path
.join(get_python_lib(), 'MaKaC')
426 x
.documentationDir
= 'doc'
427 x
.configurationDir
= 'etc'
428 x
.htdocsDir
= 'htdocs'
430 dataFiles
= _generateDataPaths((('bin', 'bin'), ('doc', 'doc'), ('etc', 'etc'), ('migrations', 'migrations')))
432 foundPackages
= list('MaKaC.%s' % pkg
for pkg
in
433 find_packages(where
='indico/MaKaC'))
434 foundPackages
.append('MaKaC')
435 foundPackages
.append('htdocs')
437 # add our namespace package
438 foundPackages
+= list('indico.%s' % pkg
for pkg
in
439 find_packages(where
='indico',
440 exclude
=['htdocs*', 'MaKaC*']))
441 foundPackages
.append('indico')
442 foundPackages
+= list('indico_zodbimport.' + pkg
for pkg
in find_packages(where
='indico_zodbimport'))
443 foundPackages
.append('indico_zodbimport')
445 cmdclass
= {'sdist': sdist_indico
,
446 'bdist': _bdist_indico(dataFiles
),
447 'bdist_egg': _bdist_egg_indico(dataFiles
),
448 'develop_config': develop_config
,
449 'develop': develop_indico
,
451 'egg_filename': egg_filename
456 version
=_versionInit(),
457 description
="Indico is a full-featured conference lifecycle management and meeting/lecture scheduling tool",
458 author
="Indico Team",
459 author_email
="indico-team@cern.ch",
460 url
="http://indico-software.org",
461 download_url
="http://indico-software.org/wiki/Releases/Indico1.2",
463 long_description
="Indico allows you to schedule conferences, from single talks to complex meetings with "
464 "sessions and contributions. It also includes an advanced user delegation mechanism, "
465 "allows paper reviewing, archival of conference information and electronic proceedings",
466 license
="http://www.gnu.org/licenses/gpl-3.0.txt",
469 indico_scheduler = indico.modules.scheduler.daemon_script:main
470 indico_initial_setup = MaKaC.consoleScripts.indicoInitialSetup:main
471 indico_ctl = MaKaC.consoleScripts.indicoCtl:main
472 indico = indico.cli.manage:main
473 indico-zodbimport = indico_zodbimport.cli:main
476 indico = indico.testing.pytest_plugin
478 [indico.zodb_importers]
479 roombooking = indico_zodbimport.modules.roombooking:RoomBookingImporter
480 payment = indico_zodbimport.modules.payment:PaymentImporter
481 api = indico_zodbimport.modules.api:APIImporter
482 users = indico_zodbimport.modules.users:UserImporter
483 groups = indico_zodbimport.modules.groups:GroupImporter
484 evaluation_alarms = indico_zodbimport.modules.evaluation_alarms:EvaluationAlarmImporter
485 static_sites = indico_zodbimport.modules.static_sites:StaticSitesImporter
488 packages
=foundPackages
,
489 package_dir
={'indico': 'indico',
490 'htdocs': os
.path
.join('indico', 'htdocs'),
491 'MaKaC': os
.path
.join('indico', 'MaKaC')},
492 package_data
={'indico': ['*.*']},
493 include_package_data
=True,
494 namespace_packages
=['indico'],
495 install_requires
=_getInstallRequires(),
496 tests_require
=['nose', 'rednose', 'twill', 'selenium', 'figleaf', 'contextlib2'],
497 data_files
=dataFiles
,
498 dependency_links
=DEPENDENCY_URLS
501 #delete the temp folder used for logging
502 if 'test' in sys
.argv
:
503 shutil
.rmtree(tempLoggingDir
)