Fix enterprise mypy type checking to catch type mismatches (#13140)

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
Rohit Malhotra
2026-03-04 13:43:46 -05:00
committed by GitHub
parent 6f8bf24226
commit 039e208167
6 changed files with 28 additions and 11 deletions

View File

@@ -50,8 +50,10 @@ repos:
- ./ - ./
- stripe==11.5.0 - stripe==11.5.0
- pygithub==2.6.1 - pygithub==2.6.1
# To see gaps add `--html-report mypy-report/` # Use -p (package) to avoid dual module name conflict when using MYPYPATH
entry: mypy --config-file enterprise/dev_config/python/mypy.ini enterprise/ # MYPYPATH=enterprise allows resolving bare imports like "from integrations.xxx"
# Note: tests package excluded to avoid conflict with core openhands tests
entry: bash -c 'MYPYPATH=enterprise mypy --config-file enterprise/dev_config/python/mypy.ini -p integrations -p server -p storage -p sync -p experiments'
always_run: true always_run: true
pass_filenames: false pass_filenames: false
files: ^enterprise/ files: ^enterprise/

View File

@@ -2,7 +2,6 @@
warn_unused_configs = True warn_unused_configs = True
ignore_missing_imports = True ignore_missing_imports = True
check_untyped_defs = True check_untyped_defs = True
explicit_package_bases = True
warn_unreachable = True warn_unreachable = True
warn_redundant_casts = True warn_redundant_casts = True
no_implicit_optional = True no_implicit_optional = True

View File

@@ -310,7 +310,10 @@ class GithubManager(Manager[GithubViewType]):
issue.create_comment(message) issue.create_comment(message)
else: else:
logger.warning('Unsupported location') # Catch any new types added to GithubViewType that aren't handled above
logger.warning( # type: ignore[unreachable]
f'Unsupported github_view type: {type(github_view).__name__}'
)
return return
async def start_job(self, github_view: GithubViewType) -> None: async def start_job(self, github_view: GithubViewType) -> None:

View File

@@ -76,7 +76,7 @@ class InvitationResponse(BaseModel):
inviter_email: str | None = None inviter_email: str | None = None
@classmethod @classmethod
def from_invitation( async def from_invitation(
cls, cls,
invitation: OrgInvitation, invitation: OrgInvitation,
inviter_email: str | None = None, inviter_email: str | None = None,
@@ -94,7 +94,7 @@ class InvitationResponse(BaseModel):
if invitation.role: if invitation.role:
role_name = invitation.role.name role_name = invitation.role.name
elif invitation.role_id: elif invitation.role_id:
role = RoleStore.get_role_by_id(invitation.role_id) role = await RoleStore.get_role_by_id(invitation.role_id)
role_name = role.name if role else '' role_name = role.name if role else ''
return cls( return cls(

View File

@@ -91,8 +91,11 @@ async def create_invitation(
}, },
) )
successful_responses = [
await InvitationResponse.from_invitation(inv) for inv in successful
]
return BatchInvitationResponse( return BatchInvitationResponse(
successful=[InvitationResponse.from_invitation(inv) for inv in successful], successful=successful_responses,
failed=[ failed=[
InvitationFailure(email=email, error=error) for email, error in failed InvitationFailure(email=email, error=error) for email, error in failed
], ],

View File

@@ -781,7 +781,7 @@ async def get_org_members(
) )
if not success: if not success:
error_map = { error_map: dict[str | None, tuple[int, str]] = {
'not_a_member': ( 'not_a_member': (
status.HTTP_403_FORBIDDEN, status.HTTP_403_FORBIDDEN,
'You are not a member of this organization', 'You are not a member of this organization',
@@ -790,9 +790,14 @@ async def get_org_members(
status.HTTP_400_BAD_REQUEST, status.HTTP_400_BAD_REQUEST,
'Invalid page_id format', 'Invalid page_id format',
), ),
None: (
status.HTTP_500_INTERNAL_SERVER_ERROR,
'An error occurred',
),
} }
status_code, detail = error_map.get( status_code, detail = error_map.get(
error_code, (status.HTTP_500_INTERNAL_SERVER_ERROR, 'An error occurred') error_code,
(status.HTTP_500_INTERNAL_SERVER_ERROR, 'An error occurred'),
) )
raise HTTPException(status_code=status_code, detail=detail) raise HTTPException(status_code=status_code, detail=detail)
@@ -900,7 +905,7 @@ async def remove_org_member(
) )
if not success: if not success:
error_map = { error_map: dict[str | None, tuple[int, str]] = {
'not_a_member': ( 'not_a_member': (
status.HTTP_403_FORBIDDEN, status.HTTP_403_FORBIDDEN,
'You are not a member of this organization', 'You are not a member of this organization',
@@ -925,9 +930,14 @@ async def remove_org_member(
status.HTTP_500_INTERNAL_SERVER_ERROR, status.HTTP_500_INTERNAL_SERVER_ERROR,
'Failed to remove member', 'Failed to remove member',
), ),
None: (
status.HTTP_500_INTERNAL_SERVER_ERROR,
'An error occurred',
),
} }
status_code, detail = error_map.get( status_code, detail = error_map.get(
error, (status.HTTP_500_INTERNAL_SERVER_ERROR, 'An error occurred') error,
(status.HTTP_500_INTERNAL_SERVER_ERROR, 'An error occurred'),
) )
raise HTTPException(status_code=status_code, detail=detail) raise HTTPException(status_code=status_code, detail=detail)