LbAPLocal 0.15.0__tar.gz → 0.16.0__tar.gz

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.
Files changed (168) hide show
  1. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/.gitlab-ci.yml +14 -0
  2. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/PKG-INFO +1 -1
  3. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cli/main.py +94 -75
  4. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal.egg-info/PKG-INFO +1 -1
  5. lbaplocal-0.16.0/src/LbAPLocal.egg-info/scm_version.json +8 -0
  6. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_execute.py +54 -1
  7. lbaplocal-0.15.0/src/LbAPLocal.egg-info/scm_version.json +0 -8
  8. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/.coveragerc +0 -0
  9. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/.gitattributes +0 -0
  10. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/.gitignore +0 -0
  11. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/.pre-commit-config.yaml +0 -0
  12. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/CONTRIBUTING.md +0 -0
  13. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/LICENSE +0 -0
  14. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/README.md +0 -0
  15. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/example.json +0 -0
  16. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/pyproject.toml +0 -0
  17. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/setup.cfg +0 -0
  18. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/__init__.py +0 -0
  19. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cli/__init__.py +0 -0
  20. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cli/cvmfs.py +0 -0
  21. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cli/decfile_lexer.py +0 -0
  22. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cli/generate.py +0 -0
  23. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cli/legacy.py +0 -0
  24. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cli/mc_lookup.py +0 -0
  25. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cli/mc_wizard.py +0 -0
  26. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cli/textual_ui.py +0 -0
  27. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cli/wizards.py +0 -0
  28. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cwl/__init__.py +0 -0
  29. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cwl/app_runner.py +0 -0
  30. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cwl/generate_replica_map.py +0 -0
  31. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cwl/quickjs_engine.py +0 -0
  32. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cwl/rewrite.py +0 -0
  33. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/cwl/runner.py +0 -0
  34. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/handlers/__init__.py +0 -0
  35. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/handlers/anaprod.py +0 -0
  36. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/handlers/mc_request.py +0 -0
  37. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/job_slice.py +0 -0
  38. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/log_parsing.py +0 -0
  39. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/models.py +0 -0
  40. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/reason_analysis.py +0 -0
  41. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/reason_driver.py +0 -0
  42. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/testing.py +0 -0
  43. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal/utils.py +0 -0
  44. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal.egg-info/SOURCES.txt +0 -0
  45. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal.egg-info/dependency_links.txt +0 -0
  46. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal.egg-info/entry_points.txt +0 -0
  47. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal.egg-info/requires.txt +0 -0
  48. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal.egg-info/scm_file_list.json +0 -0
  49. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/src/LbAPLocal.egg-info/top_level.txt +0 -0
  50. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/capture_fixtures.py +0 -0
  51. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/cassettes/test_execute/test_run_test[2016_MagDown_PromptMC_D02KK-2444].yaml +0 -0
  52. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/cassettes/test_execute/test_run_test[2016_MagDown_PromptMC_D02KK_noautoconf-2444].yaml +0 -0
  53. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/cassettes/test_execute/test_run_test[2016_MagUp_PromptMC_D02KK-2393].yaml +0 -0
  54. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/cassettes/test_execute/test_run_test[2016_MagUp_PromptMC_D02KK_noautoconf-2393].yaml +0 -0
  55. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/conftest.py +0 -0
  56. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/.gitignore +0 -0
  57. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/.gitlab-ci.yml +0 -0
  58. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/AnalysisProductions.xenv +0 -0
  59. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/Bc2Bspi2JpsiPhi.py +0 -0
  60. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/Bd2JpsiKstar.py +0 -0
  61. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/Bd2JpsiKstar_stripping.py +0 -0
  62. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/Bs2DsPi.py +0 -0
  63. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/Bs2JpsiPhi.py +0 -0
  64. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/Bs2JpsiPhi_Prompt.py +0 -0
  65. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/Bs2JpsiPhi_Prompt_PVMixer.py +0 -0
  66. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/Bs2JpsiPhi_Swave.py +0 -0
  67. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/Bu2JpsiKplus.py +0 -0
  68. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/Bu2JpsiKplus_stripping.py +0 -0
  69. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/LbJpsipK.py +0 -0
  70. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/README.md +0 -0
  71. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/helpers/__init__.py +0 -0
  72. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/helpers/stripping.py +0 -0
  73. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/helpers/tuple_maker.py +0 -0
  74. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/info.yaml +0 -0
  75. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/BsToJpsiPhi/sequence_setup.py +0 -0
  76. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/COPYING +0 -0
  77. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/RDs/README.md +0 -0
  78. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/RDs/Run1_Signal.py +0 -0
  79. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/RDs/Run2_Signal.py +0 -0
  80. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/RDs/helpers/__init__.py +0 -0
  81. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/RDs/helpers/signal_tuple_maker.py +0 -0
  82. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/RDs/info.yaml +0 -0
  83. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/README.md +0 -0
  84. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/__init__.py +0 -0
  85. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/2011_datatype.py +0 -0
  86. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/2012_datatype.py +0 -0
  87. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/2015_datatype.py +0 -0
  88. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/2016_datatype.py +0 -0
  89. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/2017_datatype.py +0 -0
  90. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/2018_datatype.py +0 -0
  91. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/B0ToK0ee.py +0 -0
  92. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/B0ToK0mumu.py +0 -0
  93. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/BpToKee.py +0 -0
  94. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/BpToKmumu.py +0 -0
  95. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/LbToL0ee.py +0 -0
  96. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/LbToL0eeSS.py +0 -0
  97. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/LbToL0emu.py +0 -0
  98. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/LbToL0emuSS.py +0 -0
  99. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/LbToL0mumu.py +0 -0
  100. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/LbToL0mumuSS.py +0 -0
  101. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/README.md +0 -0
  102. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/__init__.py +0 -0
  103. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/general_options.py +0 -0
  104. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/helpers/MC_tuple_maker.py +0 -0
  105. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/helpers/__init__.py +0 -0
  106. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/helpers/decay_descriptors.py +0 -0
  107. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/helpers/locations.py +0 -0
  108. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/helpers/related_info.py +0 -0
  109. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/helpers/stripping.py +0 -0
  110. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/helpers/tags.py +0 -0
  111. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/helpers/tuple_maker.py +0 -0
  112. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/info.yaml +0 -0
  113. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_general_options_DST.py +0 -0
  114. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_general_options_FDST.py +0 -0
  115. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_general_options_FMDST.py +0 -0
  116. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_general_options_MDST.py +0 -0
  117. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Bd2JpsiKs_ee.py +0 -0
  118. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Bd2JpsiKs_mm.py +0 -0
  119. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Bd2Ksee.py +0 -0
  120. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Bd2Ksmm.py +0 -0
  121. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Bd2PsiKs_ee.py +0 -0
  122. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Bd2PsiKs_mm.py +0 -0
  123. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Bu2JpsiK_ee.py +0 -0
  124. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Bu2JpsiK_mm.py +0 -0
  125. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Lb2JpsiL_ee.py +0 -0
  126. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Lb2JpsiL_mm.py +0 -0
  127. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Lb2Lee.py +0 -0
  128. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Lb2Lem.py +0 -0
  129. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Lb2Lmm.py +0 -0
  130. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Lb2PsiL_ee.py +0 -0
  131. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/mc_samples/MC_Lb2PsiL_mm.py +0 -0
  132. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/sequence_setup.py +0 -0
  133. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/cbtesting/stripping_seq.py +0 -0
  134. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/executabletests/2016_MagDown_PromptMC_D02KK_autoconf.py +0 -0
  135. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/executabletests/2016_MagUp_PromptMC_D02KK_autoconf.py +0 -0
  136. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/executabletests/info.yaml +0 -0
  137. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/data-pkg-repo/executabletests/ntuple_options.py +0 -0
  138. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/example-logs/error-failed-to-read-file.log +0 -0
  139. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/example-logs/error-illegal-instruction.log +0 -0
  140. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/example-logs/error-missing-shared-library.log +0 -0
  141. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/example-logs/error-platform-unsupported.log +0 -0
  142. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/example-logs/error-related-info-missing.log +0 -0
  143. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/example-logs/good-DaVinci_00110296_00000038_1.log +0 -0
  144. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/example-logs/good-DaVinci_00110296_00000194_1.log +0 -0
  145. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/data/example-logs/good-Gauss_00104988_00000011_1.log +0 -0
  146. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/fixture_loader.py +0 -0
  147. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/fixtures/executabletests/2016_MagDown_PromptMC_D02KK/query_result.json +0 -0
  148. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/fixtures/executabletests/2016_MagUp_PromptMC_D02KK/query_result.json +0 -0
  149. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/fixtures/executabletests/manifest.yaml +0 -0
  150. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/reslice_fixture.py +0 -0
  151. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test-input-dst/00070767_00000711_7.AllStreams_slice.dst +0 -0
  152. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test-input-dst/00070793_00000685_7.AllStreams_slice.dst +0 -0
  153. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_app_runner.py +0 -0
  154. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_cli.py +0 -0
  155. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_cwl_cli.py +0 -0
  156. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_cwl_runner.py +0 -0
  157. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_generate.py +0 -0
  158. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_get_mc.py +0 -0
  159. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_handlers.py +0 -0
  160. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_input_resolution.py +0 -0
  161. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_local_datapkg.py +0 -0
  162. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_log_parse.py +0 -0
  163. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_mc_lookup.py +0 -0
  164. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_no_dirac_cwl.py +0 -0
  165. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_parse_yaml_catalog.py +0 -0
  166. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_quickjs_engine.py +0 -0
  167. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_reason_analysis.py +0 -0
  168. {lbaplocal-0.15.0 → lbaplocal-0.16.0}/tests/test_reason_driver_integration.py +0 -0
