Skip to content

Conversation

@seanthegeek
Copy link
Contributor

No description provided.

Copilot AI and others added 7 commits December 19, 2025 20:43
…ct annotations in spf.py

Co-authored-by: seanthegeek <44679+seanthegeek@users.noreply.github.com>
Co-authored-by: seanthegeek <44679+seanthegeek@users.noreply.github.com>
Co-authored-by: seanthegeek <44679+seanthegeek@users.noreply.github.com>
There isn't a way to make a TypeDict field optional until Python 3.11, and we need to support 3.9. Leaving the typedicts in place for now, so that they can be used when Python 3.10 is no longer suported.
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request finalizes typing improvements for spf.py and bimi.py, replacing OrderedDict with standard dict types, adding comprehensive TypedDict definitions for structured data, and improving type annotations throughout. The changes modernize the codebase to use Python 3.9+ type hints and make the code more maintainable with explicit type definitions.

Key changes:

  • Replaced OrderedDict with regular dict and added TypedDict definitions for structured return types in spf.py
  • Added comprehensive TypedDict definitions for BIMI record structures in bimi.py
  • Updated function signatures to use Sequence[str | Nameserver] for nameserver parameters and removed unnecessary Optional wrappers around primitive types with defaults
  • Minor formatting improvements in other files (line breaks, blank lines, trailing whitespace)

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
checkdmarc/spf.py Major refactoring replacing OrderedDict with TypedDict-based structures, updated type annotations, and improved mechanism parsing with explicit type definitions
checkdmarc/bimi.py Added TypedDict definitions for BIMI structures (SVGMetadata, CertificateMetadata, BIMIQueryResult, etc.) and updated function return types
checkdmarc/smtp_tls_reporting.py Formatting change to split long class definition across multiple lines
checkdmarc/mta_sts.py Formatting improvements (line splits and trailing whitespace removal)
checkdmarc/dmarc.py Added blank lines after TypedDict docstrings for consistency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 675 to 678
else:
warnings.append(
"Any text after the all mechanism other than an exp modifier is ignored."
)
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The else clause is incorrectly indented and will execute when the try block succeeds without exception, not when an exception occurs. This should be dedented to be at the same level as the if statement on line 639, so it only executes when items_after_all doesn't start with "exp=".

Suggested change
else:
warnings.append(
"Any text after the all mechanism other than an exp modifier is ignored."
)
else:
warnings.append(
"Any text after the all mechanism other than an exp modifier is ignored."
)

Copilot uses AI. Check for mistakes.
Comment on lines 997 to 999
warnings.append("No TXT records at exp value {exp}.")
if len(exp_txt_records) > 1:
warnings.append("Too many TXT records at exp value {exp}.")
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The f-string formatting is missing. The string should be an f-string to interpolate the exp variable: f"No TXT records at exp value {exp}."

Suggested change
warnings.append("No TXT records at exp value {exp}.")
if len(exp_txt_records) > 1:
warnings.append("Too many TXT records at exp value {exp}.")
warnings.append(f"No TXT records at exp value {exp}.")
if len(exp_txt_records) > 1:
warnings.append(f"Too many TXT records at exp value {exp}.")

Copilot uses AI. Check for mistakes.
Comment on lines 997 to 999
warnings.append("No TXT records at exp value {exp}.")
if len(exp_txt_records) > 1:
warnings.append("Too many TXT records at exp value {exp}.")
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The f-string formatting is missing. The string should be an f-string to interpolate the exp variable: f"Too many TXT records at exp value {exp}."

Suggested change
warnings.append("No TXT records at exp value {exp}.")
if len(exp_txt_records) > 1:
warnings.append("Too many TXT records at exp value {exp}.")
warnings.append(f"No TXT records at exp value {exp}.")
if len(exp_txt_records) > 1:
warnings.append(f"Too many TXT records at exp value {exp}.")

Copilot uses AI. Check for mistakes.
Comment on lines +1119 to 1125
a_records = get_a_records(
value,
nameservers=nameservers,
resolver=resolver,
timeout=timeout,
timeout_retries=timeout_retries,
)
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ptr mechanism logic calls get_a_records(value, ...) but doesn't handle the case where value is an empty string. Unlike the "a" and "mx" mechanisms which default to the current domain when value is empty, the ptr mechanism doesn't check for this. This could cause an error if value is empty.

Copilot uses AI. Check for mistakes.
# TypedDict definitions for BIMI record structures


# These typedicts can't be used in Python 3.9-3.10 because these is no way to set a field as optional
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment contains a grammatical error. It should say "there is no way" instead of "these is no way".

Suggested change
# These typedicts can't be used in Python 3.9-3.10 because these is no way to set a field as optional
# These typedicts can't be used in Python 3.9-3.10 because there is no way to set a field as optional

Copilot uses AI. Check for mistakes.
Comment on lines +822 to +834
mx_host_addresses = {}
for host in mx_hosts:
hostname = host["hostname"]
# --- perform A/AAAA resolution for each MX host ---
try:
_addresses = get_a_records(
hostname,
nameservers=nameservers,
resolver=resolver,
timeout=timeout,
timeout_retries=timeout_retries,
)
mx_host_addresses[hostname] = _addresses
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variable mx_host_addresses is populated but never used. The MX mechanism stores mx_hosts (which contains just the MX records) instead of storing the resolved addresses. This appears to be dead code that should either be removed or the mechanism should store the resolved addresses.

Copilot uses AI. Check for mistakes.
"""Raised when a duplicate SPF include is found"""


class SPFRecordNotFound(SPFError):
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class does not call SPFError.init during initialization. (SPFRecordNotFound.init may be missing a call to a base class init)

Copilot uses AI. Check for mistakes.
Comment on lines +1145 to +1151
other_spf_dns_mechanism: SPFDNSLookupMechanism = {
"action": action,
"mechanism": mechanism,
"value": value,
"dns_lookups": mechanism_dns_lookups,
"void_dns_lookups": mechanism_void_dns_lookups,
}
Copy link

Copilot AI Dec 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This statement is unreachable.

Copilot uses AI. Check for mistakes.
@seanthegeek seanthegeek merged commit 6840704 into main Dec 20, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants