regscale-cli 6.16.0.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.

Potentially problematic release.


This version of regscale-cli might be problematic. Click here for more details.

Files changed (481) hide show
  1. regscale/__init__.py +1 -0
  2. regscale/airflow/__init__.py +9 -0
  3. regscale/airflow/azure/__init__.py +9 -0
  4. regscale/airflow/azure/cli.py +89 -0
  5. regscale/airflow/azure/upload_dags.py +116 -0
  6. regscale/airflow/click_dags.py +127 -0
  7. regscale/airflow/click_mixins.py +82 -0
  8. regscale/airflow/config.py +25 -0
  9. regscale/airflow/factories/__init__.py +0 -0
  10. regscale/airflow/factories/connections.py +58 -0
  11. regscale/airflow/factories/workflows.py +78 -0
  12. regscale/airflow/hierarchy.py +88 -0
  13. regscale/airflow/operators/__init__.py +0 -0
  14. regscale/airflow/operators/click.py +36 -0
  15. regscale/airflow/sensors/__init__.py +0 -0
  16. regscale/airflow/sensors/sql.py +107 -0
  17. regscale/airflow/sessions/__init__.py +0 -0
  18. regscale/airflow/sessions/sql/__init__.py +3 -0
  19. regscale/airflow/sessions/sql/queries.py +64 -0
  20. regscale/airflow/sessions/sql/sql_server_queries.py +248 -0
  21. regscale/airflow/tasks/__init__.py +0 -0
  22. regscale/airflow/tasks/branches.py +22 -0
  23. regscale/airflow/tasks/cli.py +116 -0
  24. regscale/airflow/tasks/click.py +73 -0
  25. regscale/airflow/tasks/debugging.py +9 -0
  26. regscale/airflow/tasks/groups.py +116 -0
  27. regscale/airflow/tasks/init.py +60 -0
  28. regscale/airflow/tasks/states.py +47 -0
  29. regscale/airflow/tasks/workflows.py +36 -0
  30. regscale/ansible/__init__.py +9 -0
  31. regscale/core/__init__.py +0 -0
  32. regscale/core/app/__init__.py +3 -0
  33. regscale/core/app/api.py +571 -0
  34. regscale/core/app/application.py +665 -0
  35. regscale/core/app/internal/__init__.py +136 -0
  36. regscale/core/app/internal/admin_actions.py +230 -0
  37. regscale/core/app/internal/assessments_editor.py +873 -0
  38. regscale/core/app/internal/catalog.py +316 -0
  39. regscale/core/app/internal/comparison.py +459 -0
  40. regscale/core/app/internal/control_editor.py +571 -0
  41. regscale/core/app/internal/encrypt.py +79 -0
  42. regscale/core/app/internal/evidence.py +1240 -0
  43. regscale/core/app/internal/file_uploads.py +151 -0
  44. regscale/core/app/internal/healthcheck.py +66 -0
  45. regscale/core/app/internal/login.py +305 -0
  46. regscale/core/app/internal/migrations.py +240 -0
  47. regscale/core/app/internal/model_editor.py +1701 -0
  48. regscale/core/app/internal/poam_editor.py +632 -0
  49. regscale/core/app/internal/workflow.py +105 -0
  50. regscale/core/app/logz.py +74 -0
  51. regscale/core/app/utils/XMLIR.py +258 -0
  52. regscale/core/app/utils/__init__.py +0 -0
  53. regscale/core/app/utils/api_handler.py +358 -0
  54. regscale/core/app/utils/app_utils.py +1110 -0
  55. regscale/core/app/utils/catalog_utils/__init__.py +0 -0
  56. regscale/core/app/utils/catalog_utils/common.py +91 -0
  57. regscale/core/app/utils/catalog_utils/compare_catalog.py +193 -0
  58. regscale/core/app/utils/catalog_utils/diagnostic_catalog.py +97 -0
  59. regscale/core/app/utils/catalog_utils/download_catalog.py +103 -0
  60. regscale/core/app/utils/catalog_utils/update_catalog.py +718 -0
  61. regscale/core/app/utils/catalog_utils/update_catalog_v2.py +1378 -0
  62. regscale/core/app/utils/catalog_utils/update_catalog_v3.py +1272 -0
  63. regscale/core/app/utils/catalog_utils/update_plans.py +334 -0
  64. regscale/core/app/utils/file_utils.py +238 -0
  65. regscale/core/app/utils/parser_utils.py +81 -0
  66. regscale/core/app/utils/pickle_file_handler.py +57 -0
  67. regscale/core/app/utils/regscale_utils.py +319 -0
  68. regscale/core/app/utils/report_utils.py +119 -0
  69. regscale/core/app/utils/variables.py +226 -0
  70. regscale/core/decorators.py +31 -0
  71. regscale/core/lazy_group.py +65 -0
  72. regscale/core/login.py +63 -0
  73. regscale/core/server/__init__.py +0 -0
  74. regscale/core/server/flask_api.py +473 -0
  75. regscale/core/server/helpers.py +373 -0
  76. regscale/core/server/rest.py +64 -0
  77. regscale/core/server/static/css/bootstrap.css +6030 -0
  78. regscale/core/server/static/css/bootstrap.min.css +6 -0
  79. regscale/core/server/static/css/main.css +176 -0
  80. regscale/core/server/static/images/regscale-cli.svg +49 -0
  81. regscale/core/server/static/images/regscale.svg +38 -0
  82. regscale/core/server/templates/base.html +74 -0
  83. regscale/core/server/templates/index.html +43 -0
  84. regscale/core/server/templates/login.html +28 -0
  85. regscale/core/server/templates/make_base64.html +22 -0
  86. regscale/core/server/templates/upload_STIG.html +109 -0
  87. regscale/core/server/templates/upload_STIG_result.html +26 -0
  88. regscale/core/server/templates/upload_ssp.html +144 -0
  89. regscale/core/server/templates/upload_ssp_result.html +128 -0
  90. regscale/core/static/__init__.py +0 -0
  91. regscale/core/static/regex.py +14 -0
  92. regscale/core/utils/__init__.py +117 -0
  93. regscale/core/utils/click_utils.py +13 -0
  94. regscale/core/utils/date.py +238 -0
  95. regscale/core/utils/graphql.py +254 -0
  96. regscale/core/utils/urls.py +23 -0
  97. regscale/dev/__init__.py +6 -0
  98. regscale/dev/analysis.py +454 -0
  99. regscale/dev/cli.py +235 -0
  100. regscale/dev/code_gen.py +492 -0
  101. regscale/dev/dirs.py +69 -0
  102. regscale/dev/docs.py +384 -0
  103. regscale/dev/monitoring.py +26 -0
  104. regscale/dev/profiling.py +216 -0
  105. regscale/exceptions/__init__.py +4 -0
  106. regscale/exceptions/license_exception.py +7 -0
  107. regscale/exceptions/validation_exception.py +9 -0
  108. regscale/integrations/__init__.py +1 -0
  109. regscale/integrations/commercial/__init__.py +486 -0
  110. regscale/integrations/commercial/ad.py +433 -0
  111. regscale/integrations/commercial/amazon/__init__.py +0 -0
  112. regscale/integrations/commercial/amazon/common.py +106 -0
  113. regscale/integrations/commercial/aqua/__init__.py +0 -0
  114. regscale/integrations/commercial/aqua/aqua.py +91 -0
  115. regscale/integrations/commercial/aws/__init__.py +6 -0
  116. regscale/integrations/commercial/aws/cli.py +322 -0
  117. regscale/integrations/commercial/aws/inventory/__init__.py +110 -0
  118. regscale/integrations/commercial/aws/inventory/base.py +64 -0
  119. regscale/integrations/commercial/aws/inventory/resources/__init__.py +19 -0
  120. regscale/integrations/commercial/aws/inventory/resources/compute.py +234 -0
  121. regscale/integrations/commercial/aws/inventory/resources/containers.py +113 -0
  122. regscale/integrations/commercial/aws/inventory/resources/database.py +101 -0
  123. regscale/integrations/commercial/aws/inventory/resources/integration.py +237 -0
  124. regscale/integrations/commercial/aws/inventory/resources/networking.py +253 -0
  125. regscale/integrations/commercial/aws/inventory/resources/security.py +240 -0
  126. regscale/integrations/commercial/aws/inventory/resources/storage.py +91 -0
  127. regscale/integrations/commercial/aws/scanner.py +823 -0
  128. regscale/integrations/commercial/azure/__init__.py +0 -0
  129. regscale/integrations/commercial/azure/common.py +32 -0
  130. regscale/integrations/commercial/azure/intune.py +488 -0
  131. regscale/integrations/commercial/azure/scanner.py +49 -0
  132. regscale/integrations/commercial/burp.py +78 -0
  133. regscale/integrations/commercial/cpe.py +144 -0
  134. regscale/integrations/commercial/crowdstrike.py +1117 -0
  135. regscale/integrations/commercial/defender.py +1511 -0
  136. regscale/integrations/commercial/dependabot.py +210 -0
  137. regscale/integrations/commercial/durosuite/__init__.py +0 -0
  138. regscale/integrations/commercial/durosuite/api.py +1546 -0
  139. regscale/integrations/commercial/durosuite/process_devices.py +101 -0
  140. regscale/integrations/commercial/durosuite/scanner.py +637 -0
  141. regscale/integrations/commercial/durosuite/variables.py +21 -0
  142. regscale/integrations/commercial/ecr.py +90 -0
  143. regscale/integrations/commercial/gcp/__init__.py +237 -0
  144. regscale/integrations/commercial/gcp/auth.py +96 -0
  145. regscale/integrations/commercial/gcp/control_tests.py +238 -0
  146. regscale/integrations/commercial/gcp/variables.py +18 -0
  147. regscale/integrations/commercial/gitlab.py +332 -0
  148. regscale/integrations/commercial/grype.py +165 -0
  149. regscale/integrations/commercial/ibm.py +90 -0
  150. regscale/integrations/commercial/import_all/__init__.py +0 -0
  151. regscale/integrations/commercial/import_all/import_all_cmd.py +467 -0
  152. regscale/integrations/commercial/import_all/scan_file_fingerprints.json +27 -0
  153. regscale/integrations/commercial/jira.py +1046 -0
  154. regscale/integrations/commercial/mappings/__init__.py +0 -0
  155. regscale/integrations/commercial/mappings/csf_controls.json +713 -0
  156. regscale/integrations/commercial/mappings/nist_800_53_r5_controls.json +1516 -0
  157. regscale/integrations/commercial/nessus/__init__.py +0 -0
  158. regscale/integrations/commercial/nessus/nessus_utils.py +429 -0
  159. regscale/integrations/commercial/nessus/scanner.py +416 -0
  160. regscale/integrations/commercial/nexpose.py +90 -0
  161. regscale/integrations/commercial/okta.py +798 -0
  162. regscale/integrations/commercial/opentext/__init__.py +0 -0
  163. regscale/integrations/commercial/opentext/click.py +99 -0
  164. regscale/integrations/commercial/opentext/scanner.py +143 -0
  165. regscale/integrations/commercial/prisma.py +91 -0
  166. regscale/integrations/commercial/qualys.py +1462 -0
  167. regscale/integrations/commercial/salesforce.py +980 -0
  168. regscale/integrations/commercial/sap/__init__.py +0 -0
  169. regscale/integrations/commercial/sap/click.py +31 -0
  170. regscale/integrations/commercial/sap/sysdig/__init__.py +0 -0
  171. regscale/integrations/commercial/sap/sysdig/click.py +57 -0
  172. regscale/integrations/commercial/sap/sysdig/sysdig_scanner.py +190 -0
  173. regscale/integrations/commercial/sap/tenable/__init__.py +0 -0
  174. regscale/integrations/commercial/sap/tenable/click.py +49 -0
  175. regscale/integrations/commercial/sap/tenable/scanner.py +196 -0
  176. regscale/integrations/commercial/servicenow.py +1756 -0
  177. regscale/integrations/commercial/sicura/__init__.py +0 -0
  178. regscale/integrations/commercial/sicura/api.py +855 -0
  179. regscale/integrations/commercial/sicura/commands.py +73 -0
  180. regscale/integrations/commercial/sicura/scanner.py +481 -0
  181. regscale/integrations/commercial/sicura/variables.py +16 -0
  182. regscale/integrations/commercial/snyk.py +90 -0
  183. regscale/integrations/commercial/sonarcloud.py +260 -0
  184. regscale/integrations/commercial/sqlserver.py +369 -0
  185. regscale/integrations/commercial/stig_mapper_integration/__init__.py +0 -0
  186. regscale/integrations/commercial/stig_mapper_integration/click_commands.py +38 -0
  187. regscale/integrations/commercial/stig_mapper_integration/mapping_engine.py +353 -0
  188. regscale/integrations/commercial/stigv2/__init__.py +0 -0
  189. regscale/integrations/commercial/stigv2/ckl_parser.py +349 -0
  190. regscale/integrations/commercial/stigv2/click_commands.py +95 -0
  191. regscale/integrations/commercial/stigv2/stig_integration.py +202 -0
  192. regscale/integrations/commercial/synqly/__init__.py +0 -0
  193. regscale/integrations/commercial/synqly/assets.py +46 -0
  194. regscale/integrations/commercial/synqly/ticketing.py +132 -0
  195. regscale/integrations/commercial/synqly/vulnerabilities.py +223 -0
  196. regscale/integrations/commercial/synqly_jira.py +840 -0
  197. regscale/integrations/commercial/tenablev2/__init__.py +0 -0
  198. regscale/integrations/commercial/tenablev2/authenticate.py +31 -0
  199. regscale/integrations/commercial/tenablev2/click.py +1584 -0
  200. regscale/integrations/commercial/tenablev2/scanner.py +504 -0
  201. regscale/integrations/commercial/tenablev2/stig_parsers.py +140 -0
  202. regscale/integrations/commercial/tenablev2/utils.py +78 -0
  203. regscale/integrations/commercial/tenablev2/variables.py +17 -0
  204. regscale/integrations/commercial/trivy.py +162 -0
  205. regscale/integrations/commercial/veracode.py +96 -0
  206. regscale/integrations/commercial/wizv2/WizDataMixin.py +97 -0
  207. regscale/integrations/commercial/wizv2/__init__.py +0 -0
  208. regscale/integrations/commercial/wizv2/click.py +429 -0
  209. regscale/integrations/commercial/wizv2/constants.py +1001 -0
  210. regscale/integrations/commercial/wizv2/issue.py +361 -0
  211. regscale/integrations/commercial/wizv2/models.py +112 -0
  212. regscale/integrations/commercial/wizv2/parsers.py +339 -0
  213. regscale/integrations/commercial/wizv2/sbom.py +115 -0
  214. regscale/integrations/commercial/wizv2/scanner.py +416 -0
  215. regscale/integrations/commercial/wizv2/utils.py +796 -0
  216. regscale/integrations/commercial/wizv2/variables.py +39 -0
  217. regscale/integrations/commercial/wizv2/wiz_auth.py +159 -0
  218. regscale/integrations/commercial/xray.py +91 -0
  219. regscale/integrations/integration/__init__.py +2 -0
  220. regscale/integrations/integration/integration.py +26 -0
  221. regscale/integrations/integration/inventory.py +17 -0
  222. regscale/integrations/integration/issue.py +100 -0
  223. regscale/integrations/integration_override.py +149 -0
  224. regscale/integrations/public/__init__.py +103 -0
  225. regscale/integrations/public/cisa.py +641 -0
  226. regscale/integrations/public/criticality_updater.py +70 -0
  227. regscale/integrations/public/emass.py +411 -0
  228. regscale/integrations/public/emass_slcm_import.py +697 -0
  229. regscale/integrations/public/fedramp/__init__.py +0 -0
  230. regscale/integrations/public/fedramp/appendix_parser.py +548 -0
  231. regscale/integrations/public/fedramp/click.py +479 -0
  232. regscale/integrations/public/fedramp/components.py +714 -0
  233. regscale/integrations/public/fedramp/docx_parser.py +259 -0
  234. regscale/integrations/public/fedramp/fedramp_cis_crm.py +1124 -0
  235. regscale/integrations/public/fedramp/fedramp_common.py +3181 -0
  236. regscale/integrations/public/fedramp/fedramp_docx.py +388 -0
  237. regscale/integrations/public/fedramp/fedramp_five.py +2343 -0
  238. regscale/integrations/public/fedramp/fedramp_traversal.py +138 -0
  239. regscale/integrations/public/fedramp/import_fedramp_r4_ssp.py +279 -0
  240. regscale/integrations/public/fedramp/import_workbook.py +495 -0
  241. regscale/integrations/public/fedramp/inventory_items.py +244 -0
  242. regscale/integrations/public/fedramp/mappings/__init__.py +0 -0
  243. regscale/integrations/public/fedramp/mappings/fedramp_r4_parts.json +7388 -0
  244. regscale/integrations/public/fedramp/mappings/fedramp_r5_params.json +8636 -0
  245. regscale/integrations/public/fedramp/mappings/fedramp_r5_parts.json +9605 -0
  246. regscale/integrations/public/fedramp/mappings/system_roles.py +34 -0
  247. regscale/integrations/public/fedramp/mappings/user.py +175 -0
  248. regscale/integrations/public/fedramp/mappings/values.py +141 -0
  249. regscale/integrations/public/fedramp/markdown_parser.py +150 -0
  250. regscale/integrations/public/fedramp/metadata.py +689 -0
  251. regscale/integrations/public/fedramp/models/__init__.py +59 -0
  252. regscale/integrations/public/fedramp/models/leveraged_auth_new.py +168 -0
  253. regscale/integrations/public/fedramp/models/poam_importer.py +522 -0
  254. regscale/integrations/public/fedramp/parts_mapper.py +107 -0
  255. regscale/integrations/public/fedramp/poam/__init__.py +0 -0
  256. regscale/integrations/public/fedramp/poam/scanner.py +851 -0
  257. regscale/integrations/public/fedramp/properties.py +201 -0
  258. regscale/integrations/public/fedramp/reporting.py +84 -0
  259. regscale/integrations/public/fedramp/resources.py +496 -0
  260. regscale/integrations/public/fedramp/rosetta.py +110 -0
  261. regscale/integrations/public/fedramp/ssp_logger.py +87 -0
  262. regscale/integrations/public/fedramp/system_characteristics.py +922 -0
  263. regscale/integrations/public/fedramp/system_control_implementations.py +582 -0
  264. regscale/integrations/public/fedramp/system_implementation.py +190 -0
  265. regscale/integrations/public/fedramp/xml_utils.py +87 -0
  266. regscale/integrations/public/nist_catalog.py +275 -0
  267. regscale/integrations/public/oscal.py +1946 -0
  268. regscale/integrations/public/otx.py +169 -0
  269. regscale/integrations/scanner_integration.py +2692 -0
  270. regscale/integrations/variables.py +25 -0
  271. regscale/models/__init__.py +7 -0
  272. regscale/models/app_models/__init__.py +5 -0
  273. regscale/models/app_models/catalog_compare.py +213 -0
  274. regscale/models/app_models/click.py +252 -0
  275. regscale/models/app_models/datetime_encoder.py +21 -0
  276. regscale/models/app_models/import_validater.py +321 -0
  277. regscale/models/app_models/mapping.py +260 -0
  278. regscale/models/app_models/pipeline.py +37 -0
  279. regscale/models/click_models.py +413 -0
  280. regscale/models/config.py +154 -0
  281. regscale/models/email_style.css +67 -0
  282. regscale/models/hierarchy.py +8 -0
  283. regscale/models/inspect_models.py +79 -0
  284. regscale/models/integration_models/__init__.py +0 -0
  285. regscale/models/integration_models/amazon_models/__init__.py +0 -0
  286. regscale/models/integration_models/amazon_models/inspector.py +262 -0
  287. regscale/models/integration_models/amazon_models/inspector_scan.py +206 -0
  288. regscale/models/integration_models/aqua.py +247 -0
  289. regscale/models/integration_models/azure_alerts.py +255 -0
  290. regscale/models/integration_models/base64.py +23 -0
  291. regscale/models/integration_models/burp.py +433 -0
  292. regscale/models/integration_models/burp_models.py +128 -0
  293. regscale/models/integration_models/cisa_kev_data.json +19333 -0
  294. regscale/models/integration_models/defender_data.py +93 -0
  295. regscale/models/integration_models/defenderimport.py +143 -0
  296. regscale/models/integration_models/drf.py +443 -0
  297. regscale/models/integration_models/ecr_models/__init__.py +0 -0
  298. regscale/models/integration_models/ecr_models/data.py +69 -0
  299. regscale/models/integration_models/ecr_models/ecr.py +239 -0
  300. regscale/models/integration_models/flat_file_importer.py +1079 -0
  301. regscale/models/integration_models/grype_import.py +247 -0
  302. regscale/models/integration_models/ibm.py +126 -0
  303. regscale/models/integration_models/implementation_results.py +85 -0
  304. regscale/models/integration_models/nexpose.py +140 -0
  305. regscale/models/integration_models/prisma.py +202 -0
  306. regscale/models/integration_models/qualys.py +720 -0
  307. regscale/models/integration_models/qualys_scanner.py +160 -0
  308. regscale/models/integration_models/sbom/__init__.py +0 -0
  309. regscale/models/integration_models/sbom/cyclone_dx.py +139 -0
  310. regscale/models/integration_models/send_reminders.py +620 -0
  311. regscale/models/integration_models/snyk.py +155 -0
  312. regscale/models/integration_models/synqly_models/__init__.py +0 -0
  313. regscale/models/integration_models/synqly_models/capabilities.json +1 -0
  314. regscale/models/integration_models/synqly_models/connector_types.py +22 -0
  315. regscale/models/integration_models/synqly_models/connectors/__init__.py +7 -0
  316. regscale/models/integration_models/synqly_models/connectors/assets.py +97 -0
  317. regscale/models/integration_models/synqly_models/connectors/ticketing.py +583 -0
  318. regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +169 -0
  319. regscale/models/integration_models/synqly_models/ocsf_mapper.py +331 -0
  320. regscale/models/integration_models/synqly_models/param.py +72 -0
  321. regscale/models/integration_models/synqly_models/synqly_model.py +733 -0
  322. regscale/models/integration_models/synqly_models/tenants.py +39 -0
  323. regscale/models/integration_models/tenable_models/__init__.py +0 -0
  324. regscale/models/integration_models/tenable_models/integration.py +187 -0
  325. regscale/models/integration_models/tenable_models/models.py +513 -0
  326. regscale/models/integration_models/trivy_import.py +231 -0
  327. regscale/models/integration_models/veracode.py +217 -0
  328. regscale/models/integration_models/xray.py +135 -0
  329. regscale/models/locking.py +100 -0
  330. regscale/models/platform.py +110 -0
  331. regscale/models/regscale_models/__init__.py +67 -0
  332. regscale/models/regscale_models/assessment.py +570 -0
  333. regscale/models/regscale_models/assessment_plan.py +52 -0
  334. regscale/models/regscale_models/asset.py +567 -0
  335. regscale/models/regscale_models/asset_mapping.py +190 -0
  336. regscale/models/regscale_models/case.py +42 -0
  337. regscale/models/regscale_models/catalog.py +261 -0
  338. regscale/models/regscale_models/cci.py +46 -0
  339. regscale/models/regscale_models/change.py +167 -0
  340. regscale/models/regscale_models/checklist.py +372 -0
  341. regscale/models/regscale_models/comment.py +49 -0
  342. regscale/models/regscale_models/compliance_settings.py +112 -0
  343. regscale/models/regscale_models/component.py +412 -0
  344. regscale/models/regscale_models/component_mapping.py +65 -0
  345. regscale/models/regscale_models/control.py +38 -0
  346. regscale/models/regscale_models/control_implementation.py +1128 -0
  347. regscale/models/regscale_models/control_objective.py +261 -0
  348. regscale/models/regscale_models/control_parameter.py +100 -0
  349. regscale/models/regscale_models/control_test.py +34 -0
  350. regscale/models/regscale_models/control_test_plan.py +75 -0
  351. regscale/models/regscale_models/control_test_result.py +52 -0
  352. regscale/models/regscale_models/custom_field.py +245 -0
  353. regscale/models/regscale_models/data.py +109 -0
  354. regscale/models/regscale_models/data_center.py +40 -0
  355. regscale/models/regscale_models/deviation.py +203 -0
  356. regscale/models/regscale_models/email.py +97 -0
  357. regscale/models/regscale_models/evidence.py +47 -0
  358. regscale/models/regscale_models/evidence_mapping.py +40 -0
  359. regscale/models/regscale_models/facility.py +59 -0
  360. regscale/models/regscale_models/file.py +382 -0
  361. regscale/models/regscale_models/filetag.py +37 -0
  362. regscale/models/regscale_models/form_field_value.py +94 -0
  363. regscale/models/regscale_models/group.py +169 -0
  364. regscale/models/regscale_models/implementation_objective.py +335 -0
  365. regscale/models/regscale_models/implementation_option.py +275 -0
  366. regscale/models/regscale_models/implementation_role.py +33 -0
  367. regscale/models/regscale_models/incident.py +177 -0
  368. regscale/models/regscale_models/interconnection.py +43 -0
  369. regscale/models/regscale_models/issue.py +1176 -0
  370. regscale/models/regscale_models/leveraged_authorization.py +125 -0
  371. regscale/models/regscale_models/line_of_inquiry.py +52 -0
  372. regscale/models/regscale_models/link.py +205 -0
  373. regscale/models/regscale_models/meta_data.py +64 -0
  374. regscale/models/regscale_models/mixins/__init__.py +0 -0
  375. regscale/models/regscale_models/mixins/parent_cache.py +124 -0
  376. regscale/models/regscale_models/module.py +224 -0
  377. regscale/models/regscale_models/modules.py +191 -0
  378. regscale/models/regscale_models/objective.py +14 -0
  379. regscale/models/regscale_models/parameter.py +87 -0
  380. regscale/models/regscale_models/ports_protocol.py +81 -0
  381. regscale/models/regscale_models/privacy.py +89 -0
  382. regscale/models/regscale_models/profile.py +50 -0
  383. regscale/models/regscale_models/profile_link.py +68 -0
  384. regscale/models/regscale_models/profile_mapping.py +124 -0
  385. regscale/models/regscale_models/project.py +63 -0
  386. regscale/models/regscale_models/property.py +278 -0
  387. regscale/models/regscale_models/question.py +85 -0
  388. regscale/models/regscale_models/questionnaire.py +87 -0
  389. regscale/models/regscale_models/questionnaire_instance.py +177 -0
  390. regscale/models/regscale_models/rbac.py +132 -0
  391. regscale/models/regscale_models/reference.py +86 -0
  392. regscale/models/regscale_models/regscale_model.py +1643 -0
  393. regscale/models/regscale_models/requirement.py +29 -0
  394. regscale/models/regscale_models/risk.py +274 -0
  395. regscale/models/regscale_models/sbom.py +54 -0
  396. regscale/models/regscale_models/scan_history.py +436 -0
  397. regscale/models/regscale_models/search.py +53 -0
  398. regscale/models/regscale_models/security_control.py +132 -0
  399. regscale/models/regscale_models/security_plan.py +204 -0
  400. regscale/models/regscale_models/software_inventory.py +159 -0
  401. regscale/models/regscale_models/stake_holder.py +64 -0
  402. regscale/models/regscale_models/stig.py +647 -0
  403. regscale/models/regscale_models/supply_chain.py +152 -0
  404. regscale/models/regscale_models/system_role.py +188 -0
  405. regscale/models/regscale_models/system_role_external_assignment.py +40 -0
  406. regscale/models/regscale_models/tag.py +37 -0
  407. regscale/models/regscale_models/tag_mapping.py +19 -0
  408. regscale/models/regscale_models/task.py +133 -0
  409. regscale/models/regscale_models/threat.py +196 -0
  410. regscale/models/regscale_models/user.py +175 -0
  411. regscale/models/regscale_models/user_group.py +55 -0
  412. regscale/models/regscale_models/vulnerability.py +242 -0
  413. regscale/models/regscale_models/vulnerability_mapping.py +162 -0
  414. regscale/models/regscale_models/workflow.py +55 -0
  415. regscale/models/regscale_models/workflow_action.py +34 -0
  416. regscale/models/regscale_models/workflow_instance.py +269 -0
  417. regscale/models/regscale_models/workflow_instance_step.py +114 -0
  418. regscale/models/regscale_models/workflow_template.py +58 -0
  419. regscale/models/regscale_models/workflow_template_step.py +45 -0
  420. regscale/regscale.py +815 -0
  421. regscale/utils/__init__.py +7 -0
  422. regscale/utils/b64conversion.py +14 -0
  423. regscale/utils/click_utils.py +118 -0
  424. regscale/utils/decorators.py +48 -0
  425. regscale/utils/dict_utils.py +59 -0
  426. regscale/utils/files.py +79 -0
  427. regscale/utils/fxns.py +30 -0
  428. regscale/utils/graphql_client.py +113 -0
  429. regscale/utils/lists.py +16 -0
  430. regscale/utils/numbers.py +12 -0
  431. regscale/utils/shell.py +148 -0
  432. regscale/utils/string.py +121 -0
  433. regscale/utils/synqly_utils.py +165 -0
  434. regscale/utils/threading/__init__.py +8 -0
  435. regscale/utils/threading/threadhandler.py +131 -0
  436. regscale/utils/threading/threadsafe_counter.py +47 -0
  437. regscale/utils/threading/threadsafe_dict.py +242 -0
  438. regscale/utils/threading/threadsafe_list.py +83 -0
  439. regscale/utils/version.py +104 -0
  440. regscale/validation/__init__.py +0 -0
  441. regscale/validation/address.py +37 -0
  442. regscale/validation/record.py +48 -0
  443. regscale/visualization/__init__.py +5 -0
  444. regscale/visualization/click.py +34 -0
  445. regscale_cli-6.16.0.0.dist-info/LICENSE +21 -0
  446. regscale_cli-6.16.0.0.dist-info/METADATA +659 -0
  447. regscale_cli-6.16.0.0.dist-info/RECORD +481 -0
  448. regscale_cli-6.16.0.0.dist-info/WHEEL +5 -0
  449. regscale_cli-6.16.0.0.dist-info/entry_points.txt +6 -0
  450. regscale_cli-6.16.0.0.dist-info/top_level.txt +2 -0
  451. tests/fixtures/__init__.py +2 -0
  452. tests/fixtures/api.py +87 -0
  453. tests/fixtures/models.py +91 -0
  454. tests/fixtures/test_fixture.py +144 -0
  455. tests/mocks/__init__.py +0 -0
  456. tests/mocks/objects.py +3 -0
  457. tests/mocks/response.py +32 -0
  458. tests/mocks/xml.py +13 -0
  459. tests/regscale/__init__.py +0 -0
  460. tests/regscale/core/__init__.py +0 -0
  461. tests/regscale/core/test_api.py +232 -0
  462. tests/regscale/core/test_app.py +406 -0
  463. tests/regscale/core/test_login.py +37 -0
  464. tests/regscale/core/test_logz.py +66 -0
  465. tests/regscale/core/test_sbom_generator.py +87 -0
  466. tests/regscale/core/test_validation_utils.py +163 -0
  467. tests/regscale/core/test_version.py +78 -0
  468. tests/regscale/models/__init__.py +0 -0
  469. tests/regscale/models/test_asset.py +71 -0
  470. tests/regscale/models/test_config.py +26 -0
  471. tests/regscale/models/test_control_implementation.py +27 -0
  472. tests/regscale/models/test_import.py +97 -0
  473. tests/regscale/models/test_issue.py +36 -0
  474. tests/regscale/models/test_mapping.py +52 -0
  475. tests/regscale/models/test_platform.py +31 -0
  476. tests/regscale/models/test_regscale_model.py +346 -0
  477. tests/regscale/models/test_report.py +32 -0
  478. tests/regscale/models/test_tenable_integrations.py +118 -0
  479. tests/regscale/models/test_user_model.py +121 -0
  480. tests/regscale/test_about.py +19 -0
  481. tests/regscale/test_authorization.py +65 -0
