Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,6 @@ plugins = ["pydantic.mypy"]
module = "litellm.*"
ignore_missing_imports = true

[[tool.mypy.overrides]]
module = "tests.*"
disallow_untyped_defs = false

[tool.pydantic-mypy]
init_forbid_extra = true
init_typed = true
Expand Down
22 changes: 11 additions & 11 deletions tests/unit/budget/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@
# ── Factories ──────────────────────────────────────────────────────


class BudgetAlertConfigFactory(ModelFactory):
class BudgetAlertConfigFactory(ModelFactory[BudgetAlertConfig]):
__model__ = BudgetAlertConfig
warn_at = 75
critical_at = 90
hard_stop_at = 100


class AutoDowngradeConfigFactory(ModelFactory):
class AutoDowngradeConfigFactory(ModelFactory[AutoDowngradeConfig]):
__model__ = AutoDowngradeConfig
enabled = False
downgrade_map = ()


class BudgetConfigFactory(ModelFactory):
class BudgetConfigFactory(ModelFactory[BudgetConfig]):
__model__ = BudgetConfig
total_monthly = 100.0
per_task_limit = 5.0
Expand All @@ -49,44 +49,44 @@ class BudgetConfigFactory(ModelFactory):
auto_downgrade = AutoDowngradeConfigFactory


class TeamBudgetFactory(ModelFactory):
class TeamBudgetFactory(ModelFactory[TeamBudget]):
__model__ = TeamBudget
budget_percent = 10.0


class DepartmentBudgetFactory(ModelFactory):
class DepartmentBudgetFactory(ModelFactory[DepartmentBudget]):
__model__ = DepartmentBudget
budget_percent = 25.0
teams = ()


class BudgetHierarchyFactory(ModelFactory):
class BudgetHierarchyFactory(ModelFactory[BudgetHierarchy]):
__model__ = BudgetHierarchy
departments = ()


class CostRecordFactory(ModelFactory):
class CostRecordFactory(ModelFactory[CostRecord]):
__model__ = CostRecord
input_tokens = 1000
output_tokens = 500
cost_usd = 0.05


class PeriodSpendingFactory(ModelFactory):
class PeriodSpendingFactory(ModelFactory[PeriodSpending]):
__model__ = PeriodSpending
start = datetime(2026, 2, 1, tzinfo=UTC)
end = datetime(2026, 3, 1, tzinfo=UTC)


class AgentSpendingFactory(ModelFactory):
class AgentSpendingFactory(ModelFactory[AgentSpending]):
__model__ = AgentSpending


class DepartmentSpendingFactory(ModelFactory):
class DepartmentSpendingFactory(ModelFactory[DepartmentSpending]):
__model__ = DepartmentSpending


class SpendingSummaryFactory(ModelFactory):
class SpendingSummaryFactory(ModelFactory[SpendingSummary]):
__model__ = SpendingSummary
period = PeriodSpendingFactory
by_agent = ()
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/budget/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def test_hard_stop_at_boundary_100(self) -> None:
def test_float_threshold_rejected(self) -> None:
"""Reject float value for threshold (strict int)."""
with pytest.raises(ValidationError):
BudgetAlertConfig(warn_at=75.5, critical_at=90, hard_stop_at=100)
BudgetAlertConfig(warn_at=75.5, critical_at=90, hard_stop_at=100) # type: ignore[arg-type]

def test_negative_threshold_rejected(self) -> None:
"""Reject negative threshold values."""
Expand Down Expand Up @@ -153,7 +153,7 @@ def test_duplicate_source_alias_rejected(self) -> None:
def test_float_threshold_rejected(self) -> None:
"""Reject float value for threshold (strict int)."""
with pytest.raises(ValidationError):
AutoDowngradeConfig(threshold=85.5)
AutoDowngradeConfig(threshold=85.5) # type: ignore[arg-type]

def test_threshold_boundary_0(self) -> None:
"""Accept threshold at lower boundary (0)."""
Expand Down
12 changes: 6 additions & 6 deletions tests/unit/budget/test_enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ def test_all_members_exist(self) -> None:

def test_values_are_strings(self) -> None:
"""Verify StrEnum produces string values."""
assert BudgetAlertLevel.NORMAL == "normal"
assert BudgetAlertLevel.WARNING == "warning"
assert BudgetAlertLevel.CRITICAL == "critical"
assert BudgetAlertLevel.HARD_STOP == "hard_stop"
assert BudgetAlertLevel.NORMAL.value == "normal"
assert BudgetAlertLevel.WARNING.value == "warning"
assert BudgetAlertLevel.CRITICAL.value == "critical"
assert BudgetAlertLevel.HARD_STOP.value == "hard_stop"

