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.
- regscale/__init__.py +1 -0
- regscale/airflow/__init__.py +9 -0
- regscale/airflow/azure/__init__.py +9 -0
- regscale/airflow/azure/cli.py +89 -0
- regscale/airflow/azure/upload_dags.py +116 -0
- regscale/airflow/click_dags.py +127 -0
- regscale/airflow/click_mixins.py +82 -0
- regscale/airflow/config.py +25 -0
- regscale/airflow/factories/__init__.py +0 -0
- regscale/airflow/factories/connections.py +58 -0
- regscale/airflow/factories/workflows.py +78 -0
- regscale/airflow/hierarchy.py +88 -0
- regscale/airflow/operators/__init__.py +0 -0
- regscale/airflow/operators/click.py +36 -0
- regscale/airflow/sensors/__init__.py +0 -0
- regscale/airflow/sensors/sql.py +107 -0
- regscale/airflow/sessions/__init__.py +0 -0
- regscale/airflow/sessions/sql/__init__.py +3 -0
- regscale/airflow/sessions/sql/queries.py +64 -0
- regscale/airflow/sessions/sql/sql_server_queries.py +248 -0
- regscale/airflow/tasks/__init__.py +0 -0
- regscale/airflow/tasks/branches.py +22 -0
- regscale/airflow/tasks/cli.py +116 -0
- regscale/airflow/tasks/click.py +73 -0
- regscale/airflow/tasks/debugging.py +9 -0
- regscale/airflow/tasks/groups.py +116 -0
- regscale/airflow/tasks/init.py +60 -0
- regscale/airflow/tasks/states.py +47 -0
- regscale/airflow/tasks/workflows.py +36 -0
- regscale/ansible/__init__.py +9 -0
- regscale/core/__init__.py +0 -0
- regscale/core/app/__init__.py +3 -0
- regscale/core/app/api.py +571 -0
- regscale/core/app/application.py +665 -0
- regscale/core/app/internal/__init__.py +136 -0
- regscale/core/app/internal/admin_actions.py +230 -0
- regscale/core/app/internal/assessments_editor.py +873 -0
- regscale/core/app/internal/catalog.py +316 -0
- regscale/core/app/internal/comparison.py +459 -0
- regscale/core/app/internal/control_editor.py +571 -0
- regscale/core/app/internal/encrypt.py +79 -0
- regscale/core/app/internal/evidence.py +1240 -0
- regscale/core/app/internal/file_uploads.py +151 -0
- regscale/core/app/internal/healthcheck.py +66 -0
- regscale/core/app/internal/login.py +305 -0
- regscale/core/app/internal/migrations.py +240 -0
- regscale/core/app/internal/model_editor.py +1701 -0
- regscale/core/app/internal/poam_editor.py +632 -0
- regscale/core/app/internal/workflow.py +105 -0
- regscale/core/app/logz.py +74 -0
- regscale/core/app/utils/XMLIR.py +258 -0
- regscale/core/app/utils/__init__.py +0 -0
- regscale/core/app/utils/api_handler.py +358 -0
- regscale/core/app/utils/app_utils.py +1110 -0
- regscale/core/app/utils/catalog_utils/__init__.py +0 -0
- regscale/core/app/utils/catalog_utils/common.py +91 -0
- regscale/core/app/utils/catalog_utils/compare_catalog.py +193 -0
- regscale/core/app/utils/catalog_utils/diagnostic_catalog.py +97 -0
- regscale/core/app/utils/catalog_utils/download_catalog.py +103 -0
- regscale/core/app/utils/catalog_utils/update_catalog.py +718 -0
- regscale/core/app/utils/catalog_utils/update_catalog_v2.py +1378 -0
- regscale/core/app/utils/catalog_utils/update_catalog_v3.py +1272 -0
- regscale/core/app/utils/catalog_utils/update_plans.py +334 -0
- regscale/core/app/utils/file_utils.py +238 -0
- regscale/core/app/utils/parser_utils.py +81 -0
- regscale/core/app/utils/pickle_file_handler.py +57 -0
- regscale/core/app/utils/regscale_utils.py +319 -0
- regscale/core/app/utils/report_utils.py +119 -0
- regscale/core/app/utils/variables.py +226 -0
- regscale/core/decorators.py +31 -0
- regscale/core/lazy_group.py +65 -0
- regscale/core/login.py +63 -0
- regscale/core/server/__init__.py +0 -0
- regscale/core/server/flask_api.py +473 -0
- regscale/core/server/helpers.py +373 -0
- regscale/core/server/rest.py +64 -0
- regscale/core/server/static/css/bootstrap.css +6030 -0
- regscale/core/server/static/css/bootstrap.min.css +6 -0
- regscale/core/server/static/css/main.css +176 -0
- regscale/core/server/static/images/regscale-cli.svg +49 -0
- regscale/core/server/static/images/regscale.svg +38 -0
- regscale/core/server/templates/base.html +74 -0
- regscale/core/server/templates/index.html +43 -0
- regscale/core/server/templates/login.html +28 -0
- regscale/core/server/templates/make_base64.html +22 -0
- regscale/core/server/templates/upload_STIG.html +109 -0
- regscale/core/server/templates/upload_STIG_result.html +26 -0
- regscale/core/server/templates/upload_ssp.html +144 -0
- regscale/core/server/templates/upload_ssp_result.html +128 -0
- regscale/core/static/__init__.py +0 -0
- regscale/core/static/regex.py +14 -0
- regscale/core/utils/__init__.py +117 -0
- regscale/core/utils/click_utils.py +13 -0
- regscale/core/utils/date.py +238 -0
- regscale/core/utils/graphql.py +254 -0
- regscale/core/utils/urls.py +23 -0
- regscale/dev/__init__.py +6 -0
- regscale/dev/analysis.py +454 -0
- regscale/dev/cli.py +235 -0
- regscale/dev/code_gen.py +492 -0
- regscale/dev/dirs.py +69 -0
- regscale/dev/docs.py +384 -0
- regscale/dev/monitoring.py +26 -0
- regscale/dev/profiling.py +216 -0
- regscale/exceptions/__init__.py +4 -0
- regscale/exceptions/license_exception.py +7 -0
- regscale/exceptions/validation_exception.py +9 -0
- regscale/integrations/__init__.py +1 -0
- regscale/integrations/commercial/__init__.py +486 -0
- regscale/integrations/commercial/ad.py +433 -0
- regscale/integrations/commercial/amazon/__init__.py +0 -0
- regscale/integrations/commercial/amazon/common.py +106 -0
- regscale/integrations/commercial/aqua/__init__.py +0 -0
- regscale/integrations/commercial/aqua/aqua.py +91 -0
- regscale/integrations/commercial/aws/__init__.py +6 -0
- regscale/integrations/commercial/aws/cli.py +322 -0
- regscale/integrations/commercial/aws/inventory/__init__.py +110 -0
- regscale/integrations/commercial/aws/inventory/base.py +64 -0
- regscale/integrations/commercial/aws/inventory/resources/__init__.py +19 -0
- regscale/integrations/commercial/aws/inventory/resources/compute.py +234 -0
- regscale/integrations/commercial/aws/inventory/resources/containers.py +113 -0
- regscale/integrations/commercial/aws/inventory/resources/database.py +101 -0
- regscale/integrations/commercial/aws/inventory/resources/integration.py +237 -0
- regscale/integrations/commercial/aws/inventory/resources/networking.py +253 -0
- regscale/integrations/commercial/aws/inventory/resources/security.py +240 -0
- regscale/integrations/commercial/aws/inventory/resources/storage.py +91 -0
- regscale/integrations/commercial/aws/scanner.py +823 -0
- regscale/integrations/commercial/azure/__init__.py +0 -0
- regscale/integrations/commercial/azure/common.py +32 -0
- regscale/integrations/commercial/azure/intune.py +488 -0
- regscale/integrations/commercial/azure/scanner.py +49 -0
- regscale/integrations/commercial/burp.py +78 -0
- regscale/integrations/commercial/cpe.py +144 -0
- regscale/integrations/commercial/crowdstrike.py +1117 -0
- regscale/integrations/commercial/defender.py +1511 -0
- regscale/integrations/commercial/dependabot.py +210 -0
- regscale/integrations/commercial/durosuite/__init__.py +0 -0
- regscale/integrations/commercial/durosuite/api.py +1546 -0
- regscale/integrations/commercial/durosuite/process_devices.py +101 -0
- regscale/integrations/commercial/durosuite/scanner.py +637 -0
- regscale/integrations/commercial/durosuite/variables.py +21 -0
- regscale/integrations/commercial/ecr.py +90 -0
- regscale/integrations/commercial/gcp/__init__.py +237 -0
- regscale/integrations/commercial/gcp/auth.py +96 -0
- regscale/integrations/commercial/gcp/control_tests.py +238 -0
- regscale/integrations/commercial/gcp/variables.py +18 -0
- regscale/integrations/commercial/gitlab.py +332 -0
- regscale/integrations/commercial/grype.py +165 -0
- regscale/integrations/commercial/ibm.py +90 -0
- regscale/integrations/commercial/import_all/__init__.py +0 -0
- regscale/integrations/commercial/import_all/import_all_cmd.py +467 -0
- regscale/integrations/commercial/import_all/scan_file_fingerprints.json +27 -0
- regscale/integrations/commercial/jira.py +1046 -0
- regscale/integrations/commercial/mappings/__init__.py +0 -0
- regscale/integrations/commercial/mappings/csf_controls.json +713 -0
- regscale/integrations/commercial/mappings/nist_800_53_r5_controls.json +1516 -0
- regscale/integrations/commercial/nessus/__init__.py +0 -0
- regscale/integrations/commercial/nessus/nessus_utils.py +429 -0
- regscale/integrations/commercial/nessus/scanner.py +416 -0
- regscale/integrations/commercial/nexpose.py +90 -0
- regscale/integrations/commercial/okta.py +798 -0
- regscale/integrations/commercial/opentext/__init__.py +0 -0
- regscale/integrations/commercial/opentext/click.py +99 -0
- regscale/integrations/commercial/opentext/scanner.py +143 -0
- regscale/integrations/commercial/prisma.py +91 -0
- regscale/integrations/commercial/qualys.py +1462 -0
- regscale/integrations/commercial/salesforce.py +980 -0
- regscale/integrations/commercial/sap/__init__.py +0 -0
- regscale/integrations/commercial/sap/click.py +31 -0
- regscale/integrations/commercial/sap/sysdig/__init__.py +0 -0
- regscale/integrations/commercial/sap/sysdig/click.py +57 -0
- regscale/integrations/commercial/sap/sysdig/sysdig_scanner.py +190 -0
- regscale/integrations/commercial/sap/tenable/__init__.py +0 -0
- regscale/integrations/commercial/sap/tenable/click.py +49 -0
- regscale/integrations/commercial/sap/tenable/scanner.py +196 -0
- regscale/integrations/commercial/servicenow.py +1756 -0
- regscale/integrations/commercial/sicura/__init__.py +0 -0
- regscale/integrations/commercial/sicura/api.py +855 -0
- regscale/integrations/commercial/sicura/commands.py +73 -0
- regscale/integrations/commercial/sicura/scanner.py +481 -0
- regscale/integrations/commercial/sicura/variables.py +16 -0
- regscale/integrations/commercial/snyk.py +90 -0
- regscale/integrations/commercial/sonarcloud.py +260 -0
- regscale/integrations/commercial/sqlserver.py +369 -0
- regscale/integrations/commercial/stig_mapper_integration/__init__.py +0 -0
- regscale/integrations/commercial/stig_mapper_integration/click_commands.py +38 -0
- regscale/integrations/commercial/stig_mapper_integration/mapping_engine.py +353 -0
- regscale/integrations/commercial/stigv2/__init__.py +0 -0
- regscale/integrations/commercial/stigv2/ckl_parser.py +349 -0
- regscale/integrations/commercial/stigv2/click_commands.py +95 -0
- regscale/integrations/commercial/stigv2/stig_integration.py +202 -0
- regscale/integrations/commercial/synqly/__init__.py +0 -0
- regscale/integrations/commercial/synqly/assets.py +46 -0
- regscale/integrations/commercial/synqly/ticketing.py +132 -0
- regscale/integrations/commercial/synqly/vulnerabilities.py +223 -0
- regscale/integrations/commercial/synqly_jira.py +840 -0
- regscale/integrations/commercial/tenablev2/__init__.py +0 -0
- regscale/integrations/commercial/tenablev2/authenticate.py +31 -0
- regscale/integrations/commercial/tenablev2/click.py +1584 -0
- regscale/integrations/commercial/tenablev2/scanner.py +504 -0
- regscale/integrations/commercial/tenablev2/stig_parsers.py +140 -0
- regscale/integrations/commercial/tenablev2/utils.py +78 -0
- regscale/integrations/commercial/tenablev2/variables.py +17 -0
- regscale/integrations/commercial/trivy.py +162 -0
- regscale/integrations/commercial/veracode.py +96 -0
- regscale/integrations/commercial/wizv2/WizDataMixin.py +97 -0
- regscale/integrations/commercial/wizv2/__init__.py +0 -0
- regscale/integrations/commercial/wizv2/click.py +429 -0
- regscale/integrations/commercial/wizv2/constants.py +1001 -0
- regscale/integrations/commercial/wizv2/issue.py +361 -0
- regscale/integrations/commercial/wizv2/models.py +112 -0
- regscale/integrations/commercial/wizv2/parsers.py +339 -0
- regscale/integrations/commercial/wizv2/sbom.py +115 -0
- regscale/integrations/commercial/wizv2/scanner.py +416 -0
- regscale/integrations/commercial/wizv2/utils.py +796 -0
- regscale/integrations/commercial/wizv2/variables.py +39 -0
- regscale/integrations/commercial/wizv2/wiz_auth.py +159 -0
- regscale/integrations/commercial/xray.py +91 -0
- regscale/integrations/integration/__init__.py +2 -0
- regscale/integrations/integration/integration.py +26 -0
- regscale/integrations/integration/inventory.py +17 -0
- regscale/integrations/integration/issue.py +100 -0
- regscale/integrations/integration_override.py +149 -0
- regscale/integrations/public/__init__.py +103 -0
- regscale/integrations/public/cisa.py +641 -0
- regscale/integrations/public/criticality_updater.py +70 -0
- regscale/integrations/public/emass.py +411 -0
- regscale/integrations/public/emass_slcm_import.py +697 -0
- regscale/integrations/public/fedramp/__init__.py +0 -0
- regscale/integrations/public/fedramp/appendix_parser.py +548 -0
- regscale/integrations/public/fedramp/click.py +479 -0
- regscale/integrations/public/fedramp/components.py +714 -0
- regscale/integrations/public/fedramp/docx_parser.py +259 -0
- regscale/integrations/public/fedramp/fedramp_cis_crm.py +1124 -0
- regscale/integrations/public/fedramp/fedramp_common.py +3181 -0
- regscale/integrations/public/fedramp/fedramp_docx.py +388 -0
- regscale/integrations/public/fedramp/fedramp_five.py +2343 -0
- regscale/integrations/public/fedramp/fedramp_traversal.py +138 -0
- regscale/integrations/public/fedramp/import_fedramp_r4_ssp.py +279 -0
- regscale/integrations/public/fedramp/import_workbook.py +495 -0
- regscale/integrations/public/fedramp/inventory_items.py +244 -0
- regscale/integrations/public/fedramp/mappings/__init__.py +0 -0
- regscale/integrations/public/fedramp/mappings/fedramp_r4_parts.json +7388 -0
- regscale/integrations/public/fedramp/mappings/fedramp_r5_params.json +8636 -0
- regscale/integrations/public/fedramp/mappings/fedramp_r5_parts.json +9605 -0
- regscale/integrations/public/fedramp/mappings/system_roles.py +34 -0
- regscale/integrations/public/fedramp/mappings/user.py +175 -0
- regscale/integrations/public/fedramp/mappings/values.py +141 -0
- regscale/integrations/public/fedramp/markdown_parser.py +150 -0
- regscale/integrations/public/fedramp/metadata.py +689 -0
- regscale/integrations/public/fedramp/models/__init__.py +59 -0
- regscale/integrations/public/fedramp/models/leveraged_auth_new.py +168 -0
- regscale/integrations/public/fedramp/models/poam_importer.py +522 -0
- regscale/integrations/public/fedramp/parts_mapper.py +107 -0
- regscale/integrations/public/fedramp/poam/__init__.py +0 -0
- regscale/integrations/public/fedramp/poam/scanner.py +851 -0
- regscale/integrations/public/fedramp/properties.py +201 -0
- regscale/integrations/public/fedramp/reporting.py +84 -0
- regscale/integrations/public/fedramp/resources.py +496 -0
- regscale/integrations/public/fedramp/rosetta.py +110 -0
- regscale/integrations/public/fedramp/ssp_logger.py +87 -0
- regscale/integrations/public/fedramp/system_characteristics.py +922 -0
- regscale/integrations/public/fedramp/system_control_implementations.py +582 -0
- regscale/integrations/public/fedramp/system_implementation.py +190 -0
- regscale/integrations/public/fedramp/xml_utils.py +87 -0
- regscale/integrations/public/nist_catalog.py +275 -0
- regscale/integrations/public/oscal.py +1946 -0
- regscale/integrations/public/otx.py +169 -0
- regscale/integrations/scanner_integration.py +2692 -0
- regscale/integrations/variables.py +25 -0
- regscale/models/__init__.py +7 -0
- regscale/models/app_models/__init__.py +5 -0
- regscale/models/app_models/catalog_compare.py +213 -0
- regscale/models/app_models/click.py +252 -0
- regscale/models/app_models/datetime_encoder.py +21 -0
- regscale/models/app_models/import_validater.py +321 -0
- regscale/models/app_models/mapping.py +260 -0
- regscale/models/app_models/pipeline.py +37 -0
- regscale/models/click_models.py +413 -0
- regscale/models/config.py +154 -0
- regscale/models/email_style.css +67 -0
- regscale/models/hierarchy.py +8 -0
- regscale/models/inspect_models.py +79 -0
- regscale/models/integration_models/__init__.py +0 -0
- regscale/models/integration_models/amazon_models/__init__.py +0 -0
- regscale/models/integration_models/amazon_models/inspector.py +262 -0
- regscale/models/integration_models/amazon_models/inspector_scan.py +206 -0
- regscale/models/integration_models/aqua.py +247 -0
- regscale/models/integration_models/azure_alerts.py +255 -0
- regscale/models/integration_models/base64.py +23 -0
- regscale/models/integration_models/burp.py +433 -0
- regscale/models/integration_models/burp_models.py +128 -0
- regscale/models/integration_models/cisa_kev_data.json +19333 -0
- regscale/models/integration_models/defender_data.py +93 -0
- regscale/models/integration_models/defenderimport.py +143 -0
- regscale/models/integration_models/drf.py +443 -0
- regscale/models/integration_models/ecr_models/__init__.py +0 -0
- regscale/models/integration_models/ecr_models/data.py +69 -0
- regscale/models/integration_models/ecr_models/ecr.py +239 -0
- regscale/models/integration_models/flat_file_importer.py +1079 -0
- regscale/models/integration_models/grype_import.py +247 -0
- regscale/models/integration_models/ibm.py +126 -0
- regscale/models/integration_models/implementation_results.py +85 -0
- regscale/models/integration_models/nexpose.py +140 -0
- regscale/models/integration_models/prisma.py +202 -0
- regscale/models/integration_models/qualys.py +720 -0
- regscale/models/integration_models/qualys_scanner.py +160 -0
- regscale/models/integration_models/sbom/__init__.py +0 -0
- regscale/models/integration_models/sbom/cyclone_dx.py +139 -0
- regscale/models/integration_models/send_reminders.py +620 -0
- regscale/models/integration_models/snyk.py +155 -0
- regscale/models/integration_models/synqly_models/__init__.py +0 -0
- regscale/models/integration_models/synqly_models/capabilities.json +1 -0
- regscale/models/integration_models/synqly_models/connector_types.py +22 -0
- regscale/models/integration_models/synqly_models/connectors/__init__.py +7 -0
- regscale/models/integration_models/synqly_models/connectors/assets.py +97 -0
- regscale/models/integration_models/synqly_models/connectors/ticketing.py +583 -0
- regscale/models/integration_models/synqly_models/connectors/vulnerabilities.py +169 -0
- regscale/models/integration_models/synqly_models/ocsf_mapper.py +331 -0
- regscale/models/integration_models/synqly_models/param.py +72 -0
- regscale/models/integration_models/synqly_models/synqly_model.py +733 -0
- regscale/models/integration_models/synqly_models/tenants.py +39 -0
- regscale/models/integration_models/tenable_models/__init__.py +0 -0
- regscale/models/integration_models/tenable_models/integration.py +187 -0
- regscale/models/integration_models/tenable_models/models.py +513 -0
- regscale/models/integration_models/trivy_import.py +231 -0
- regscale/models/integration_models/veracode.py +217 -0
- regscale/models/integration_models/xray.py +135 -0
- regscale/models/locking.py +100 -0
- regscale/models/platform.py +110 -0
- regscale/models/regscale_models/__init__.py +67 -0
- regscale/models/regscale_models/assessment.py +570 -0
- regscale/models/regscale_models/assessment_plan.py +52 -0
- regscale/models/regscale_models/asset.py +567 -0
- regscale/models/regscale_models/asset_mapping.py +190 -0
- regscale/models/regscale_models/case.py +42 -0
- regscale/models/regscale_models/catalog.py +261 -0
- regscale/models/regscale_models/cci.py +46 -0
- regscale/models/regscale_models/change.py +167 -0
- regscale/models/regscale_models/checklist.py +372 -0
- regscale/models/regscale_models/comment.py +49 -0
- regscale/models/regscale_models/compliance_settings.py +112 -0
- regscale/models/regscale_models/component.py +412 -0
- regscale/models/regscale_models/component_mapping.py +65 -0
- regscale/models/regscale_models/control.py +38 -0
- regscale/models/regscale_models/control_implementation.py +1128 -0
- regscale/models/regscale_models/control_objective.py +261 -0
- regscale/models/regscale_models/control_parameter.py +100 -0
- regscale/models/regscale_models/control_test.py +34 -0
- regscale/models/regscale_models/control_test_plan.py +75 -0
- regscale/models/regscale_models/control_test_result.py +52 -0
- regscale/models/regscale_models/custom_field.py +245 -0
- regscale/models/regscale_models/data.py +109 -0
- regscale/models/regscale_models/data_center.py +40 -0
- regscale/models/regscale_models/deviation.py +203 -0
- regscale/models/regscale_models/email.py +97 -0
- regscale/models/regscale_models/evidence.py +47 -0
- regscale/models/regscale_models/evidence_mapping.py +40 -0
- regscale/models/regscale_models/facility.py +59 -0
- regscale/models/regscale_models/file.py +382 -0
- regscale/models/regscale_models/filetag.py +37 -0
- regscale/models/regscale_models/form_field_value.py +94 -0
- regscale/models/regscale_models/group.py +169 -0
- regscale/models/regscale_models/implementation_objective.py +335 -0
- regscale/models/regscale_models/implementation_option.py +275 -0
- regscale/models/regscale_models/implementation_role.py +33 -0
- regscale/models/regscale_models/incident.py +177 -0
- regscale/models/regscale_models/interconnection.py +43 -0
- regscale/models/regscale_models/issue.py +1176 -0
- regscale/models/regscale_models/leveraged_authorization.py +125 -0
- regscale/models/regscale_models/line_of_inquiry.py +52 -0
- regscale/models/regscale_models/link.py +205 -0
- regscale/models/regscale_models/meta_data.py +64 -0
- regscale/models/regscale_models/mixins/__init__.py +0 -0
- regscale/models/regscale_models/mixins/parent_cache.py +124 -0
- regscale/models/regscale_models/module.py +224 -0
- regscale/models/regscale_models/modules.py +191 -0
- regscale/models/regscale_models/objective.py +14 -0
- regscale/models/regscale_models/parameter.py +87 -0
- regscale/models/regscale_models/ports_protocol.py +81 -0
- regscale/models/regscale_models/privacy.py +89 -0
- regscale/models/regscale_models/profile.py +50 -0
- regscale/models/regscale_models/profile_link.py +68 -0
- regscale/models/regscale_models/profile_mapping.py +124 -0
- regscale/models/regscale_models/project.py +63 -0
- regscale/models/regscale_models/property.py +278 -0
- regscale/models/regscale_models/question.py +85 -0
- regscale/models/regscale_models/questionnaire.py +87 -0
- regscale/models/regscale_models/questionnaire_instance.py +177 -0
- regscale/models/regscale_models/rbac.py +132 -0
- regscale/models/regscale_models/reference.py +86 -0
- regscale/models/regscale_models/regscale_model.py +1643 -0
- regscale/models/regscale_models/requirement.py +29 -0
- regscale/models/regscale_models/risk.py +274 -0
- regscale/models/regscale_models/sbom.py +54 -0
- regscale/models/regscale_models/scan_history.py +436 -0
- regscale/models/regscale_models/search.py +53 -0
- regscale/models/regscale_models/security_control.py +132 -0
- regscale/models/regscale_models/security_plan.py +204 -0
- regscale/models/regscale_models/software_inventory.py +159 -0
- regscale/models/regscale_models/stake_holder.py +64 -0
- regscale/models/regscale_models/stig.py +647 -0
- regscale/models/regscale_models/supply_chain.py +152 -0
- regscale/models/regscale_models/system_role.py +188 -0
- regscale/models/regscale_models/system_role_external_assignment.py +40 -0
- regscale/models/regscale_models/tag.py +37 -0
- regscale/models/regscale_models/tag_mapping.py +19 -0
- regscale/models/regscale_models/task.py +133 -0
- regscale/models/regscale_models/threat.py +196 -0
- regscale/models/regscale_models/user.py +175 -0
- regscale/models/regscale_models/user_group.py +55 -0
- regscale/models/regscale_models/vulnerability.py +242 -0
- regscale/models/regscale_models/vulnerability_mapping.py +162 -0
- regscale/models/regscale_models/workflow.py +55 -0
- regscale/models/regscale_models/workflow_action.py +34 -0
- regscale/models/regscale_models/workflow_instance.py +269 -0
- regscale/models/regscale_models/workflow_instance_step.py +114 -0
- regscale/models/regscale_models/workflow_template.py +58 -0
- regscale/models/regscale_models/workflow_template_step.py +45 -0
- regscale/regscale.py +815 -0
- regscale/utils/__init__.py +7 -0
- regscale/utils/b64conversion.py +14 -0
- regscale/utils/click_utils.py +118 -0
- regscale/utils/decorators.py +48 -0
- regscale/utils/dict_utils.py +59 -0
- regscale/utils/files.py +79 -0
- regscale/utils/fxns.py +30 -0
- regscale/utils/graphql_client.py +113 -0
- regscale/utils/lists.py +16 -0
- regscale/utils/numbers.py +12 -0
- regscale/utils/shell.py +148 -0
- regscale/utils/string.py +121 -0
- regscale/utils/synqly_utils.py +165 -0
- regscale/utils/threading/__init__.py +8 -0
- regscale/utils/threading/threadhandler.py +131 -0
- regscale/utils/threading/threadsafe_counter.py +47 -0
- regscale/utils/threading/threadsafe_dict.py +242 -0
- regscale/utils/threading/threadsafe_list.py +83 -0
- regscale/utils/version.py +104 -0
- regscale/validation/__init__.py +0 -0
- regscale/validation/address.py +37 -0
- regscale/validation/record.py +48 -0
- regscale/visualization/__init__.py +5 -0
- regscale/visualization/click.py +34 -0
- regscale_cli-6.16.0.0.dist-info/LICENSE +21 -0
- regscale_cli-6.16.0.0.dist-info/METADATA +659 -0
- regscale_cli-6.16.0.0.dist-info/RECORD +481 -0
- regscale_cli-6.16.0.0.dist-info/WHEEL +5 -0
- regscale_cli-6.16.0.0.dist-info/entry_points.txt +6 -0
- regscale_cli-6.16.0.0.dist-info/top_level.txt +2 -0
- tests/fixtures/__init__.py +2 -0
- tests/fixtures/api.py +87 -0
- tests/fixtures/models.py +91 -0
- tests/fixtures/test_fixture.py +144 -0
- tests/mocks/__init__.py +0 -0
- tests/mocks/objects.py +3 -0
- tests/mocks/response.py +32 -0
- tests/mocks/xml.py +13 -0
- tests/regscale/__init__.py +0 -0
- tests/regscale/core/__init__.py +0 -0
- tests/regscale/core/test_api.py +232 -0
- tests/regscale/core/test_app.py +406 -0
- tests/regscale/core/test_login.py +37 -0
- tests/regscale/core/test_logz.py +66 -0
- tests/regscale/core/test_sbom_generator.py +87 -0
- tests/regscale/core/test_validation_utils.py +163 -0
- tests/regscale/core/test_version.py +78 -0
- tests/regscale/models/__init__.py +0 -0
- tests/regscale/models/test_asset.py +71 -0
- tests/regscale/models/test_config.py +26 -0
- tests/regscale/models/test_control_implementation.py +27 -0
- tests/regscale/models/test_import.py +97 -0
- tests/regscale/models/test_issue.py +36 -0
- tests/regscale/models/test_mapping.py +52 -0
- tests/regscale/models/test_platform.py +31 -0
- tests/regscale/models/test_regscale_model.py +346 -0
- tests/regscale/models/test_report.py +32 -0
- tests/regscale/models/test_tenable_integrations.py +118 -0
- tests/regscale/models/test_user_model.py +121 -0
- tests/regscale/test_about.py +19 -0
- tests/regscale/test_authorization.py +65 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
{% extends "base.html" %}
|
|
2
|
+
{% block content %}
|
|
3
|
+
<style>
|
|
4
|
+
.level-info {
|
|
5
|
+
color: forestgreen;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.level-warning {
|
|
9
|
+
color: yellow
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.level-error {
|
|
13
|
+
color: red
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
ul {
|
|
17
|
+
list-style-type: none;
|
|
18
|
+
padding: 0;
|
|
19
|
+
margin: 0;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
li {
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: baseline;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
li .number {
|
|
28
|
+
width: 50px;
|
|
29
|
+
text-align: right;
|
|
30
|
+
font-family: monospace;
|
|
31
|
+
padding-right: 10px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
li .text {
|
|
35
|
+
flex: 1;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.event-text {
|
|
39
|
+
word-wrap: break-word;
|
|
40
|
+
word-break: break-all;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.event-text-word-break {
|
|
44
|
+
word-wrap: break-word;
|
|
45
|
+
word-break: break-word;
|
|
46
|
+
}
|
|
47
|
+
</style>
|
|
48
|
+
<div class="row">
|
|
49
|
+
<div class="col-md-12">
|
|
50
|
+
<div style="padding: '10px'; display: 'grid'; justify-items: 'center'; align-items: 'center'; width: '100%';">
|
|
51
|
+
<div style="display: grid; justify-items: center; align-items: center;">
|
|
52
|
+
<h2>Security Plan Processing Results for Source Document "{{ filename }}"</h2>
|
|
53
|
+
<br>
|
|
54
|
+
<h1>System Security Plan Created!</h1>
|
|
55
|
+
<h3 style="padding: 5px;"><i>"{{result_output.ssp_title}}" (# {{ result_output.ssp_id }}) in
|
|
56
|
+
RegScale</i></h3>
|
|
57
|
+
<br>
|
|
58
|
+
<a href="{{ site_info.domain }}/form/securityplans/{{ result_output.ssp_id }}"
|
|
59
|
+
target="_blank"
|
|
60
|
+
style="text-align: center;"
|
|
61
|
+
rel="noopener"
|
|
62
|
+
>
|
|
63
|
+
<button type="button" class="btn btn-primary" target="_blank">
|
|
64
|
+
View Security Plan In RegScale ↗
|
|
65
|
+
</button>
|
|
66
|
+
</a>
|
|
67
|
+
</div>
|
|
68
|
+
<p> </p>
|
|
69
|
+
<div class="col-md-12 border bg-light" style="padding: 20px; border-radius: 10px;">
|
|
70
|
+
<h2 class="level-info">Summary</h2>
|
|
71
|
+
<div style="padding: 10px; border-radius: 10px;">
|
|
72
|
+
<h2><b>{{ results.Info + results.Error }}</b> Items in source document processed</h2>
|
|
73
|
+
<ul style="font-size: 1.25em;">
|
|
74
|
+
<li><span class="number"><b>{{ results.Info }}</b></span><span class="text">Items successfully mapped to created Security Plan</span></li>
|
|
75
|
+
<li><span class="number"><b>{{ results.Error }}</b></span><span class="text">Items failed to map to created Security Plan</span></li>
|
|
76
|
+
<li><span class="number"><b>{{ result_output.implementations_loaded }}</b></span><span class="text">Control items successfully mapped to created Security Plan<span class="text"></li>
|
|
77
|
+
</ul>
|
|
78
|
+
<hr>
|
|
79
|
+
<h3>{{ (results.Info / (results.Info + results.Error) *
|
|
80
|
+
100)|round(1)}}% <i>Item processing success rate</i>
|
|
81
|
+
</h3>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
<p> </p>
|
|
85
|
+
<div class="col-md-12 border bg-light" style="padding: 20px; border-radius: 10px;">
|
|
86
|
+
<h2 class="level-info">Items by Category</h2>
|
|
87
|
+
<ul>
|
|
88
|
+
{% for item in category_counts.items() %}
|
|
89
|
+
<li><span class="number">{{ item[1] }}</span><span class="text">{{ item[0] }}</span></li>
|
|
90
|
+
{% endfor %}
|
|
91
|
+
</ul>
|
|
92
|
+
<br>
|
|
93
|
+
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
<p> </p>
|
|
97
|
+
<div class="col-md-12">
|
|
98
|
+
<div class="p-12 border bg-light" style="padding: 10px; border-radius: 10px;">
|
|
99
|
+
|
|
100
|
+
{% for level, rows in csv_data_grouped.items()%}
|
|
101
|
+
<h2 class="level-{{ level|lower }}">{{ level }} Results</h2>
|
|
102
|
+
<caption><i>The {{ level|lower }} statements found processing source document.</i></caption>
|
|
103
|
+
<table style="table-layout: fixed; width: 100%;">
|
|
104
|
+
<thead>
|
|
105
|
+
<tr style="text-align: left;">
|
|
106
|
+
<th class="event-text-word-break" style="width: 20%;">NIST Model Layer Item</th>
|
|
107
|
+
<th style="width: 20%;">Record Type</th>
|
|
108
|
+
<th style="width: 60%;">Event</th>
|
|
109
|
+
</tr>
|
|
110
|
+
</thead>
|
|
111
|
+
<tbody>
|
|
112
|
+
{% for row in rows %}
|
|
113
|
+
<tr>
|
|
114
|
+
<td class="event-text-word-break">{{ row['model_layer'] }}</td>
|
|
115
|
+
<td class="event-text-word-break">{{ row['record_type'] }}</td>
|
|
116
|
+
<td class="event-text">{{ row['event'] }}</td>
|
|
117
|
+
</tr>
|
|
118
|
+
{% endfor %}
|
|
119
|
+
</tbody>
|
|
120
|
+
</table>
|
|
121
|
+
{% endfor %}
|
|
122
|
+
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
{% endblock %}
|
|
File without changes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Compiled Regexes for use."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
URL_REGEX = re.compile(
|
|
7
|
+
r"^(?:http)s?://" # http:// or https://
|
|
8
|
+
r"(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|" # domain...
|
|
9
|
+
r"localhost|" # localhost...
|
|
10
|
+
r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})" # ...or ip
|
|
11
|
+
r"(?::\d+)?" # optional port
|
|
12
|
+
r"(?:/?|[/?]\S+)$",
|
|
13
|
+
re.IGNORECASE,
|
|
14
|
+
)
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"""Utility functions for the application"""
|
|
2
|
+
|
|
3
|
+
from typing import Union, Optional
|
|
4
|
+
|
|
5
|
+
UDP = "UDP"
|
|
6
|
+
TCP = "TCP"
|
|
7
|
+
TCP_UDP = "TCP/UDP"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def snakify(name: str) -> str:
|
|
11
|
+
"""
|
|
12
|
+
Convert a string to snake_case
|
|
13
|
+
|
|
14
|
+
:param str name: String to convert
|
|
15
|
+
:returns: String in snake_case
|
|
16
|
+
:rtype: str
|
|
17
|
+
"""
|
|
18
|
+
return name.lower().replace(" ", "_")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def get_protocol_from_port(port: Union[int, str]) -> Optional[str]:
|
|
22
|
+
"""
|
|
23
|
+
Determines the protocol from a port number for well known ports
|
|
24
|
+
|
|
25
|
+
:param Union[int, str] port: Port number (int or str)
|
|
26
|
+
:returns: Protocol name or None if not found
|
|
27
|
+
:rtype: Optional[str]
|
|
28
|
+
"""
|
|
29
|
+
port_to_protocol = {
|
|
30
|
+
20: "FTP", # File Transfer Protocol (FTP) Data Transfer
|
|
31
|
+
21: "FTP", # File Transfer Protocol (FTP) Command Control
|
|
32
|
+
22: "SSH", # Secure Shell (SSH)
|
|
33
|
+
23: "Telnet", # Telnet protocol
|
|
34
|
+
25: "SMTP", # Simple Mail Transfer Protocol (SMTP)
|
|
35
|
+
53: "DNS", # Domain Name System (DNS)
|
|
36
|
+
67: "DHCP", # Dynamic Host Configuration Protocol (DHCP) Server
|
|
37
|
+
68: "DHCP", # Dynamic Host Configuration Protocol (DHCP) Client
|
|
38
|
+
80: "HTTP", # Hypertext Transfer Protocol (HTTP)
|
|
39
|
+
110: "POP3", # Post Office Protocol v3 (POP3)
|
|
40
|
+
123: "NTP", # Network Time Protocol (NTP)
|
|
41
|
+
143: "IMAP", # Internet Message Access Protocol (IMAP)
|
|
42
|
+
161: "SNMP", # Simple Network Management Protocol (SNMP)
|
|
43
|
+
162: "SNMP", # Simple Network Management Protocol (SNMP) Trap
|
|
44
|
+
443: "HTTPS", # Hypertext Transfer Protocol Secure (HTTPS)
|
|
45
|
+
445: "SMB", # Server Message Block (SMB)
|
|
46
|
+
465: "SMTPS", # Simple Mail Transfer Protocol Secure (SMTPS)
|
|
47
|
+
993: "IMAPS", # Internet Message Access Protocol Secure (IMAPS)
|
|
48
|
+
995: "POP3S", # Post Office Protocol 3 Secure (POP3S)
|
|
49
|
+
1433: "MSSQL", # Microsoft SQL Server
|
|
50
|
+
3306: "MySQL", # MySQL Database Service
|
|
51
|
+
3389: "RDP", # Remote Desktop Protocol (RDP)
|
|
52
|
+
5432: "PostgreSQL", # PostgreSQL Database
|
|
53
|
+
5672: "AMQP", # Advanced Message Queuing Protocol (AMQP)
|
|
54
|
+
5900: "VNC", # Virtual Network Computing (VNC)
|
|
55
|
+
6379: "Redis", # Redis Key-Value Store
|
|
56
|
+
8080: "HTTP-ALT", # Alternative HTTP
|
|
57
|
+
8443: "HTTPS-ALT", # Alternative HTTPS
|
|
58
|
+
27017: "MongoDB", # MongoDB Database
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
port = int(port) # Ensure port is an integer
|
|
62
|
+
|
|
63
|
+
return port_to_protocol.get(port, None)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def get_base_protocol_from_port(port: Union[int, str]) -> str:
|
|
67
|
+
"""
|
|
68
|
+
Returns the well-known base protocol for a port such as TCP, UDP, both TCP/UDP, or other based on the port number
|
|
69
|
+
:param Union[int, str] port: Port number
|
|
70
|
+
:returns: Protocol category
|
|
71
|
+
:rtype: str
|
|
72
|
+
"""
|
|
73
|
+
port = int(port) # Ensure port is an integer
|
|
74
|
+
|
|
75
|
+
both_tcp_udp_ports = [
|
|
76
|
+
20,
|
|
77
|
+
21,
|
|
78
|
+
22,
|
|
79
|
+
23,
|
|
80
|
+
25,
|
|
81
|
+
53,
|
|
82
|
+
80,
|
|
83
|
+
110,
|
|
84
|
+
123,
|
|
85
|
+
143,
|
|
86
|
+
161,
|
|
87
|
+
162,
|
|
88
|
+
443,
|
|
89
|
+
465,
|
|
90
|
+
993,
|
|
91
|
+
995,
|
|
92
|
+
1433,
|
|
93
|
+
3306,
|
|
94
|
+
3389,
|
|
95
|
+
5432,
|
|
96
|
+
5672,
|
|
97
|
+
5900,
|
|
98
|
+
6379,
|
|
99
|
+
8080,
|
|
100
|
+
8443,
|
|
101
|
+
27017,
|
|
102
|
+
]
|
|
103
|
+
well_known_udp_ports = [7, 9, 19, 49, 67, 68, 69, 123, 161, 162, 514]
|
|
104
|
+
well_known_tcp_ports = list(set(range(0, 1024)) - set(well_known_udp_ports) - set(both_tcp_udp_ports))
|
|
105
|
+
|
|
106
|
+
if port in well_known_udp_ports:
|
|
107
|
+
return UDP # Well-known ports for UDP
|
|
108
|
+
elif port in both_tcp_udp_ports:
|
|
109
|
+
return TCP_UDP # Ports used for both TCP and UDP
|
|
110
|
+
elif port in well_known_tcp_ports:
|
|
111
|
+
return TCP # Well-known ports for TCP
|
|
112
|
+
elif 1024 <= port <= 49151:
|
|
113
|
+
return TCP_UDP # Registered ports for both TCP and UDP
|
|
114
|
+
elif 49152 <= port <= 65535:
|
|
115
|
+
return TCP_UDP # Dynamic or private ports for both TCP and UDP
|
|
116
|
+
else:
|
|
117
|
+
return "Other" # Ports that don't fit into the standard categories
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""Use the click methods to generate an importable click hierarchy."""
|
|
2
|
+
|
|
3
|
+
from regscale.regscale import cli
|
|
4
|
+
from regscale.utils.click_utils import process_click_group
|
|
5
|
+
|
|
6
|
+
REGSCALE_CLI = process_click_group(group=cli, prefix="regscale")
|
|
7
|
+
|
|
8
|
+
REGSCALE_CLI_SERIALIZABLE = process_click_group(group=cli)
|
|
9
|
+
|
|
10
|
+
if __name__ == "__main__":
|
|
11
|
+
from pprint import pprint
|
|
12
|
+
|
|
13
|
+
pprint(REGSCALE_CLI)
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""Utility functions for handling date and datetime conversions"""
|
|
4
|
+
|
|
5
|
+
import datetime
|
|
6
|
+
import logging
|
|
7
|
+
from typing import List, Union, Optional
|
|
8
|
+
|
|
9
|
+
from pandas import Timestamp
|
|
10
|
+
from dateutil.parser import parse, ParserError
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger("regscale")
|
|
14
|
+
default_date_format = "%Y-%m-%dT%H:%M:%S%z"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def date_str(date_object: Union[str, datetime.datetime, datetime.date, None], date_format: Optional[str] = None) -> str:
|
|
18
|
+
"""
|
|
19
|
+
Convert a date/datetime object to a date string.
|
|
20
|
+
|
|
21
|
+
:param Union[str, datetime.datetime, datetime.date, None] date_object: The date/datetime object to convert.
|
|
22
|
+
:param Optional[str] date_format: The format to use for the date string.
|
|
23
|
+
:return: The date as a string.
|
|
24
|
+
"""
|
|
25
|
+
if isinstance(date_object, str):
|
|
26
|
+
date_object = date_obj(date_object)
|
|
27
|
+
if isinstance(date_object, datetime.datetime):
|
|
28
|
+
if date_format:
|
|
29
|
+
return date_object.strftime(date_format)
|
|
30
|
+
return date_object.date().isoformat()
|
|
31
|
+
if isinstance(date_object, datetime.date):
|
|
32
|
+
if date_format:
|
|
33
|
+
return date_object.strftime(date_format)
|
|
34
|
+
return date_object.isoformat()
|
|
35
|
+
if isinstance(date_object, Timestamp):
|
|
36
|
+
return date_object.date().isoformat()
|
|
37
|
+
return ""
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def datetime_str(
|
|
41
|
+
date_object: Union[str, datetime.datetime, datetime.date, None], date_format: Optional[str] = None
|
|
42
|
+
) -> str:
|
|
43
|
+
"""
|
|
44
|
+
Convert a date/datetime object to a datetime string.
|
|
45
|
+
|
|
46
|
+
:param Union[str, datetime.datetime, datetime.date, None] date_object: The date/datetime object to convert.
|
|
47
|
+
:param Optional[str] date_format: The format to use for the datetime string.
|
|
48
|
+
:return: The datetime as a string.
|
|
49
|
+
"""
|
|
50
|
+
if not date_format:
|
|
51
|
+
date_format = default_date_format
|
|
52
|
+
if isinstance(date_object, str):
|
|
53
|
+
date_object = datetime_obj(date_object)
|
|
54
|
+
if isinstance(date_object, datetime.datetime):
|
|
55
|
+
return date_object.strftime(date_format)
|
|
56
|
+
if isinstance(date_object, datetime.date):
|
|
57
|
+
return date_object.strftime(date_format)
|
|
58
|
+
return ""
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def date_obj(date_str: Union[str, datetime.datetime, datetime.date, int, None]) -> Optional[datetime.date]:
|
|
62
|
+
"""
|
|
63
|
+
Convert a string, datetime, date, or integer to a date object.
|
|
64
|
+
|
|
65
|
+
:param Union[str, datetime.datetime, datetime.date, int] date_str: The value to convert.
|
|
66
|
+
:return: The date object.
|
|
67
|
+
"""
|
|
68
|
+
if isinstance(date_str, (str, int)):
|
|
69
|
+
dt_obj = datetime_obj(date_str)
|
|
70
|
+
return dt_obj.date() if dt_obj else None
|
|
71
|
+
if isinstance(date_str, datetime.datetime):
|
|
72
|
+
return date_str.date()
|
|
73
|
+
if isinstance(date_str, datetime.date):
|
|
74
|
+
return date_str
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def datetime_obj(date_str: Union[str, datetime.datetime, datetime.date, int, None]) -> Optional[datetime.datetime]:
|
|
79
|
+
"""
|
|
80
|
+
Convert a string, datetime, date, integer, or timestamp string to a datetime object.
|
|
81
|
+
|
|
82
|
+
:param Union[str, datetime.datetime, datetime.date, int, None] date_str: The value to convert.
|
|
83
|
+
:return: The datetime object.
|
|
84
|
+
"""
|
|
85
|
+
if isinstance(date_str, str):
|
|
86
|
+
# Check if the string looks like a timestamp integer
|
|
87
|
+
if date_str.isdigit():
|
|
88
|
+
return datetime.datetime.fromtimestamp(int(date_str))
|
|
89
|
+
try:
|
|
90
|
+
return parse(date_str)
|
|
91
|
+
except ParserError as e:
|
|
92
|
+
if date_str and str(date_str).lower() not in ["n/a", "none"]:
|
|
93
|
+
logger.warning(f"Warning could not parse date string: {date_str}\n{e}")
|
|
94
|
+
return None
|
|
95
|
+
if isinstance(date_str, datetime.datetime):
|
|
96
|
+
return date_str
|
|
97
|
+
if isinstance(date_str, datetime.date):
|
|
98
|
+
return datetime.datetime.combine(date_str, datetime.datetime.min.time())
|
|
99
|
+
if isinstance(date_str, int):
|
|
100
|
+
return datetime.datetime.fromtimestamp(date_str)
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def time_str(time_obj: Union[str, datetime.datetime, datetime.time]) -> str:
|
|
105
|
+
"""
|
|
106
|
+
Convert a datetime/time object to a string.
|
|
107
|
+
|
|
108
|
+
:param Union[str, datetime.datetime, datetime.time] time_obj: The datetime/time object to convert.
|
|
109
|
+
:return: The time as a string.
|
|
110
|
+
"""
|
|
111
|
+
if isinstance(time_obj, str):
|
|
112
|
+
return time_obj
|
|
113
|
+
if isinstance(time_obj, datetime.datetime):
|
|
114
|
+
time_obj = time_obj.time()
|
|
115
|
+
if isinstance(time_obj, datetime.time):
|
|
116
|
+
return time_obj.__format__("%-I:%M%p")
|
|
117
|
+
return ""
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def time_widget_str(time_obj: Union[str, datetime.datetime, datetime.time]) -> str:
|
|
121
|
+
"""
|
|
122
|
+
Convert a time object to a string for a widget.
|
|
123
|
+
|
|
124
|
+
:param Union[str, datetime.datetime, datetime.time] time_obj: The time object to convert.
|
|
125
|
+
:return: The time as a string for a widget.
|
|
126
|
+
"""
|
|
127
|
+
if isinstance(time_obj, str):
|
|
128
|
+
return time_obj
|
|
129
|
+
if isinstance(time_obj, datetime.datetime):
|
|
130
|
+
time_obj = time_obj.time()
|
|
131
|
+
if isinstance(time_obj, datetime.time):
|
|
132
|
+
return time_obj.__format__("%-I:%M ") + time_obj.__format__("%p").lower()
|
|
133
|
+
return ""
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def parse_time(time_str: str) -> datetime.time:
|
|
137
|
+
"""
|
|
138
|
+
Parse a time string.
|
|
139
|
+
|
|
140
|
+
:param str time_str: The time string to parse.
|
|
141
|
+
:return: The parsed time.
|
|
142
|
+
:rtype: datetime.time
|
|
143
|
+
"""
|
|
144
|
+
try:
|
|
145
|
+
return parse(f"1/1/2011 {time_str.zfill(4)}").time()
|
|
146
|
+
except ValueError:
|
|
147
|
+
return parse(f"1/1/2011 {time_str.zfill(len(time_str) + 1)}").time()
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def is_weekday(date_obj: datetime.date) -> bool:
|
|
151
|
+
"""
|
|
152
|
+
Check if a date is a weekday.
|
|
153
|
+
|
|
154
|
+
:param datetime.date date_obj: The date to check.
|
|
155
|
+
:return: True if the date is a weekday, False otherwise.
|
|
156
|
+
:rtype: bool
|
|
157
|
+
"""
|
|
158
|
+
return date_obj.weekday() < 5
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def days_between(
|
|
162
|
+
start: Union[str, datetime.datetime, datetime.date],
|
|
163
|
+
end: Union[str, datetime.datetime, datetime.date],
|
|
164
|
+
) -> List[str]:
|
|
165
|
+
"""
|
|
166
|
+
Get the days between two dates.
|
|
167
|
+
|
|
168
|
+
:param Union[str, datetime.datetime, datetime.date] start: The start date.
|
|
169
|
+
:param Union[str, datetime.datetime, datetime.date] end: The end date.
|
|
170
|
+
:return: A list of dates between the start and end dates.
|
|
171
|
+
"""
|
|
172
|
+
delta = date_obj(end) - date_obj(start)
|
|
173
|
+
return [(date_obj(start) + datetime.timedelta(days=i)).strftime("%Y/%m/%d") for i in range(delta.days + 1)]
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def weekend_days_between(
|
|
177
|
+
start: Union[str, datetime.datetime, datetime.date],
|
|
178
|
+
end: Union[str, datetime.datetime, datetime.date],
|
|
179
|
+
) -> List[str]:
|
|
180
|
+
"""
|
|
181
|
+
Get the weekend days between two dates.
|
|
182
|
+
|
|
183
|
+
:param Union[str, datetime.datetime, datetime.date] start: The start date.
|
|
184
|
+
:param Union[str, datetime.datetime, datetime.date] end: The end date.
|
|
185
|
+
:return: A list of weekend dates between the start and end dates.
|
|
186
|
+
"""
|
|
187
|
+
return [day for day in days_between(start, end) if not is_weekday(date_obj(day))]
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
def days_from_today(i: int) -> datetime.date:
|
|
191
|
+
"""
|
|
192
|
+
Get the date a certain number of days from today.
|
|
193
|
+
|
|
194
|
+
:param int i: The number of days from today.
|
|
195
|
+
:return: The date i days from today.
|
|
196
|
+
:rtype: datetime.date
|
|
197
|
+
"""
|
|
198
|
+
return datetime.date.today() + datetime.timedelta(days=i)
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def get_day_increment(
|
|
202
|
+
start: Union[str, datetime.datetime, datetime.date],
|
|
203
|
+
days: int,
|
|
204
|
+
excluded_dates: Optional[List[Union[str, datetime.datetime, datetime.date]]] = None,
|
|
205
|
+
) -> datetime.date:
|
|
206
|
+
"""
|
|
207
|
+
Get the date a certain number of days from a start date, excluding certain dates.
|
|
208
|
+
|
|
209
|
+
:param Union[str, datetime.datetime, datetime.date] start: The start date.
|
|
210
|
+
:param int days: The number of days from the start date.
|
|
211
|
+
:param Optional[List[Union[str, datetime.datetime, datetime.date]]] excluded_dates: A list of dates to exclude.
|
|
212
|
+
:return: The date days days from the start date, excluding the excluded dates.
|
|
213
|
+
"""
|
|
214
|
+
start = date_obj(start)
|
|
215
|
+
end = start + datetime.timedelta(days=days)
|
|
216
|
+
if excluded_dates:
|
|
217
|
+
for excluded_date in sorted([date_obj(x) for x in excluded_dates]):
|
|
218
|
+
if start <= excluded_date <= end:
|
|
219
|
+
end += datetime.timedelta(days=1)
|
|
220
|
+
return end
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def normalize_date(dt: str, fmt: str) -> str:
|
|
224
|
+
"""
|
|
225
|
+
Normalize string date to a standard format, if possible.
|
|
226
|
+
|
|
227
|
+
:param str dt: Date to normalize
|
|
228
|
+
:param str fmt: Format of the date
|
|
229
|
+
:return: Normalized Date
|
|
230
|
+
:rtype: str
|
|
231
|
+
"""
|
|
232
|
+
if isinstance(dt, str):
|
|
233
|
+
try:
|
|
234
|
+
new_dt = datetime.datetime.strptime(dt, fmt)
|
|
235
|
+
return new_dt.strftime("%Y-%m-%d %H:%M:%S")
|
|
236
|
+
except ValueError:
|
|
237
|
+
return dt
|
|
238
|
+
return dt
|