1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 _gangaVersion = "$Name: Ganga-5-6-2 $"
25
26 import re
27
28 r = re.compile(r'\$[N]ame: (?P<version>\S+) \$').match(_gangaVersion)
29 if r:
30 _gangaVersion = r.group('version')
31 else:
32 _gangaVersion = "SVN_TRUNK"
33
34
35
36 import os.path, Ganga
37 _gangaPythonPath = os.path.dirname(os.path.dirname(Ganga.__file__))
38
39 from Ganga.Utility.files import fullpath
40
41 import sys,time
42
43
44
45
46
47
48
49
50
51
52
53 TRANSITION_MESSAGE_545 = """
54 -------------------------------------
55 THIS IS A NEW MAJOR RELEASE OF GANGA
56 -------------------------------------
57
58 In Ganga 5.5.0 a new version of the Ganga XML Repository (v6.0) is
59 introduced. Its main features are enhanced reliability, concurrent
60 access from several ganga sessions, and the introduction of a Ganga
61 "box", where any Ganga object can be saved.
62
63 On the first startup of 5.5.0, old AMGA and XML repositories as well as
64 GangaTasks from the same gangadir will be automatically imported. The
65 old repositories and tasks will not be touched, only a file
66 "converted.to.XML.6.0" will be created in
67 <gangadir>/repository/Name/LocalAMGA or respectively LocalXML/jobs,
68 LocalXML/templates or <gangadir>/tasks.xml.converted.to.XML.6.0.
69
70 To repeat the import process from scratch, just delete these files
71 together with the new repository <gangadir>/repository/Name/LocalXML/6.0
72
73 The new repository may use much more disk space than the old AMGA
74 repository, and some more space than the old XML repository. This does
75 however only affect <gangadir>/repository, and not the usually much
76 larger workspace directory <gangadir>/workspace.
77
78 When you are happy with the conversion and completely sure you do not
79 want to revert to a previous release you can delete the old repository
80 and tasks located in
81
82 <gangadir>/repository/Name/LocalAMGA
83 <gangadir>/repository/Name/LocalXML/5.0
84 <gangadir>/tasks.xml
85
86 -------------------------------------
87 THIS IS A NEW MAJOR RELEASE OF GANGA
88 -------------------------------------
89 """
90
91
93 """ High level API to create instances of Ganga programs and configure/run it """
94
95 - def __init__(self,hello_string=None,argv=sys.argv):
96 """ make an instance of Ganga program
97 use default hello_string if not specified
98 use sys.argv as arguments if not specified"""
99
100 self.argv = argv[:]
101
102
103
104 self.start_time = time.time()
105
106 if hello_string is None:
107 self.hello_string = """
108 *** Welcome to Ganga ***
109 Version: %s
110 Documentation and support: http://cern.ch/ganga
111 Type help() or help('index') for online help.
112
113 This is free software (GPL), and you are welcome to redistribute it
114 under certain conditions; type license() for details.
115
116 """ % _gangaVersion
117 else:
118 self.hello_string = hello_string
119
120
121 self.interactive = True
122
123 import os.path
124 self.default_config_file = os.path.expanduser('~/.gangarc')
125
126
127
128
129
130 - def exit(self,*msg):
131 print >> sys.stderr, self.hello_string
132 for m in msg:
133 print >> sys.stderr,'ganga:',m
134 sys.exit(1)
135
136
137
139 from optparse import OptionParser
140
141 usage = self.hello_string+"""\nusage: %prog [options] [script] [args] ..."""
142
143 parser = OptionParser(usage,version=_gangaVersion)
144
145 parser.add_option("-i", dest="force_interactive", action="store_true",
146 help='enter interactive mode after running script')
147
148 parser.add_option("--webgui", dest="webgui", action="store_true", default='False',
149 help='starts web GUI monitoring server')
150
151 parser.add_option('--gui',dest="GUI",action='store_true',default=False,help='Run Ganga in the GUI mode.')
152
153 parser.add_option("--config", dest="config_file",action="store", metavar="FILE",
154 help='read user configuration from FILE, overrides the GANGA_CONFIG_FILE environment variable. Default: ~/.gangarc')
155
156 parser.add_option("--config-path",dest='config_path',action="store", default=None,
157 help='site/experiment config customization path, overrides the GANGA_CONFIG_PATH environment variable. The relative paths are resolved wrt to the release directory. To use a specific file you should specify the absolute path. Default: None')
158
159 parser.add_option("-g","--generate-config",dest='generate_config',action="store_const",const=1,
160 help='generate a default config file, backup the existing one')
161
162 parser.add_option("-o","--option",dest='cmdline_options',action="append", default=[],metavar='EXPR',
163 help='set configuration options, may be repeated mutiple times,'
164 'for example: -o[Logging]Ganga.Lib=DEBUG -oGangaLHCb=INFO -o[Configuration]TextShell = IPython '
165 'The VALUE of *_PATH option is prepended. To reset it use :::VALUE')
166
167 parser.add_option("--quiet", dest="force_loglevel",action="store_const",const='ERROR',
168 help='only ERROR messages are printed')
169
170 parser.add_option("--very-quiet", dest="force_loglevel",action="store_const",const='CRITICAL',
171 help='only CRITICAL messages are printed')
172
173 parser.add_option("--debug",dest="force_loglevel",action="store_const",const='DEBUG',
174 help='all messages including DEBUG are printed')
175
176 parser.add_option("--no-mon",dest='monitoring',action="store_const",const=0,
177 help='disable the monitoring loop (useful if you run multiple Ganga sessions)')
178
179 parser.add_option("--no-prompt",dest='prompt',action="store_const",const=0,
180 help='never prompt interactively for anything except IPython (FIXME: this is not fully implemented)')
181
182 parser.add_option("--no-rexec", dest = "rexec", action="store_const",const=0,
183 help='rely on existing environment and do not re-exec ganga process'
184 'to setup runtime plugin modules (affects LD_LIBRARY_PATH)')
185
186 parser.add_option("--test",dest='TEST',action="store_true", default=False,
187 help='run Ganga test(s) using internal test-runner. It requires GangaTest package to be installed.'
188 'Usage example: *ganga --test Ganga/test/MyTestcase* .'
189 'Refer to [TestingFramework] section in Ganga config for more information on how to configure the test runner.')
190
191 parser.set_defaults(force_interactive=False, config_file=None, force_loglevel=None,rexec=1, monitoring=1, prompt=1, generate_config=None)
192 parser.disable_interspersed_args()
193
194 (self.options, self.args) = parser.parse_args(args=self.argv[1:])
195
196 def file_opens(f,message):
197 try:
198 return file(f)
199 except IOError,x:
200 self.exit(message,x)
201
202 self.options.config_file_set_explicitly = not self.options.config_file is None
203
204
205 if self.options.config_file is None:
206 self.options.config_file = os.environ.get('GANGA_CONFIG_FILE',None)
207
208 if self.options.config_file:
209 import Ganga.Utility.files
210 self.options.config_file = Ganga.Utility.files.expandfilename(self.options.config_file)
211 file_opens(self.options.config_file,'reading configuration file')
212
213
214 if len(self.args) > 0:
215 if not self.options.force_interactive:
216 self.interactive = False
217
218
219
220
221
223 import os
224
225 def generate(where):
226 import shutil
227
228 flavour = Ganga.Utility.Config.Config.getFlavour()
229 print "Using flavour %s"%flavour
230 if flavour:
231 configtemplate = "CONFIG_TEMPLATE_%s.INI"%flavour
232 else:
233 configtemplate = "CONFIG_TEMPLATE.INI"
234 shutil.copy(os.path.join(os.path.dirname(_gangaPythonPath),'templates',configtemplate),where)
235 print >> sys.stderr, 'Created standard config file',where
236
237 gangadir = os.path.expanduser('~/gangadir')
238 if not os.path.exists(gangadir) \
239 and not os.path.exists(self.default_config_file) \
240 and not self.options.config_file_set_explicitly:
241
242 if self.options.prompt:
243 print >> sys.stderr, 'It seems that you run Ganga for the first time'
244 print >> sys.stderr, 'Ganga will send a udp packet each time you start it in order to help the development team understand how ganga is used. You can disable this in the config file by resetting [Configuration]UsageMonitoringURL= '
245 if self.options.generate_config:
246 yes = 'Y'
247 else:
248 yes = raw_input('Would you like to create config file ~/.gangarc with standard settings ([y]/n) ?')
249
250 if yes == '' or yes[0:1].upper() == 'Y':
251 generate(self.default_config_file)
252 raw_input('Press <Enter> to continue.')
253
254 os.mkdir(gangadir)
255
256 else:
257
258
259 def store_backup(f):
260 if os.path.exists(f):
261 i = 0
262 for i in range(100):
263 bn = "%s.%.2d"%(f,i)
264 if not os.path.exists(bn):
265 os.rename(self.default_config_file,bn)
266 return bn
267 raise ValueError('too many backup files')
268
269 if self.options.generate_config:
270 try:
271 backup_name = store_backup(self.default_config_file)
272 except Exception,x:
273 self.exit('Failed to create backup file %s'%backup_name)
274 else:
275 print >> sys.stderr, 'Copied current config file to',backup_name
276 generate(self.default_config_file)
277 sys.exit(0)
278
279
307
308
309 def set_cmdline_config_options(sects=None):
310 try:
311 opts = parse_cmdline_config_options(self.options.cmdline_options)
312 for section,option,val in opts:
313 should_set = True
314 if not sects is None and not section in sects:
315 should_set = False
316 if should_set:
317 config = Ganga.Utility.Config.setSessionValue(section,option,val)
318 except ConfigError,x:
319 self.exit('command line option error: %s'%str(x))
320
321
322 set_cmdline_config_options(sects=['Logging'])
323
324
325 if self.options.rexec and not os.environ.has_key('GANGA_INTERNAL_PROCREEXEC') and not self.options.generate_config and not os.environ.has_key('GANGA_NEVER_REEXEC'):
326 if self.options.force_loglevel != 'DEBUG':
327 self.options.force_loglevel = 'CRITICAL'
328 pass
329 else:
330 if logLevel: self.options.force_loglevel = logLevel
331 if self.options.force_loglevel in (None,'DEBUG'):
332 print >> sys.stderr, self.hello_string
333
334
335 if self.options.config_file is None:
336 self.options.config_file = self.default_config_file
337
338
339
340 import Ganga.Utility.logging
341
342 Ganga.Utility.logging.force_global_level(self.options.force_loglevel)
343
344 try:
345 cf = file(self.options.config_file)
346 first_line = cf.readline()
347 import re
348 r = re.compile(r'# Ganga configuration file \(\$[N]ame: (?P<version>\S+) \$\)').match(first_line)
349 if not r:
350 Ganga.Utility.logging.getLogger().error('file %s does not seem to be a Ganga config file',self.options.config_file)
351 Ganga.Utility.logging.getLogger().error('try -g option to create valid ~/.gangarc')
352 else:
353 cv = r.group('version').split('-')
354 if cv[1] == '4':
355 Ganga.Utility.logging.getLogger().error('file %s is old an Ganga 4 configuration file (%s)',self.options.config_file,r.group('version'))
356 Ganga.Utility.logging.getLogger().error('try -g option to create valid ~/.gangarc')
357 else:
358 if cv[1] != '5':
359 Ganga.Utility.logging.getLogger().error('file %s was created by a development release (%s)',self.options.config_file, r.group('version'))
360 Ganga.Utility.logging.getLogger().error('try -g option to create valid ~/.gangarc')
361 except IOError,x:
362 pass
363
364 if self.options.config_path is None:
365 try:
366 self.options.config_path = os.environ['GANGA_CONFIG_PATH']
367 except KeyError:
368 self.options.config_path = ''
369
370 import Ganga.Utility.files, Ganga.Utility.util
371 self.options.config_path = Ganga.Utility.files.expandfilename(self.options.config_path)
372
373 try:
374 hostname = Ganga.Utility.util.hostname()
375 except Exception,x:
376 hostname = 'localhost'
377
378
379
380
381 syscfg = Ganga.Utility.Config.makeConfig('System',"parameters of this ganga session (read-only)",cfile=False)
382 syscfg.addOption('GANGA_VERSION',_gangaVersion,'')
383 syscfg.addOption('GANGA_PYTHONPATH',_gangaPythonPath,'location of the ganga core packages')
384 syscfg.addOption('GANGA_CONFIG_PATH',self.options.config_path, 'site/group specific configuration files as specified by --config-path or GANGA_CONFIG_PATH variable')
385 syscfg.addOption('GANGA_CONFIG_FILE',self.options.config_file,'current user config file used')
386 syscfg.addOption('GANGA_HOSTNAME',hostname,'local hostname where ganga is running')
387
388 def deny_modification(name,x):
389 raise Ganga.Utility.Config.ConfigError('Cannot modify [System] settings (attempted %s=%s)'%(name,x))
390 syscfg.attachUserHandler(deny_modification,None)
391 syscfg.attachSessionHandler(deny_modification,None)
392
393 import Ganga.Utility.Config
394
395
396
397
398 from Ganga.Utility.Config import Config, makeConfig
399 config = makeConfig( "Configuration", "global configuration parameters.\nthis is a catch all section." )
400 config.addOption('SCRIPTS_PATH','Ganga/scripts',"""the search path to scripts directory.
401 When running a script from the system shell (e.g. ganga script) this path is used to search for script""")
402
403 config.addOption('LOAD_PATH', '', "the search path for the load() function")
404 config.addOption('RUNTIME_PATH','',"""path to runtime plugin packages where custom handlers may be added.
405 Normally you should not worry about it.
406 If an element of the path is just a name (like in the example below)
407 then the plugins will be loaded using current python path. This means that
408 some packages such as GangaTest may be taken from the release area.""",
409 examples="""RUNTIME_PATH = GangaGUI
410 RUNTIME_PATH = /my/SpecialExtensions:GangaTest """)
411
412 config.addOption('TextShell','IPython',""" The type of the interactive shell: IPython (cooler) or Console (limited)""")
413 config.addOption('StartupGPI','','block of GPI commands executed at startup')
414 config.addOption('gangadir',Ganga.Utility.Config.expandvars(None,'~/gangadir'),'Location of local job repositories and workspaces. Default is ~/gangadir but in somecases (such as LSF CNAF) this needs to be modified to point to the shared file system directory.',filter=Ganga.Utility.Config.expandvars)
415 config.addOption('repositorytype','LocalXML','Type of the repository.',examples='LocalXML')
416 config.addOption('workspacetype','LocalFilesystem','Type of workspace. Workspace is a place where input and output sandbox of jobs are stored. Currently the only supported type is LocalFilesystem.')
417
418 config.addOption('user','','User name. The same person may have different roles (user names) and still use the same gangadir. Unless explicitly set this option defaults to the real user name.')
419
420 import getpass
421 try:
422 config.options['user'].default_value = getpass.getuser()
423 except Exception,x:
424 raise Ganga.Utility.Config.ConfigError('Cannot get default user name'+str(x))
425
426 gpiconfig = Ganga.Utility.Config.makeConfig('GPI_Semantics','Customization of GPI behaviour. These options may affect the semantics of the Ganga GPI interface (what may result in a different behaviour of scripts and commands).')
427
428 gpiconfig.addOption('job_submit_keep_going', False, 'Keep on submitting as many subjobs as possible. Option to j.submit(), see Job class for details')
429 gpiconfig.addOption('job_submit_keep_on_fail', False,'Do not revert job to new status even if submission failed. Option to j.submit(), see Job class for details')
430
431 ipconfig = Ganga.Utility.Config.makeConfig('TextShell_IPython','''IPython shell configuration
432 See IPython manual for more details:
433 http://ipython.scipy.org/doc/manual''')
434 try:
435 from IPython import __version__ as ipver
436 except ImportError:
437 ipver="0.6.13"
438 if ipver == "0.6.13":
439 noautocall = "'-noautocall'"
440 else:
441 noautocall = "'-autocall','0'"
442
443 ipconfig.addOption('args',"['-colors','LightBG', %s]"%noautocall,'FIXME')
444
445
446 import spyware
447
448 import Ganga.Utility.ColourText
449
450 disply_config = makeConfig('Display', """control the content and appearence of printing ganga objects: attributes,colours,etc.
451 If ANSI text colours are enabled, then individual colours may be specified like this:
452 fg.xxx - Foreground: %s
453 bg.xxx - Background: %s
454 fx.xxx - Effects: %s
455 """ % (Ganga.Utility.ColourText.Foreground.__doc__, Ganga.Utility.ColourText.Background.__doc__,Ganga.Utility.ColourText.Effects.__doc__ ))
456
457
458 shellconfig = makeConfig( "Shell", "configuration parameters for internal Shell utility." )
459 shellconfig.addOption('IgnoredVars',['_','SHVL','PWD'],'list of env variables not inherited in Shell environment')
460
461
462
463
464 config_files = Ganga.Utility.Config.expandConfigPath(self.options.config_path,_gangaPythonPath)
465 config_files.reverse()
466 config_files.append(self.options.config_file)
467
468
469
470
471 system_vars = {}
472 for opt in syscfg:
473 system_vars[opt]=syscfg[opt]
474
475 Ganga.Utility.Config.configure(config_files,system_vars)
476
477
478
479
480
481 Ganga.Utility.logging.bootstrap()
482
483 if not self.options.monitoring:
484 self.options.cmdline_options.append('[PollThread]autostart=False')
485 self.logger = Ganga.Utility.logging.getLogger(modulename=True)
486 self.logger.debug('default user name is %s',config['user'])
487 self.logger.debug('user specified cmdline_options: %s',str(self.options.cmdline_options))
488
489
490
491
492
493 set_cmdline_config_options()
494
495 self.new_user_wizard()
496
497 if self.options.GUI:
498
499
500 config.setSessionValue('TextShell','GUI')
501 config.setSessionValue('RUNTIME_PATH','GangaGUI')
502
503 if self.options.TEST:
504
505
506 config.setSessionValue('RUNTIME_PATH','GangaTest')
507
508
509
510
543
544 paths = map(transform,filter(lambda x:x, config['RUNTIME_PATH'].split(':')))
545
546 for path in paths:
547 r = RuntimePackage(path)
548 except KeyError:
549 pass
550
551
552 if not os.environ.has_key('GANGA_INTERNAL_PROCREEXEC') and not os.environ.has_key('GANGA_NEVER_REEXEC'):
553 self.logger.debug('initializing runtime environment')
554
555 for r in allRuntimes.values():
556 try:
557 _env = r.getEnvironment()
558 if _env:
559 os.environ.update(_env)
560 except Exception,x:
561 Ganga.Utility.logging.log_user_exception()
562 self.logger.error("can't get environment for %s, possible problem with the return value of getEvironment()",r.name,)
563 raise
564
565
566
567
568 if self.options.rexec:
569 self.logger.debug('re-executing the process for LD_LIBRARY_PATH changes to take effect')
570 os.environ['GANGA_INTERNAL_PROCREEXEC'] = '1'
571 prog = os.path.normpath(sys.argv[0])
572 os.execv(prog,sys.argv)
573
574 else:
575 self.logger.debug('skipped the environment initialization -- the processed has been re-execed and setup was done already')
576
577
578 if os.environ.has_key('GANGA_INTERNAL_PROCREEXEC'):
579 del os.environ['GANGA_INTERNAL_PROCREEXEC']
580
581
583 import Ganga.Utility.Config
584 config = Ganga.Utility.Config.getConfig('Configuration')
585
586
587 if not os.path.exists(os.path.join(config['gangadir'],'repository',config['user'],'LocalXML','6.0')):
588 print TRANSITION_MESSAGE_545
589
590 from Ganga.Core import GangaException
591 from Ganga.Utility.Runtime import allRuntimes
592 import Ganga.Utility.logging
593
594
595 for r in allRuntimes.values():
596 try:
597 r.loadPlugins()
598 except Exception,x:
599 Ganga.Utility.logging.log_user_exception()
600 self.logger.error("problems with loading plugins for %s -- ignored",r.name,)
601
602 from GPIexport import exportToGPI
603
604 from Ganga.Utility.Plugin import allPlugins
605
606
607 for k in allPlugins.allCategories():
608 for n in allPlugins.allClasses(k):
609 cls = allPlugins.find(k,n)
610 if not cls._declared_property('hidden'):
611 exportToGPI(n,cls._proxyClass,'Classes')
612
613
614
615 default_plugins_cfg = Ganga.Utility.Config.makeConfig('Plugins','''General control of plugin mechanism.
616 Set the default plugin in a given category.
617 For example:
618 default_applications = DaVinci
619 default_backends = LCG
620 ''')
621
622 for opt in default_plugins_cfg:
623 try:
624 category,tag = opt.split('_')
625 except ValueError:
626 self.logger.warning("do not understand option %s in [Plugins]",opt)
627 else:
628 if tag == 'default':
629 try:
630 allPlugins.setDefault(category,default_plugins_cfg[opt])
631 except Ganga.Utility.Plugin.PluginManagerError,x:
632 self.logger.warning('cannot set the default plugin "%s": %s',opt,x)
633 else:
634 self.logger.warning("do not understand option %s in [Plugins]",opt)
635
636
637
638 batch_default_name = Ganga.Utility.Config.getConfig('Configuration').getEffectiveOption('Batch')
639 try:
640 batch_default = allPlugins.find('backends',batch_default_name)
641 except Exception,x:
642 raise Ganga.Utility.Config.ConfigError('Check configuration. Unable to set default Batch backend alias (%s)'%str(x))
643 else:
644 allPlugins.add(batch_default,'backends','Batch')
645 exportToGPI('Batch',batch_default._proxyClass,'Classes')
646
647 from Ganga.GPIDev.Base import ProtectedAttributeError, ReadOnlyObjectError, GangaAttributeError
648 from Ganga.GPIDev.Lib.Job.Job import JobError
649
650 exportToGPI('GangaAttributeError',GangaAttributeError,'Exceptions')
651 exportToGPI('ProtectedAttributeError',ProtectedAttributeError,'Exceptions')
652 exportToGPI('ReadOnlyObjectError',ReadOnlyObjectError,'Exceptions')
653 exportToGPI('JobError',JobError,'Exceptions')
654
655
656 import Ganga.GPIDev.MonitoringServices
657
658 def license():
659 'Print the full license (GPL)'
660 print file(os.path.join(_gangaPythonPath,'..','LICENSE_GPL')).read()
661
662 exportToGPI('license',license,'Functions')
663
664
665 from Ganga.GPIDev.Base.Proxy import GPIProxyObjectFactory
666 from Ganga.GPIDev.Credentials import getCredential
667
668
669
670
671
672 credential = getCredential(name = 'GridProxy', create = False)
673 if credential:
674 exportToGPI('gridProxy',GPIProxyObjectFactory(credential),'Objects','Grid proxy management object.')
675
676 credential = getCredential('AfsToken')
677 if credential:
678 exportToGPI('afsToken',GPIProxyObjectFactory(credential),'Objects','AFS token management object.')
679
680
681
682 from Ganga.GPIDev.Persistency import export, load
683 exportToGPI('load',load,'Functions')
684 exportToGPI('export',export,'Functions')
685
686 def typename(obj):
687 'Return a name of Ganga object as a string, example: typename(j.application) -> "DaVinci"'
688 return obj._impl._name
689
690 def categoryname(obj):
691 'Return a category of Ganga object as a string, example: categoryname(j.application) -> "applications"'
692 return obj._impl._category
693
694 def plugins(category=None):
695 """List loaded plugins.
696
697 If no argument is given return a dictionary of all loaded plugins.
698 Keys are category name. Values are lists of plugin names in each
699 category.
700
701 If a category is specified (for example 'splitters') return a list
702 of all plugin names in this category.
703 """
704 from Ganga.Utility.Plugin import allPlugins
705 if category:
706 return allPlugins.allClasses(category).keys()
707 else:
708 d = {}
709 for c in allPlugins.allCategories():
710 d[c] = allPlugins.allCategories()[c].keys()
711 return d
712
713
714 def list_plugins(category):
715 'List all plugins in a given category, OBSOLETE: use plugins(category)'
716 self.logger.warning('This function is deprecated, use plugins("%s") instead',category)
717 from Ganga.Utility.Plugin import allPlugins
718 return allPlugins.allClasses(category).keys()
719
720 def applications():
721 'return a list of all available applications, OBSOLETE: use plugins("applications")'
722 return list_plugins('applications')
723
724 def backends():
725 'return a list of all available backends, OBSOLETE: use plugins("backends")'
726 return list_plugins('backends')
727
728 exportToGPI('applications',applications,'Functions')
729 exportToGPI('backends',backends,'Functions')
730 exportToGPI('list_plugins',list_plugins,'Functions')
731
732
733 exportToGPI('typename',typename,'Functions')
734 exportToGPI('categoryname',categoryname,'Functions')
735 exportToGPI('plugins',plugins,'Functions')
736
737
738 def force_job_completed(j):
739 "obsoleted, use j.force_status('completed') instead"
740 raise GangaException("obsoleted, use j.force_status('completed') instead")
741
742 def force_job_failed(j):
743 "obsoleted, use j.force_status('failed') instead"
744 raise GangaException("obsoleted, use j.force_status('failed') instead")
745
746 exportToGPI('force_job_completed',force_job_completed,'Functions')
747 exportToGPI('force_job_failed',force_job_failed,'Functions')
748
749
750 import Repository_runtime
751 import Ganga.Core
752 import associations
753
754
755
756 for n,r in zip(allRuntimes.keys(),allRuntimes.values()):
757 try:
758 r.bootstrap(Ganga.GPI.__dict__)
759 except Exception,x:
760 Ganga.Utility.logging.log_user_exception()
761 self.logger.error('problems with bootstrapping %s -- ignored',n)
762
763
764 import Ganga.GPIDev.Lib.Registry
765 from Ganga.GPIDev.Lib.JobTree import JobTree,TreeError
766 import Ganga.GPIDev.Lib.Tasks
767
768
769 for n,k,d in Repository_runtime.bootstrap():
770
771 exportToGPI(n,k,'Objects',d)
772
773
774 from Ganga.Core.GangaRepository import getRegistry
775 jobtree = GPIProxyObjectFactory(getRegistry("jobs").getJobTree())
776 exportToGPI('jobtree',jobtree,'Objects','Logical tree view of the jobs')
777 exportToGPI('TreeError',TreeError,'Exceptions')
778
779
780 import Workspace_runtime
781 Workspace_runtime.bootstrap()
782
783
784
785
786
787
788
789 from Ganga.GPIDev.Base.VPrinter import full_print
790 exportToGPI('full_print',full_print,'Functions')
791
792
793 Ganga.Core.bootstrap(Ganga.GPI.jobs._impl,self.interactive)
794
795 import Ganga.GPIDev.Lib.Config
796 exportToGPI('config',Ganga.GPIDev.Lib.Config.config,'Objects','access to Ganga configuration')
797 exportToGPI('ConfigError',Ganga.GPIDev.Lib.Config.ConfigError,'Exceptions')
798
799 from Ganga.Utility.feedback_report import report
800
801 exportToGPI('report',report,'Functions')
802
803
804 Ganga.GPIDev.Lib.Config.bootstrap()
805
806
807
808
809 for r in allRuntimes.values():
810 try:
811 r.postBootstrapHook()
812 except Exception,x:
813 Ganga.Utility.logging.log_user_exception()
814 self.logger.error("problems with post bootstrap hook for %s",r.name,)
815
817 """
818 run the testing framework
819 """
820
821 try:
822 from GangaTest.Framework import runner
823 from GangaTest.Framework import htmlizer
824 from GangaTest.Framework import xmldifferencer
825
826 tfconfig = Ganga.Utility.Config.getConfig('TestingFramework')
827 rc = 1
828 if tfconfig['EnableTestRunner']:
829 self.logger.info("Starting Ganga Test Runner")
830
831 if not self.args:
832 self.logger.warning("Please specify the tests to run ( i.e. ganga --test Ganga/test )")
833 return -1
834
835 rc = runner.start(test_selection=" ".join(self.args))
836 else:
837 self.logger.info("Test Runner is disabled (set EnableTestRunner=True to enable it)")
838
839 if rc > 0 and tfconfig['EnableHTMLReporter']:
840 self.logger.info("Generating tests HTML reports")
841 rc = htmlizer.main(tfconfig)
842 elif rc > 0 and tfconfig['EnableXMLDifferencer']:
843 self.logger.info("Generating difference HTML reports")
844 rc = xmldifferencer.main(self.args)
845 return rc
846 except ImportError,e:
847 self.logger.error("You need GangaTest external package in order to invoke Ganga test-runner.")
848 print e
849 return -1
850
851
852
853 - def run(self,local_ns=None):
854
855 if self.options.webgui == True:
856 from Ganga.Runtime.http_server import start_server
857 start_server()
858
859 def override_credits():
860 credits._Printer__data += '\n\nGanga: The Ganga Developers (http://cern.ch/ganga)\n'
861 copyright._Printer__data += '\n\nCopyright (c) 2000-2008 The Ganga Developers (http://cern.ch/ganga)\n'
862
863 if local_ns is None:
864 import __main__
865 local_ns = __main__.__dict__
866
867 self.local_ns = local_ns
868
869
870 from Ganga.Utility.Runtime import allRuntimes
871 for r in allRuntimes.values():
872 r.loadTemplates( local_ns )
873
874
875 fileName = fullpath('~/.ganga.py')
876 if os.path.exists(fileName):
877 try:
878 execfile( fileName, local_ns )
879 except Exception, x:
880 self.logger.error('Failed to source %s (Error was "%s"). Check your file for syntax errors.', fileName, str(x))
881
882 from Ganga.Utility.Config import getConfig
883 config=getConfig('Configuration')
884
885 from Ganga.Utility.Config import getConfig
886 config=getConfig('Configuration')
887 if config['StartupGPI']:
888
889
890
891 code = config['StartupGPI'].replace('\\t','\t').replace('\\n','\n')
892 exec code in local_ns
893
894
895 import spyware
896
897
898 runs_script = len(self.args)>0
899 session_type = config['TextShell']
900 if runs_script:
901 if not self.interactive:
902 session_type = 'batch'
903 else:
904 session_type += 'startup_script'
905
906 spyware.ganga_started(session_type,interactive=self.interactive,GUI=self.options.GUI,webgui=self.options.webgui,script_file=runs_script, text_shell=config['TextShell'],test_framework=self.options.TEST)
907
908 if self.options.TEST:
909 sys.argv = self.args
910 try:
911 rc = self.startTestRunner()
912 except (KeyboardInterrupt, SystemExit):
913 self.logger.warning('Test Runner interrupted!')
914 sys.exit(1)
915 sys.exit(rc)
916
917 if len(self.args) > 0:
918
919 saved_argv = sys.argv
920 sys.argv = self.args
921
922 import Ganga.Utility.Runtime
923 path = Ganga.Utility.Runtime.getSearchPath()
924 script = Ganga.Utility.Runtime.getScriptPath( self.args[ 0 ], path )
925
926 if script:
927 execfile( script, local_ns )
928 else:
929 self.logger.error( "'%s' not found" % self.args[ 0 ] )
930 self.logger.info( "Searched in path %s" % path )
931 sys.exit(1)
932 sys.argv = saved_argv
933
934
935 if not self.interactive:
936 sys.exit(0)
937
938
939
940
941 def _display(obj):
942 if isinstance(obj,type):
943 print
944 print obj
945 return
946 if hasattr(obj,'_display'):
947 print
948 print obj._display(1)
949 return
950 if hasattr(obj,'_impl') and hasattr(obj._impl,'_display'):
951 print
952 print obj._display(1)
953 return
954 print obj
955
956 shell = config['TextShell']
957
958 import Ganga.Utility.Config.Config
959
960
961 if shell == 'IPython':
962 ipconfig = Ganga.Utility.Config.getConfig('TextShell_IPython')
963
964
965 args = eval(ipconfig['args'])
966
967 try:
968 self.logger.warning('Environment variable IPYTHONDIR=%s exists and overrides the default history file for Ganga IPython commands',os.environ['IPYTHONDIR'])
969 except KeyError:
970 newpath = os.path.expanduser('~/.ipython-ganga')
971 oldpath = os.path.expanduser('~/.ipython')
972 os.environ['IPYTHONDIR'] = newpath
973 if not os.path.exists(newpath) and os.path.exists(oldpath):
974 self.logger.warning('Default location of IPython history files has changed.')
975 self.logger.warning('Ganga will now try to copy your old settings from %s to the new path %s. If you do not want that, quit Ganga and wipe off the content of new path: rm -rf %s/*',oldpath,newpath,newpath)
976 import shutil
977 shutil.copytree(oldpath,newpath)
978
979
980
981
982
983 from Ganga.Utility.logging import enableCaching
984
985 import Ganga.Utility.logging
986 Ganga.Utility.logging.enableCaching()
987
988 def ganga_prompt():
989 if Ganga.Utility.logging.cached_screen_handler:
990 Ganga.Utility.logging.cached_screen_handler.flush()
991
992 credentialsWarningPrompt = ''
993
994 from Ganga.Core.InternalServices import Coordinator
995 if not Coordinator.servicesEnabled:
996 invalidCreds = Coordinator.getMissingCredentials()
997 if invalidCreds:
998 credentialsWarningPrompt = '[%s required]' % ','.join(invalidCreds)
999 if credentialsWarningPrompt:
1000 credentialsWarningPrompt+='\n'
1001
1002 return credentialsWarningPrompt
1003
1004 from IPython.Shell import IPShellEmbed
1005
1006 ipopts = {'prompt_in1':'${ganga_prompt()}In [\#]:',
1007 'readline_omit__names':2
1008 }
1009 ipshell = IPShellEmbed(argv=args,rc_override=ipopts)
1010
1011 ipshell.IP.outputcache.display = _display
1012 ipshell.IP.user_ns['ganga_prompt'] = ganga_prompt
1013
1014
1015 import IPythonMagic
1016
1017
1018
1019 def ganga_exc_handler(self,etype,value,tb):
1020
1021 print '\n',value,
1022 from Ganga.Core import GangaException
1023 ipshell.IP.set_custom_exc((GangaException,),ganga_exc_handler)
1024 override_credits()
1025 ret = ipshell(local_ns=local_ns,global_ns=local_ns)
1026 elif shell == 'GUI':
1027 override_credits()
1028 import GangaGUI.Ganga_GUI
1029 GangaGUI.Ganga_GUI.main()
1030 else:
1031 override_credits()
1032 import code
1033 sys.displayhook = _display
1034 c = code.InteractiveConsole(locals=local_ns)
1035 c.interact()
1036
1038
1039 import sys
1040
1041 if self.options.force_loglevel == 'DEBUG':
1042 import traceback
1043 traceback.print_exc(file=sys.stderr)
1044 else:
1045 print >>sys.stderr, x
1046 print >>sys.stderr, '(consider --debug option for more information)'
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386