# Released under the MIT License. See LICENSE for details.#"""Standard snippets that can be pulled into project pcommand scripts.A snippet is a mini-program that directly takes input from stdin and doessome focused task. This module is a repository of common snippets that canbe imported into projects' pcommand script for easy reuse."""from__future__importannotationsimportsysfromtypingimportTYPE_CHECKINGfromefrotoolsimportpcommandifTYPE_CHECKING:pass
[docs]defwith_build_lock()->None:"""Run a shell command wrapped in a build-lock."""fromefro.errorimportCleanErrorfromefrotools.buildlockimportBuildLockimportsubprocesspcommand.disallow_in_batch()args=sys.argv[2:]iflen(args)<2:raiseCleanError('Expected one lock-name arg and at least one command arg')withBuildLock(args[0],projroot=str(pcommand.PROJROOT)):subprocess.run(' '.join(args[1:]),check=True,shell=True)
[docs]defsortlines()->None:"""Sort provided lines. For tidying import lists, etc."""fromefro.errorimportCleanErrorpcommand.disallow_in_batch()iflen(sys.argv)!=3:raiseCleanError('Expected 1 arg.')val=sys.argv[2]lines=val.splitlines()print('\n'.join(sorted(lines,key=lambdal:l.lower())))
[docs]defopenal_build_android()->None:"""Build openalsoft for android."""fromefro.errorimportCleanErrorfromefrotools.openalbuildimportbuild_openalpcommand.disallow_in_batch()args=sys.argv[2:]iflen(args)!=2:raiseCleanError('Expected one <ARCH> arg: arm, arm64, x86, x86_64'' and one <MODE> arg: debug, release')build_openal(args[0],args[1])
[docs]defopenal_gather()->None:"""Gather built opealsoft libs into src."""fromefro.errorimportCleanErrorfromefrotools.openalbuildimportgatherpcommand.disallow_in_batch()args=sys.argv[2:]ifargs:raiseCleanError('No args expected.')gather()
[docs]defpyright()->None:"""Run Pyright checks on project Python code."""importsubprocessfromefro.terminalimportClrfromefro.errorimportCleanErrorpcommand.disallow_in_batch()print(f'{Clr.BLU}Running Pyright (experimental)...{Clr.RST}')try:subprocess.run(['pyright','--project','.pyrightconfig.json'],check=True)exceptExceptionasexc:raiseCleanError('Pyright failed.')fromexc
[docs]defbuild_pcommandbatch()->None:"""Build a version of pcommand geared for large batches of commands."""fromefro.errorimportCleanErrorfromefro.terminalimportClrimportefrotools.pcommandbatchaspcbpcommand.disallow_in_batch()args=pcommand.get_args()iflen(args)<2:raiseCleanError('Expected at least 2 args.')inpaths=args[:-1]outpath=args[-1]print(f'Creating batch executable: {Clr.BLD}{outpath}{Clr.RST}')pcb.build_pcommandbatch(inpaths,outpath)
[docs]defbatchserver()->None:"""Run a server for handling pcommands."""fromefro.errorimportCleanErrorfromefro.utilimportextract_argimportefrotools.pcommandbatchaspcbpcommand.disallow_in_batch()args=pcommand.get_args()idle_timeout_secs=int(extract_arg(args,'--timeout',required=True))project_dir=extract_arg(args,'--project-dir',required=True)instance=extract_arg(args,'--instance',required=True)ifargs:raiseCleanError(f'Unexpected args: {args}.')pcb.batchserver(idle_timeout_secs=idle_timeout_secs,project_dir=project_dir,instance=instance,)
[docs]defpcommandbatch_speed_test()->None:"""Test batch mode speeds."""# pylint: disable=too-many-localsimporttimeimportsubprocessimportthreadingfrommultiprocessingimportcpu_countfromconcurrent.futuresimportThreadPoolExecutorfromefro.errorimportCleanErrorfromefro.terminalimportClrargs=pcommand.get_args()iflen(args)!=1:raiseCleanError('Expected one arg.')batch_binary_path=args[0]thread_count=cpu_count()class_Test:def__init__(self)->None:self.in_flight=0self.lock=threading.Lock()self.total_runs=0defrun_standalone(self)->None:"""Run an instance of the test in standalone mode."""subprocess.run(['tools/pcommand','null'],check=True)self._finish_run()defrun_batch(self)->None:"""Run an instance of the test in batch mode."""subprocess.run([batch_binary_path,'null'],check=True)self._finish_run()def_finish_run(self)->None:withself.lock:self.in_flight-=1assertself.in_flight>=0self.total_runs+=1test_duration=5.0forname,batchin[('regular pcommand',False),('pcommandbatch',True)]:print(f'{Clr.BLU}Testing {name} speed...{Clr.RST}')start_time=time.monotonic()test=_Test()total_runs_at_timeout=0withThreadPoolExecutor(max_workers=thread_count)asexecutor:# Convert the generator to a list to trigger any# exceptions that occurred.whileTrue:# Try to keep all worker threads busy.whiletest.in_flight<thread_count*2:withtest.lock:test.in_flight+=1executor.submit(test.run_batchifbatchelsetest.run_standalone)iftime.monotonic()-start_time>test_duration:total_runs_at_timeout=test.total_runsbreaktime.sleep(0.0001)print(f'Total runs in {test_duration:.0f} seconds:'f' {Clr.SMAG}{Clr.BLD}{total_runs_at_timeout}{Clr.RST}.')
[docs]defnull()->None:"""Do nothing. Useful for speed tests and whatnot."""