@@ -12,6 +12,15 @@ stages:
12
12
  - test
13
13
  - deploy
14
14
 
15
+ include:
16
+ - remote: https://raw.githubusercontent.com/chrisburr/release/888e9de9c33649c558cd319de367e7520219322e/gitlab/trusted-publish.yml
17
+ inputs:
18
+ feedstock: lbaplocal-feedstock
19
+ repository: chrisburr/release
20
+ ref: 888e9de9c33649c558cd319de367e7520219322e
21
+ rules:
22
+ - if: $CI_COMMIT_TAG && $CI_PROJECT_PATH == "lhcb-dpa/analysis-productions/lbaplocal"
23
+
15
24
  pixi:
16
25
  parallel:
17
26
  matrix:
@@ -57,3 +66,8 @@ deploy-packages:
57
66
  - python -m build
58
67
  - if [ -z "$TWINE_PASSWORD" ] ; then echo "Set TWINE_PASSWORD in CI variables" ; exit 1 ; fi
59
68
  - twine upload -u __token__ dist/*
69
+
70
+ # Ask conda-forge to update the feedstock once the release is on PyPI
71
+ update-feedstock-version:
72
+ needs:
73
+ - deploy-packages
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: LbAPLocal
3
- Version: 0.15.0
3
+ Version: 0.16.0
4
4
  Summary: Tool to locally run tests for AnalysisProductions
5
5
  Author: LHCb
6
6
  Project-URL: Homepage, https://gitlab.cern.ch/lhcb-dpa/analysis-productions/lbaplocal
@@ -1768,11 +1768,11 @@ def test(
1768
1768
  ] = None,
1769
1769
  job_name: Annotated[Optional[str], typer.Argument(help="Job name to test")] = None,
1770
1770
  dependent_input: Annotated[
1771
- Optional[str],
1771
+ Optional[list[str]],
1772
1772
  typer.Option(
1773
1773
  "-i",
1774
1774
  "--input",
1775
- help="Specific input file (LFN or local path)",
1775
+ help="Specific input file (LFN or local path); repeat for multiple files",
1776
1776
  ),
1777
1777
  ] = None,
1778
1778
  interactive: Annotated[
@@ -1850,6 +1850,7 @@ def test(
1850
1850
  lb-ap test # Interactive wizard
1851
1851
  lb-ap test MyAnalysis MyJob # Uses 1 LFN by default
1852
1852
  lb-ap test MyAnalysis MyJob -n 100 # Slice input to 100 events
1853
+ lb-ap test MyAnalysis MyJob -i LFN:/lhcb/... -i ./local.dst # Custom inputs
1853
1854
  lb-ap test MyAnalysis MyJob --download # Download input files locally
1854
1855
  lb-ap test MyAnalysis MyJob --n-lfns 5 # Test with 5 LFNs
1855
1856
  lb-ap test MyAnalysis MyJob --pick-smallest-lfn # Use smallest LFN
@@ -3902,11 +3903,11 @@ def cwl_test(
3902
3903
  ] = None,
3903
3904
  job_name: Annotated[Optional[str], typer.Argument(help="Job name to test")] = None,
3904
3905
  dependent_input: Annotated[
3905
- Optional[str],
3906
+ Optional[list[str]],
3906
3907
  typer.Option(
3907
3908
  "-i",
3908
3909
  "--input",
3909
- help="Specific input file (LFN or local path)",
3910
+ help="Specific input file (LFN or local path); repeat for multiple files",
3910
3911
  ),
3911
3912
  ] = None,
3912
3913
  n_events: Annotated[
@@ -4007,7 +4008,8 @@ def cwl_test(
4007
4008
 
4008
4009
  production_name = params["production_name"]
4009
4010
  job_name = params["job_name"]
4010
- dependent_input = params.get("dependent_input") or dependent_input
4011
+ if params.get("dependent_input"):
4012
+ dependent_input = [params["dependent_input"]]
4011
4013
  n_events = params.get("n_events") or n_events
4012
4014
  skip_validation = params.get("skip_validation", skip_validation)
4013
4015
 
@@ -4050,7 +4052,7 @@ def cwl_test(
4050
4052
  f"[cyan]Production:[/cyan] {production_name}\n"
4051
4053
  f"[cyan]Job:[/cyan] {job_name}\n"
4052
4054
  f"[cyan]Events:[/cyan] {n_events or 'default'}\n"
4053
- f"[cyan]Input:[/cyan] {dependent_input or 'default'}\n"
4055
+ f"[cyan]Input:[/cyan] {', '.join(dependent_input) if dependent_input else 'default'}\n"
4054
4056
  f"[cyan]Output:[/cyan] {output_dir}",
4055
4057
  title="🧪 CWL Test Configuration",
4056
4058
  border_style="cyan",
@@ -4124,9 +4126,18 @@ def cwl_test(
4124
4126
  console.print(f"\n[bold cyan]Slicing input to {n_events} events[/bold cyan]")
4125
4127
  slice_dir = output_dir / "sliced_input"
4126
4128
 
4127
- if dependent_input and not dependent_input.startswith("LFN:"):
4129
+ # Slicing produces a single N-event file, so only the first custom
4130
+ # input is used.
4131
+ slice_source = dependent_input[0] if dependent_input else None
4132
+ if dependent_input and len(dependent_input) > 1:
4133
+ console.print(
4134
+ f"[yellow]⚠ -n slices a single file; using only the first input "
4135
+ f"({slice_source}) and ignoring {len(dependent_input) - 1} other(s)[/yellow]"
4136
+ )
4137
+
4138
+ if slice_source and not slice_source.startswith("LFN:"):
4128
4139
  # Case B: Custom local file — slice directly
4129
- input_for_slice = str(Path(dependent_input).resolve())
4140
+ input_for_slice = str(Path(slice_source).resolve())
4130
4141
  else:
4131
4142
  # Case A (no -i) or Case C (-i with LFN): need to resolve a PFN
4132
4143
  import importlib.util
@@ -4140,9 +4151,9 @@ def cwl_test(
4140
4151
 
4141
4152
  slice_map_path = output_dir / "slice-replica-map.json"
4142
4153
 
4143
- if dependent_input and dependent_input.startswith("LFN:"):
4154
+ if slice_source and slice_source.startswith("LFN:"):
4144
4155
  # Case C: Custom LFN input
4145
- lfn_path = dependent_input.removeprefix("LFN:")
4156
+ lfn_path = slice_source.removeprefix("LFN:")
4146
4157
  cmd_map = [
4147
4158
  "lb-dirac",
4148
4159
  "python",
@@ -4223,7 +4234,7 @@ def cwl_test(
4223
4234
  )
4224
4235
 
4225
4236
  # Replace dependent_input with the sliced local file
4226
- dependent_input = str(sliced_path)
4237
+ dependent_input = [str(sliced_path)]
4227
4238
 
4228
4239
  # Step 2b: Resolve/rewrite input data for execution.
4229
4240
  #
@@ -4236,6 +4247,8 @@ def cwl_test(
4236
4247
  # specific LFN), then rewrite the CWL with the resolved PFN string --
4237
4248
  # never pass an unresolved "LFN:..." string to
4238
4249
  # rewrite_cwl_for_custom_input, which raises on that.
4250
+ # -i may be repeated and may mix B and C; all LFNs are resolved in one
4251
+ # replica-map call and the inputs keep their command-line order.
4239
4252
  cwl_inputs_path = None
4240
4253
  # NOTE: replica_map_path is a user-facing debug artifact (and, in the
4241
4254
  # LFN case, the resolve_lfn_to_pfn input); unlike the retired DIRAC-based
@@ -4243,16 +4256,79 @@ def cwl_test(
4243
4256
  # resolved PFNs flow through the inputs YAML instead.
4244
4257
  replica_map_path = None
4245
4258
 
4246
- def rewrite_for_custom_input(input_value):
4247
- """Rewrite the CWL for a resolved custom input, exiting on failure."""
4259
+ if dependent_input:
4260
+ # Strip the LFN: prefix — DIRAC APIs expect bare paths
4261
+ custom_lfns = [
4262
+ item.removeprefix("LFN:")
4263
+ for item in dependent_input
4264
+ if item.startswith("LFN:")
4265
+ ]
4266
+ lfn_pfn_map = {}
4267
+ if custom_lfns:
4268
+ console.print(
4269
+ f"\n[bold cyan]Generating replica map for {len(custom_lfns)} "
4270
+ f"custom input LFN(s)[/bold cyan]"
4271
+ )
4272
+ import importlib.util
4273
+
4274
+ spec = importlib.util.find_spec("LbAPLocal.cwl.generate_replica_map")
4275
+ if spec is None or spec.origin is None:
4276
+ err_console.print(
4277
+ "[bold red]✗ Could not find LbAPLocal.cwl.generate_replica_map module[/bold red]"
4278
+ )
4279
+ raise typer.Exit(code=1)
4280
+
4281
+ map_path = output_dir / f"{cwl_workflow_path.stem}-replica-map.json"
4282
+ cmd_map = ["lb-dirac", "python", spec.origin]
4283
+ for lfn_path in custom_lfns:
4284
+ cmd_map += ["--lfns", lfn_path]
4285
+ cmd_map += ["--output-map", str(map_path)]
4286
+ if download:
4287
+ cmd_map.append("--download")
4288
+ result = subprocess.run(cmd_map, capture_output=True, text=True)
4289
+ if result.returncode != 0:
4290
+ # generate_replica_map prints errors to stdout via rich Console
4291
+ error_output = result.stderr or result.stdout
4292
+ err_console.print(
4293
+ f"[bold red]✗ Failed to generate replica map:[/bold red]\n{error_output}"
4294
+ )
4295
+ raise typer.Exit(code=1)
4296
+ replica_map_path = map_path
4297
+ console.print(f"[green]✓ Generated replica map:[/green] {replica_map_path}")
4298
+
4299
+ from LbAPLocal.cwl.generate_replica_map import resolve_lfn_to_pfn
4300
+
4301
+ lfn_pfn_map = resolve_lfn_to_pfn(map_path)
4302
+ missing = [lfn for lfn in custom_lfns if lfn not in lfn_pfn_map]
4303
+ if missing:
4304
+ err_console.print(
4305
+ f"[bold red]✗ Replica map has no entry for:[/bold red] "
4306
+ f"{', '.join(missing)} ({map_path})"
4307
+ )
4308
+ raise typer.Exit(code=1)
4309
+ for lfn in custom_lfns:
4310
+ console.print(
4311
+ f"[green]✓ Resolved custom input to PFN:[/green] {lfn_pfn_map[lfn]}"
4312
+ )
4313
+
4314
+ resolved_inputs = [
4315
+ (
4316
+ lfn_pfn_map[item.removeprefix("LFN:")]
4317
+ if item.startswith("LFN:")
4318
+ else item
4319
+ )
4320
+ for item in dependent_input
4321
+ ]
4322
+
4248
4323
  from LbAPLocal.cwl.rewrite import rewrite_cwl_for_custom_input
4249
4324
 
4250
4325
  console.print(
4251
- f"\n[bold cyan]Rewriting CWL for custom input:[/bold cyan] {input_value}"
4326
+ f"\n[bold cyan]Rewriting CWL for custom input(s):[/bold cyan] "
4327
+ f"{', '.join(resolved_inputs)}"
4252
4328
  )
4253
4329
  try:
4254
- workflow_path, inputs_path = rewrite_cwl_for_custom_input(
4255
- cwl_workflow_path, [input_value], job_name
4330
+ cwl_workflow_path, cwl_inputs_path = rewrite_cwl_for_custom_input(
4331
+ cwl_workflow_path, resolved_inputs, job_name
4256
4332
  )
4257
4333
  except Exception as e:
4258
4334
  err_console.print(f"[bold red]✗ CWL rewriting failed:[/bold red] {e}")
@@ -4260,65 +4336,8 @@ def cwl_test(
4260
4336
 
4261
4337
  err_console.print(traceback.format_exc())
4262
4338
  raise typer.Exit(code=1)
4263
- console.print(f"[green]✓ Modified CWL workflow:[/green] {workflow_path}")
4264
- console.print(f"[green]✓ Custom inputs file:[/green] {inputs_path}")
4265
- return workflow_path, inputs_path
4266
-
4267
- if dependent_input and dependent_input.startswith("LFN:"):
4268
- console.print(
4269
- "\n[bold cyan]Generating replica map for custom input LFN[/bold cyan]"
4270
- )
4271
- import importlib.util
4272
-
4273
- spec = importlib.util.find_spec("LbAPLocal.cwl.generate_replica_map")
4274
- if spec is None or spec.origin is None:
4275
- err_console.print(
4276
- "[bold red]✗ Could not find LbAPLocal.cwl.generate_replica_map module[/bold red]"
4277
- )
4278
- raise typer.Exit(code=1)
4279
-
4280
- map_path = output_dir / f"{cwl_workflow_path.stem}-replica-map.json"
4281
- # Strip the LFN: prefix — DIRAC APIs expect bare paths
4282
- lfn_path = dependent_input.removeprefix("LFN:")
4283
- cmd_map = [
4284
- "lb-dirac",
4285
- "python",
4286
- spec.origin,
4287
- "--lfns",
4288
- lfn_path,
4289
- "--output-map",
4290
- str(map_path),
4291
- ]
4292
- if download:
4293
- cmd_map.append("--download")
4294
- result = subprocess.run(cmd_map, capture_output=True, text=True)
4295
- if result.returncode != 0:
4296
- # generate_replica_map prints errors to stdout via rich Console
4297
- error_output = result.stderr or result.stdout
4298
- err_console.print(
4299
- f"[bold red]✗ Failed to generate replica map:[/bold red]\n{error_output}"
4300
- )
4301
- raise typer.Exit(code=1)
4302
- replica_map_path = map_path
4303
- console.print(f"[green]✓ Generated replica map:[/green] {replica_map_path}")
4304
-
4305
- from LbAPLocal.cwl.generate_replica_map import resolve_lfn_to_pfn
4306
-
4307
- lfn_pfn_map = resolve_lfn_to_pfn(map_path)
4308
- if not lfn_pfn_map:
4309
- err_console.print(
4310
- f"[bold red]✗ Replica map contains no entries:[/bold red] {map_path}"
4311
- )
4312
- raise typer.Exit(code=1)
4313
- resolved_input = next(iter(lfn_pfn_map.values()))
4314
- console.print(
4315
- f"[green]✓ Resolved custom input to PFN:[/green] {resolved_input}"
4316
- )
4317
-
4318
- cwl_workflow_path, cwl_inputs_path = rewrite_for_custom_input(resolved_input)
4319
-
4320
- elif dependent_input:
4321
- cwl_workflow_path, cwl_inputs_path = rewrite_for_custom_input(dependent_input)
4339
+ console.print(f"[green]✓ Modified CWL workflow:[/green] {cwl_workflow_path}")
4340
+ console.print(f"[green]✓ Custom inputs file:[/green] {cwl_inputs_path}")
4322
4341
 
4323
4342
  else:
4324
4343
  # Resolve input data for the default (no -i) case: BK query from the
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: LbAPLocal
3
- Version: 0.15.0
3
+ Version: 0.16.0
4
4
  Summary: Tool to locally run tests for AnalysisProductions
5
5
  Author: LHCb
6
6
  Project-URL: Homepage, https://gitlab.cern.ch/lhcb-dpa/analysis-productions/lbaplocal
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.16.0",
3
+ "distance": 0,
4
+ "node": "gc92615b0f05b80a84cfe467f7d4176dd8f00fc95",
5
+ "dirty": false,
6
+ "branch": "HEAD",
7
+ "node_date": "2026-10-06"
8
+ }
@@ -114,7 +114,7 @@ def test_cwl_test_custom_input_lfn(
114
114
  cwl_test(
115
115
  production_name=cwl_fixture_set.production_name,
116
116
  job_name=job_name,
117
- dependent_input=f"LFN:{lfn}",
117
+ dependent_input=[f"LFN:{lfn}"],
118
118
  skip_validation=True,
119
119
  output_dir=output_dir,
120
120
  )
@@ -153,6 +153,59 @@ def test_cwl_test_custom_input_lfn(
153
153
  assert root_outputs, f"No .root output file found under {cwl_output}"
154
154
 
155
155
 
156
+ @pytest.mark.slow
157
+ def test_cwl_test_multiple_custom_inputs(
158
+ data_pkg_repo, mock_dirac_calls, cwl_fixture_set, tmp_path, monkeypatch
159
+ ):
160
+ """Test repeated `-i` mixing an LFN and a local path.
161
+
162
+ Both inputs must reach the rewritten CWL's `custom-input` entries in
163
+ command-line order, with the LFN resolved via the replica map. The two
164
+ inputs are distinct fixture DSTs: Gaudi crashes opening two files that
165
+ share a GUID, so a copy of the same DST can't be used.
166
+ """
167
+ import typer
168
+
169
+ from LbAPLocal.cli.main import cwl_test
170
+
171
+ monkeypatch.setattr(
172
+ LbAPLocal.cli,
173
+ "get_auth_headers",
174
+ lambda: dict(headers={"Authorization": "Bearer "}),
175
+ )
176
+
177
+ job_name = "2016_MagDown_PromptMC_D02KK"
178
+ lfn = cwl_fixture_set.get_lfn(job_name)
179
+ dst_path = cwl_fixture_set.get_dst_path(job_name)
180
+ local_path = cwl_fixture_set.get_dst_path("2016_MagUp_PromptMC_D02KK")
181
+
182
+ output_dir = tmp_path / "cwl_output"
183
+
184
+ try:
185
+ cwl_test(
186
+ production_name=cwl_fixture_set.production_name,
187
+ job_name=job_name,
188
+ dependent_input=[f"LFN:{lfn}", str(local_path)],
189
+ skip_validation=True,
190
+ output_dir=output_dir,
191
+ )
192
+ except (typer.Exit, SystemExit) as e:
193
+ exit_code = getattr(e, "exit_code", getattr(e, "code", 1))
194
+ pytest.fail(f"cwl_test exited with code {exit_code}")
195
+
196
+ custom_inputs_files = list(output_dir.glob("*_custom_inputs.yml"))
197
+ assert custom_inputs_files, "No custom inputs file generated"
198
+ custom_inputs = yaml.safe_load(custom_inputs_files[0].read_text())
199
+ entries = custom_inputs["custom-input"]
200
+ assert [e["class"] for e in entries] == ["File", "File"]
201
+ assert [e["location"] for e in entries] == [
202
+ dst_path.resolve().as_uri(),
203
+ local_path.resolve().as_uri(),
204
+ ]
205
+
206
+ assert list(output_dir.glob("*-replica-map.json")), "No replica map generated"
207
+
208
+
156
209
  # ============================================================================
157
210
  # Legacy tests (deprecated, kept temporarily)
158
211
  # ============================================================================
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "0.15.0",
3
- "distance": 0,
4
- "node": "g9bb93815ef9dd1fb277f618aba2545808563f636",
5
- "dirty": false,
6
- "branch": "HEAD",
7
- "node_date": "2026-08-27"
8
- }
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes