Best Python code snippet using pytest-benchmark
SConscript
Source:SConscript
1import os2import subprocess3import sys4import platform5import atexit6import time7import SCons.Util8# because of an implementation detail commandlines are limited to 10000 characters on windows using mingw. the following fix was copied from9# http://scons.org/wiki/LongCmdLinesOnWin32 and circumvents this issue.10class ourSpawn:11 def ourspawn(self, sh, escape, cmd, args, env):12 newargs = ' '.join(args[1:])13 cmdline = cmd + " " + newargs14 startupinfo = subprocess.STARTUPINFO()15 startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW16 proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE,17 stderr=subprocess.PIPE, startupinfo=startupinfo, shell=False, env=env)18 data, err = proc.communicate()19 rv = proc.wait()20 if rv:21 print("=====")22 print(err)23 print("=====")24 return rv25def SetupSpawn(env):26 buf = ourSpawn()27 buf.ourenv = env28 env['SPAWN'] = buf.ourspawn29def FatalError(message):30 print(message)31 raise SystemExit(1)32#wrapper around SCons' AddOption33def AddSconsOption(name, default, hasArgs, help):34 AddOption("--{0}".format(name), dest=name, action=("store" if hasArgs else "store_true"), default=default, help=help)35AddSconsOption('win', False, False, "Target Windows.")36AddSconsOption('lin', False, False, "Target Linux.")37AddSconsOption('mac', False, False, "Target Mac OS X.")38AddSconsOption('msvc', False, False, "Use the Microsoft Visual Studio compiler.")39AddSconsOption("tool", False, True, "Tool prefix appended before gcc/g++.")40AddSconsOption('beta', False, False, "Beta build.")41AddSconsOption('save-version', False, True, "Save version.")42AddSconsOption('minor-version', False, True, "Minor version.")43AddSconsOption('build-number', False, True, "Build number.")44AddSconsOption('snapshot', False, False, "Snapshot build.")45AddSconsOption('snapshot-id', False, True, "Snapshot build ID.")46AddSconsOption('64bit', False, False, "Compile a 64 bit binary.")47AddSconsOption('32bit', False, False, "Compile a 32 bit binary.")48AddSconsOption("universal", False, False, "compile universal binaries on Mac OS X.")49AddSconsOption('no-sse', False, False, "Disable SSE optimizations.")50AddSconsOption('sse', True, False, "Enable SSE optimizations (default).")51AddSconsOption('sse2', True, False, "Enable SSE2 optimizations (default).")52AddSconsOption('sse3', False, False, "Enable SSE3 optimizations.")53AddSconsOption('native', False, False, "Enable optimizations specific to your cpu.")54AddSconsOption('release', False, False, "Enable loop / compiling optimizations.")55AddSconsOption('debugging', False, False, "Compile with debug symbols.")56AddSconsOption('symbols', False, False, "Preserve (don't strip) symbols")57AddSconsOption('static', False, False, "Compile statically.")58AddSconsOption('opengl', False, False, "Build with OpenGL interface support.")59AddSconsOption('opengl-renderer', False, False, "Build with OpenGL renderer support (turns on --opengl).") #Note: this has nothing to do with --renderer, only tells the game to render particles with opengl60AddSconsOption('renderer', False, False, "Build the save renderer.")61AddSconsOption('font', False, False, "Build the font editor.")62AddSconsOption('wall', False, False, "Error on all warnings.")63AddSconsOption('no-warnings', False, False, "Disable all compiler warnings.")64AddSconsOption('nolua', False, False, "Disable Lua.")65AddSconsOption('luajit', False, False, "Enable LuaJIT")66AddSconsOption('lua52', False, False, "Compile using lua 5.2")67AddSconsOption('nofft', False, False, "Disable FFT.")68AddSconsOption("output", False, True, "Executable output name.")69#detect platform automatically, but it can be overrided70tool = GetOption('tool')71isX86 = platform.machine() in ["amd64", "AMD64", "i386", "i686", "x86", "x86_64"]72platform = compilePlatform = platform.system()73if GetOption('win'):74 platform = "Windows"75elif GetOption('lin'):76 platform = "Linux"77elif GetOption('mac'):78 platform = "Darwin"79elif compilePlatform not in ["Linux", "Windows", "Darwin", "FreeBSD"]:80 FatalError("Unknown platform: {0}".format(platform))81msvc = GetOption('msvc')82if msvc and platform != "Windows":83 FatalError("Error: --msvc only works on windows")84#Create SCons Environment85if GetOption('msvc'):86 env = Environment(tools=['default'], ENV=os.environ, TARGET_ARCH='x86')87elif platform == "Windows" and not GetOption('msvc'):88 env = Environment(tools=['mingw'], ENV=os.environ)89else:90 env = Environment(tools=['default'], ENV=os.environ)91#attempt to automatically find cross compiler92if not tool and compilePlatform == "Linux" and compilePlatform != platform:93 if platform == "Darwin":94 crossList = ["i686-apple-darwin9", "i686-apple-darwin10"]95 elif not GetOption('64bit'):96 crossList = ["mingw32", "i686-w64-mingw32", "i386-mingw32msvc", "i486-mingw32msvc", "i586-mingw32msvc", "i686-mingw32msvc"]97 else:98 crossList = ["x86_64-w64-mingw32", "amd64-mingw32msvc"]99 for i in crossList:100 #found a cross compiler, set tool here, which will update everything in env later101 if WhereIs("{0}-g++".format(i)):102 tool = i+"-"103 break104 if not tool:105 print("Could not automatically find cross compiler, use --tool to specify manually")106#set tool prefix107#more things may need to be set (http://clam-project.org/clam/trunk/CLAM/scons/sconstools/crossmingw.py), but this works for us108if tool:109 env['CC'] = tool+env['CC']110 env['CXX'] = tool+env['CXX']111 if platform == "Windows":112 env['RC'] = tool+env['RC']113 env['STRIP'] = tool+'strip'114 if os.path.isdir("/usr/{0}/bin".format(tool[:-1])):115 env['ENV']['PATH'] = "/usr/{0}/bin:{1}".format(tool[:-1], os.environ['PATH'])116 if platform == "Darwin":117 sdlconfigpath = "/usr/lib/apple/SDKs/MacOSX10.5.sdk/usr/bin"118 if os.path.isdir(sdlconfigpath):119 env['ENV']['PATH'] = "{0}:{1}".format(sdlconfigpath, env['ENV']['PATH'])120#copy environment variables because scons doesn't do this by default121for var in ["CC","CXX","LD","LIBPATH","STRIP"]:122 if var in os.environ:123 env[var] = os.environ[var]124 print("copying environment variable {0}={1!r}".format(var,os.environ[var]))125# variables containing several space separated things126for var in ["CFLAGS","CCFLAGS","CXXFLAGS","LINKFLAGS","CPPDEFINES","CPPPATH"]:127 if var in os.environ:128 if var in env:129 env[var] += SCons.Util.CLVar(os.environ[var])130 else:131 env[var] = SCons.Util.CLVar(os.environ[var])132 print("copying environment variable {0}={1!r}".format(var,os.environ[var]))133#Used for intro text / executable name, actual bit flags are only set if the --64bit/--32bit command line args are given134def add32bitflags(env):135 env["BIT"] = 32136def add64bitflags(env):137 if platform == "Windows":138 env.Append(CPPDEFINES=['__CRT__NO_INLINE'])139 env.Append(LINKFLAGS=['-Wl,--stack=16777216'])140 env.Append(CPPDEFINES=['_64BIT'])141 env["BIT"] = 64142#add 32/64 bit defines before configuration143if GetOption('64bit'):144 env.Append(LINKFLAGS=['-m64'])145 env.Append(CCFLAGS=['-m64'])146 add64bitflags(env)147elif GetOption('32bit'):148 env.Append(LINKFLAGS=['-m32'])149 env.Append(CCFLAGS=['-m32'])150 add32bitflags(env)151if GetOption('universal'):152 if platform != "Darwin":153 FatalError("Error: --universal only works on Mac OS X")154 else:155 env.Append(CCFLAGS=['-arch', 'i386', '-arch', 'x86_64'])156 env.Append(LINKFLAGS=['-arch', 'i386', '-arch', 'x86_64'])157env.Append(CPPPATH=['src/', 'data/', 'generated/'])158if GetOption("msvc"):159 if GetOption("static"):160 env.Append(LIBPATH=['StaticLibs/'])161 else:162 env.Append(LIBPATH=['Libraries/'])163 env.Append(CPPPATH=['includes/'])164#Check 32/64 bit165def CheckBit(context):166 context.Message('Checking if 64 bit... ')167 program = """#include <stdlib.h>168 #include <stdio.h>169 int main() {170 printf("%d", (int)sizeof(size_t));171 return 0;172 }173 """174 ret = context.TryCompile(program, '.c')175 if ret == 0:176 return False177 ret = context.TryRun(program, '.c')178 if ret[1] == '':179 return False180 context.Result(int(ret[1]) == 8)181 if int(ret[1]) == 8:182 print("Adding 64 bit compile flags")183 add64bitflags(context.env)184 elif int(ret[1]) == 4:185 print("Adding 32 bit compile flags")186 add32bitflags(context.env)187 return ret[1]188#Custom function to check for Mac OS X frameworks189def CheckFramework(context, framework):190 import SCons.Conftest191 #Extreme hack, TODO: maybe think of a better one (like replicating CheckLib here) or at least just fix the message192 oldLinkFlags = env["LINKFLAGS"]193 context.env.Append(LINKFLAGS=["-framework", framework])194 context.Display("Checking for Darwin Framework {0}...".format(framework))195 ret = SCons.Conftest.CheckLib(context, ["m"], autoadd = 0)196 context.did_show_result = 1197 if not ret:198 context.env.Append(LINKFLAGS=["-framework", framework])199 if framework != "Cocoa":200 env.Append(CPPPATH=['/Library/Frameworks/{0}.framework/Headers/'.format(framework)])201 else:202 context.env.Replace(LINKFLAGS=oldLinkFlags)203 return not ret204#function that finds libraries and appends them to LIBS205def findLibs(env, conf):206 #Windows specific libs207 if platform == "Windows":208 if msvc:209 libChecks = ['shell32', 'wsock32', 'user32', 'Advapi32', 'ws2_32']210 if GetOption('static'):211 libChecks += ['imm32', 'version', 'Ole32', 'OleAut32']212 for i in libChecks:213 if not conf.CheckLib(i):214 FatalError("Error: some windows libraries not found or not installed, make sure your compiler is set up correctly")215 else:216 if not conf.CheckLib('mingw32') or not conf.CheckLib('ws2_32'):217 FatalError("Error: some windows libraries not found or not installed, make sure your compiler is set up correctly")218 if not GetOption('renderer') and not conf.CheckLib('SDL2main'):219 FatalError("libSDL2main not found or not installed")220 #Look for SDL221 runSdlConfig = platform == "Linux" or compilePlatform == "Linux" or platform == "FreeBSD"222 #if platform == "Darwin" and conf.CheckFramework("SDL"):223 # runSdlConfig = False224 if not conf.CheckLib("SDL2"):225 FatalError("SDL2 development library not found or not installed")226 if runSdlConfig:227 try:228 env.ParseConfig('sdl2-config --cflags')229 if GetOption('static'):230 env.ParseConfig('sdl2-config --static-libs')231 else:232 env.ParseConfig('sdl2-config --libs')233 except:234 pass235 #look for SDL.h236 if conf.CheckCHeader('SDL2/SDL.h'):237 env.Append(CPPDEFINES=["SDL_INC"])238 elif not conf.CheckCHeader('SDL.h'):239 FatalError("SDL.h not found")240 if not GetOption('nolua') and not GetOption('renderer') and not GetOption('font'):241 #Look for Lua242 if platform == "FreeBSD":243 luaver = "lua-5.1"244 else:245 luaver = "lua5.1"246 if GetOption('luajit'):247 if not conf.CheckLib(['luajit-5.1', 'luajit5.1', 'luajit2.0', 'luajit', 'libluajit']):248 FatalError("luajit development library not found or not installed")249 env.Append(CPPDEFINES=["LUAJIT"])250 luaver = "luajit"251 elif GetOption('lua52'):252 if not conf.CheckLib(['lua5.2', 'lua-5.2', 'lua52', 'lua']):253 FatalError("lua5.2 development library not found or not installed")254 env.Append(CPPDEFINES=["LUA_COMPAT_ALL"])255 if platform == "FreeBSD":256 luaver = "lua-5.2"257 else:258 luaver = "lua5.2"259 else:260 if not conf.CheckLib(['lua5.1', 'lua-5.1', 'lua51', 'lua']):261 if platform != "Darwin" or not conf.CheckFramework("Lua"):262 FatalError("lua5.1 development library not found or not installed")263 foundpkg = False264 if platform == "Linux" or platform == "FreeBSD":265 try:266 env.ParseConfig("pkg-config --cflags {0}".format(luaver))267 env.ParseConfig("pkg-config --libs {0}".format(luaver))268 env.Append(CPPDEFINES=["LUA_R_INCL"])269 foundpkg = True270 except:271 pass272 if not foundpkg:273 #Look for lua.h274 foundheader = False275 if GetOption('luajit'):276 foundheader = conf.CheckCHeader('luajit-2.0/lua.h')277 elif GetOption('lua52'):278 foundheader = conf.CheckCHeader('lua5.2/lua.h') or conf.CheckCHeader('lua52/lua.h')279 else:280 foundheader = conf.CheckCHeader('lua5.1/lua.h') or conf.CheckCHeader('lua51/lua.h')281 if not foundheader:282 if conf.CheckCHeader('lua.h'):283 env.Append(CPPDEFINES=["LUA_R_INCL"])284 else:285 FatalError("lua.h not found")286 #needed for static lua compiles (in some cases)287 if platform == "Linux":288 conf.CheckLib('dl')289 #Look for fftw290 if not GetOption('nofft') and not conf.CheckLib(['fftw3f', 'fftw3f-3', 'libfftw3f-3', 'libfftw3f']):291 FatalError("fftw3f development library not found or not installed")292 #Look for bz2293 if not conf.CheckLib(['bz2', 'libbz2']):294 FatalError("bz2 development library not found or not installed")295 #Check bz2 header too for some reason296 if not conf.CheckCHeader('bzlib.h'):297 FatalError("bzip2 headers not found")298 #Look for libz299 if not conf.CheckLib(['z', 'zlib']):300 FatalError("libz not found or not installed")301 #Look for pthreads302 if not conf.CheckLib(['pthread', 'pthreadVC2']):303 FatalError("pthreads development library not found or not installed")304 if msvc:305 if not conf.CheckHeader('dirent.h') or not conf.CheckHeader('fftw3.h') or not conf.CheckHeader('pthread.h') or not conf.CheckHeader('zlib.h'):306 FatalError("Required headers not found")307 else:308 #Look for libm309 if not conf.CheckLib('m'):310 FatalError("libm not found or not installed")311 #Look for OpenGL libraries312 if GetOption('opengl'):313 if platform == "Linux" or platform == "FreeBSD":314 if not conf.CheckLib('GL'):315 FatalError("libGL not found or not installed")316 try:317 env.ParseConfig('pkg-config --libs glew gl glu')318 except:319 FatalError(sys.exc_info()[0])320 elif platform == "Windows":321 if not conf.CheckLib('opengl32'):322 FatalError("opengl32 not found or not installed")323 if not conf.CheckLib('glew32'):324 FatalError("glew32 not found or not installed")325 elif platform == "Darwin":326 if not conf.CheckFramework("OpenGL"):327 FatalError("OpenGL framework not found or not installed")328 if platform == "Linux" or platform == "FreeBSD":329 if not conf.CheckLib('X11'):330 FatalError("X11 development library not found or not installed")331 if not conf.CheckLib('rt'):332 FatalError("librt not found or not installed")333 elif platform == "Windows":334 #These need to go last335 if not conf.CheckLib('gdi32') or not conf.CheckLib('winmm') or (not msvc and not conf.CheckLib('dxguid')):336 FatalError("Error: some windows libraries not found or not installed, make sure your compiler is set up correctly")337 elif platform == "Darwin":338 if not conf.CheckFramework("Cocoa"):339 FatalError("Cocoa framework not found or not installed")340if GetOption('clean'):341 import shutil342 try:343 shutil.rmtree("generated/")344 except:345 print("couldn't remove build/generated/")346elif not GetOption('help'):347 conf = Configure(env)348 conf.AddTest('CheckFramework', CheckFramework)349 conf.AddTest('CheckBit', CheckBit)350 if not conf.CheckCC() or not conf.CheckCXX():351 FatalError("compiler not correctly configured")352 if platform == compilePlatform and isX86 and not GetOption('32bit') and not GetOption('64bit') and not GetOption('msvc'):353 conf.CheckBit()354 findLibs(env, conf)355 env = conf.Finish()356if not msvc:357 env.Append(CXXFLAGS=['-std=c++11', '-U__STRICT_ANSI__'])358 env.Append(CXXFLAGS=['-Wno-invalid-offsetof'])359 if platform == "Linux":360 env.Append(CXXFLAGS=['-Wno-unused-result'])361#Add platform specific flags and defines362if platform == "Windows":363 env.Append(CPPDEFINES=["WIN", "_WIN32_WINNT=0x0501", "_USING_V110_SDK71_"])364 if msvc:365 env.Append(CCFLAGS=['/Gm', '/Zi', '/EHsc', '/FS', '/GS']) #enable minimal rebuild, ?, enable exceptions, allow -j to work in debug builds, enable security check366 if GetOption('renderer'):367 env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])368 else:369 env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS,"5.01"'])370 env.Append(LINKFLAGS=['/OPT:REF', '/OPT:ICF'])371 env.Append(CPPDEFINES=['_SCL_SECURE_NO_WARNINGS']) #Disable warnings about 'std::print'372 if GetOption('static'):373 env.Append(LINKFLAGS=['/NODEFAULTLIB:msvcrt.lib', '/LTCG'])374 elif not GetOption('debugging'):375 env.Append(LINKFLAGS=['/NODEFAULTLIB:msvcrtd.lib'])376 else:377 env.Append(LINKFLAGS=['-mwindows'])378elif platform == "Linux" or platform == "FreeBSD":379 env.Append(CPPDEFINES=['LIN'])380elif platform == "Darwin":381 env.Append(CPPDEFINES=['MACOSX'])382 #env.Append(LINKFLAGS=['-headerpad_max_install_names']) #needed in some cross compiles383 if GetOption('luajit'):384 env.Append(LINKFLAGS=['-pagezero_size', '10000', '-image_base', '100000000'])385#Add architecture flags and defines386if isX86:387 env.Append(CPPDEFINES='X86')388if not GetOption('no-sse'):389 if GetOption('sse'):390 if msvc:391 if not GetOption('sse2'):392 env.Append(CCFLAGS=['/arch:SSE'])393 else:394 env.Append(CCFLAGS=['-msse'])395 env.Append(CPPDEFINES=['X86_SSE'])396 if GetOption('sse2'):397 if msvc:398 env.Append(CCFLAGS=['/arch:SSE2'])399 else:400 env.Append(CCFLAGS=['-msse2'])401 env.Append(CPPDEFINES=['X86_SSE2'])402 if GetOption('sse3'):403 if msvc:404 FatalError("--sse3 doesn't work with --msvc")405 else:406 env.Append(CCFLAGS=['-msse3'])407 env.Append(CPPDEFINES=['X86_SSE3'])408if GetOption('native') and not msvc:409 env.Append(CCFLAGS=['-march=native'])410#Add optimization flags and defines411if GetOption('debugging'):412 if msvc:413 env.Append(CCFLAGS=['/Od'])414 if GetOption('static'):415 env.Append(CCFLAGS=['/MTd'])416 else:417 env.Append(CCFLAGS=['/MDd'])418 else:419 env.Append(CCFLAGS=['-Wall', '-g'])420 env.Append(CPPDEFINES=['DEBUG'])421elif GetOption('release'):422 if msvc:423 # Certain options (like /GL and /GS) cause TPT to be flagged as a virus. Don't include them424 env.Append(CCFLAGS=['/O2', '/Oy-', '/fp:fast'])425 if GetOption('static'):426 env.Append(CCFLAGS=['/MT'])427 else:428 env.Append(CCFLAGS=['/MD'])429 else:430 env.Append(CCFLAGS=['-O3', '-ftree-vectorize', '-funsafe-math-optimizations', '-ffast-math', '-fomit-frame-pointer'])431 if platform != "Darwin":432 env.Append(CCFLAGS=['-funsafe-loop-optimizations'])433if GetOption('static'):434 if platform == "Windows":435 if compilePlatform == "Windows" and not msvc:436 env.Append(CPPDEFINES=['_PTW32_STATIC_LIB'])437 else:438 env.Append(CPPDEFINES=['PTW32_STATIC_LIB'])439 if msvc:440 env.Append(CPPDEFINES=['ZLIB_WINAPI'])441 else:442 env.Append(LINKFLAGS=['-Wl,-Bstatic'])443#Add other flags and defines444if not GetOption('nofft'):445 env.Append(CPPDEFINES=['GRAVFFT'])446if not GetOption('nolua') and not GetOption('renderer') and not GetOption('font'):447 env.Append(CPPDEFINES=['LUACONSOLE'])448if GetOption('opengl') or GetOption('opengl-renderer'):449 env.Append(CPPDEFINES=['OGLI', 'PIX32OGL'])450 if GetOption('opengl-renderer'):451 env.Append(CPPDEFINES=['OGLR'])452if GetOption('renderer'):453 env.Append(CPPDEFINES=['RENDERER'])454if GetOption('font'):455 env.Append(CPPDEFINES=['FONTEDITOR'])456if GetOption("wall"):457 if msvc:458 env.Append(CCFLAGS=['/WX'])459 else:460 env.Append(CCFLAGS=['-Werror'])461elif GetOption("no-warnings"):462 if msvc:463 env.Append(CCFLAGS=['/W0'])464 else:465 env.Append(CCFLAGS=['-w'])466#Add version defines467if GetOption('save-version'):468 env.Append(CPPDEFINES=["SAVE_VERSION={0}".format(GetOption('save-version'))])469if GetOption('minor-version'):470 env.Append(CPPDEFINES=["MINOR_VERSION={0}".format(GetOption('minor-version'))])471if GetOption('build-number'):472 env.Append(CPPDEFINES=["BUILD_NUM={0}".format(GetOption('build-number'))])473if GetOption('snapshot-id'):474 env.Append(CPPDEFINES=["SNAPSHOT", "SNAPSHOT_ID={0}".format(GetOption('snapshot-id'))])475elif GetOption('snapshot'):476 env.Append(CPPDEFINES=["SNAPSHOT", "SNAPSHOT_ID={0}".format(str(int(time.time())))])477if GetOption('beta'):478 env.Append(CPPDEFINES=['BETA'])479#Generate list of sources to compile480sources = Glob("src/*.cpp") + Glob("src/*/*.cpp") + Glob("src/*/*/*.cpp") + Glob("generated/*.cpp") + Glob("data/*.cpp")481if not GetOption('nolua') and not GetOption('renderer') and not GetOption('font'):482 sources += Glob("src/lua/socket/*.c") + Glob("src/lua/LuaCompat.c")483if platform == "Windows":484 sources += env.RES('resources/powder-res.rc')485 if not msvc:486 sources = filter(lambda source: not 'src\\simulation\\Gravity.cpp' in str(source), sources)487 sources = filter(lambda source: not 'src/simulation/Gravity.cpp' in str(source), sources)488 envCopy = env.Clone()489 envCopy.Append(CCFLAGS='-mstackrealign')490 sources += envCopy.Object('src/simulation/Gravity.cpp')491#elif platform == "Darwin":492# sources += ["src/SDLMain.m"]493#Program output name494if GetOption('output'):495 programName = GetOption('output')496else:497 programName = "powder"498 if GetOption('renderer'):499 programName = "render"500 if GetOption('font'):501 programName = "font"502 if "BIT" in env and env["BIT"] == 64:503 programName += "64"504 if isX86 and GetOption('no-sse'):505 programName += "-legacy"506 if platform == "Windows":507 programName = programName.capitalize()508 programName += ".exe"509 elif platform == "Darwin":510 programName += "-x"511#strip binary after compilation512def strip():513 global programName514 global env515 try:516 os.system("{0} {1}/{2}".format(env['STRIP'] if 'STRIP' in env else "strip", GetOption('builddir'), programName))517 except:518 print("Couldn't strip binary")519if not GetOption('debugging') and not GetOption('symbols') and not GetOption('clean') and not GetOption('help') and not msvc:520 atexit.register(strip)521#Long command line fix for mingw on windows522if compilePlatform == "Windows" and not msvc:523 SetupSpawn(env)524#Once we get here, finally compile525env.Decider('MD5-timestamp')526SetOption('implicit_cache', 1)527t = env.Program(target=programName, source=sources)...
doPlotUtils.py
Source:doPlotUtils.py
1#!/usr/bin/env python2####################################3#4# doPlotUtils.py5#6# generic Plotting script, with importable doPlot function7#8# Laurie McClymont - UCL9# Written ~ August 201610#11###################################12import os, sys, time, argparse, copy, glob13from array import array14from math import sqrt, log, isnan, isinf15from os import path16import ROOT17from ROOT import gROOT, gStyle18gROOT.ProcessLine("gErrorIgnoreLevel > 2000;")19gStyle.SetOptTitle( 0 )20import AtlasStyle21AtlasStyle.SetAtlasStyle()22verbose=False23quiet=False24def root_colours(input):25 if input=='Red': output=ROOT.kRed26 elif input=='Green': output=ROOT.kGreen27 elif input=='Yellow': output=ROOT.kYellow28 elif input=='Blue': output=ROOT.kBlue29 elif input=='Magenta': output=ROOT.kMagenta30 elif input=='Cyan': output=ROOT.kCyan31 elif input=='DarkCyan': output=ROOT.kCyan+132 elif input=='DarkGreen': output=ROOT.kGreen+233 elif input=='Orange': output=ROOT.kOrange34 elif input=='Black': output=ROOT.kBlack35 elif input=='Gray': output=ROOT.kGray36 elif input=='Grey': output=ROOT.kGray37 elif input=='White': output=ROOT.kWhite38 elif input=='DarkGrey': output=ROOT.kGray+239 elif input=='Violet': output=ROOT.kViolet+140 else: output=int(input)41 return output42def root_markerStyles(input):43 if input=='Circle':44 output=2045 elif input=='Square':46 output=2147 elif input=='Triangle':48 output=2249 elif input=='circle':50 output=2451 elif input=='square':52 output=2553 elif input=='triangle':54 output=2655 else:56 output=int(input)57 return output58def root_fillStyles(inputRaw):59 60 try:61 input=inputRaw.lower()62 except:63 input=inputRaw64 65 if input=="solid":66 output=100167 elif input=="heavydots":68 output=3001 69 elif (input=="mediumdots" or input=="dots"):70 output=3002 71 elif input=="lightdots":72 output=3002 73 74 else:75 output=int(inputRaw)76 return output77def getListsFromString(string):78 # Make 2 comma safe79 string.replace(',,',',')80 #print "Doing make string safe"81 Lists = []82 for List in string.split(","):83 Lists.append(List.split(":"))84 return Lists85def getOptionMapFromString(optionString, verbose=False): 86 optionMap={}87 optionLists=getListsFromString(optionString)88 for optionList in optionLists:89 try:90 optionMap[optionList[0]]=optionList[1].replace("\comma",",")91 except:92 raise SystemError("doPlot: optionMap problem, optionList:", optionList)93 if(verbose): print " ", optionList[0], ":", optionList[1]94 return optionMap95defaultOptionString="Type:Hist,nPads:2,Logx:0,Logy:0,colour:Black,pad1DrawOption:,pad2DrawOption:,atlasLabel:Internal,atlasLabelPos:0.2-0.85,plotStringPos:0.2-0.7-0.9,plotName:test"96defaultOptionString+=",yTitle:Frequency,yTitleSize:0.06,yTitleOffset:1,xTitleSize:0.05,xTitleOffset:0.02"97defaultOptionString+=",ratio_yTitle:Ratio,ratio_yTitleSize:0.13,ratio_yTitleOffset:0.5,ratio_xTitleSize:0.15,ratio_xTitleOffset:0.9"98defaultOptionString+=",ratio_xLabelSize:0.1,ratio_yLabelSize:0.1,ratio_yLabelDivisions:5-0-5"99defaultOptionString+=",pad:1,legendPos:0.6-0.7-0.9-0.9,plotSuffix:pdf-C-png,verbose:0,newRightMargin:1"100if(verbose): print101if(verbose): print "Default Settings for map"102defaultOptionMap=getOptionMapFromString(defaultOptionString)103def getOption(option, optionMap):104 try:105 ret = optionMap[option]106 except:107 try: ret=defaultOptionMap[option]108 except: ret = 0109 if ret=="0": return 0110 return ret111def openHistsAndStrings(histsAndStrings, verbose=False):112 histsAndMaps=[]113 114 for histAndString in histsAndStrings:115 histAndMap=[]116 histAndMap.append(histAndString[0])117 histAndMap.append(getOptionMapFromString(histAndString[1]))118 histsAndMaps.append(histAndMap)119 return histsAndMaps120def setupCanvas(opts):121 ## Setup Canvas ##122 canvName="c"123 canv = ROOT.TCanvas(canvName,canvName,60,50,800,600)124 #canv = ROOT.TCanvas()125 canv.Clear()126 canv.cd()127 128 pad1 = ROOT.TPad("pad1","pad1",0,0.3,1,1)129 pad2 = ROOT.TPad("pad2","pad2",0,0.01,1,0.37)130 if(int(getOption('newRightMargin',opts)) > 0 ):131 pad1.SetRightMargin(0.1)132 pad2.SetRightMargin(0.1)133 pad1.Draw()134 pad2.Draw()135 136 if(getOption('verbose',opts)): print "nPads:", getOption("nPads",opts)137 if int( getOption("nPads",opts) ) > 1:138 pad2.SetTopMargin(0.03)139 pad2.SetBottomMargin(0.35) 140 pad1.Draw()141 pad2.Draw()142 pad2.SetGridx()143 pad2.SetGridy()144 else:145 pad1.SetPad(0,0,1,1)146 pad1.Draw()147 pad1.cd()148 if int(getOption("Logx",opts)) > 0:149 pad1.SetLogx()150 pad2.SetLogx()151 if(getOption('verbose',opts)): print " Setting Logx"152 if int(getOption("Logy",opts)) > 0:153 pad1.SetLogy()154 if(getOption('verbose',opts)): print " Setting Logy"155 if int(getOption("Logz",opts)) > 0:156 pad1.SetLogz()157 if(getOption('verbose',opts)): print " Setting Logz"158 if int(getOption("Gridx",opts)) > 0:159 pad1.SetGridx()160 if(getOption('verbose',opts)): print " Setting Gridx"161 if int(getOption("Gridy",opts)) > 0:162 pad1.SetGridy()163 if(getOption('verbose',opts)): print " Setting Gridy"164 if getOption("legend",opts):165 legendPos=getOption("legendPos",opts).split("-")166 legend=ROOT.TLegend( float(legendPos[0]), float(legendPos[1]), float(legendPos[2]), float(legendPos[3]) )167 if getOption("legendFillColour",opts)!=0:168 legend.SetFillColor(int(getOption("legendFillColour",opts)))169 else:170 legend.SetFillStyle(0)171 172 if getOption("legendTextSize",opts)!=0:173 legend.SetTextSize(float(getOption("legendTextSize",opts)))174 else:175 legend.SetTextSize(0.04)176 if getOption("legendColumns",opts):177 legend.SetNColumns(int(getOption("legendColumns",opts)))178 179 opts["legend"]=legend180 if(getOption('verbose',opts)): print " Added a legend"181 return canv, pad1, pad2182def setupHist(histAndMap,opts):183 hist=histAndMap[0]184 map=histAndMap[1]185 if(getOption('verbose',opts)): print186 if(getOption('verbose',opts)): print "Setting options for histMap", hist.GetName()187 188 if( getOption("type",map)=="Function"):189 hist=histAndMap[0].GetHistogram()190 #if( getOption("type",map)=="graph"):191 # hist=histAndMap[0].GetHistogram()192 193 xRange=getOption("xRange",opts)194 if xRange!=0:195 if ";" in xRange:196 xLow=xRange.split(";")[0]197 xUp=xRange.split(";")[1]198 else:199 xLow=xRange.split("-")[0]200 xUp=xRange.split("-")[1]201 hist.GetXaxis().SetRangeUser( float(xLow), float(xUp) )202 if(getOption('verbose',opts)): print "Setting xRange to be", str(xLow)+"-"+str(xUp)203 204 yRange=getOption("yRange",map)205 if yRange==0:206 yRange=getOption("yRange",opts) 207 if yRange!=0:208 if ";" in yRange:209 yLow=yRange.split(";")[0]210 yUp=yRange.split(";")[1]211 else:212 yLow=yRange.split("-")[0]213 yUp=yRange.split("-")[1]214 if( getOption("type",map)!="graph"):215 hist.GetYaxis().SetRangeUser( float(yLow), float(yUp) )216 else:217 hist.GetHistogram().SetMinimum( float(yLow) )218 hist.GetHistogram().SetMaximum( float(yUp) )219 if(getOption('verbose',opts)): print "Setting yRange to be", yRange220 elif (int(getOption("Logy",opts)) > 0) and (int( getOption("pad",map) )==1):221 yLow=max(0.5,hist.GetMinimum()/20)222 yUp=hist.GetMaximum()*100223 hist.GetYaxis().SetRangeUser( float(yLow), float(yUp) )224 if(getOption('verbose',opts)): print "Setting yRange to be", str(yLow)+"-"+str(yUp)225 hist.SetLineColor( root_colours(getOption("colour",map) ) )226 hist.SetMarkerColor( root_colours(getOption("colour",map) ) )227 hist.SetMarkerStyle(root_markerStyles(getOption("markerStyle",map) ) )228 if getOption("fillColour",map): fillColour=root_colours(getOption("fillColour",map) ) 229 else: fillColour=root_colours(getOption("colour",map) )230 hist.SetFillColor(fillColour)231 hist.SetFillStyle( root_fillStyles(getOption("fillStyle",map) ) )232 233 if(getOption('verbose',opts)): print "Setting colour to ", getOption("colour",map)234 if(getOption('verbose',opts)): print "Setting fillColour to ", fillColour235 if(getOption('verbose',opts)): print "Setting markerStyle to ", getOption("markerStyle",map)236 if(getOption('verbose',opts)): print "Setting fillStyle to ", getOption("fillStyle",map)237 ##print "=> hist.SetFillStyle("+str(root_fillStyles(getOption("fillStyle",map) ) )+"), from "+str(getOption("fillStyle",map))238 239 # Check if first histogram for pad240 if int( getOption("pad",map) )==1:241 drawOption=getOption("pad1DrawOption",opts)242 pad=""243 elif int( getOption("pad",map) )==2:244 drawOption=getOption("pad2DrawOption",opts)245 pad="ratio_"246 #If first histogram247 if "same" not in drawOption:248 hist.GetXaxis().SetMoreLogLabels() # Always249 250 #Set Titles251 if getOption("yTitle",map) != "Frequency" and getOption("yTitle",map) != 0:252 hist.GetYaxis().SetTitle(getOption("yTitle",map)) 253 elif getOption(pad+"yTitle",opts) != 0:254 hist.GetYaxis().SetTitle(getOption(pad+"yTitle",opts))255 if ( int(getOption("nPads",opts)) == int( getOption("pad",map) )): 256 if getOption("xTitle",opts)!=0:257 hist.GetXaxis().SetTitle(getOption("xTitle",opts))258 if(getOption('verbose',opts)): print "xTitle:", getOption("xTitle",opts), "in pad",getOption("pad",map)259 #if getOption(pad+"xTitle",opts)!=0:260 # hist.GetXaxis().SetTitle(getOption(pad+"xTitle",opts))261 if getOption(pad+"yTitleSize",opts)!=0:262 hist.GetYaxis().SetTitleSize(float(getOption(pad+"yTitleSize",opts)))263 if getOption(pad+"xTitleSize",opts)!=0:264 hist.GetXaxis().SetTitleSize(float(getOption(pad+"xTitleSize",opts)))265 if getOption(pad+"yTitleOffset",opts)!=0:266 hist.GetYaxis().SetTitleOffset(float(getOption(pad+"yTitleOffset",opts)))267 if getOption(pad+"xTitleOffset",opts)!=0:268 hist.GetXaxis().SetTitleOffset(float(getOption(pad+"xTitleOffset",opts)))269 #Set for labels270 if getOption(pad+"yLabelSize",opts)!=0:271 hist.GetYaxis().SetLabelSize(float(getOption(pad+"yLabelSize",opts)))272 if getOption(pad+"xLabelSize",opts)!=0:273 hist.GetXaxis().SetLabelSize(float(getOption(pad+"xLabelSize",opts)))274 if getOption(pad+"yLabelOffset",opts)!=0:275 hist.GetYaxis().SetLabelOffset(float(getOption(pad+"yLabelOffset",opts)))276 if getOption(pad+"xLabelOffset",opts)!=0:277 hist.GetXaxis().SetLabelOffset(float(getOption(pad+"xLabelOffset",opts)))278 if getOption(pad+"yLabelDivisions",opts)!=0:279 ndivisions=getOption(pad+"yLabelDivisions",opts).split('-')280 hist.GetYaxis().SetNdivisions(int(ndivisions[0]),int(ndivisions[1]),int(ndivisions[2]))281 if getOption(pad+"xLabelDivisions",opts)!=0:282 ndivisions=getOption(pad+"xLabelDivisions",opts).split('-')283 hist.GetXaxis().SetNdivisions(int(ndivisions[0]),int(ndivisions[1]),int(ndivisions[2]))284 285 286 histAndMap[0]=hist287def drawHist(histAndMap,opts,pad1,pad2):288 hist=histAndMap[0]289 map=histAndMap[1]290 drawOption=""291 292 if int( getOption("pad",map) )==1:293 drawOption=getOption("pad1DrawOption",opts)294 opts["pad1DrawOption"]="same"295 pad1.cd()296 elif int( getOption("pad",map) )==2:297 drawOption=getOption("pad2DrawOption",opts)298 opts["pad2DrawOption"]="same"299 pad2.cd()300 else:301 if(getOption('verbose',opts)): print "Don't know which pad to put", hist.GetName()302 return303 if getOption("drawOption",map):304 drawOption+=getOption("drawOption",map)305 306 hist.Draw(drawOption)307 308 ############309 ##Add to legend310 legOption="epl"311 if getOption("fillStyle",map):312 legOption="fepl"313 if getOption("legend",opts) and getOption("legend",map):314 opts["legend"].AddEntry(hist, getOption("legend",map), legOption)315 if(getOption('verbose',opts)): print " Added to legend"316 317 histAndMap[1]=map318 if(getOption('verbose',opts)): print " Drawn hist", hist.GetName(), "with drawOption", drawOption, "in pad", int( getOption("pad",map) )319 return320def finaliseCanvas(opts, canv, pad1, pad2):321 pad1.cd()322 if(getOption('verbose',opts)): print "Let's do finalise canvas"323 if getOption("atlasLabel",opts)!=0:324 labelPosX=float(getOption("atlasLabelPos",opts).split('-')[0])325 labelPosY=float(getOption("atlasLabelPos",opts).split('-')[1])326 if(getOption('verbose',opts)): print "labelPos ",labelPosX, labelPosY327 AtlasStyle.ATLAS_LABEL(labelPosX,labelPosY, 1, getOption("atlasLabel",opts))328 AtlasStyle.myText(labelPosX,(labelPosY-0.05),1,"#scale[0.9]{#sqrt{s} = 13 TeV}");329 if getOption("lumi",opts)!=0:330 #AtlasStyle.myText(labelPosX,(labelPosY-0.12),1,"#scale[0.9]{#int L dt = "+args.lumi+ " fb^{-1}}")331 if("24.5" in getOption("lumi",opts)): print " doPlot: Doing low mass lumi fix (24.5 -> 24.3)"332 lumi=getOption("lumi",opts).replace("24.5","24.3")333 AtlasStyle.myText(labelPosX,(labelPosY-0.1),1,"#scale[0.9]{"+lumi+" fb^{-1}}");334 gStyle.SetOptStat(0)335 legend=getOption("legend",opts)336 if legend:337 legend.Draw()338 #Add a string to the plot339 plotString=getOption("plotString",opts)340 if(getOption('verbose',opts)): print "plotString is", plotString341 if plotString!=0:342 plotStringList= plotString.split('+')343 plotStringPos=getOption("plotStringPos",opts).split('-')344 yPos = float(plotStringPos[1]) # Init position of y345 for string in plotStringList:346 #print "AtlasStyle.myText(0.65,",yPos,",1,","#scale[0.9]{"+string+"}",")"347 if(getOption('verbose',opts)): print " -",string348 AtlasStyle.myText(float(plotStringPos[0]),yPos,1,"#scale["+plotStringPos[2]+"]{"+string+"}")349 yPos=yPos-0.05350 351def doPlot( histsAndStrings, optionString):352 verbose=False353 if("verbose:" in optionString): verbose=True354 355 #getDefault()356 if verbose: print357 if verbose: print " ****************** do Plot **********************"358 359 if verbose: print "Getting histsAndStrings"360 histsAndMaps = openHistsAndStrings(histsAndStrings , verbose )361 362 if verbose: print "Getting general options"363 opts=getOptionMapFromString(optionString, verbose )364 (canv, pad1, pad2) = setupCanvas(opts)365 # Loop over hists366 for histAndMap in histsAndMaps:367 #Setup Hist368 setupHist(histAndMap,opts)369 #Draw Hist370 drawHist(histAndMap,opts,pad1,pad2)371 # Finalise Canvas (add text to plots, legends ect...)372 finaliseCanvas(opts, canv, pad1, pad2)373 # Create directory for plot if not already done374 plotDirName=getOption("plotName",opts).rsplit('/', 1)[0]375 if not os.path.isdir(plotDirName):376 os.makedirs(plotDirName)377 378 # Print Canvas379 suffixList=getOption("plotSuffix",opts).split("-")380 for suffix in suffixList:381 canv.Print(getOption("plotName",opts)+"."+suffix)382 print " doPlot prints to "+getOption("plotName",opts)+"."+suffixList[0]383 if verbose: print " ****************************************************"384 385 386def main():387 print "Hello"388 389 histsAndStrings=[]390 optionString="Logx:0,nPads:2,plotString:Testing+Testing2,lumi:12,legend:YesPlease"391 file=ROOT.TFile.Open("Systematics2016/BJetTrig-00-03-05_full/BJetTriggerEfficiencies.root", "READ")392 print "****", file.GetName()393 testHist1=file.Get("eff_MC_offJets70_match_hlt70_jetPt")394 testHist2=file.Get("eff_Data_offJets70_match_hlt70_jetPt")395 print "****", testHist1.GetName()396 print "****", testHist2.GetName()397 histsAndStrings=[ [testHist1,"yRange:0-2,markerStyle:Circle,pad:1,legend:test1"], [testHist2,"colour:Red,pad:2,legend:test2"] ]398 doPlot(histsAndStrings,optionString)399if __name__ == "__main__":400 main()...
conftest.py
Source:conftest.py
...152 )153 return sim154@pytest.fixture(scope="session")155def exe_cmd(request):156 return request.config.getoption("--exe_cmd")157@pytest.fixture(scope="session")158def candidate_sim(request):159 domain_dir = request.config.getoption("--domain_dir")160 compiler = request.config.getoption("--compiler")161 candidate_dir = request.config.getoption("--candidate_dir")162 configuration = request.config.getoption("--config")163 option_suite = request.config.getoption("--option_suite")164 ncores = request.config.getoption("--ncores")165 nnodes = request.config.getoption("--nnodes")166 scheduler = request.config.getoption("--scheduler")167 account = request.config.getoption("--account")168 walltime = request.config.getoption("--walltime")169 queue = request.config.getoption("--queue")170 candidate_sim = _make_sim(171 domain_dir=domain_dir,172 compiler=compiler,173 source_dir=candidate_dir,174 configuration=configuration,175 option_suite=option_suite,176 ncores=ncores,177 nnodes=nnodes,178 scheduler=scheduler,179 account=account,180 walltime=walltime,181 queue=queue182 )183 return candidate_sim184# Since we want to leverage the NWM compiles (both candidate and reference, ptoentially),185# we create additional simulation fixtures where we hard-code the alternate configurations,186# those are "channel-only" and "nwm_output_ana", currently.187@pytest.fixture(scope="session")188def candidate_channel_only_sim(request):189 domain_dir = request.config.getoption("--domain_dir")190 compiler = request.config.getoption("--compiler")191 candidate_dir = request.config.getoption("--candidate_dir")192 option_suite = request.config.getoption("--option_suite")193 ncores = request.config.getoption("--ncores")194 nnodes = request.config.getoption("--nnodes")195 scheduler = request.config.getoption("--scheduler")196 account = request.config.getoption("--account")197 walltime = request.config.getoption("--walltime")198 queue = request.config.getoption("--queue")199 configuration = "nwm_channel-only"200 candidate_channel_only_sim = _make_sim(201 domain_dir=domain_dir,202 compiler=compiler,203 source_dir=candidate_dir,204 configuration=configuration,205 option_suite=option_suite,206 ncores=ncores,207 nnodes=nnodes,208 scheduler=scheduler,209 account=account,210 walltime=walltime,211 queue=queue212 )213 return candidate_channel_only_sim214@pytest.fixture(scope="session")215def candidate_nwm_output_sim(request):216 domain_dir = request.config.getoption("--domain_dir")217 compiler = request.config.getoption("--compiler")218 candidate_dir = request.config.getoption("--candidate_dir")219 option_suite = request.config.getoption("--option_suite")220 ncores = request.config.getoption("--ncores")221 nnodes = request.config.getoption("--nnodes")222 scheduler = request.config.getoption("--scheduler")223 account = request.config.getoption("--account")224 walltime = request.config.getoption("--walltime")225 queue = request.config.getoption("--queue")226 configuration = request.config.getoption("--config")227 if configuration == 'nwm_long_range':228 configuration = "nwm_output_long_range"229 else:230 configuration = "nwm_output_ana"231 candidate_nwm_output_sim = _make_sim(232 domain_dir=domain_dir,233 compiler=compiler,234 source_dir=candidate_dir,235 configuration=configuration,236 option_suite=option_suite,237 ncores=ncores,238 nnodes=nnodes,239 scheduler=scheduler,240 account=account,241 walltime=walltime,242 queue=queue243 )244 return candidate_nwm_output_sim245@pytest.fixture(scope="session")246def reference_sim(request):247 domain_dir = request.config.getoption("--domain_dir")248 compiler = request.config.getoption("--compiler")249 reference_dir = request.config.getoption("--reference_dir")250 configuration = request.config.getoption("--config")251 option_suite = request.config.getoption("--option_suite")252 ncores = request.config.getoption("--ncores")253 nnodes = request.config.getoption("--nnodes")254 scheduler = request.config.getoption("--scheduler")255 account = request.config.getoption("--account")256 walltime = request.config.getoption("--walltime")257 queue = request.config.getoption("--queue")258 reference_sim = _make_sim(259 domain_dir=domain_dir,260 compiler=compiler,261 source_dir=reference_dir,262 configuration=configuration,263 option_suite=option_suite,264 ncores=ncores,265 nnodes=nnodes,266 scheduler=scheduler,267 account=account,268 walltime=walltime,269 queue=queue270 )271 return reference_sim272# Since we want to leverage the NWM compiles (both candidate and reference, ptoentially),273# we create additional simulation fixtures where we hard-code the alternate configurations,274# those are "channel-only" and "nwm_output_ana", currently.275@pytest.fixture(scope="session")276def reference_nwm_output_sim(request):277 domain_dir = request.config.getoption("--domain_dir")278 compiler = request.config.getoption("--compiler")279 reference_dir = request.config.getoption("--reference_dir")280 option_suite = request.config.getoption("--option_suite")281 ncores = request.config.getoption("--ncores")282 nnodes = request.config.getoption("--nnodes")283 scheduler = request.config.getoption("--scheduler")284 account = request.config.getoption("--account")285 walltime = request.config.getoption("--walltime")286 queue = request.config.getoption("--queue")287 configuration = request.config.getoption("--config")288 if configuration == 'nwm_long_range':289 configuration = "nwm_output_long_range"290 else:291 configuration = "nwm_output_ana"292 reference_nwm_output_sim = _make_sim(293 domain_dir=domain_dir,294 compiler=compiler,295 source_dir=reference_dir,296 configuration=configuration,297 option_suite=option_suite,298 ncores=ncores,299 nnodes=nnodes,300 scheduler=scheduler,301 account=account,302 walltime=walltime,303 queue=queue304 )305 return reference_nwm_output_sim306@pytest.fixture(scope="session")307def output_dir(request):308 configuration = request.config.getoption("--config")309 output_dir = request.config.getoption("--output_dir")310 use_existing_test_dir = request.config.getoption("--use_existing_test_dir")311 output_dir = pathlib.Path(output_dir)312 output_dir = output_dir / configuration313 if not use_existing_test_dir:314 output_dir.mkdir(parents=True)315 return output_dir316@pytest.fixture(scope="session")317def ncores(request):318 return int(request.config.getoption("--ncores"))319@pytest.fixture(scope="session")320def xrcmp_n_cores(request):...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!