@@ -0,0 +1,7 @@
1
+ from .dict_utils import *
2
+ from .click_utils import *
3
+ from .files import *
4
+ from .graphql_client import *
5
+ from .string import *
6
+ from .numbers import *
7
+ from .lists import *
@@ -0,0 +1,14 @@
1
+ from base64 import b64decode, b64encode
2
+ from io import BytesIO
3
+
4
+
5
+ def encode_file_to_base64(file_path):
6
+ with open(file_path, "rb") as file:
7
+ file_bytes = file.read()
8
+ encoded_string = b64encode(file_bytes)
9
+ return encoded_string.decode("utf-8")
10
+
11
+
12
+ def decode_base64_to_bytesio(encoded_string):
13
+ decoded_bytes = b64decode(encoded_string)
14
+ return BytesIO(decoded_bytes)
@@ -0,0 +1,118 @@
1
+ """Provide utilities for interacting with click Objects."""
2
+
3
+ from typing import Any, Dict, Optional, Union
4
+
5
+ import click
6
+
7
+
8
+ def process_click_group(
9
+ group: Union[click.Group, click.Command],
10
+ prefix: Optional[str] = None,
11
+ ) -> Dict[str, Any]:
12
+ """
13
+ Process a click group into a dictionary
14
+
15
+ :param Union[click.Group, click.Command] group: a click.Group or click.Command to extract info from
16
+ :param Optional[str] prefix: an optional prefix to name the application, defaults to `group.name`
17
+ :return: a dictionary of the click group
18
+ :rtype: Dict[str, Any]
19
+ """
20
+ prefix = f"{group.name}" if prefix is None else f"{prefix}__{group.name}"
21
+ cmd_dict = {
22
+ "group": group,
23
+ "group_name": prefix,
24
+ }
25
+ for cmd_name, cmd in group.commands.items():
26
+ new_prefix = f"{prefix}__{cmd_name}"
27
+ if isinstance(cmd, click.Group):
28
+ cmd_dict[cmd_name] = process_click_group(cmd, new_prefix)
29
+ elif isinstance(cmd, click.Command):
30
+ cmd_dict[cmd_name] = process_command(cmd, new_prefix)
31
+ return cmd_dict
32
+
33
+
34
+ def process_command(
35
+ cmd: click.Command,
36
+ cmd_name: str,
37
+ ) -> Dict[str, Any]:
38
+ """
39
+ Process a click command into a dictionary
40
+
41
+ :param click.Command cmd: a click.Command object
42
+ :param str cmd_name: the name of the command
43
+ :return: a dictionary of the click command
44
+ :rtype: Dict[str, Any]
45
+ """
46
+ return {
47
+ "cmd": cmd,
48
+ "name": cmd_name,
49
+ "params": {param.name: process_option(param) for param in cmd.params if isinstance(param, click.Option)},
50
+ "callback": cmd.callback,
51
+ }
52
+
53
+
54
+ def process_option(
55
+ option: click.Option,
56
+ ) -> Dict[str, Any]:
57
+ """
58
+ Process a click Option
59
+
60
+ :param click.Option option: a click Option object
61
+ :return: a dictionary of the click option
62
+ :rtype: Dict[str, Any]
63
+ """
64
+ return {
65
+ "option": option,
66
+ "name": option.name,
67
+ "default": option.default,
68
+ "type": str(option.type),
69
+ "prompt": option.prompt,
70
+ "confirmation_prompt": option.confirmation_prompt,
71
+ "is_flag": option.is_flag,
72
+ "is_bool_flag": option.is_bool_flag,
73
+ "count": option.count,
74
+ "allow_from_autoenv": option.allow_from_autoenv,
75
+ "expose_value": option.expose_value,
76
+ "is_eager": option.is_eager,
77
+ "callback": option.callback,
78
+ }
79
+
80
+
81
+ def find_file_path_parameters(group: Union[click.Group, click.Command], prefix: str = None) -> dict:
82
+ """
83
+ Find all file path parameters in a click group
84
+
85
+ :param Union[click.Group, click.Command] group: a click.Group or click.Command to extract info from
86
+ :param str prefix: an optional prefix to name the application, defaults to `group.name`
87
+ :return: a dictionary of file path parameters
88
+ :rtype: dict
89
+ """
90
+ file_path_parameters = {}
91
+
92
+ def add_to_dict(_key: str, _param: Any) -> None:
93
+ """
94
+ Helper function to add to the dictionary
95
+
96
+ :param str _key: the key to add to the dictionary
97
+ :param Any _param: the parameter to add to the dictionary
98
+ :rtype: None
99
+ """
100
+ if _key not in file_path_parameters:
101
+ file_path_parameters[_key] = []
102
+ file_path_parameters[_key].append(_param)
103
+
104
+ for cmd_name, cmd in group.commands.items():
105
+ current_suffix = cmd_name if not prefix else f"{prefix}__{cmd_name}"
106
+
107
+ if isinstance(cmd, click.Group):
108
+ file_path_parameters[cmd_name] = find_file_path_parameters(cmd, prefix)
109
+ inner_parameters = find_file_path_parameters(cmd, current_suffix)
110
+ for key, values in inner_parameters.items():
111
+ add_to_dict(key, values)
112
+ else:
113
+ for param in cmd.params:
114
+ if isinstance(param.type, (click.Path, click.File)):
115
+ add_to_dict(current_suffix, param)
116
+ elif "file" in param.name or "path" in param.name:
117
+ add_to_dict(current_suffix, param)
118
+ return file_path_parameters
@@ -0,0 +1,48 @@
1
+ """
2
+ App decorators
3
+ """
4
+
5
+ import warnings
6
+ import functools
7
+
8
+
9
+ def deprecated(reason="This method is deprecated and may be removed in a future version."):
10
+ """
11
+ Decorator to mark functions as deprecated.
12
+
13
+ :param reason: The reason for deprecation.
14
+ """
15
+
16
+ def decorator(func):
17
+ """
18
+ Decorator to mark functions as deprecated.
19
+ :param func:
20
+ :return:
21
+ """
22
+
23
+ @functools.wraps(func)
24
+ def wrapper(*args, **kwargs):
25
+ """
26
+ Wrapper function to mark functions as deprecated.
27
+ :param args:
28
+ :param kwargs:
29
+ :return:
30
+ """
31
+ warnings.warn(f"{func.__name__} is deprecated: {reason}", category=DeprecationWarning, stacklevel=2)
32
+ return func(*args, **kwargs)
33
+
34
+ return wrapper
35
+
36
+ return decorator
37
+
38
+
39
+ class classproperty: # pylint: disable=invalid-name # noqa: N801
40
+ """
41
+ A class property decorator.
42
+ """
43
+
44
+ def __init__(self, func):
45
+ self.func = func
46
+
47
+ def __get__(self, instance, owner):
48
+ return self.func(owner)
@@ -0,0 +1,59 @@
1
+ """
2
+ This module contains utility functions for working with dictionaries.
3
+ """
4
+
5
+ from typing import Dict, List, Tuple, Any, Optional
6
+
7
+
8
+ def get_value(data: dict, key: str) -> Any:
9
+ """
10
+ Get a value from a dictionary even if nested dict using dot notation.
11
+ If the value is within a list, return a list of values. (e.g. "key1.key2" -> {key1: {key2: value2}}) -> value2
12
+ also fetches values from nested lists. (e.g. "key1.key2" -> {key1: [{key2: value2}, {key2: value3}]} -> [value2, value3])
13
+ :param dict data: The dictionary to get the value from.
14
+ :param str key: The key to get the value for.
15
+ :return: The value from the dictionary or None if the key is not found.
16
+ :rtype: Any
17
+ """
18
+ keys = key.split(".")
19
+ value = data
20
+ for k in keys:
21
+ if isinstance(value, list):
22
+ value = [item.get(k, None) if isinstance(item, dict) else None for item in value]
23
+ elif isinstance(value, dict):
24
+ value = value.get(k, None)
25
+ else:
26
+ return None
27
+ if value and any(isinstance(i, list) for i in value):
28
+ value = [item for sublist in value for item in sublist if item is not None]
29
+ return value
30
+
31
+
32
+ def flatten_dict(
33
+ d: Dict[str, Any], prefix: str = "", result: Optional[List[Tuple[str, Any]]] = None
34
+ ) -> List[Tuple[str, Any]]:
35
+ """
36
+ Recursively flattens a nested dictionary or list of dictionaries into a list of tuples,
37
+ preserving the hierarchy in the keys.
38
+
39
+ :param Dict[str, Any] d: The dictionary or list of dictionaries to flatten.
40
+ :param str prefix: The current prefix representing the hierarchy of keys, defaults to an empty string.
41
+ :param Optional[List[Tuple[str, Any]]] result: The accumulated list of tuples, This is used internally and should
42
+ not be set by the caller. defaults to None.
43
+ :return: A list of tuples where each tuple is a key-value pair, with the key representing the hierarchical path.
44
+ :rtype: List[Tuple[str, Any]]
45
+ """
46
+ if result is None:
47
+ result = []
48
+ if isinstance(d, dict):
49
+ for key, value in d.items():
50
+ new_key = f"{prefix}{key}" if prefix else key
51
+ if isinstance(value, (dict, list)):
52
+ flatten_dict(value, f"{new_key}.", result)
53
+ else:
54
+ result.append((new_key, value))
55
+ elif isinstance(d, list):
56
+ for index, item in enumerate(d):
57
+ flatten_dict(item, f"{prefix}{index}.", result)
58
+
59
+ return result
@@ -0,0 +1,79 @@
1
+ """Provide functions for dealing with files."""
2
+
3
+ import os
4
+ from pathlib import Path
5
+ from tempfile import gettempdir
6
+ from types import TracebackType
7
+ from typing import Union, TextIO, Optional, Type
8
+
9
+
10
+ def print_file_contents(file_path: Union[str, Path]) -> None:
11
+ """
12
+ Print a file's contents to the console.
13
+
14
+ :param Union[str, Path] file_path: a string or Path object
15
+ :rtype: None
16
+ """
17
+ if isinstance(file_path, str):
18
+ file_path = Path(file_path)
19
+ if file_path.is_file():
20
+ print(f'File "{file_path}" found!')
21
+ print(file_path.read_text(encoding="utf-8"))
22
+
23
+
24
+ def print_current_directory(print_yaml: bool = False) -> None:
25
+ """
26
+ Print the contents of the current directory and its path
27
+
28
+ :param bool print_yaml: should the contents of the yaml file be printed, defaults to False
29
+ :rtype: None
30
+ """
31
+ current_dir = os.getcwd()
32
+ print(f"Current Working Directory: {current_dir}")
33
+ if print_yaml:
34
+ init_file = os.path.join(current_dir, "init.yaml")
35
+ print_file_contents(init_file)
36
+
37
+
38
+ class CustomTempFile:
39
+ """
40
+ A context manager for creating temporary files
41
+
42
+ :param Union[str, Path] filename: the name of the file
43
+ :param bool delete: should the file be deleted when the context is exited? (default: True)
44
+ """
45
+
46
+ def __init__(self, filename: Union[str, Path], delete: bool = True):
47
+ self.temp_dir = gettempdir()
48
+ self.temp_filename = os.path.join(self.temp_dir, filename)
49
+ self.delete = delete
50
+ self.temp_file = None
51
+
52
+ def __enter__(self) -> TextIO:
53
+ """
54
+ Open the file with read/write permissions
55
+
56
+ :return: the file object
57
+ :rtype: TextIO
58
+ """
59
+ self.temp_file = open(self.temp_filename, "w+")
60
+ return self.temp_file
61
+
62
+ def __exit__(
63
+ self, exc_type: Optional[Type[BaseException]], exc_val: Optional[BaseException], exc_tb: Optional[TracebackType]
64
+ ) -> None:
65
+ """
66
+ Close the file
67
+
68
+ :param Optional[Type[BaseException]] exc_type: The exception type
69
+ :param Optional[BaseException] exc_val: The exception value
70
+ :param Optional[TracebackType] exc_tb: The traceback
71
+ :rtype: None
72
+ """
73
+ # Close the file
74
+ if self.temp_file:
75
+ self.temp_file.close()
76
+
77
+ # Optionally, delete the file
78
+ if self.delete:
79
+ os.remove(self.temp_filename)
regscale/utils/fxns.py ADDED
@@ -0,0 +1,30 @@
1
+ """Provide utilities for dealing with functions."""
2
+
3
+ import inspect
4
+ from typing import Any, List
5
+
6
+
7
+ def get_callback_param(command: Any) -> List[str]:
8
+ """
9
+ Return a list of parameter names in the callback function of a command
10
+
11
+ :param Any command: a function to get the parameters for
12
+ :return: a list of parameter names
13
+ :rtype: List[str]
14
+ """
15
+ callback = command.callback
16
+ sig = inspect.signature(callback)
17
+ return list(sig.parameters.keys())
18
+
19
+
20
+ def get_callback_defaults(command: Any) -> dict:
21
+ """
22
+ Return a dictionary of callback defaults.
23
+
24
+ :param Any command: a function to get the defaults for
25
+ :return: a dictionary of parameter names and their defaults
26
+ :rtype: dict
27
+ """
28
+ callback = command.callback
29
+ sig = inspect.signature(callback)
30
+ return {name: param.default if param.default != param.empty else None for name, param in sig.parameters.items()}
@@ -0,0 +1,113 @@
1
+ """
2
+ A module for making paginated GraphQL queries.
3
+ """
4
+
5
+ import logging
6
+ from typing import List, Dict, Optional, Any
7
+
8
+ from regscale.core.app.utils.app_utils import create_progress_object
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ class PaginatedGraphQLClient:
14
+ """
15
+ A class for making paginated GraphQL queries.
16
+
17
+ :param str endpoint: The GraphQL endpoint.
18
+ :param str query: The GraphQL query.
19
+ :param Optional[Dict[str, str]] headers: Optional headers to include in the request.
20
+ :param str logging_level: The logging level for the client (default: 'CRITICAL').
21
+ """
22
+
23
+ def __init__(
24
+ self,
25
+ endpoint: str,
26
+ query: str,
27
+ headers: Optional[Dict[str, str]] = None,
28
+ logging_level: str = logging.CRITICAL,
29
+ ) -> None:
30
+ from gql import gql, Client # Optimize import performance
31
+ from gql.transport.requests import RequestsHTTPTransport
32
+ from gql.transport.requests import log as requests_logger
33
+
34
+ self.log_level = logging_level
35
+ self.endpoint = endpoint
36
+ self.query = gql(query)
37
+ self.headers = headers or {} # Ensure headers are a dictionary
38
+ self.transport = RequestsHTTPTransport(url=endpoint, headers=self.headers)
39
+ self.client = Client(transport=self.transport)
40
+ self.job_progress = create_progress_object()
41
+ requests_logger.setLevel(level=self.log_level)
42
+
43
+ def fetch_all(
44
+ self,
45
+ topic_key: str,
46
+ variables: Optional[Dict[str, Any]] = None,
47
+ ) -> List[Dict[str, Any]]:
48
+ """
49
+ Fetches all results from the paginated query.
50
+
51
+ :param str topic_key: The key to the topic in the response.
52
+ :param Optional[Dict[str, Any]] variables: Optional query variables.
53
+ :return: A list of results.
54
+ :rtype: List[Dict[str, Any]]
55
+ """
56
+ self.job_progress.add_task("[#f68d1f]Fetching data...", total=None)
57
+ results = []
58
+ next_cursor = None
59
+ has_next_page = True
60
+ page_info_default = {"hasNextPage": False, "endCursor": None}
61
+ while has_next_page:
62
+ data = self.fetch_page(variables=variables, after=next_cursor)
63
+ if data:
64
+ results.extend(data.get(topic_key, {}).get("nodes", []))
65
+ page_info = data.get(topic_key, {}).get("pageInfo", page_info_default)
66
+ logger.debug(f"pageInfo: {page_info}")
67
+ has_next_page = page_info.get("hasNextPage", False)
68
+ next_cursor = page_info.get("endCursor", None)
69
+ if not has_next_page:
70
+ break
71
+ else:
72
+ break
73
+ return results
74
+
75
+ def fetch_page(self, variables: Optional[Dict[str, Any]] = None, after: Optional[str] = None) -> Dict[str, Any]:
76
+ """
77
+ Fetches a single page of results.
78
+
79
+ :param Optional[Dict[str, Any]] variables: Optional query variables.
80
+ :param Optional[str] after: The cursor for pagination (optional, defaults to None for the first page).
81
+ :return: A dictionary containing the fetched page of results and pagination information.
82
+ :rtype: Dict[str, Any]
83
+ :raises: Exception if an error occurs during the query execution
84
+ """
85
+ variables = variables or {}
86
+ variables["after"] = after
87
+
88
+ try:
89
+ result = self.client.execute(self.query, variable_values=variables)
90
+ return result
91
+ except Exception as e:
92
+ logger.error(f"An error occurred while executing the query: {str(e)}", exc_info=True)
93
+ logger.error(f"Query: {self.query}")
94
+ logger.error(f"Variables: {variables}")
95
+ raise
96
+
97
+ def fetch_results(self, variables: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
98
+ """
99
+ Fetches a single page of results.
100
+
101
+ :param Optional[Dict[str, Any]] variables: Optional query variables.
102
+ :return: A dictionary containing the fetched page of results and pagination information.
103
+ :rtype: Dict[str, Any]
104
+ :raises: Exception if an error occurs during the query execution
105
+ """
106
+ try:
107
+ result = self.client.execute(self.query, variable_values=variables)
108
+ return result
109
+ except Exception as e:
110
+ logger.error(f"An error occurred while executing the query: {str(e)}", exc_info=True)
111
+ logger.error(f"Query: {self.query}")
112
+ logger.error(f"Variables: {variables}")
113
+ raise
@@ -0,0 +1,16 @@
1
+ """Provide utility functions for dealing with lists."""
2
+
3
+ from typing import Any, Tuple
4
+
5
+
6
+ def add_and_return_unique(*lists: Tuple[Any]) -> list: # noqa: DOC103
7
+ """Add lists together and return a list of unique elements
8
+
9
+ :param Tuple[Any] *lists: lists to add together
10
+ :return: a list of unique elements
11
+ :rtype: list
12
+ """
13
+ unique_elements = set()
14
+ for lst in lists:
15
+ unique_elements.update(lst)
16
+ return list(unique_elements)
@@ -0,0 +1,12 @@
1
+ """Define functions relating to numbers"""
2
+
3
+ from typing import Any
4
+
5
+
6
+ def is_number(value: Any) -> bool:
7
+ """Determine if a value is a number
8
+ :param Any value: value to check
9
+ :return: whether the value is a number
10
+ :rtype: bool
11
+ """
12
+ return isinstance(value, (int, float, complex))
@@ -0,0 +1,148 @@
1
+ """Define methods for use with CLI operations."""
2
+
3
+ from pprint import pprint
4
+ from shlex import split as shlexsplit
5
+ from subprocess import (
6
+ check_output,
7
+ Popen,
8
+ PIPE,
9
+ run,
10
+ CalledProcessError,
11
+ )
12
+ from typing import Union
13
+
14
+
15
+ def strbyte(string: str, encoding: str = "utf-8") -> bytes:
16
+ """Convert a string to bytes
17
+
18
+ String will have `\n` append and converted to encoding.
19
+
20
+ :param str string: the string to convert to bytes
21
+ :param str encoding: the encoding to use, defaults to "utf-8"
22
+ :return: a bytes object
23
+ :rtype: bytes
24
+ """
25
+ if not string.endswith("\n"):
26
+ string += "\n"
27
+ return bytes(string, encoding=encoding)
28
+
29
+
30
+ # FIXME - this was useful early on -- will any of this be useful once the SDK is in-place?
31
+ def send_input_to_process_via_communicate(
32
+ process: Popen,
33
+ input_: str,
34
+ encoding: str = "utf-8",
35
+ ) -> tuple:
36
+ """Send an input string to a process
37
+
38
+ When passed a Popen process, send the input as an encoded bytes
39
+
40
+ :param Popen process: the Popen process
41
+ :param str input_: a string to send to the process
42
+ :param str encoding: specify the encoding, defaults to "utf-8"
43
+ :return: a tuple of stdout, stderr
44
+ :rtype: tuple
45
+ """
46
+ return process.communicate(strbyte(string=input_, encoding=encoding))
47
+
48
+
49
+ def run_command(
50
+ cmd: Union[str, list],
51
+ ) -> bool:
52
+ """Run a shell command
53
+
54
+ Use python subprocess to run a command.
55
+
56
+ :param Union[str, list] cmd: a list or string of commands to execute
57
+ :raises CalledProcessError: if the command returns an error
58
+ :return: a bool indicating success or failure
59
+ :rtype: bool
60
+ """
61
+ if isinstance(cmd, str):
62
+ cmd = shlexsplit(cmd)
63
+ try:
64
+ run(cmd, check=True, stdout=PIPE, stderr=PIPE)
65
+ return True
66
+ except CalledProcessError as exc:
67
+ print(f"Command '{' '.join(cmd)}' returned with error (code {exc.returncode}): {exc.output.decode()}")
68
+ raise exc
69
+
70
+
71
+ def run_command_and_store_output(
72
+ cmd: Union[str, list],
73
+ output: bool = False,
74
+ ) -> str:
75
+ """Run a shell command and store the output
76
+
77
+ Runs a simple shell command and stores the output as a string.
78
+
79
+ :param Union[str, list] cmd: a list or string of commands
80
+ :param bool output: should pprint be used to display, defaults to False
81
+ :return: A string of the command output
82
+ :rtype: str
83
+ """
84
+ if isinstance(cmd, list):
85
+ cmd = " ".join(cmd)
86
+ cmd_output = check_output(cmd, shell=True, text=True)
87
+ if output:
88
+ pprint(f"Command output:\n{cmd_output}")
89
+ return cmd_output
90
+
91
+
92
+ def send_input_to_process(
93
+ process: Popen,
94
+ input_: str,
95
+ ) -> None:
96
+ """Send an input string to a process
97
+
98
+ When passed a Popen process, send the input as an encoded bytes
99
+
100
+ :param Popen process: the Popen process
101
+ :param str input_: a string to send to the process
102
+ return: None
103
+ """
104
+ process.stdin.write(input_)
105
+ process.stdin.flush()
106
+
107
+
108
+ def run_command_interactively(
109
+ cmd: Union[str, list],
110
+ inputs: Union[str, list],
111
+ output: bool = False,
112
+ include_error: bool = False,
113
+ ) -> str:
114
+ """Run a command by sending inputs
115
+
116
+ Runs a shell command and send inputs to it
117
+
118
+ :param Union[str, list] cmd: the initial command to invoke
119
+ :param Union[str, list] inputs: a single str of inputs or a list to pass to the command interactively
120
+ :param bool output: should output be pprinted? defaults to False
121
+ :param bool include_error: should error be output as well?, default False
122
+ :return: A string of the command output
123
+ :rtype: str
124
+ """
125
+ if isinstance(cmd, list):
126
+ cmd = " ".join(cmd)
127
+
128
+ process = Popen(shlexsplit(cmd), stdin=PIPE, stdout=PIPE, stderr=PIPE, text=True)
129
+
130
+ if isinstance(inputs, str):
131
+ inputs = [inputs]
132
+
133
+ for input_ in inputs:
134
+ send_input_to_process(process=process, input_=input_)
135
+
136
+ stdout, stderr = process.communicate()
137
+ output_std = stdout or ""
138
+ output_err = stderr or ""
139
+
140
+ if output:
141
+ pprint(output_std)
142
+ if include_error:
143
+ pprint(output_err)
144
+
145
+ result = output_std
146
+ if include_error:
147
+ result += "\n" + output_err
148
+ return result