Source code for django_tenant_options.management.commands.validateoptions
"""Command to validate django-tenant-options configuration (setup doctor)."""importsysfromdjango.core.management.baseimportBaseCommandfromdjango_tenant_options.diagnosticsimportrun_diagnosticsfromdjango_tenant_options.helpersimportall_option_subclassesfromdjango_tenant_options.helpersimportall_selection_subclasses
[docs]classCommand(BaseCommand):"""Validate django-tenant-options configuration."""help="Validates all Option and Selection models are properly configured"
[docs]defadd_arguments(self,parser):"""Register optional flags."""parser.add_argument("--quiet",action="store_true",help="Suppress the per-model checklist; print only warnings, errors, and the summary.",)parser.add_argument("--strict",action="store_true",help="Treat warnings as errors for the exit code (exit 1 if any warnings).",)
[docs]defhandle(self,*args,**options):"""Run validation checks and render results."""quiet=options.get("quiet",False)strict=options.get("strict",False)self.stdout.write("\n"+"="*70)self.stdout.write(self.style.MIGRATE_HEADING(" Django Tenant Options Configuration Validation"))self.stdout.write("="*70+"\n")# Forward the (possibly monkeypatched) module-level resolvers so tests that# patch them on this command module continue to take effect.result=run_diagnostics(option_resolver=all_option_subclasses,selection_resolver=all_selection_subclasses,)ifnotquiet:self._render_checklist(result)self.stdout.write("\n"+"="*70)ifresult.errors:self.stdout.write(self.style.ERROR("\nERRORS FOUND:"))self.stdout.write(self.style.ERROR("="*70))fori,errorinenumerate(result.errors,1):self.stdout.write(self.style.ERROR(f"\n{i}. {error}"))ifresult.warnings:self.stdout.write(self.style.WARNING("\n\nWARNINGS:"))self.stdout.write(self.style.WARNING("="*70))fori,warninginenumerate(result.warnings,1):self.stdout.write(self.style.WARNING(f"\n{i}. {warning}"))ifnotresult.errorsandnotresult.warnings:self.stdout.write(self.style.SUCCESS("\nAll validations passed!"))self.stdout.write(self.style.SUCCESS("\nYour django-tenant-options configuration is properly set up."))# Summary line (always printed, even with --quiet). A plaintext status word# is included so the outcome is unambiguous when color is stripped (CI logs,# piped output, color-blind terminals) - not conveyed by color alone.status="FAILED"ifresult.errorselse("PASSED WITH WARNINGS"ifresult.warningselse"PASSED")summary=(f"{status} - Summary: {result.passed_count} checks passed, "f"{len(result.warnings)} warning(s), {len(result.errors)} error(s)")ifresult.errors:self.stdout.write(self.style.ERROR(f"\n{summary}"))elifresult.warnings:self.stdout.write(self.style.WARNING(f"\n{summary}"))else:self.stdout.write(self.style.SUCCESS(f"\n{summary}"))self.stdout.write("\n"+"="*70+"\n")# Exit with error code if errors found (useful for CI/CD).ifresult.errors:sys.exit(1)# Under --strict, warnings also fail the run.ifstrictandresult.warnings:sys.exit(1)
def_render_checklist(self,result):"""Print the per-model info (passed-check) lines grouped by model name. Info lines are formatted as "<ModelName>: <detail>"; group by the model name prefix and print each detail with a check mark. """grouped={}order=[]forinfoinresult.infos:model_name,_,detail=info.partition(": ")ifmodel_namenotingrouped:grouped[model_name]=[]order.append(model_name)grouped[model_name].append(detailorinfo)formodel_nameinorder:self.stdout.write(self.style.MIGRATE_LABEL(f"\n{model_name}"))fordetailingrouped[model_name]:self.stdout.write(f" [x] {detail}")