wmglobalqueue 2.4.5.1__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.
Files changed (347) hide show
  1. Utils/CPMetrics.py +270 -0
  2. Utils/CertTools.py +100 -0
  3. Utils/EmailAlert.py +50 -0
  4. Utils/ExtendedUnitTestCase.py +62 -0
  5. Utils/FileTools.py +182 -0
  6. Utils/IteratorTools.py +80 -0
  7. Utils/MathUtils.py +31 -0
  8. Utils/MemoryCache.py +119 -0
  9. Utils/Patterns.py +24 -0
  10. Utils/Pipeline.py +137 -0
  11. Utils/PortForward.py +97 -0
  12. Utils/ProcFS.py +112 -0
  13. Utils/ProcessStats.py +194 -0
  14. Utils/PythonVersion.py +17 -0
  15. Utils/Signals.py +36 -0
  16. Utils/TemporaryEnvironment.py +27 -0
  17. Utils/Throttled.py +227 -0
  18. Utils/Timers.py +130 -0
  19. Utils/Timestamps.py +86 -0
  20. Utils/TokenManager.py +143 -0
  21. Utils/Tracing.py +60 -0
  22. Utils/TwPrint.py +98 -0
  23. Utils/Utilities.py +318 -0
  24. Utils/__init__.py +11 -0
  25. Utils/wmcoreDTools.py +707 -0
  26. WMCore/ACDC/Collection.py +57 -0
  27. WMCore/ACDC/CollectionTypes.py +12 -0
  28. WMCore/ACDC/CouchCollection.py +67 -0
  29. WMCore/ACDC/CouchFileset.py +238 -0
  30. WMCore/ACDC/CouchService.py +73 -0
  31. WMCore/ACDC/DataCollectionService.py +485 -0
  32. WMCore/ACDC/Fileset.py +94 -0
  33. WMCore/ACDC/__init__.py +11 -0
  34. WMCore/Algorithms/Alarm.py +39 -0
  35. WMCore/Algorithms/MathAlgos.py +274 -0
  36. WMCore/Algorithms/MiscAlgos.py +67 -0
  37. WMCore/Algorithms/ParseXMLFile.py +115 -0
  38. WMCore/Algorithms/Permissions.py +27 -0
  39. WMCore/Algorithms/Singleton.py +58 -0
  40. WMCore/Algorithms/SubprocessAlgos.py +129 -0
  41. WMCore/Algorithms/__init__.py +7 -0
  42. WMCore/Cache/GenericDataCache.py +98 -0
  43. WMCore/Cache/WMConfigCache.py +572 -0
  44. WMCore/Cache/__init__.py +0 -0
  45. WMCore/Configuration.py +659 -0
  46. WMCore/DAOFactory.py +47 -0
  47. WMCore/DataStructs/File.py +177 -0
  48. WMCore/DataStructs/Fileset.py +140 -0
  49. WMCore/DataStructs/Job.py +182 -0
  50. WMCore/DataStructs/JobGroup.py +142 -0
  51. WMCore/DataStructs/JobPackage.py +49 -0
  52. WMCore/DataStructs/LumiList.py +734 -0
  53. WMCore/DataStructs/Mask.py +219 -0
  54. WMCore/DataStructs/MathStructs/ContinuousSummaryHistogram.py +197 -0
  55. WMCore/DataStructs/MathStructs/DiscreteSummaryHistogram.py +92 -0
  56. WMCore/DataStructs/MathStructs/SummaryHistogram.py +117 -0
  57. WMCore/DataStructs/MathStructs/__init__.py +0 -0
  58. WMCore/DataStructs/Pickleable.py +24 -0
  59. WMCore/DataStructs/Run.py +256 -0
  60. WMCore/DataStructs/Subscription.py +175 -0
  61. WMCore/DataStructs/WMObject.py +47 -0
  62. WMCore/DataStructs/WorkUnit.py +112 -0
  63. WMCore/DataStructs/Workflow.py +60 -0
  64. WMCore/DataStructs/__init__.py +8 -0
  65. WMCore/Database/CMSCouch.py +1430 -0
  66. WMCore/Database/ConfigDBMap.py +29 -0
  67. WMCore/Database/CouchMonitoring.py +450 -0
  68. WMCore/Database/CouchUtils.py +118 -0
  69. WMCore/Database/DBCore.py +198 -0
  70. WMCore/Database/DBCreator.py +113 -0
  71. WMCore/Database/DBExceptionHandler.py +59 -0
  72. WMCore/Database/DBFactory.py +117 -0
  73. WMCore/Database/DBFormatter.py +177 -0
  74. WMCore/Database/Dialects.py +13 -0
  75. WMCore/Database/ExecuteDAO.py +327 -0
  76. WMCore/Database/MongoDB.py +241 -0
  77. WMCore/Database/MySQL/Destroy.py +42 -0
  78. WMCore/Database/MySQL/ListUserContent.py +20 -0
  79. WMCore/Database/MySQL/__init__.py +9 -0
  80. WMCore/Database/MySQLCore.py +132 -0
  81. WMCore/Database/Oracle/Destroy.py +56 -0
  82. WMCore/Database/Oracle/ListUserContent.py +19 -0
  83. WMCore/Database/Oracle/__init__.py +9 -0
  84. WMCore/Database/ResultSet.py +44 -0
  85. WMCore/Database/Transaction.py +91 -0
  86. WMCore/Database/__init__.py +9 -0
  87. WMCore/Database/ipy_profile_couch.py +438 -0
  88. WMCore/GlobalWorkQueue/CherryPyThreads/CleanUpTask.py +29 -0
  89. WMCore/GlobalWorkQueue/CherryPyThreads/HeartbeatMonitor.py +105 -0
  90. WMCore/GlobalWorkQueue/CherryPyThreads/LocationUpdateTask.py +28 -0
  91. WMCore/GlobalWorkQueue/CherryPyThreads/ReqMgrInteractionTask.py +35 -0
  92. WMCore/GlobalWorkQueue/CherryPyThreads/__init__.py +0 -0
  93. WMCore/GlobalWorkQueue/__init__.py +0 -0
  94. WMCore/GroupUser/CouchObject.py +127 -0
  95. WMCore/GroupUser/Decorators.py +51 -0
  96. WMCore/GroupUser/Group.py +33 -0
  97. WMCore/GroupUser/Interface.py +73 -0
  98. WMCore/GroupUser/User.py +96 -0
  99. WMCore/GroupUser/__init__.py +11 -0
  100. WMCore/Lexicon.py +836 -0
  101. WMCore/REST/Auth.py +202 -0
  102. WMCore/REST/CherryPyPeriodicTask.py +166 -0
  103. WMCore/REST/Error.py +333 -0
  104. WMCore/REST/Format.py +642 -0
  105. WMCore/REST/HeartbeatMonitorBase.py +90 -0
  106. WMCore/REST/Main.py +636 -0
  107. WMCore/REST/Server.py +2435 -0
  108. WMCore/REST/Services.py +24 -0
  109. WMCore/REST/Test.py +120 -0
  110. WMCore/REST/Tools.py +38 -0
  111. WMCore/REST/Validation.py +250 -0
  112. WMCore/REST/__init__.py +1 -0
  113. WMCore/ReqMgr/DataStructs/RequestStatus.py +209 -0
  114. WMCore/ReqMgr/DataStructs/RequestType.py +13 -0
  115. WMCore/ReqMgr/DataStructs/__init__.py +0 -0
  116. WMCore/ReqMgr/__init__.py +1 -0
  117. WMCore/Services/AlertManager/AlertManagerAPI.py +111 -0
  118. WMCore/Services/AlertManager/__init__.py +0 -0
  119. WMCore/Services/CRIC/CRIC.py +238 -0
  120. WMCore/Services/CRIC/__init__.py +0 -0
  121. WMCore/Services/DBS/DBS3Reader.py +1044 -0
  122. WMCore/Services/DBS/DBSConcurrency.py +44 -0
  123. WMCore/Services/DBS/DBSErrors.py +112 -0
  124. WMCore/Services/DBS/DBSReader.py +23 -0
  125. WMCore/Services/DBS/DBSUtils.py +166 -0
  126. WMCore/Services/DBS/DBSWriterObjects.py +381 -0
  127. WMCore/Services/DBS/ProdException.py +133 -0
  128. WMCore/Services/DBS/__init__.py +8 -0
  129. WMCore/Services/FWJRDB/FWJRDBAPI.py +118 -0
  130. WMCore/Services/FWJRDB/__init__.py +0 -0
  131. WMCore/Services/HTTPS/HTTPSAuthHandler.py +66 -0
  132. WMCore/Services/HTTPS/__init__.py +0 -0
  133. WMCore/Services/LogDB/LogDB.py +201 -0
  134. WMCore/Services/LogDB/LogDBBackend.py +191 -0
  135. WMCore/Services/LogDB/LogDBExceptions.py +11 -0
  136. WMCore/Services/LogDB/LogDBReport.py +85 -0
  137. WMCore/Services/LogDB/__init__.py +0 -0
  138. WMCore/Services/MSPileup/__init__.py +0 -0
  139. WMCore/Services/MSUtils/MSUtils.py +54 -0
  140. WMCore/Services/MSUtils/__init__.py +0 -0
  141. WMCore/Services/McM/McM.py +173 -0
  142. WMCore/Services/McM/__init__.py +8 -0
  143. WMCore/Services/MonIT/Grafana.py +133 -0
  144. WMCore/Services/MonIT/__init__.py +0 -0
  145. WMCore/Services/PyCondor/PyCondorAPI.py +154 -0
  146. WMCore/Services/PyCondor/__init__.py +0 -0
  147. WMCore/Services/ReqMgr/ReqMgr.py +261 -0
  148. WMCore/Services/ReqMgr/__init__.py +0 -0
  149. WMCore/Services/ReqMgrAux/ReqMgrAux.py +419 -0
  150. WMCore/Services/ReqMgrAux/__init__.py +0 -0
  151. WMCore/Services/RequestDB/RequestDBReader.py +267 -0
  152. WMCore/Services/RequestDB/RequestDBWriter.py +39 -0
  153. WMCore/Services/RequestDB/__init__.py +0 -0
  154. WMCore/Services/Requests.py +624 -0
  155. WMCore/Services/Rucio/Rucio.py +1290 -0
  156. WMCore/Services/Rucio/RucioUtils.py +74 -0
  157. WMCore/Services/Rucio/__init__.py +0 -0
  158. WMCore/Services/RucioConMon/RucioConMon.py +121 -0
  159. WMCore/Services/RucioConMon/__init__.py +0 -0
  160. WMCore/Services/Service.py +400 -0
  161. WMCore/Services/StompAMQ/__init__.py +0 -0
  162. WMCore/Services/TagCollector/TagCollector.py +155 -0
  163. WMCore/Services/TagCollector/XMLUtils.py +98 -0
  164. WMCore/Services/TagCollector/__init__.py +0 -0
  165. WMCore/Services/UUIDLib.py +13 -0
  166. WMCore/Services/UserFileCache/UserFileCache.py +160 -0
  167. WMCore/Services/UserFileCache/__init__.py +8 -0
  168. WMCore/Services/WMAgent/WMAgent.py +63 -0
  169. WMCore/Services/WMAgent/__init__.py +0 -0
  170. WMCore/Services/WMArchive/CMSSWMetrics.py +526 -0
  171. WMCore/Services/WMArchive/DataMap.py +463 -0
  172. WMCore/Services/WMArchive/WMArchive.py +33 -0
  173. WMCore/Services/WMArchive/__init__.py +0 -0
  174. WMCore/Services/WMBS/WMBS.py +97 -0
  175. WMCore/Services/WMBS/__init__.py +0 -0
  176. WMCore/Services/WMStats/DataStruct/RequestInfoCollection.py +300 -0
  177. WMCore/Services/WMStats/DataStruct/__init__.py +0 -0
  178. WMCore/Services/WMStats/WMStatsPycurl.py +145 -0
  179. WMCore/Services/WMStats/WMStatsReader.py +445 -0
  180. WMCore/Services/WMStats/WMStatsWriter.py +273 -0
  181. WMCore/Services/WMStats/__init__.py +0 -0
  182. WMCore/Services/WMStatsServer/WMStatsServer.py +134 -0
  183. WMCore/Services/WMStatsServer/__init__.py +0 -0
  184. WMCore/Services/WorkQueue/WorkQueue.py +492 -0
  185. WMCore/Services/WorkQueue/__init__.py +0 -0
  186. WMCore/Services/__init__.py +8 -0
  187. WMCore/Services/pycurl_manager.py +574 -0
  188. WMCore/WMBase.py +50 -0
  189. WMCore/WMConnectionBase.py +164 -0
  190. WMCore/WMException.py +183 -0
  191. WMCore/WMExceptions.py +269 -0
  192. WMCore/WMFactory.py +76 -0
  193. WMCore/WMInit.py +377 -0
  194. WMCore/WMLogging.py +104 -0
  195. WMCore/WMSpec/ConfigSectionTree.py +442 -0
  196. WMCore/WMSpec/Persistency.py +135 -0
  197. WMCore/WMSpec/Steps/BuildMaster.py +87 -0
  198. WMCore/WMSpec/Steps/BuildTools.py +201 -0
  199. WMCore/WMSpec/Steps/Builder.py +97 -0
  200. WMCore/WMSpec/Steps/Diagnostic.py +89 -0
  201. WMCore/WMSpec/Steps/Emulator.py +62 -0
  202. WMCore/WMSpec/Steps/ExecuteMaster.py +208 -0
  203. WMCore/WMSpec/Steps/Executor.py +210 -0
  204. WMCore/WMSpec/Steps/StepFactory.py +213 -0
  205. WMCore/WMSpec/Steps/TaskEmulator.py +75 -0
  206. WMCore/WMSpec/Steps/Template.py +204 -0
  207. WMCore/WMSpec/Steps/Templates/AlcaHarvest.py +76 -0
  208. WMCore/WMSpec/Steps/Templates/CMSSW.py +613 -0
  209. WMCore/WMSpec/Steps/Templates/DQMUpload.py +59 -0
  210. WMCore/WMSpec/Steps/Templates/DeleteFiles.py +70 -0
  211. WMCore/WMSpec/Steps/Templates/LogArchive.py +84 -0
  212. WMCore/WMSpec/Steps/Templates/LogCollect.py +105 -0
  213. WMCore/WMSpec/Steps/Templates/StageOut.py +105 -0
  214. WMCore/WMSpec/Steps/Templates/__init__.py +10 -0
  215. WMCore/WMSpec/Steps/WMExecutionFailure.py +21 -0
  216. WMCore/WMSpec/Steps/__init__.py +8 -0
  217. WMCore/WMSpec/Utilities.py +63 -0
  218. WMCore/WMSpec/WMSpecErrors.py +12 -0
  219. WMCore/WMSpec/WMStep.py +347 -0
  220. WMCore/WMSpec/WMTask.py +1997 -0
  221. WMCore/WMSpec/WMWorkload.py +2288 -0
  222. WMCore/WMSpec/WMWorkloadTools.py +382 -0
  223. WMCore/WMSpec/__init__.py +9 -0
  224. WMCore/WorkQueue/DataLocationMapper.py +273 -0
  225. WMCore/WorkQueue/DataStructs/ACDCBlock.py +47 -0
  226. WMCore/WorkQueue/DataStructs/Block.py +48 -0
  227. WMCore/WorkQueue/DataStructs/CouchWorkQueueElement.py +148 -0
  228. WMCore/WorkQueue/DataStructs/WorkQueueElement.py +274 -0
  229. WMCore/WorkQueue/DataStructs/WorkQueueElementResult.py +152 -0
  230. WMCore/WorkQueue/DataStructs/WorkQueueElementsSummary.py +185 -0
  231. WMCore/WorkQueue/DataStructs/__init__.py +0 -0
  232. WMCore/WorkQueue/Policy/End/EndPolicyInterface.py +44 -0
  233. WMCore/WorkQueue/Policy/End/SingleShot.py +22 -0
  234. WMCore/WorkQueue/Policy/End/__init__.py +32 -0
  235. WMCore/WorkQueue/Policy/PolicyInterface.py +17 -0
  236. WMCore/WorkQueue/Policy/Start/Block.py +258 -0
  237. WMCore/WorkQueue/Policy/Start/Dataset.py +180 -0
  238. WMCore/WorkQueue/Policy/Start/MonteCarlo.py +131 -0
  239. WMCore/WorkQueue/Policy/Start/ResubmitBlock.py +171 -0
  240. WMCore/WorkQueue/Policy/Start/StartPolicyInterface.py +316 -0
  241. WMCore/WorkQueue/Policy/Start/__init__.py +34 -0
  242. WMCore/WorkQueue/Policy/__init__.py +57 -0
  243. WMCore/WorkQueue/WMBSHelper.py +772 -0
  244. WMCore/WorkQueue/WorkQueue.py +1237 -0
  245. WMCore/WorkQueue/WorkQueueBackend.py +750 -0
  246. WMCore/WorkQueue/WorkQueueBase.py +39 -0
  247. WMCore/WorkQueue/WorkQueueExceptions.py +44 -0
  248. WMCore/WorkQueue/WorkQueueReqMgrInterface.py +278 -0
  249. WMCore/WorkQueue/WorkQueueUtils.py +130 -0
  250. WMCore/WorkQueue/__init__.py +13 -0
  251. WMCore/Wrappers/JsonWrapper/JSONThunker.py +342 -0
  252. WMCore/Wrappers/JsonWrapper/__init__.py +7 -0
  253. WMCore/Wrappers/__init__.py +6 -0
  254. WMCore/__init__.py +10 -0
  255. wmglobalqueue-2.4.5.1.data/data/bin/wmc-dist-patch +15 -0
  256. wmglobalqueue-2.4.5.1.data/data/bin/wmc-dist-unpatch +8 -0
  257. wmglobalqueue-2.4.5.1.data/data/bin/wmc-httpd +3 -0
  258. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/.couchapprc +1 -0
  259. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/README.md +40 -0
  260. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/index.html +264 -0
  261. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/ElementInfoByWorkflow.js +96 -0
  262. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/StuckElementInfo.js +57 -0
  263. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/WorkloadInfoTable.js +80 -0
  264. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/dataTable.js +70 -0
  265. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/js/namespace.js +23 -0
  266. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/_attachments/style/main.css +75 -0
  267. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/couchapp.json +4 -0
  268. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/filters/childQueueFilter.js +13 -0
  269. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/filters/filterDeletedDocs.js +3 -0
  270. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/filters/queueFilter.js +11 -0
  271. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/language +1 -0
  272. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lib/mustache.js +333 -0
  273. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lib/validate.js +27 -0
  274. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lib/workqueue_utils.js +61 -0
  275. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/elementsDetail.js +28 -0
  276. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/filter.js +86 -0
  277. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/stuckElements.js +38 -0
  278. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/workRestrictions.js +153 -0
  279. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/lists/workflowSummary.js +28 -0
  280. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/rewrites.json +73 -0
  281. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/shows/redirect.js +23 -0
  282. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/shows/status.js +40 -0
  283. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/ElementSummaryByWorkflow.html +27 -0
  284. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/StuckElementSummary.html +26 -0
  285. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/TaskStatus.html +23 -0
  286. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/WorkflowSummary.html +27 -0
  287. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/partials/workqueue-common-lib.html +2 -0
  288. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/partials/yui-lib-remote.html +16 -0
  289. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/templates/partials/yui-lib.html +18 -0
  290. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/updates/in-place.js +50 -0
  291. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/validate_doc_update.js +8 -0
  292. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.couch.app.js +235 -0
  293. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/vendor/couchapp/_attachments/jquery.pathbinder.js +173 -0
  294. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeData/map.js +8 -0
  295. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeData/reduce.js +2 -0
  296. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeParentData/map.js +8 -0
  297. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activeParentData/reduce.js +2 -0
  298. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activePileupData/map.js +8 -0
  299. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/activePileupData/reduce.js +2 -0
  300. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/analyticsData/map.js +11 -0
  301. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/analyticsData/reduce.js +1 -0
  302. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/availableByPriority/map.js +6 -0
  303. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/conflicts/map.js +5 -0
  304. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elements/map.js +5 -0
  305. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByData/map.js +8 -0
  306. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByParent/map.js +8 -0
  307. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByParentData/map.js +8 -0
  308. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByPileupData/map.js +8 -0
  309. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByStatus/map.js +8 -0
  310. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsBySubscription/map.js +6 -0
  311. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByWorkflow/map.js +8 -0
  312. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsByWorkflow/reduce.js +3 -0
  313. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/elementsDetailByWorkflowAndStatus/map.js +26 -0
  314. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/map.js +10 -0
  315. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobInjectStatusByRequest/reduce.js +1 -0
  316. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobStatusByRequest/map.js +6 -0
  317. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobStatusByRequest/reduce.js +1 -0
  318. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/map.js +6 -0
  319. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndPriority/reduce.js +1 -0
  320. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/map.js +6 -0
  321. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByChildQueueAndStatus/reduce.js +1 -0
  322. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByRequest/map.js +6 -0
  323. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByRequest/reduce.js +1 -0
  324. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatus/map.js +6 -0
  325. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatus/reduce.js +1 -0
  326. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/map.js +6 -0
  327. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/jobsByStatusAndPriority/reduce.js +1 -0
  328. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/openRequests/map.js +6 -0
  329. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/recent-items/map.js +5 -0
  330. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/map.js +6 -0
  331. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/siteWhitelistByRequest/reduce.js +1 -0
  332. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/specsByWorkflow/map.js +5 -0
  333. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/stuckElements/map.js +38 -0
  334. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/map.js +12 -0
  335. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsInjectStatusByRequest/reduce.js +3 -0
  336. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrl/map.js +6 -0
  337. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrl/reduce.js +2 -0
  338. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/map.js +6 -0
  339. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/wmbsUrlByRequest/reduce.js +2 -0
  340. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/workflowSummary/map.js +9 -0
  341. wmglobalqueue-2.4.5.1.data/data/data/couchapps/WorkQueue/views/workflowSummary/reduce.js +10 -0
  342. wmglobalqueue-2.4.5.1.dist-info/METADATA +26 -0
  343. wmglobalqueue-2.4.5.1.dist-info/RECORD +347 -0
  344. wmglobalqueue-2.4.5.1.dist-info/WHEEL +5 -0
  345. wmglobalqueue-2.4.5.1.dist-info/licenses/LICENSE +202 -0
  346. wmglobalqueue-2.4.5.1.dist-info/licenses/NOTICE +16 -0
  347. wmglobalqueue-2.4.5.1.dist-info/top_level.txt +2 -0