def test_membership(self) -> None:
"""Verify string-based membership check works."""
assert "normal" in BudgetAlertLevel.__members__.values()
assert "warning" in BudgetAlertLevel.__members__.values()
assert "normal" in [m.value for m in BudgetAlertLevel]
assert "warning" in [m.value for m in BudgetAlertLevel]
29 changes: 15 additions & 14 deletions tests/unit/communication/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
RateLimitConfig,
)
from ai_company.communication.enums import (
AttachmentType,
ChannelType,
MessagePriority,
MessageType,
Expand All @@ -26,11 +27,11 @@
# ── Factories ──────────────────────────────────────────────────────


class AttachmentFactory(ModelFactory):
class AttachmentFactory(ModelFactory[Attachment]):
__model__ = Attachment


class MessageMetadataFactory(ModelFactory):
class MessageMetadataFactory(ModelFactory[MessageMetadata]):
__model__ = MessageMetadata
task_id = None
project_id = None
Expand All @@ -39,52 +40,52 @@ class MessageMetadataFactory(ModelFactory):
extra = ()


class MessageFactory(ModelFactory):
class MessageFactory(ModelFactory[Message]):
__model__ = Message
priority = MessagePriority.NORMAL
attachments = ()
metadata = MessageMetadataFactory


class ChannelFactory(ModelFactory):
class ChannelFactory(ModelFactory[Channel]):
__model__ = Channel
type = ChannelType.TOPIC
subscribers = ()


class MessageBusConfigFactory(ModelFactory):
class MessageBusConfigFactory(ModelFactory[MessageBusConfig]):
__model__ = MessageBusConfig


class MeetingTypeConfigFactory(ModelFactory):
class MeetingTypeConfigFactory(ModelFactory[MeetingTypeConfig]):
__model__ = MeetingTypeConfig
frequency = "daily"
trigger = None


class MeetingsConfigFactory(ModelFactory):
class MeetingsConfigFactory(ModelFactory[MeetingsConfig]):
__model__ = MeetingsConfig
types = ()


class HierarchyConfigFactory(ModelFactory):
class HierarchyConfigFactory(ModelFactory[HierarchyConfig]):
__model__ = HierarchyConfig


class RateLimitConfigFactory(ModelFactory):
class RateLimitConfigFactory(ModelFactory[RateLimitConfig]):
__model__ = RateLimitConfig


class CircuitBreakerConfigFactory(ModelFactory):
class CircuitBreakerConfigFactory(ModelFactory[CircuitBreakerConfig]):
__model__ = CircuitBreakerConfig


class LoopPreventionConfigFactory(ModelFactory):
class LoopPreventionConfigFactory(ModelFactory[LoopPreventionConfig]):
__model__ = LoopPreventionConfig
ancestry_tracking = True


class CommunicationConfigFactory(ModelFactory):
class CommunicationConfigFactory(ModelFactory[CommunicationConfig]):
__model__ = CommunicationConfig
meetings = MeetingsConfigFactory
loop_prevention = LoopPreventionConfigFactory
Expand All @@ -95,7 +96,7 @@ class CommunicationConfigFactory(ModelFactory):

@pytest.fixture
def sample_attachment() -> Attachment:
return Attachment(type="artifact", ref="pr-42")
return Attachment(type=AttachmentType.ARTIFACT, ref="pr-42")


@pytest.fixture
Expand All @@ -118,7 +119,7 @@ def sample_message(sample_metadata: MessageMetadata) -> Message:
priority=MessagePriority.NORMAL,
channel="#backend",
content="Completed API endpoint for user authentication.",
attachments=(Attachment(type="artifact", ref="pr-42"),),
attachments=(Attachment(type=AttachmentType.ARTIFACT, ref="pr-42"),),
metadata=sample_metadata,
)

Expand Down
2 changes: 1 addition & 1 deletion tests/unit/communication/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ def test_ancestry_tracking_false_rejected(self) -> None:
ValidationError,
match="Input should be True",
):
LoopPreventionConfig(ancestry_tracking=False)
LoopPreventionConfig(ancestry_tracking=False) # type: ignore[arg-type]

def test_zero_delegation_depth_rejected(self) -> None:
with pytest.raises(ValidationError):
Expand Down
52 changes: 26 additions & 26 deletions tests/unit/communication/test_enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@ def test_member_count(self) -> None:
assert len(MessageType) == 8

def test_values(self) -> None:
assert MessageType.TASK_UPDATE == "task_update"
assert MessageType.QUESTION == "question"
assert MessageType.ANNOUNCEMENT == "announcement"
assert MessageType.REVIEW_REQUEST == "review_request"
assert MessageType.APPROVAL == "approval"
assert MessageType.DELEGATION == "delegation"
assert MessageType.STATUS_REPORT == "status_report"
assert MessageType.ESCALATION == "escalation"
assert MessageType.TASK_UPDATE.value == "task_update"
assert MessageType.QUESTION.value == "question"
assert MessageType.ANNOUNCEMENT.value == "announcement"
assert MessageType.REVIEW_REQUEST.value == "review_request"
assert MessageType.APPROVAL.value == "approval"
assert MessageType.DELEGATION.value == "delegation"
assert MessageType.STATUS_REPORT.value == "status_report"
assert MessageType.ESCALATION.value == "escalation"

