chore(types): Type-clean logging (43 errors) #1395
Open
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Description
Cleaned the logging/ directory and rebased on top of develop ready to merge.
Type-cleaning summary
This pull request introduces several fixes to address type errors discovered by
pyright
after enabling it for thenemoguardrails/logging/
directory. The changes enhance code robustness by handling potentialNone
values and correcting type annotations.Medium Risk
Refactoring Class Inheritance
This change modifies the class structure and is classified as medium risk as it alters the method resolution order, though it's likely a safe cleanup of unused functionality.
nemoguardrails/logging/callbacks.py
, Line 36StdOutCallbackHandler
may have been redundant or introduced conflicting method signatures.LoggingCallbackHandler
class was simplified to only inherit fromAsyncCallbackHandler
.StdOutCallbackHandler
from the base classes, the class hierarchy is simplified. This assumes that no functionality fromStdOutCallbackHandler
was being used, and all logging behavior is self-contained. This is a clean way to remove unnecessary dependencies.Low Risk
These changes are considered low risk as they primarily involve adding defensive checks and correcting type hints, which prevent runtime errors without altering core logic.
1. Handling Potentially
None
Timestampsnemoguardrails/logging/callbacks.py
(Line 207),nemoguardrails/logging/processing_log.py
(multiple lines)TypeError: unsupported operand type(s) for -: 'NoneType' and 'float'
. This error would occur when calculating durations withstarted_at
orfinished_at
timestamps that could beNone
.None
before calculating a duration. This prevents aTypeError
at runtime. The implicit assumption is that if timestamps are missing, the duration can be safely defaulted to0.0
.try...except TypeError
block is an option, but the explicitif
check is clearer and more direct.2. Guarding Against
None
Object Accessnemoguardrails/logging/processing_log.py
, Lines 158, 169, 182, and others.AttributeError: 'NoneType' object has no attribute '...'
. This would occur if objects likeactivated_rail
orexecuted_action
areNone
when their attributes are accessed.None
objects is now wrapped in a null check.if activated_rail is not None:
before using it, the code guards againstAttributeError
exceptions. This is a standard defensive pattern for handling objects that may not be initialized in all code paths.if
check is the canonical and safest way to handle this in Python.3. Safe Aggregation of Optional Numeric Stats
nemoguardrails/logging/processing_log.py
, Lines 261-276TypeError: unsupported operand type(s) for +=: 'NoneType' and 'int'
. This arises when aggregating statistics where either the current total or the value to be added isNone
.or 0
pattern is used to provide a default value for optional numeric types during summation.or 0
to coalesce anyNone
values into0
before the addition operation. This ensures the operation is always performed on numbers, preventing aTypeError
. The assumption is thatNone
should be treated as0
for statistical sums.if/else
block could achieve the same result, but the implemented solution is more concise and idiomatic.4. Correcting Exception Type Hints for Method Overriding
nemoguardrails/logging/callbacks.py
, Lines 280, 311, 342Union[Exception, KeyboardInterrupt]
) was not compatible with the superclass's expectedBaseException
.error
parameter in error handlers was broadened toBaseException
.BaseException
to correctly match the superclass signature inlangchain
. This is the correct fix becauseKeyboardInterrupt
inherits fromBaseException
, notException
, makingBaseException
the proper, compatible type for all possible exceptions.5. Resolving Type Invariance with
cast
nemoguardrails/logging/callbacks.py
, Lines 383-394Argument "handlers" has incompatible type "List[LoggingCallbackHandler]"; expected "List[BaseCallbackHandler]"
. This is a classic variance issue where a list of a subclass is not assignable to a list of a superclass.typing.cast
is used to inform the type checker that the list of handlers is compatible.cast
tells the static type checker to treat thehandlers
list as aList[BaseCallbackHandler]
, resolving the type mismatch error without any runtime impact.handlers: List[BaseCallbackHandler] = [LoggingCallbackHandler()]
. However, usingcast
is a perfectly valid and direct way to fix this issue.Test Plan
Type-checking
$ poetry run pre-commit run --all-files check yaml...............................................................Passed fix end of files.........................................................Passed trim trailing whitespace.................................................Passed isort (python)...........................................................Passed black....................................................................Passed Insert license in comments...............................................Passed pyright..................................................................Passed
Unit-tests
Local CLI check
Checklist