Utils/IteratorTools.py ADDED
@@ -0,0 +1,80 @@
1
+ #! /usr/bin/env python
2
+
3
+ from builtins import str, map
4
+ import collections.abc
5
+ from itertools import islice, chain, groupby
6
+
7
+ def grouper(iterable, n):
8
+ """
9
+ :param iterable: List of other iterable to slice
10
+ :type: iterable
11
+ :param n: Chunk size for resulting lists
12
+ :type: int
13
+ :return: iterator of the sliced list
14
+
15
+ Source: http://stackoverflow.com/questions/3992735/python-generator-that-groups-another-iterable-into-groups-of-n
16
+ """
17
+ iterable = iter(iterable)
18
+ return iter(lambda: list(islice(iterable, n)), [])
19
+
20
+
21
+ def getChunk(arr, step):
22
+ """
23
+ Return chunk of entries from given array and step, it is similar in behavior to grouper
24
+ function but instead of returning new list it provides a generator iterable object.
25
+ :param arr: input array of data
26
+ :param step: step to iterate
27
+ :return: generator, set of slices with number of entries equal to step of iteration
28
+ """
29
+ for i in range(0, len(arr), step):
30
+ yield arr[i:i + step]
31
+
32
+
33
+ def flattenList(doubleList):
34
+ """
35
+ Make flat a list of lists.
36
+ """
37
+ return list(chain.from_iterable(doubleList))
38
+
39
+
40
+ def nestedDictUpdate(d, u):
41
+ """
42
+ Code from Alex Matelli
43
+ http://stackoverflow.com/questions/3232943/update-value-of-a-nested-dictionary-of-varying-depth
44
+ """
45
+ for k, v in u.items():
46
+ if isinstance(v, collections.abc.Mapping):
47
+ r = nestedDictUpdate(d.get(k, {}), v)
48
+ d[k] = r
49
+ else:
50
+ d[k] = u[k]
51
+ return d
52
+
53
+ def convertFromUnicodeToBytes(data):
54
+ """
55
+ code fram
56
+ http://stackoverflow.com/questions/1254454/fastest-way-to-convert-a-dicts-keys-values-from-unicode-to-str
57
+ """
58
+ if isinstance(data, str):
59
+ return data.encode('utf-8')
60
+ elif isinstance(data, collections.abc.Mapping):
61
+ return dict(list(map(convertFromUnicodeToBytes, list(data.items()))))
62
+ elif isinstance(data, collections.abc.Iterable):
63
+ return type(data)(list(map(convertFromUnicodeToBytes, data)))
64
+ else:
65
+ return data
66
+
67
+
68
+ def makeListElementsUnique(listObj):
69
+ """
70
+ Given a list of lists or a list of tuples, find all duplicate elements
71
+ and make them unique.
72
+ :param listObj: an unsorted list of lists or a list of tuples, e.g.:
73
+ [[1, 1], [1, 5], [1, 1]]; or
74
+ [(1, 1), (1, 5), (1, 1)]
75
+ :return: the same list object but with no duplicates
76
+
77
+ Source: https://stackoverflow.com/questions/2213923/removing-duplicates-from-a-list-of-lists
78
+ """
79
+ listObj.sort()
80
+ return list(k for k, _ in groupby(listObj))
Utils/MathUtils.py ADDED
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ Module containing mathematical and physics utils
4
+ """
5
+
6
+
7
+ from builtins import int, str
8
+ from math import ceil
9
+
10
+
11
+ def quantize(inputVal, quanta):
12
+ """
13
+ _quantize_
14
+
15
+ Quantize the input value following the quanta provided.
16
+ """
17
+ if isinstance(inputVal, str):
18
+ inputVal = float(inputVal)
19
+ elif not isinstance(inputVal, (int, float)):
20
+ msg = "Input value has to be either int or float, not %s" % (type(inputVal))
21
+ raise ValueError(msg)
22
+
23
+ if isinstance(quanta, (str, int, float)):
24
+ quanta = int(float(quanta))
25
+ elif not isinstance(quanta, int):
26
+ msg = "Quanta value has to be either int or float, not %s" % (type(quanta))
27
+ raise ValueError(msg)
28
+
29
+ res = int(ceil(inputVal / quanta))
30
+
31
+ return res * quanta
Utils/MemoryCache.py ADDED
@@ -0,0 +1,119 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Simple in-memory and non-thread safe cache.
5
+ Note that this module does not support home-made object types, since there is
6
+ an explicit data type check when adding a new item to the cache.
7
+
8
+ It raises a TypeError exception if the cache data type chagens;
9
+ or if the user tries to extend the cache with an incompatible
10
+ data type.
11
+ """
12
+
13
+ from copy import copy
14
+
15
+ from builtins import object
16
+ from time import time
17
+
18
+
19
+ class MemoryCacheException(Exception):
20
+ def __init__(self, message):
21
+ super(MemoryCacheException, self).__init__(message)
22
+
23
+ class MemoryCache():
24
+
25
+ __slots__ = ["lastUpdate", "expiration", "_cache"]
26
+
27
+ def __init__(self, expiration, initialData=None):
28
+ """
29
+ Initializes cache object
30
+
31
+ :param expiration: expiration time in seconds
32
+ :param initialData: initial value for the cache
33
+ """
34
+ self.lastUpdate = int(time())
35
+ self.expiration = expiration
36
+ self._cache = initialData
37
+
38
+ def __contains__(self, item):
39
+ """
40
+ Check whether item is in the current cache
41
+ :param item: a simple object (string, integer, etc)
42
+ :return: True if the object can be found in the cache, False otherwise
43
+ """
44
+ return item in self._cache
45
+
46
+ def __getitem__(self, keyName):
47
+ """
48
+ If the cache is a dictionary, return that item from the cache. Else, raise an exception.
49
+ :param keyName: the key name from the dictionary
50
+ """
51
+ if isinstance(self._cache, dict):
52
+ return copy(self._cache.get(keyName))
53
+ else:
54
+ raise MemoryCacheException("Cannot retrieve an item from a non-dict MemoryCache object: {}".format(self._cache))
55
+
56
+ def reset(self):
57
+ """
58
+ Resets the cache to its current data type
59
+ """
60
+ if isinstance(self._cache, (dict, set)):
61
+ self._cache.clear()
62
+ elif isinstance(self._cache, list):
63
+ del self._cache[:]
64
+ else:
65
+ raise MemoryCacheException("The cache needs to be reset manually, data type unknown")
66
+
67
+ def isCacheExpired(self):
68
+ """
69
+ Evaluate whether the cache has already expired, returning
70
+ True if it did, otherwise it returns False
71
+ """
72
+ return self.lastUpdate + self.expiration < int(time())
73
+
74
+ def getCache(self):
75
+ """
76
+ Raises an exception if the cache has expired, otherwise returns
77
+ its data
78
+ """
79
+ if self.isCacheExpired():
80
+ expiredSince = int(time()) - (self.lastUpdate + self.expiration)
81
+ raise MemoryCacheException("Memory cache expired for %d seconds" % expiredSince)
82
+ return self._cache
83
+
84
+ def setCache(self, inputData):
85
+ """
86
+ Refresh the cache with the content provided (refresh its expiration as well)
87
+ This method enforces the user to not change the cache data type
88
+ :param inputData: data to store in the cache
89
+ """
90
+ if not isinstance(self._cache, type(inputData)):
91
+ raise TypeError("Current cache data type: %s, while new value is: %s" %
92
+ (type(self._cache), type(inputData)))
93
+ self.reset()
94
+ self.lastUpdate = int(time())
95
+ self._cache = inputData
96
+
97
+ def addItemToCache(self, inputItem):
98
+ """
99
+ Adds new item(s) to the cache, without resetting its expiration.
100
+ It, of course, only works for data caches of type: list, set or dict.
101
+ :param inputItem: additional item to be added to the current cached data
102
+ """
103
+ if isinstance(self._cache, set) and isinstance(inputItem, (list, set)):
104
+ # extend another list or set into a set
105
+ self._cache.update(inputItem)
106
+ elif isinstance(self._cache, set) and isinstance(inputItem, (int, float, str)):
107
+ # add a simple object (integer, string, etc) to a set
108
+ self._cache.add(inputItem)
109
+ elif isinstance(self._cache, list) and isinstance(inputItem, (list, set)):
110
+ # extend another list or set into a list
111
+ self._cache.extend(inputItem)
112
+ elif isinstance(self._cache, list) and isinstance(inputItem, (int, float, str)):
113
+ # add a simple object (integer, string, etc) to a list
114
+ self._cache.append(inputItem)
115
+ elif isinstance(self._cache, dict) and isinstance(inputItem, dict):
116
+ self._cache.update(inputItem)
117
+ else:
118
+ msg = "Input item type: %s cannot be added to a cache type: %s" % (type(self._cache), type(inputItem))
119
+ raise TypeError("Cache and input item data type mismatch. %s" % msg)
Utils/Patterns.py ADDED
@@ -0,0 +1,24 @@
1
+ """
2
+ Patterns module provides set of CS patterns
3
+ """
4
+ import re
5
+
6
+ class Singleton(type):
7
+ """Implementation of Singleton class"""
8
+ _instances = {}
9
+ def __call__(cls, *args, **kwargs):
10
+ if cls not in cls._instances:
11
+ cls._instances[cls] = \
12
+ super(Singleton, cls).__call__(*args, **kwargs)
13
+ return cls._instances[cls]
14
+
15
+
16
+ def getDomainName(urlStr):
17
+ """
18
+ Given a URL string, return the domain name.
19
+ :param urlStr: URL string
20
+ :return: a string with the domain name (e.g. "cmsweb-prod")
21
+ """
22
+ domainPattern = re.compile(r'https?://([^/]+)\.cern\.ch')
23
+ match = domainPattern.search(urlStr)
24
+ return match.group(1) if match else ""
Utils/Pipeline.py ADDED
@@ -0,0 +1,137 @@
1
+ """
2
+ File : Pipeline.py
3
+ Description: Provides 2 basic classes:
4
+ - Functor: A class to create function calls from a function object
5
+ and arbitrary number of arguments
6
+ - Pipeline: A class to provide building blocks for creating functional
7
+ pipelines for cumulative execution on an arbitrary object
8
+ """
9
+
10
+ from builtins import object
11
+ from functools import reduce
12
+
13
+
14
+ class Functor(object):
15
+ """
16
+ A simple functor class used to construct a function call which later to be
17
+ applied on an (any type) object.
18
+ NOTE:
19
+ It expects a function in the constructor and an (any type) object
20
+ passed to the run or __call__ methods, which methods once called they
21
+ construct and return the following function:
22
+ func(obj, *args, **kwargs)
23
+ NOTE:
24
+ All the additional arguments which the function may take must be set in
25
+ the __init__ method. If any of them are passed during run time an error
26
+ will be raised.
27
+
28
+ :func:
29
+ The function to which the rest of the constructor arguments are about
30
+ to be attached and then the newly created function will be returned.
31
+ - The function needs to take at least one parameter since the object
32
+ passed to the run/__call__ methods will always be put as a first
33
+ argument to the function.
34
+
35
+ :Example:
36
+
37
+ def adder(a, b, *args, **kwargs):
38
+ if args:
39
+ print("adder args: %s" % args)
40
+ if kwargs:
41
+ print("adder kwargs: %s" % kwargs)
42
+ res = a + b
43
+ return res
44
+
45
+ >>> x=Functor(adder, 8, 'foo', bar=True)
46
+ >>> x(2)
47
+ adder args: foo
48
+ adder kwargs: {'bar': True}
49
+ adder res: 10
50
+ 10
51
+
52
+ >>> x
53
+ <Pipeline.Functor instance at 0x7f319bbaeea8>
54
+
55
+
56
+ """
57
+ def __init__(self, func, *args, **kwargs):
58
+ """
59
+ The init method for class Functor
60
+ """
61
+ self.func = func
62
+ self.args = args
63
+ self.kwargs = kwargs
64
+
65
+ def __call__(self, obj):
66
+ """
67
+ The call method for class Functor
68
+ """
69
+ return self.run(obj)
70
+
71
+ def run(self, obj):
72
+ return self.func(obj, *self.args, **self.kwargs)
73
+
74
+
75
+ class Pipeline(object):
76
+ """
77
+ A simple Functional Pipeline Class: applies a set of functions to an object,
78
+ where the output of every previous function is an input to the next one.
79
+ """
80
+ # NOTE:
81
+ # Similar and inspiring approaches but yet some different implementations
82
+ # are discussed in the following two links [1] & [2]. With a quite good
83
+ # explanation in [1], which helped a lot. All in all at the bottom always
84
+ # sits the reduce function.
85
+ # [1]
86
+ # https://softwarejourneyman.com/python-function-pipelines.html
87
+ # [2]
88
+ # https://gitlab.com/mc706/functional-pipeline
89
+
90
+ def __init__(self, funcLine=None, name=None):
91
+ """
92
+ :funcLine: A list of functions or Functors of function + arguments (see
93
+ the Class definition above) that are to be applied sequentially
94
+ to the object.
95
+ - If any of the elements of 'funcLine' is a function, a direct
96
+ function call with the object as an argument is performed.
97
+ - If any of the elements of 'funcLine' is a Functor, then the
98
+ first argument of the Functor constructor is the function to
99
+ be evaluated and the object is passed as a first argument to
100
+ the function with all the rest of the arguments passed right
101
+ after it eg. the following Functor in the funcLine:
102
+
103
+ Functor(func, 'foo', bar=True)
104
+
105
+ will result in the following function call later when the
106
+ pipeline is executed:
107
+
108
+ func(obj, 'foo', bar=True)
109
+
110
+ :Example:
111
+ (using the adder function from above and an object of type int)
112
+
113
+ >>> pipe = Pipeline([Functor(adder, 5),
114
+ Functor(adder, 6),
115
+ Functor(adder, 7, "extraArg"),
116
+ Functor(adder, 8, update=True)])
117
+
118
+ >>> pipe.run(1)
119
+ adder res: 6
120
+ adder res: 12
121
+ adder args: extraArg
122
+ adder res: 19
123
+ adder kwargs: {'update': True}
124
+ adder res: 27
125
+ """
126
+ self.funcLine = funcLine or []
127
+ self.name = name
128
+
129
+ def getPipelineName(self):
130
+ """
131
+ __getPipelineName__
132
+ """
133
+ name = self.name or "Unnamed Pipeline"
134
+ return name
135
+
136
+ def run(self, obj):
137
+ return reduce(lambda obj, functor: functor(obj), self.funcLine, obj)
Utils/PortForward.py ADDED
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env python
2
+ """
3
+ _PortForward_
4
+
5
+ A decorator for swapping ports in an url
6
+ """
7
+
8
+ from builtins import str, bytes
9
+
10
+ def portForward(port):
11
+ """
12
+ Decorator wrapper function for port forwarding of the REST calls of any
13
+ function to a given port.
14
+
15
+ Currently there are three constraints for applying this decorator.
16
+ 1. The function to be decorated must be defined within a class and not being a static method.
17
+ The reason for that is because we need to be sure the function's signature will
18
+ always include the class instance as its first argument.
19
+ 2. The url argument must be present as the second one in the positional argument list
20
+ of the decorated function (right after the class instance argument).
21
+ 3. The url must follow the syntax specifications in RFC 1808:
22
+ https://tools.ietf.org/html/rfc1808.html
23
+
24
+ If all of the above constraints are fulfilled and the url is part of the
25
+ urlMangleList, then the url is parsed and the port is substituted with the
26
+ one provided as an argument to the decorator's wrapper function.
27
+
28
+ param port: The port to which the REST call should be forwarded.
29
+ """
30
+ def portForwardDecorator(callFunc):
31
+ """
32
+ The actual decorator
33
+ """
34
+
35
+ def portMangle(callObj, url, *args, **kwargs):
36
+ """
37
+ Function used to check if the url coming with the current argument list
38
+ is to be forwarded and if so change the port to the one provided as an
39
+ argument to the decorator wrapper.
40
+
41
+ :param classObj: This is the class object (slef from within the class)
42
+ which is always to be present in the signature of a
43
+ public method. We will never use this argument, but
44
+ we need it there for not breaking the positional
45
+ argument order
46
+ :param url: This is the actual url to be (eventually) forwarded
47
+ :param *args: The positional argument list coming from the original function
48
+ :param *kwargs: The keywords argument list coming from the original function
49
+ """
50
+ forwarded = False
51
+ try:
52
+ if isinstance(url, str):
53
+ urlToMangle = 'https://cmsweb'
54
+ if url.startswith(urlToMangle):
55
+ newUrl = url.replace('.cern.ch/', '.cern.ch:%d/' % port, 1)
56
+ forwarded = True
57
+ elif isinstance(url, bytes):
58
+ urlToMangle = b'https://cmsweb'
59
+ if url.startswith(urlToMangle):
60
+ newUrl = url.replace(b'.cern.ch/', b'.cern.ch:%d/' % port, 1)
61
+ forwarded = True
62
+
63
+ except Exception:
64
+ pass
65
+ if forwarded:
66
+ return callFunc(callObj, newUrl, *args, **kwargs)
67
+ else:
68
+ return callFunc(callObj, url, *args, **kwargs)
69
+ return portMangle
70
+ return portForwardDecorator
71
+
72
+
73
+ class PortForward():
74
+ """
75
+ A class with a call method implementing a simple way to use the functionality
76
+ provided by the protForward decorator as a pure functional call:
77
+ EXAMPLE:
78
+ from Utils.PortForward import PortForward
79
+
80
+ portForwarder = PortForward(8443)
81
+ url = 'https://cmsweb-testbed.cern.ch/couchdb'
82
+ url = portForwarder(url)
83
+ """
84
+ def __init__(self, port):
85
+ """
86
+ The init method for the PortForward call class. This one is supposed
87
+ to simply provide an initial class instance with a logger.
88
+ """
89
+ self.port = port
90
+
91
+ def __call__(self, url):
92
+ """
93
+ The call method for the PortForward class
94
+ """
95
+ def dummyCall(self, url):
96
+ return url
97
+ return portForward(self.port)(dummyCall)(self, url)
Utils/ProcFS.py ADDED
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ File : ProcFS.py
5
+ Author : Valentin Kuznetsov <vkuznet AT gmail dot com>
6
+ Description: This module provides function which rely on Linux proc fs
7
+ """
8
+ # system modules
9
+ import os
10
+
11
+ # 3rd party modules
12
+ try:
13
+ import psutil
14
+ usePsutil = True
15
+ except ImportError:
16
+ usePsutil = False
17
+
18
+
19
+ def processStatus(pid, method=None):
20
+ """
21
+ Return status of the given process PID along with its threads using psutil.
22
+ :param pid: Process ID to inspect
23
+ :param method: define which method to use procfs or psutil
24
+ :return: list of dictionaries of `{process, pid, status}` data-structure
25
+ """
26
+ if method == 'procfs' or usePsutil == False:
27
+ return processStatusViaProcFS(pid)
28
+ return processStatusViaPsutil(pid)
29
+
30
+
31
+ def processStatusViaPsutil(pid):
32
+ """
33
+ Return status of the given process PID along with its threads using psutil.
34
+ :param pid: Process ID to inspect
35
+ :return: list of dictionaries with {process, pid, status, type}
36
+ """
37
+ statusList = []
38
+
39
+ try:
40
+ proc = psutil.Process(int(pid))
41
+ processName = proc.name()
42
+ processStatus = proc.status()
43
+ statusList.append({
44
+ "process": processName,
45
+ "pid": str(pid),
46
+ "status": processStatus,
47
+ "type": "process"
48
+ })
49
+
50
+ # Iterate over threads
51
+ threads = proc.threads()
52
+ for thread in threads:
53
+ if str(pid) == str(thread.id):
54
+ continue
55
+ threadId = thread.id
56
+ # psutil doesn't provide thread name or detailed state, so we approximate
57
+ statusList.append({
58
+ "process": f"{processName}-thread",
59
+ "pid": str(threadId),
60
+ "status": "running", # threads are assumed running if present
61
+ "type": "thread"
62
+ })
63
+
64
+ except psutil.NoSuchProcess:
65
+ return [{"error": f"Process {pid} not found"}]
66
+ except Exception as e:
67
+ return [{"error": str(e)}]
68
+
69
+ return statusList
70
+
71
+
72
+ def processStatusViaProcFS(pid):
73
+ """
74
+ Return status of given process PID along with its threads via /proc FS look-up (available on all Linux OSes)
75
+ :return: list of dictionaries of `{process, pid, status}` data-structure
76
+ """
77
+ statusList = []
78
+ procPath = f"/proc/{pid}"
79
+
80
+ if not os.path.exists(procPath):
81
+ return [{"error": f"Process {pid} not found"}]
82
+
83
+ try:
84
+ with open(f"{procPath}/status", encoding='utf-8') as f:
85
+ processName = ""
86
+ processState = ""
87
+ for line in f:
88
+ if line.startswith("Name:"):
89
+ processName = line.split(":")[1].strip()
90
+ elif line.startswith("State:"):
91
+ processState = line.split(":")[1].strip()
92
+ statusList.append({"process": processName, "pid": str(pid), "status": processState, "type": "process"})
93
+
94
+ taskPath = f"{procPath}/task"
95
+ if os.path.exists(taskPath):
96
+ for threadId in os.listdir(taskPath):
97
+ if str(threadId) == str(pid):
98
+ continue
99
+ with open(f"{taskPath}/{threadId}/status", encoding='utf-8') as f:
100
+ threadName = ""
101
+ threadState = ""
102
+ for line in f:
103
+ if line.startswith("Name:"):
104
+ threadName = line.split(":")[1].strip()
105
+ elif line.startswith("State:"):
106
+ threadState = line.split(":")[1].strip()
107
+ statusList.append({"process": threadName, "pid": threadId, "status": threadState, "type": "thread"})
108
+
109
+ except Exception as e:
110
+ return [{"error": str(e)}]
111
+
112
+ return statusList