def test_string_identity(self) -> None:
assert str(MessageType.TASK_UPDATE) == "task_update"
Expand All @@ -39,10 +39,10 @@ def test_member_count(self) -> None:
assert len(MessagePriority) == 4

def test_values(self) -> None:
assert MessagePriority.LOW == "low"
assert MessagePriority.NORMAL == "normal"
assert MessagePriority.HIGH == "high"
assert MessagePriority.URGENT == "urgent"
assert MessagePriority.LOW.value == "low"
assert MessagePriority.NORMAL.value == "normal"
assert MessagePriority.HIGH.value == "high"
assert MessagePriority.URGENT.value == "urgent"

def test_normal_not_medium(self) -> None:
"""Message priority uses 'normal', not 'medium' like task Priority."""
Expand All @@ -57,9 +57,9 @@ def test_member_count(self) -> None:
assert len(ChannelType) == 3

def test_values(self) -> None:
assert ChannelType.TOPIC == "topic"
assert ChannelType.DIRECT == "direct"
assert ChannelType.BROADCAST == "broadcast"
assert ChannelType.TOPIC.value == "topic"
assert ChannelType.DIRECT.value == "direct"
assert ChannelType.BROADCAST.value == "broadcast"


@pytest.mark.unit
Expand All @@ -68,9 +68,9 @@ def test_member_count(self) -> None:
assert len(AttachmentType) == 3

def test_values(self) -> None:
assert AttachmentType.ARTIFACT == "artifact"
assert AttachmentType.FILE == "file"
assert AttachmentType.LINK == "link"
assert AttachmentType.ARTIFACT.value == "artifact"
assert AttachmentType.FILE.value == "file"
assert AttachmentType.LINK.value == "link"


@pytest.mark.unit
Expand All @@ -79,10 +79,10 @@ def test_member_count(self) -> None:
assert len(CommunicationPattern) == 4

def test_values(self) -> None:
assert CommunicationPattern.EVENT_DRIVEN == "event_driven"
assert CommunicationPattern.HIERARCHICAL == "hierarchical"
assert CommunicationPattern.MEETING_BASED == "meeting_based"
assert CommunicationPattern.HYBRID == "hybrid"
assert CommunicationPattern.EVENT_DRIVEN.value == "event_driven"
assert CommunicationPattern.HIERARCHICAL.value == "hierarchical"
assert CommunicationPattern.MEETING_BASED.value == "meeting_based"
assert CommunicationPattern.HYBRID.value == "hybrid"


@pytest.mark.unit
Expand All @@ -100,7 +100,7 @@ def test_member_count(self) -> None:
assert len(MessageBusBackend) == 4

def test_values(self) -> None:
assert MessageBusBackend.INTERNAL == "internal"
assert MessageBusBackend.REDIS == "redis"
assert MessageBusBackend.RABBITMQ == "rabbitmq"
assert MessageBusBackend.KAFKA == "kafka"
assert MessageBusBackend.INTERNAL.value == "internal"
assert MessageBusBackend.REDIS.value == "redis"
assert MessageBusBackend.RABBITMQ.value == "rabbitmq"
assert MessageBusBackend.KAFKA.value == "kafka"
16 changes: 8 additions & 8 deletions tests/unit/config/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,35 +24,35 @@
# ── Factories ──────────────────────────────────────────────────────


class ProviderModelConfigFactory(ModelFactory):
class ProviderModelConfigFactory(ModelFactory[ProviderModelConfig]):
__model__ = ProviderModelConfig


class ProviderConfigFactory(ModelFactory):
class ProviderConfigFactory(ModelFactory[ProviderConfig]):
__model__ = ProviderConfig
models = ()


class RoutingRuleConfigFactory(ModelFactory):
class RoutingRuleConfigFactory(ModelFactory[RoutingRuleConfig]):
__model__ = RoutingRuleConfig


class RoutingConfigFactory(ModelFactory):
class RoutingConfigFactory(ModelFactory[RoutingConfig]):
__model__ = RoutingConfig
rules = ()
fallback_chain = ()


class AgentConfigFactory(ModelFactory):
class AgentConfigFactory(ModelFactory[AgentConfig]):
__model__ = AgentConfig


class RootConfigFactory(ModelFactory):
class RootConfigFactory(ModelFactory[RootConfig]):
__model__ = RootConfig
departments = ()
agents = ()
custom_roles = ()
providers: dict[str, ProviderConfig] = {} # type: ignore[assignment] # noqa: RUF012
providers: dict[str, ProviderConfig] = {} # noqa: RUF012
config = CompanyConfig()
budget = BudgetConfig()
communication = CommunicationConfig()
Expand Down Expand Up @@ -139,7 +139,7 @@ def sample_root_config() -> RootConfig:


@pytest.fixture
def tmp_config_file(tmp_path: Path) -> Callable[[str, str], Path]:
def tmp_config_file(tmp_path: Path) -> Callable[..., Path]:
def _create(content: str, name: str = "config.yaml") -> Path:
path = tmp_path / name
path.write_text(content, encoding="utf-8")
Expand Down
Loading