panda-server-source 0.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- panda_server_source-0.8.0.dist-info/METADATA +55 -0
- panda_server_source-0.8.0.dist-info/RECORD +375 -0
- panda_server_source-0.8.0.dist-info/WHEEL +4 -0
- panda_server_source-0.8.0.dist-info/licenses/LICENSE.txt +202 -0
- pandajedi/__init__.py +0 -0
- pandajedi/jedibrokerage/AtlasAnalJobBroker.py +2343 -0
- pandajedi/jedibrokerage/AtlasBrokerUtils.py +1292 -0
- pandajedi/jedibrokerage/AtlasProdJobBroker.py +2064 -0
- pandajedi/jedibrokerage/AtlasProdTaskBroker.py +629 -0
- pandajedi/jedibrokerage/GenJobBroker.py +381 -0
- pandajedi/jedibrokerage/JobBrokerBase.py +133 -0
- pandajedi/jedibrokerage/TaskBrokerBase.py +15 -0
- pandajedi/jedibrokerage/__init__.py +0 -0
- pandajedi/jediconfig/__init__.py +0 -0
- pandajedi/jediconfig/jedi_config.py +40 -0
- pandajedi/jedicore/FactoryBase.py +182 -0
- pandajedi/jedicore/Interaction.py +433 -0
- pandajedi/jedicore/JediDBProxy.py +56 -0
- pandajedi/jedicore/JediDBProxyPool.py +37 -0
- pandajedi/jedicore/JediDBSchemaInfo.py +17 -0
- pandajedi/jedicore/JediException.py +13 -0
- pandajedi/jedicore/JediTaskBuffer.py +984 -0
- pandajedi/jedicore/JediTaskBufferInterface.py +50 -0
- pandajedi/jedicore/MsgWrapper.py +124 -0
- pandajedi/jedicore/ProcessUtils.py +34 -0
- pandajedi/jedicore/SiteCandidate.py +90 -0
- pandajedi/jedicore/ThreadUtils.py +205 -0
- pandajedi/jedicore/__init__.py +0 -0
- pandajedi/jediddm/AtlasDDMClient.py +1708 -0
- pandajedi/jediddm/DDMClientBase.py +16 -0
- pandajedi/jediddm/DDMInterface.py +83 -0
- pandajedi/jediddm/GenDDMClient.py +17 -0
- pandajedi/jediddm/__init__.py +0 -0
- pandajedi/jedidog/AtlasAnalWatchDog.py +648 -0
- pandajedi/jedidog/AtlasDataCarouselWatchDog.py +189 -0
- pandajedi/jedidog/AtlasDataLocalityUpdaterWatchDog.py +215 -0
- pandajedi/jedidog/AtlasProdWatchDog.py +443 -0
- pandajedi/jedidog/AtlasQueueFillerWatchDog.py +800 -0
- pandajedi/jedidog/AtlasTaskWithholderWatchDog.py +245 -0
- pandajedi/jedidog/AtlasWorkflowManagerWatchDog.py +63 -0
- pandajedi/jedidog/GenWatchDog.py +21 -0
- pandajedi/jedidog/JumboWatchDog.py +147 -0
- pandajedi/jedidog/TypicalWatchDogBase.py +122 -0
- pandajedi/jedidog/WatchDogBase.py +53 -0
- pandajedi/jedidog/__init__.py +0 -0
- pandajedi/jediexec/reniceJEDI.py +25 -0
- pandajedi/jedigen/AtlasTaskGenerator.py +110 -0
- pandajedi/jedigen/TaskGeneratorBase.py +15 -0
- pandajedi/jedigen/__init__.py +0 -0
- pandajedi/jedimsgprocessor/__init__.py +0 -0
- pandajedi/jedimsgprocessor/ai_parameter_adjuster_msg_processor +71 -0
- pandajedi/jedimsgprocessor/atlas_idds_msg_processor.py +66 -0
- pandajedi/jedimsgprocessor/base_msg_processor.py +33 -0
- pandajedi/jedimsgprocessor/forwarding_msg_processor.py +29 -0
- pandajedi/jedimsgprocessor/hpo_msg_processor.py +93 -0
- pandajedi/jedimsgprocessor/jedi_contents_feeder_msg_processor.py +63 -0
- pandajedi/jedimsgprocessor/jedi_job_generator_msg_processor.py +185 -0
- pandajedi/jedimsgprocessor/jedi_post_processor_msg_processor.py +82 -0
- pandajedi/jedimsgprocessor/kafka_msg_processor.py +44 -0
- pandajedi/jedimsgprocessor/panda_callback_msg_processor.py +182 -0
- pandajedi/jedimsgprocessor/panda_to_jedi_msg_processor.py +74 -0
- pandajedi/jedimsgprocessor/processing_msg_processor.py +134 -0
- pandajedi/jedimsgprocessor/status_report_msg_processor.py +129 -0
- pandajedi/jedimsgprocessor/tape_carousel_msg_processor.py +118 -0
- pandajedi/jedimsgprocessor/workflow_manager_msg_processor.py +89 -0
- pandajedi/jediorder/ContentsFeeder.py +785 -0
- pandajedi/jediorder/JediDaemon.py +27 -0
- pandajedi/jediorder/JediKnight.py +55 -0
- pandajedi/jediorder/JediMaster.py +238 -0
- pandajedi/jediorder/JediMsgProcessor.py +32 -0
- pandajedi/jediorder/JobBroker.py +33 -0
- pandajedi/jediorder/JobGenerator.py +2763 -0
- pandajedi/jediorder/JobSplitter.py +308 -0
- pandajedi/jediorder/JobThrottler.py +28 -0
- pandajedi/jediorder/PostProcessor.py +166 -0
- pandajedi/jediorder/TaskBroker.py +268 -0
- pandajedi/jediorder/TaskCommando.py +334 -0
- pandajedi/jediorder/TaskGenerator.py +17 -0
- pandajedi/jediorder/TaskRefiner.py +611 -0
- pandajedi/jediorder/TaskSetupper.py +17 -0
- pandajedi/jediorder/WatchDog.py +79 -0
- pandajedi/jediorder/__init__.py +0 -0
- pandajedi/jedipprocess/AtlasAnalPostProcessor.py +404 -0
- pandajedi/jedipprocess/AtlasPostProcessorUtils.py +50 -0
- pandajedi/jedipprocess/AtlasProdPostProcessor.py +178 -0
- pandajedi/jedipprocess/GenPostProcessor.py +35 -0
- pandajedi/jedipprocess/MailTemplates.py +185 -0
- pandajedi/jedipprocess/PostProcessorBase.py +269 -0
- pandajedi/jedipprocess/__init__.py +0 -0
- pandajedi/jedirefine/AtlasAnalTaskRefiner.py +259 -0
- pandajedi/jedirefine/AtlasProdTaskRefiner.py +162 -0
- pandajedi/jedirefine/GenTaskRefiner.py +61 -0
- pandajedi/jedirefine/RefinerUtils.py +154 -0
- pandajedi/jedirefine/TaskRefinerBase.py +996 -0
- pandajedi/jedirefine/__init__.py +0 -0
- pandajedi/jedisetup/AtlasTaskSetupper.py +309 -0
- pandajedi/jedisetup/GenTaskSetupper.py +16 -0
- pandajedi/jedisetup/SimpleTaskSetupper.py +152 -0
- pandajedi/jedisetup/TaskSetupperBase.py +15 -0
- pandajedi/jedisetup/__init__.py +0 -0
- pandajedi/jeditest/SchemaChecker.py +41 -0
- pandajedi/jeditest/addContWoSoTask.py +54 -0
- pandajedi/jeditest/addDataCarouselRequest.py +47 -0
- pandajedi/jeditest/addEventServiceTask.py +101 -0
- pandajedi/jeditest/addHpoTask.py +81 -0
- pandajedi/jeditest/addIDDSStageInRequest.py +56 -0
- pandajedi/jeditest/addNonAtlasTask.py +71 -0
- pandajedi/jeditest/addNonAtlasTaskEnc.py +64 -0
- pandajedi/jeditest/addTestTask.py +124 -0
- pandajedi/jeditest/addTestTaskParamToDEFT.py +70 -0
- pandajedi/jeditest/addTestTaskWithMerger.py +97 -0
- pandajedi/jeditest/brokerTest.py +78 -0
- pandajedi/jeditest/cancelDataCarouselRequest.py +35 -0
- pandajedi/jeditest/contentsFeederTest.py +28 -0
- pandajedi/jeditest/contentsFeederTestWithTask.py +18 -0
- pandajedi/jeditest/ddmTest.py +4 -0
- pandajedi/jeditest/jobGenForOneTask.py +38 -0
- pandajedi/jeditest/jobGeneratorTest.py +43 -0
- pandajedi/jeditest/jobSplitterTest.py +104 -0
- pandajedi/jeditest/jobThrottlerTest.py +22 -0
- pandajedi/jeditest/msgProcessorTest.py +9 -0
- pandajedi/jeditest/postProcessorTest.py +18 -0
- pandajedi/jeditest/resubmitDataCarouselRequest.py +35 -0
- pandajedi/jeditest/resubmitTaskParam.py +20 -0
- pandajedi/jeditest/taskBrokerTest.py +22 -0
- pandajedi/jeditest/taskBrokerTestWithTask.py +38 -0
- pandajedi/jeditest/taskBufferTest.py +5 -0
- pandajedi/jeditest/taskCommandoTest.py +28 -0
- pandajedi/jeditest/taskRefinerTest.py +30 -0
- pandajedi/jeditest/testOneTaskToRefine.py +49 -0
- pandajedi/jeditest/testOneTaskToTaskBroker.py +42 -0
- pandajedi/jeditest/testPandaDDMMap.py +62 -0
- pandajedi/jeditest/updateDataCarouselRequestParams.py +50 -0
- pandajedi/jeditest/watchDogTest.py +25 -0
- pandajedi/jeditest/workQueueTest.py +22 -0
- pandajedi/jedithrottle/AtlasAnalJobThrottler.py +19 -0
- pandajedi/jedithrottle/AtlasProdJobThrottler.py +18 -0
- pandajedi/jedithrottle/GenJobThrottler.py +26 -0
- pandajedi/jedithrottle/JobThrottlerBase.py +496 -0
- pandajedi/jedithrottle/__init__.py +0 -0
- pandaserver/__init__.py +0 -0
- pandaserver/api/__init__.py +0 -0
- pandaserver/api/v1/__init__.py +0 -0
- pandaserver/api/v1/common.py +339 -0
- pandaserver/api/v1/credential_management_api.py +372 -0
- pandaserver/api/v1/data_carousel_api.py +264 -0
- pandaserver/api/v1/event_api.py +269 -0
- pandaserver/api/v1/file_server_api.py +942 -0
- pandaserver/api/v1/harvester_api.py +445 -0
- pandaserver/api/v1/http_client.py +166 -0
- pandaserver/api/v1/idds_api.py +180 -0
- pandaserver/api/v1/job_api.py +463 -0
- pandaserver/api/v1/metaconfig_api.py +122 -0
- pandaserver/api/v1/pilot_api.py +895 -0
- pandaserver/api/v1/statistics_api.py +207 -0
- pandaserver/api/v1/system_api.py +186 -0
- pandaserver/api/v1/task_api.py +1520 -0
- pandaserver/api/v1/tests/__init__.py +0 -0
- pandaserver/api/v1/tests/credential_management_api_tests.py +116 -0
- pandaserver/api/v1/tests/data_carousel_api_tests.py +82 -0
- pandaserver/api/v1/tests/harvester_api_tests.py +188 -0
- pandaserver/api/v1/tests/idds_api_tests.py +45 -0
- pandaserver/api/v1/tests/job_api_tests.py +112 -0
- pandaserver/api/v1/tests/pilot_api_tests.py +154 -0
- pandaserver/api/v1/tests/statistics_api_tests.py +104 -0
- pandaserver/api/v1/tests/system_api_tests.py +58 -0
- pandaserver/api/v1/tests/task_api_tests.py +590 -0
- pandaserver/api/v1/version.py +2 -0
- pandaserver/api/v1/workflow_api.py +136 -0
- pandaserver/brokerage/SiteMapper.py +406 -0
- pandaserver/brokerage/__init__.py +0 -0
- pandaserver/brokerage/broker.py +272 -0
- pandaserver/config/__init__.py +0 -0
- pandaserver/config/config_utils.py +15 -0
- pandaserver/config/daemon_config.py +29 -0
- pandaserver/config/mcp_config.py +38 -0
- pandaserver/config/panda_config.py +233 -0
- pandaserver/configurator/Carbon.py +65 -0
- pandaserver/configurator/Configurator.py +908 -0
- pandaserver/configurator/__init__.py +0 -0
- pandaserver/configurator/aux.py +73 -0
- pandaserver/daemons/__init__.py +0 -0
- pandaserver/daemons/master.py +110 -0
- pandaserver/daemons/master_systemd.py +79 -0
- pandaserver/daemons/scripts/__init__.py +0 -0
- pandaserver/daemons/scripts/add_main.py +264 -0
- pandaserver/daemons/scripts/add_sub.py +221 -0
- pandaserver/daemons/scripts/cache_pilots.py +47 -0
- pandaserver/daemons/scripts/cache_schedconfig.py +286 -0
- pandaserver/daemons/scripts/carbon.py +50 -0
- pandaserver/daemons/scripts/configurator.py +94 -0
- pandaserver/daemons/scripts/copyArchive.py +1387 -0
- pandaserver/daemons/scripts/datasetManager.py +1154 -0
- pandaserver/daemons/scripts/dummy_test.py +25 -0
- pandaserver/daemons/scripts/evpPD2P.py +144 -0
- pandaserver/daemons/scripts/hs_scrapers.py +264 -0
- pandaserver/daemons/scripts/metric_collector.py +927 -0
- pandaserver/daemons/scripts/panda_activeusers_query.py +80 -0
- pandaserver/daemons/scripts/pilotStreaming.py +109 -0
- pandaserver/daemons/scripts/process_workflow_files_daemon.py +166 -0
- pandaserver/daemons/scripts/recover_lost_files_daemon.py +177 -0
- pandaserver/daemons/scripts/task_evaluator.py +405 -0
- pandaserver/daemons/scripts/tmpwatch.py +70 -0
- pandaserver/daemons/scripts/worker_synchronization.py +97 -0
- pandaserver/daemons/utils.py +753 -0
- pandaserver/dataservice/DataServiceUtils.py +323 -0
- pandaserver/dataservice/ErrorCode.py +25 -0
- pandaserver/dataservice/RecoverLostFilesCore.py +322 -0
- pandaserver/dataservice/__init__.py +0 -0
- pandaserver/dataservice/activator.py +79 -0
- pandaserver/dataservice/adder_atlas_plugin.py +1106 -0
- pandaserver/dataservice/adder_dummy_plugin.py +31 -0
- pandaserver/dataservice/adder_gen.py +954 -0
- pandaserver/dataservice/adder_plugin_base.py +27 -0
- pandaserver/dataservice/adder_result.py +75 -0
- pandaserver/dataservice/adder_simple_plugin.py +160 -0
- pandaserver/dataservice/closer.py +247 -0
- pandaserver/dataservice/closer_atlas_plugin.py +90 -0
- pandaserver/dataservice/ddm.py +1381 -0
- pandaserver/dataservice/ddm_handler.py +95 -0
- pandaserver/dataservice/dyn_data_distributer.py +824 -0
- pandaserver/dataservice/event_lookup_client_ei.py +77 -0
- pandaserver/dataservice/event_picker.py +268 -0
- pandaserver/dataservice/finisher.py +194 -0
- pandaserver/dataservice/setupper.py +225 -0
- pandaserver/dataservice/setupper_atlas_plugin.py +1851 -0
- pandaserver/dataservice/setupper_dummy_plugin.py +47 -0
- pandaserver/dataservice/setupper_plugin_base.py +67 -0
- pandaserver/jobdispatcher/DispatcherUtils.py +35 -0
- pandaserver/jobdispatcher/ErrorCode.py +19 -0
- pandaserver/jobdispatcher/JobDispatcher.py +1625 -0
- pandaserver/jobdispatcher/Protocol.py +443 -0
- pandaserver/jobdispatcher/Watcher.py +186 -0
- pandaserver/jobdispatcher/__init__.py +0 -0
- pandaserver/pandamcp/__init__.py +0 -0
- pandaserver/pandamcp/mcp_main.py +56 -0
- pandaserver/pandamcp/mcp_test_client.py +95 -0
- pandaserver/pandamcp/mcp_utils.py +74 -0
- pandaserver/proxycache/__init__.py +0 -0
- pandaserver/proxycache/panda_proxy_cache.py +240 -0
- pandaserver/proxycache/token_cache.py +141 -0
- pandaserver/server/.gacl +6 -0
- pandaserver/server/panda.py +539 -0
- pandaserver/srvcore/CoreUtils.py +572 -0
- pandaserver/srvcore/MailUtils.py +106 -0
- pandaserver/srvcore/__init__.py +0 -0
- pandaserver/srvcore/allowed_methods.py +100 -0
- pandaserver/srvcore/oidc_utils.py +152 -0
- pandaserver/srvcore/panda_request.py +196 -0
- pandaserver/srvcore/srv_msg_utils.py +42 -0
- pandaserver/taskbuffer/ConBridge.py +513 -0
- pandaserver/taskbuffer/DBProxyPool.py +95 -0
- pandaserver/taskbuffer/DataCarousel.py +3053 -0
- pandaserver/taskbuffer/DatasetSpec.py +137 -0
- pandaserver/taskbuffer/DdmSpec.py +201 -0
- pandaserver/taskbuffer/ErrorCode.py +87 -0
- pandaserver/taskbuffer/EventServiceUtils.py +396 -0
- pandaserver/taskbuffer/FileSpec.py +290 -0
- pandaserver/taskbuffer/GlobalShares.py +244 -0
- pandaserver/taskbuffer/HarvesterMetricsSpec.py +92 -0
- pandaserver/taskbuffer/Initializer.py +82 -0
- pandaserver/taskbuffer/InputChunk.py +1080 -0
- pandaserver/taskbuffer/JediCacheSpec.py +57 -0
- pandaserver/taskbuffer/JediDatasetSpec.py +588 -0
- pandaserver/taskbuffer/JediFileSpec.py +242 -0
- pandaserver/taskbuffer/JediTaskSpec.py +1687 -0
- pandaserver/taskbuffer/JobSpec.py +1006 -0
- pandaserver/taskbuffer/JobUtils.py +232 -0
- pandaserver/taskbuffer/NucleusSpec.py +116 -0
- pandaserver/taskbuffer/OraDBProxy.py +174 -0
- pandaserver/taskbuffer/PanDAMsgProcessor.py +8 -0
- pandaserver/taskbuffer/PandaDBSchemaInfo.py +18 -0
- pandaserver/taskbuffer/ParseJobXML.py +350 -0
- pandaserver/taskbuffer/PickleFileSpec.py +18 -0
- pandaserver/taskbuffer/PickleJobSpec.py +25 -0
- pandaserver/taskbuffer/PrioUtil.py +40 -0
- pandaserver/taskbuffer/ProcessGroups.py +111 -0
- pandaserver/taskbuffer/ResourceSpec.py +175 -0
- pandaserver/taskbuffer/SQLDumper.py +37 -0
- pandaserver/taskbuffer/SQLManager.py +60 -0
- pandaserver/taskbuffer/SiteSpec.py +304 -0
- pandaserver/taskbuffer/SupErrors.py +10 -0
- pandaserver/taskbuffer/TaskBuffer.py +2882 -0
- pandaserver/taskbuffer/TaskBufferInterface.py +163 -0
- pandaserver/taskbuffer/Utils.py +848 -0
- pandaserver/taskbuffer/WorkQueue.py +227 -0
- pandaserver/taskbuffer/WorkQueueMapper.py +203 -0
- pandaserver/taskbuffer/WorkerSpec.py +143 -0
- pandaserver/taskbuffer/WrappedCursor.py +487 -0
- pandaserver/taskbuffer/WrappedPickle.py +88 -0
- pandaserver/taskbuffer/WrappedPostgresConn.py +24 -0
- pandaserver/taskbuffer/__init__.py +0 -0
- pandaserver/taskbuffer/db_proxy_mods/OraDBProxy_structure.png +0 -0
- pandaserver/taskbuffer/db_proxy_mods/__init__.py +7 -0
- pandaserver/taskbuffer/db_proxy_mods/base_module.py +841 -0
- pandaserver/taskbuffer/db_proxy_mods/data_carousel_module.py +772 -0
- pandaserver/taskbuffer/db_proxy_mods/entity_module.py +3804 -0
- pandaserver/taskbuffer/db_proxy_mods/job_complex_module.py +5661 -0
- pandaserver/taskbuffer/db_proxy_mods/job_standalone_module.py +2640 -0
- pandaserver/taskbuffer/db_proxy_mods/metrics_module.py +874 -0
- pandaserver/taskbuffer/db_proxy_mods/misc_standalone_module.py +4272 -0
- pandaserver/taskbuffer/db_proxy_mods/task_complex_module.py +6172 -0
- pandaserver/taskbuffer/db_proxy_mods/task_event_module.py +4953 -0
- pandaserver/taskbuffer/db_proxy_mods/task_standalone_module.py +4999 -0
- pandaserver/taskbuffer/db_proxy_mods/task_utils_module.py +2063 -0
- pandaserver/taskbuffer/db_proxy_mods/worker_module.py +1944 -0
- pandaserver/taskbuffer/db_proxy_mods/workflow_module.py +832 -0
- pandaserver/taskbuffer/retryModule.py +552 -0
- pandaserver/taskbuffer/task_split_rules.py +308 -0
- pandaserver/taskbuffer/workflow_processor.py +249 -0
- pandaserver/taskbuffer/wrapped_oracle_conn.py +18 -0
- pandaserver/test/SchemaChecker.py +40 -0
- pandaserver/test/__init__.py +0 -0
- pandaserver/test/banUser.py +43 -0
- pandaserver/test/boostPrio.py +19 -0
- pandaserver/test/boostUser.py +35 -0
- pandaserver/test/callbackDDM.py +11 -0
- pandaserver/test/daod_on_demand.py +95 -0
- pandaserver/test/finishJob.py +184 -0
- pandaserver/test/finishTaskJEDI.py +11 -0
- pandaserver/test/getJobs.py +53 -0
- pandaserver/test/killJob.py +79 -0
- pandaserver/test/killJobLowPrio.py +99 -0
- pandaserver/test/killJobsInTask.py +56 -0
- pandaserver/test/killTask.py +80 -0
- pandaserver/test/killTaskJEDI.py +11 -0
- pandaserver/test/killUser.py +83 -0
- pandaserver/test/lsst/README.txt +7 -0
- pandaserver/test/lsst/lsstSubmit.py +139 -0
- pandaserver/test/lsst/lsstSubmitMERGEtest.py +141 -0
- pandaserver/test/lsst/lsstSubmitPhosim332.py +53 -0
- pandaserver/test/lsst/prepare-client-tarball-from-bigpanda-server.sh +41 -0
- pandaserver/test/reassignJobs.py +17 -0
- pandaserver/test/reassignSite.py +82 -0
- pandaserver/test/reassignTask.py +117 -0
- pandaserver/test/reassignWaiting.py +39 -0
- pandaserver/test/recoverLostFiles.py +7 -0
- pandaserver/test/reloadInputDS.py +51 -0
- pandaserver/test/sendCommandToJob.py +26 -0
- pandaserver/test/setDebugMode.py +38 -0
- pandaserver/test/setPriority.py +28 -0
- pandaserver/test/testEvgen.py +60 -0
- pandaserver/test/testEvgen17.py +58 -0
- pandaserver/test/testG4sim.py +81 -0
- pandaserver/test/testG4sim17.py +90 -0
- pandaserver/test/testGlobalShares.py +131 -0
- pandaserver/test/testReco.py +103 -0
- pandaserver/test/testSimulReco14.py +98 -0
- pandaserver/test/testSiteMap.py +26 -0
- pandaserver/test/testUpdateWorkerPilotStatus.py +9 -0
- pandaserver/userinterface/Client.py +1686 -0
- pandaserver/userinterface/UserIF.py +1799 -0
- pandaserver/userinterface/__init__.py +0 -0
- pandaserver/workflow/__init__.py +0 -0
- pandaserver/workflow/data_handler_plugins/base_data_handler.py +48 -0
- pandaserver/workflow/data_handler_plugins/ddm_collection_data_handler.py +100 -0
- pandaserver/workflow/data_handler_plugins/panda_task_data_handler.py +140 -0
- pandaserver/workflow/pcwl_test.py +122 -0
- pandaserver/workflow/pcwl_utils.py +384 -0
- pandaserver/workflow/psnakemake_container.json +68 -0
- pandaserver/workflow/psnakemake_task.json +62 -0
- pandaserver/workflow/psnakemake_test.py +60 -0
- pandaserver/workflow/snakeparser/__init__.py +3 -0
- pandaserver/workflow/snakeparser/extensions.py +74 -0
- pandaserver/workflow/snakeparser/log.py +53 -0
- pandaserver/workflow/snakeparser/names.py +3 -0
- pandaserver/workflow/snakeparser/parser.py +332 -0
- pandaserver/workflow/snakeparser/utils.py +29 -0
- pandaserver/workflow/step_handler_plugins/base_step_handler.py +85 -0
- pandaserver/workflow/step_handler_plugins/panda_task_step_handler.py +280 -0
- pandaserver/workflow/workflow_base.py +531 -0
- pandaserver/workflow/workflow_core.py +1974 -0
- pandaserver/workflow/workflow_core_smoketest.py +388 -0
- pandaserver/workflow/workflow_parser.py +222 -0
- pandaserver/workflow/workflow_utils.py +1047 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""
|
|
2
|
+
cache specification for JEDI
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class JediCacheSpec(object):
|
|
8
|
+
# attributes
|
|
9
|
+
attributes = (
|
|
10
|
+
"main_key",
|
|
11
|
+
"sub_key",
|
|
12
|
+
"data",
|
|
13
|
+
"last_update",
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# constructor
|
|
17
|
+
def __init__(self):
|
|
18
|
+
# install attributes
|
|
19
|
+
for attr in self.attributes:
|
|
20
|
+
object.__setattr__(self, attr, None)
|
|
21
|
+
|
|
22
|
+
# return map of values
|
|
23
|
+
def valuesMap(self):
|
|
24
|
+
ret = {}
|
|
25
|
+
for attr in self.attributes:
|
|
26
|
+
val = getattr(self, attr)
|
|
27
|
+
ret[f":{attr}"] = val
|
|
28
|
+
return ret
|
|
29
|
+
|
|
30
|
+
# pack tuple into JediCacheSpec
|
|
31
|
+
def pack(self, values):
|
|
32
|
+
for i, attr in enumerate(self.attributes):
|
|
33
|
+
val = values[i]
|
|
34
|
+
object.__setattr__(self, attr, val)
|
|
35
|
+
|
|
36
|
+
# return column names for INSERT
|
|
37
|
+
@classmethod
|
|
38
|
+
def columnNames(cls, prefix=None):
|
|
39
|
+
ret = ""
|
|
40
|
+
if prefix is None:
|
|
41
|
+
ret = ",".join(cls.attributes)
|
|
42
|
+
else:
|
|
43
|
+
ret = ",".join([f"{prefix}.{attr}" for attr in cls.attributes])
|
|
44
|
+
return ret
|
|
45
|
+
|
|
46
|
+
# return expression of bind variables for INSERT
|
|
47
|
+
@classmethod
|
|
48
|
+
def bindValuesExpression(cls):
|
|
49
|
+
values_str = ",".join([f":{attr}" for attr in cls.attributes])
|
|
50
|
+
ret = f"VALUES({values_str})"
|
|
51
|
+
return ret
|
|
52
|
+
|
|
53
|
+
# return an expression of bind variables for UPDATE
|
|
54
|
+
@classmethod
|
|
55
|
+
def bindUpdateChangesExpression(cls):
|
|
56
|
+
ret = ",".join(["{0}=:{0}".format(attr) for attr in cls.attributes])
|
|
57
|
+
return ret
|
|
@@ -0,0 +1,588 @@
|
|
|
1
|
+
"""
|
|
2
|
+
dataset specification for JEDI
|
|
3
|
+
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import math
|
|
7
|
+
import re
|
|
8
|
+
|
|
9
|
+
from pandacommon.pandautils.PandaUtils import get_sql_IN_bind_variables
|
|
10
|
+
|
|
11
|
+
from pandaserver.config import panda_config
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class JediDatasetSpec(object):
|
|
15
|
+
def __str__(self):
|
|
16
|
+
sb = []
|
|
17
|
+
for key in self.__dict__:
|
|
18
|
+
if key == "Files":
|
|
19
|
+
sb.append(f"{key}='{len(self.__dict__[key])}'")
|
|
20
|
+
else:
|
|
21
|
+
sb.append(f"{key}='{self.__dict__[key]}'")
|
|
22
|
+
return ", ".join(sb)
|
|
23
|
+
|
|
24
|
+
def __repr__(self):
|
|
25
|
+
return self.__str__()
|
|
26
|
+
|
|
27
|
+
# attributes
|
|
28
|
+
_attributes = (
|
|
29
|
+
"jediTaskID",
|
|
30
|
+
"datasetID",
|
|
31
|
+
"datasetName",
|
|
32
|
+
"containerName",
|
|
33
|
+
"type",
|
|
34
|
+
"creationTime",
|
|
35
|
+
"modificationTime",
|
|
36
|
+
"vo",
|
|
37
|
+
"cloud",
|
|
38
|
+
"site",
|
|
39
|
+
"masterID",
|
|
40
|
+
"provenanceID",
|
|
41
|
+
"status",
|
|
42
|
+
"state",
|
|
43
|
+
"stateCheckTime",
|
|
44
|
+
"stateCheckExpiration",
|
|
45
|
+
"frozenTime",
|
|
46
|
+
"nFiles",
|
|
47
|
+
"nFilesToBeUsed",
|
|
48
|
+
"nFilesUsed",
|
|
49
|
+
"nFilesFinished",
|
|
50
|
+
"nFilesFailed",
|
|
51
|
+
"nFilesOnHold",
|
|
52
|
+
"nEvents",
|
|
53
|
+
"nEventsToBeUsed",
|
|
54
|
+
"nEventsUsed",
|
|
55
|
+
"lockedBy",
|
|
56
|
+
"lockedTime",
|
|
57
|
+
"attributes",
|
|
58
|
+
"streamName",
|
|
59
|
+
"storageToken",
|
|
60
|
+
"destination",
|
|
61
|
+
"templateID",
|
|
62
|
+
"nFilesWaiting",
|
|
63
|
+
"nFilesMissing",
|
|
64
|
+
)
|
|
65
|
+
# attributes which have 0 by default
|
|
66
|
+
_zeroAttrs = ()
|
|
67
|
+
# attributes to force update
|
|
68
|
+
_forceUpdateAttrs = ("lockedBy", "lockedTime")
|
|
69
|
+
# mapping between sequence and attr
|
|
70
|
+
_seqAttrMap = {"datasetID": f"{panda_config.schemaJEDI}.JEDI_DATASETS_ID_SEQ.nextval"}
|
|
71
|
+
# token for attributes
|
|
72
|
+
attrToken = {
|
|
73
|
+
"allowNoOutput": "an",
|
|
74
|
+
"consistencyCheck": "cc",
|
|
75
|
+
"eventRatio": "er",
|
|
76
|
+
"indexConsistent": "ic",
|
|
77
|
+
"mergeOnly": "mo",
|
|
78
|
+
"nFilesPerJob": "np",
|
|
79
|
+
"num_records": "nr",
|
|
80
|
+
"offset": "of",
|
|
81
|
+
"objectStore": "os",
|
|
82
|
+
"pseudo": "ps",
|
|
83
|
+
"random": "rd",
|
|
84
|
+
"reusable": "ru",
|
|
85
|
+
"transient": "tr",
|
|
86
|
+
"useDuplicated": "ud",
|
|
87
|
+
"no_staging": "ns",
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
# constructor
|
|
91
|
+
def __init__(self):
|
|
92
|
+
# install attributes
|
|
93
|
+
for attr in self._attributes:
|
|
94
|
+
object.__setattr__(self, attr, None)
|
|
95
|
+
# file list
|
|
96
|
+
object.__setattr__(self, "Files", [])
|
|
97
|
+
# map of changed attributes
|
|
98
|
+
object.__setattr__(self, "_changedAttrs", {})
|
|
99
|
+
# distributed
|
|
100
|
+
object.__setattr__(self, "distributed", False)
|
|
101
|
+
|
|
102
|
+
# override __setattr__ to collecte the changed attributes
|
|
103
|
+
def __setattr__(self, name, value):
|
|
104
|
+
oldVal = getattr(self, name)
|
|
105
|
+
object.__setattr__(self, name, value)
|
|
106
|
+
newVal = getattr(self, name)
|
|
107
|
+
# collect changed attributes
|
|
108
|
+
if oldVal != newVal or name in self._forceUpdateAttrs:
|
|
109
|
+
self._changedAttrs[name] = value
|
|
110
|
+
|
|
111
|
+
# add File to files list
|
|
112
|
+
def addFile(self, fileSpec):
|
|
113
|
+
# append
|
|
114
|
+
self.Files.append(fileSpec)
|
|
115
|
+
|
|
116
|
+
# reset changed attribute list
|
|
117
|
+
def resetChangedList(self):
|
|
118
|
+
object.__setattr__(self, "_changedAttrs", {})
|
|
119
|
+
|
|
120
|
+
# force update
|
|
121
|
+
def forceUpdate(self, name):
|
|
122
|
+
if name in self._attributes:
|
|
123
|
+
self._changedAttrs[name] = getattr(self, name)
|
|
124
|
+
|
|
125
|
+
# return map of values
|
|
126
|
+
def valuesMap(self, useSeq=False, onlyChanged=False):
|
|
127
|
+
ret = {}
|
|
128
|
+
for attr in self._attributes:
|
|
129
|
+
# use sequence
|
|
130
|
+
if useSeq and attr in self._seqAttrMap:
|
|
131
|
+
continue
|
|
132
|
+
# only changed attributes
|
|
133
|
+
if onlyChanged:
|
|
134
|
+
if attr not in self._changedAttrs:
|
|
135
|
+
continue
|
|
136
|
+
val = getattr(self, attr)
|
|
137
|
+
if val is None:
|
|
138
|
+
if attr in self._zeroAttrs:
|
|
139
|
+
val = 0
|
|
140
|
+
else:
|
|
141
|
+
val = None
|
|
142
|
+
ret[f":{attr}"] = val
|
|
143
|
+
return ret
|
|
144
|
+
|
|
145
|
+
# pack tuple into FileSpec
|
|
146
|
+
def pack(self, values):
|
|
147
|
+
for i in range(len(self._attributes)):
|
|
148
|
+
attr = self._attributes[i]
|
|
149
|
+
val = values[i]
|
|
150
|
+
object.__setattr__(self, attr, val)
|
|
151
|
+
|
|
152
|
+
# return column names for INSERT
|
|
153
|
+
def columnNames(cls, prefix=None):
|
|
154
|
+
ret = ""
|
|
155
|
+
for attr in cls._attributes:
|
|
156
|
+
if prefix is not None:
|
|
157
|
+
ret += f"{prefix}."
|
|
158
|
+
ret += f"{attr},"
|
|
159
|
+
ret = ret[:-1]
|
|
160
|
+
return ret
|
|
161
|
+
|
|
162
|
+
columnNames = classmethod(columnNames)
|
|
163
|
+
|
|
164
|
+
# return expression of bind variables for INSERT
|
|
165
|
+
def bindValuesExpression(cls, useSeq=True):
|
|
166
|
+
ret = "VALUES("
|
|
167
|
+
for attr in cls._attributes:
|
|
168
|
+
if useSeq and attr in cls._seqAttrMap:
|
|
169
|
+
ret += f"{cls._seqAttrMap[attr]},"
|
|
170
|
+
else:
|
|
171
|
+
ret += f":{attr},"
|
|
172
|
+
ret = ret[:-1]
|
|
173
|
+
ret += ")"
|
|
174
|
+
return ret
|
|
175
|
+
|
|
176
|
+
bindValuesExpression = classmethod(bindValuesExpression)
|
|
177
|
+
|
|
178
|
+
# return an expression of bind variables for UPDATE to update only changed attributes
|
|
179
|
+
def bindUpdateChangesExpression(self):
|
|
180
|
+
ret = ""
|
|
181
|
+
for attr in self._attributes:
|
|
182
|
+
if attr in self._changedAttrs:
|
|
183
|
+
ret += f"{attr}=:{attr},"
|
|
184
|
+
ret = ret[:-1]
|
|
185
|
+
ret += " "
|
|
186
|
+
return ret
|
|
187
|
+
|
|
188
|
+
# set dataset attribute
|
|
189
|
+
def setDatasetAttribute(self, attr):
|
|
190
|
+
if self.attributes is None:
|
|
191
|
+
self.attributes = ""
|
|
192
|
+
else:
|
|
193
|
+
self.attributes += ","
|
|
194
|
+
self.attributes += attr
|
|
195
|
+
|
|
196
|
+
# set dataset attribute with label
|
|
197
|
+
def setDatasetAttributeWithLabel(self, label):
|
|
198
|
+
if label not in self.attrToken:
|
|
199
|
+
return
|
|
200
|
+
attr = self.attrToken[label]
|
|
201
|
+
if self.attributes is None:
|
|
202
|
+
self.attributes = ""
|
|
203
|
+
else:
|
|
204
|
+
self.attributes += ","
|
|
205
|
+
self.attributes += attr
|
|
206
|
+
|
|
207
|
+
# return list of status to update contents
|
|
208
|
+
def statusToUpdateContents(cls):
|
|
209
|
+
return ["defined", "toupdate"]
|
|
210
|
+
|
|
211
|
+
statusToUpdateContents = classmethod(statusToUpdateContents)
|
|
212
|
+
|
|
213
|
+
# return list of types for input
|
|
214
|
+
def getInputTypes(cls):
|
|
215
|
+
return ["input", "pseudo_input"]
|
|
216
|
+
|
|
217
|
+
getInputTypes = classmethod(getInputTypes)
|
|
218
|
+
|
|
219
|
+
# return list of types to generate jobs
|
|
220
|
+
def getProcessTypes(cls):
|
|
221
|
+
return cls.getInputTypes() + ["pp_input"] + cls.getMergeProcessTypes()
|
|
222
|
+
|
|
223
|
+
getProcessTypes = classmethod(getProcessTypes)
|
|
224
|
+
|
|
225
|
+
# return list of types for merging
|
|
226
|
+
def getMergeProcessTypes(cls):
|
|
227
|
+
return ["trn_log", "trn_output"]
|
|
228
|
+
|
|
229
|
+
getMergeProcessTypes = classmethod(getMergeProcessTypes)
|
|
230
|
+
|
|
231
|
+
# get type of unknown input
|
|
232
|
+
def getUnknownInputType(cls):
|
|
233
|
+
return "trn_unknown"
|
|
234
|
+
|
|
235
|
+
getUnknownInputType = classmethod(getUnknownInputType)
|
|
236
|
+
|
|
237
|
+
# check if JEDI needs to keep track of file usage
|
|
238
|
+
def toKeepTrack(self):
|
|
239
|
+
if self.isNoSplit() and self.isRepeated():
|
|
240
|
+
return False
|
|
241
|
+
elif self.isReusable():
|
|
242
|
+
return False
|
|
243
|
+
else:
|
|
244
|
+
return True
|
|
245
|
+
|
|
246
|
+
# check if it is not split
|
|
247
|
+
def isNoSplit(self):
|
|
248
|
+
if self.attributes is not None and "nosplit" in self.attributes:
|
|
249
|
+
return True
|
|
250
|
+
else:
|
|
251
|
+
return False
|
|
252
|
+
|
|
253
|
+
# check if it is repeatedly used
|
|
254
|
+
def isRepeated(self):
|
|
255
|
+
if self.attributes is not None and "repeat" in self.attributes:
|
|
256
|
+
return True
|
|
257
|
+
else:
|
|
258
|
+
return False
|
|
259
|
+
|
|
260
|
+
# check if it is randomly used
|
|
261
|
+
def isRandom(self):
|
|
262
|
+
if self.attributes is not None and "rd" in self.attributes.split(","):
|
|
263
|
+
return True
|
|
264
|
+
else:
|
|
265
|
+
return False
|
|
266
|
+
|
|
267
|
+
# check if it is reusable
|
|
268
|
+
def isReusable(self):
|
|
269
|
+
if self.attributes is not None and "ru" in self.attributes.split(","):
|
|
270
|
+
return True
|
|
271
|
+
else:
|
|
272
|
+
return False
|
|
273
|
+
|
|
274
|
+
# check if consistency is checked
|
|
275
|
+
def checkConsistency(self):
|
|
276
|
+
if self.attributes is not None and "cc" in self.attributes.split(","):
|
|
277
|
+
return True
|
|
278
|
+
else:
|
|
279
|
+
return False
|
|
280
|
+
|
|
281
|
+
# set consistency is checked
|
|
282
|
+
def enableCheckConsistency(self):
|
|
283
|
+
if self.attributes in [None, ""]:
|
|
284
|
+
self.attributes = "cc"
|
|
285
|
+
elif "cc" not in self.attributes.split(","):
|
|
286
|
+
self.attributes += ",cc"
|
|
287
|
+
|
|
288
|
+
# check if it is pseudo
|
|
289
|
+
def isPseudo(self):
|
|
290
|
+
if self.datasetName in ["pseudo_dataset", "seq_number"] or self.type in ["pp_input"]:
|
|
291
|
+
return True
|
|
292
|
+
if self.attributes is not None and self.attrToken["pseudo"] in self.attributes.split(","):
|
|
293
|
+
return True
|
|
294
|
+
return False
|
|
295
|
+
|
|
296
|
+
# check if it is a many-time dataset which is treated as long-standing at T2s
|
|
297
|
+
def isManyTime(self):
|
|
298
|
+
if self.attributes is not None and "manytime" in self.attributes:
|
|
299
|
+
return True
|
|
300
|
+
else:
|
|
301
|
+
return False
|
|
302
|
+
|
|
303
|
+
# check if it is seq number
|
|
304
|
+
def isSeqNumber(self):
|
|
305
|
+
if self.datasetName in ["seq_number"]:
|
|
306
|
+
return True
|
|
307
|
+
else:
|
|
308
|
+
return False
|
|
309
|
+
|
|
310
|
+
# check if duplicated files are used
|
|
311
|
+
def useDuplicatedFiles(self):
|
|
312
|
+
if self.attributes is not None and ("usedup" in self.attributes or "ud" in self.attributes.split(",")):
|
|
313
|
+
return True
|
|
314
|
+
else:
|
|
315
|
+
return False
|
|
316
|
+
|
|
317
|
+
# check if it is a master dataset
|
|
318
|
+
def isMaster(self):
|
|
319
|
+
if self.masterID is None and self.type in self.getProcessTypes():
|
|
320
|
+
return True
|
|
321
|
+
else:
|
|
322
|
+
return False
|
|
323
|
+
|
|
324
|
+
# check if it is a master input dataset
|
|
325
|
+
def isMasterInput(self):
|
|
326
|
+
if self.masterID is None and self.type in self.getInputTypes():
|
|
327
|
+
return True
|
|
328
|
+
else:
|
|
329
|
+
return False
|
|
330
|
+
|
|
331
|
+
# remove nosplit attribute
|
|
332
|
+
def remAttribute(self, attrName):
|
|
333
|
+
if self.attributes is not None:
|
|
334
|
+
self.attributes = re.sub(attrName, "", self.attributes)
|
|
335
|
+
self.attributes = re.sub(",,", ",", self.attributes)
|
|
336
|
+
self.attributes = re.sub("^,", "", self.attributes)
|
|
337
|
+
self.attributes = re.sub(",$", "", self.attributes)
|
|
338
|
+
if self.attributes == "":
|
|
339
|
+
self.attributes = None
|
|
340
|
+
|
|
341
|
+
# remove nosplit attribute
|
|
342
|
+
def remNoSplit(self):
|
|
343
|
+
self.remAttribute("nosplit")
|
|
344
|
+
|
|
345
|
+
# remove repeat attribute
|
|
346
|
+
def remRepeat(self):
|
|
347
|
+
self.remAttribute("repeat")
|
|
348
|
+
|
|
349
|
+
# get the ratio to master
|
|
350
|
+
def getRatioToMaster(self):
|
|
351
|
+
try:
|
|
352
|
+
tmpMatch = re.search("ratio=(\d+(\.\d+)*)", self.attributes)
|
|
353
|
+
if tmpMatch is not None:
|
|
354
|
+
ratioStr = tmpMatch.group(1)
|
|
355
|
+
try:
|
|
356
|
+
# integer
|
|
357
|
+
return int(ratioStr)
|
|
358
|
+
except Exception:
|
|
359
|
+
pass
|
|
360
|
+
try:
|
|
361
|
+
# float
|
|
362
|
+
return float(ratioStr)
|
|
363
|
+
except Exception:
|
|
364
|
+
pass
|
|
365
|
+
except Exception:
|
|
366
|
+
pass
|
|
367
|
+
return 1
|
|
368
|
+
|
|
369
|
+
# get N multiplied by ratio
|
|
370
|
+
def getNumMultByRatio(self, num):
|
|
371
|
+
# no split
|
|
372
|
+
if self.isNoSplit():
|
|
373
|
+
return None
|
|
374
|
+
# get ratio
|
|
375
|
+
ratioVal = self.getRatioToMaster()
|
|
376
|
+
# integer or float
|
|
377
|
+
if isinstance(ratioVal, int):
|
|
378
|
+
retVal = num * ratioVal
|
|
379
|
+
else:
|
|
380
|
+
retVal = float(num) * ratioVal
|
|
381
|
+
retVal = int(math.ceil(retVal))
|
|
382
|
+
return retVal
|
|
383
|
+
|
|
384
|
+
# unique map key for output
|
|
385
|
+
def outputMapKey(self):
|
|
386
|
+
mapKey = f"{self.datasetName}#{self.provenanceID}"
|
|
387
|
+
return mapKey
|
|
388
|
+
|
|
389
|
+
# unique map key
|
|
390
|
+
def uniqueMapKey(self):
|
|
391
|
+
mapKey = f"{self.datasetName}#{self.datasetID}"
|
|
392
|
+
return mapKey
|
|
393
|
+
|
|
394
|
+
# set offset
|
|
395
|
+
def setOffset(self, offset):
|
|
396
|
+
self.setDatasetAttribute(f"{self.attrToken['offset']}={offset}")
|
|
397
|
+
|
|
398
|
+
# get offset
|
|
399
|
+
def getOffset(self):
|
|
400
|
+
if self.attributes is not None:
|
|
401
|
+
tmpMatch = re.search(self.attrToken["offset"] + "=(\d+)", self.attributes)
|
|
402
|
+
if tmpMatch is not None:
|
|
403
|
+
offset = int(tmpMatch.group(1))
|
|
404
|
+
return offset
|
|
405
|
+
return 0
|
|
406
|
+
|
|
407
|
+
# set number of records
|
|
408
|
+
def setNumRecords(self, n):
|
|
409
|
+
self.setDatasetAttribute(f"{self.attrToken['num_records']}={n}")
|
|
410
|
+
|
|
411
|
+
# get number of records
|
|
412
|
+
def getNumRecords(self):
|
|
413
|
+
if self.attributes is not None:
|
|
414
|
+
for item in self.attributes.split(","):
|
|
415
|
+
tmpMatch = re.search(self.attrToken["num_records"] + "=(\d+)", item)
|
|
416
|
+
if tmpMatch is not None:
|
|
417
|
+
num_records = int(tmpMatch.group(1))
|
|
418
|
+
return num_records
|
|
419
|
+
return None
|
|
420
|
+
|
|
421
|
+
# set object store
|
|
422
|
+
def setObjectStore(self, objectStore):
|
|
423
|
+
self.setDatasetAttribute(f"{self.attrToken['objectStore']}={objectStore}")
|
|
424
|
+
|
|
425
|
+
# get object store
|
|
426
|
+
def getObjectStore(self):
|
|
427
|
+
if self.attributes is not None:
|
|
428
|
+
tmpMatch = re.search(self.attrToken["objectStore"] + "=([^,]+)", self.attributes)
|
|
429
|
+
if tmpMatch is not None:
|
|
430
|
+
return tmpMatch.group(1)
|
|
431
|
+
return None
|
|
432
|
+
|
|
433
|
+
# set the number of files per job
|
|
434
|
+
def setNumFilesPerJob(self, num):
|
|
435
|
+
self.setDatasetAttribute(f"{self.attrToken['nFilesPerJob']}={num}")
|
|
436
|
+
|
|
437
|
+
# get the number of files per job
|
|
438
|
+
def getNumFilesPerJob(self):
|
|
439
|
+
if self.attributes is not None:
|
|
440
|
+
tmpMatch = re.search(self.attrToken["nFilesPerJob"] + "=(\d+)", self.attributes)
|
|
441
|
+
if tmpMatch is not None:
|
|
442
|
+
num = int(tmpMatch.group(1))
|
|
443
|
+
return num
|
|
444
|
+
# use continuous numbers for seq_number
|
|
445
|
+
if self.isSeqNumber():
|
|
446
|
+
return 1
|
|
447
|
+
return None
|
|
448
|
+
|
|
449
|
+
# check if unmerged dataset
|
|
450
|
+
def toMerge(self):
|
|
451
|
+
if self.type.startswith("trn_"):
|
|
452
|
+
return True
|
|
453
|
+
return False
|
|
454
|
+
|
|
455
|
+
# set transient
|
|
456
|
+
def setTransient(self, val):
|
|
457
|
+
if val is True:
|
|
458
|
+
val = 1
|
|
459
|
+
else:
|
|
460
|
+
val = 0
|
|
461
|
+
self.setDatasetAttribute(f"{self.attrToken['transient']}={val}")
|
|
462
|
+
|
|
463
|
+
# get transient
|
|
464
|
+
def getTransient(self):
|
|
465
|
+
if self.attributes is not None:
|
|
466
|
+
for item in self.attributes.split(","):
|
|
467
|
+
tmpMatch = re.search(self.attrToken["transient"] + "=(\d+)", item)
|
|
468
|
+
if tmpMatch is not None:
|
|
469
|
+
val = int(tmpMatch.group(1))
|
|
470
|
+
if val == 1:
|
|
471
|
+
return True
|
|
472
|
+
else:
|
|
473
|
+
return False
|
|
474
|
+
return None
|
|
475
|
+
|
|
476
|
+
# check if no output is allowed
|
|
477
|
+
def isAllowedNoOutput(self):
|
|
478
|
+
if self.attributes is not None and self.attrToken["allowNoOutput"] in self.attributes.split(","):
|
|
479
|
+
return True
|
|
480
|
+
else:
|
|
481
|
+
return False
|
|
482
|
+
|
|
483
|
+
# allow no output
|
|
484
|
+
def allowNoOutput(self):
|
|
485
|
+
if self.attributes in [None, ""]:
|
|
486
|
+
items = []
|
|
487
|
+
else:
|
|
488
|
+
items = self.attributes.split(",")
|
|
489
|
+
if self.attrToken["allowNoOutput"] not in items:
|
|
490
|
+
items.append(self.attrToken["allowNoOutput"])
|
|
491
|
+
self.attributes = ",".join(items)
|
|
492
|
+
|
|
493
|
+
# check if index consistency is required
|
|
494
|
+
def indexConsistent(self):
|
|
495
|
+
if self.attributes is not None and self.attrToken["indexConsistent"] in self.attributes.split(","):
|
|
496
|
+
return True
|
|
497
|
+
else:
|
|
498
|
+
return False
|
|
499
|
+
|
|
500
|
+
# set distributed
|
|
501
|
+
def setDistributed(self):
|
|
502
|
+
self.distributed = True
|
|
503
|
+
|
|
504
|
+
# reset distributed
|
|
505
|
+
def reset_distributed(self):
|
|
506
|
+
self.distributed = False
|
|
507
|
+
|
|
508
|
+
# check if distributed
|
|
509
|
+
def isDistributed(self):
|
|
510
|
+
return self.distributed
|
|
511
|
+
|
|
512
|
+
# set event ratio
|
|
513
|
+
def setEventRatio(self, num):
|
|
514
|
+
self.setDatasetAttribute(f"{self.attrToken['eventRatio']}={num}")
|
|
515
|
+
|
|
516
|
+
# get event ratio
|
|
517
|
+
def getEventRatio(self):
|
|
518
|
+
if self.attributes is not None:
|
|
519
|
+
for item in self.attributes.split(","):
|
|
520
|
+
tmpMatch = re.search(self.attrToken["eventRatio"] + "=(\d+(\.\d+)*)", item)
|
|
521
|
+
if tmpMatch is not None:
|
|
522
|
+
ratioStr = tmpMatch.group(1)
|
|
523
|
+
try:
|
|
524
|
+
# integer
|
|
525
|
+
return int(ratioStr)
|
|
526
|
+
except Exception:
|
|
527
|
+
pass
|
|
528
|
+
try:
|
|
529
|
+
# float
|
|
530
|
+
return float(ratioStr)
|
|
531
|
+
except Exception:
|
|
532
|
+
pass
|
|
533
|
+
return None
|
|
534
|
+
|
|
535
|
+
# set pseudo
|
|
536
|
+
def setPseudo(self):
|
|
537
|
+
if self.attributes in [None, ""]:
|
|
538
|
+
items = []
|
|
539
|
+
else:
|
|
540
|
+
items = self.attributes.split(",")
|
|
541
|
+
if self.attrToken["pseudo"] not in items:
|
|
542
|
+
items.append(self.attrToken["pseudo"])
|
|
543
|
+
self.attributes = ",".join(items)
|
|
544
|
+
|
|
545
|
+
# merge only
|
|
546
|
+
def is_merge_only(self):
|
|
547
|
+
try:
|
|
548
|
+
return self.attrToken["mergeOnly"] in self.attributes.split(",")
|
|
549
|
+
except Exception:
|
|
550
|
+
return False
|
|
551
|
+
|
|
552
|
+
# sort files by old PandaIDs and move files with no PandaIDs to the end
|
|
553
|
+
def sort_files_by_panda_ids(self):
|
|
554
|
+
self.Files = sorted([f for f in self.Files if f.PandaID is not None], key=lambda x: x.PandaID) + [f for f in self.Files if f.PandaID is None]
|
|
555
|
+
|
|
556
|
+
# set no staging
|
|
557
|
+
def set_no_staging(self, value: bool):
|
|
558
|
+
"""
|
|
559
|
+
Set no_staging (ns) attribute for dataset
|
|
560
|
+
|
|
561
|
+
Args:
|
|
562
|
+
value (bool): value of no_staging; will set attribute = 1 for True or 0 for False
|
|
563
|
+
"""
|
|
564
|
+
num_repr = 1 if value else 0
|
|
565
|
+
self.setDatasetAttribute(f"{self.attrToken['no_staging']}={num_repr}")
|
|
566
|
+
|
|
567
|
+
# get whether is no_staging
|
|
568
|
+
def is_no_staging(self) -> bool:
|
|
569
|
+
"""
|
|
570
|
+
Set no_staging (ns) attribute for dataset
|
|
571
|
+
|
|
572
|
+
Returns:
|
|
573
|
+
bool: whether with no_staging
|
|
574
|
+
"""
|
|
575
|
+
if self.attributes is not None:
|
|
576
|
+
for item in self.attributes.split(","):
|
|
577
|
+
tmpMatch = re.search(self.attrToken["no_staging"] + "=(\d+)", item)
|
|
578
|
+
if tmpMatch is not None:
|
|
579
|
+
num_repr = int(tmpMatch.group(1))
|
|
580
|
+
value = bool(num_repr)
|
|
581
|
+
return value
|
|
582
|
+
return False
|
|
583
|
+
|
|
584
|
+
|
|
585
|
+
# often-used bind variables
|
|
586
|
+
INPUT_TYPES_var_str, INPUT_TYPES_var_map = get_sql_IN_bind_variables(JediDatasetSpec.getInputTypes(), prefix=":type_", value_as_suffix=True)
|
|
587
|
+
PROCESS_TYPES_var_str, PROCESS_TYPES_var_map = get_sql_IN_bind_variables(JediDatasetSpec.getProcessTypes(), prefix=":type_", value_as_suffix=True)
|
|
588
|
+
MERGE_TYPES_var_str, MERGE_TYPES_var_map = get_sql_IN_bind_variables(JediDatasetSpec.getMergeProcessTypes(), prefix=":type_", value_as_suffix=True)
|