Skip to content

Commit ec7adb1

Browse files
committed
fix: correct FeatureUsageFlag to use IntFlag and return str from __str__
The FeatureUsageFlag enum has two issues: 1. The __str__ method returns self.value (an int) instead of a string, violating Python's data model requirement that __str__ must return str. This causes TypeError on all Python versions when calling str() on enum members. 2. The class inherits from (int, Enum) instead of IntFlag, even though the values are clearly bit flags (powers of 2). This prevents proper bitwise operations - combining flags with | returns plain int instead of FeatureUsageFlag. Changes Made: - Changed FeatureUsageFlag base class from (int, Enum) to IntFlag - Fixed __str__ to return str(self.value) instead of self.value - Added test suite for all enum classes
1 parent a33614f commit ec7adb1

File tree

2 files changed

+117
-3
lines changed

2 files changed

+117
-3
lines changed

src/msgraph_core/_enums.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# ------------------------------------
55
#pylint: disable=invalid-name
66

7-
from enum import Enum
7+
from enum import Enum, IntFlag
88

99

1010
class APIVersion(str, Enum):
@@ -16,7 +16,7 @@ def __str__(self):
1616
return self.value
1717

1818

19-
class FeatureUsageFlag(int, Enum):
19+
class FeatureUsageFlag(IntFlag):
2020
"""Enumerated list of values used to flag usage of specific middleware"""
2121

2222
NONE = 0
@@ -27,7 +27,7 @@ class FeatureUsageFlag(int, Enum):
2727
LOGGING_HANDLER_ENABLED = 16
2828

2929
def __str__(self):
30-
return self.value
30+
return str(self.value)
3131

3232

3333
class NationalClouds(str, Enum):

tests/test_enums.py

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
"""Tests for msgraph_core._enums module."""
2+
from enum import Enum, IntFlag
3+
4+
from msgraph_core._enums import APIVersion, FeatureUsageFlag, NationalClouds
5+
6+
7+
def test_feature_usage_flag_str_returns_string_type():
8+
"""__str__() must return str, not int (Python data model requirement)."""
9+
for flag in FeatureUsageFlag:
10+
result = str(flag)
11+
assert isinstance(result, str), (
12+
f"str({flag.name}) returned {type(result).__name__}, expected str"
13+
)
14+
15+
16+
def test_feature_usage_flag_str_returns_numeric_value_as_string():
17+
"""__str__() should return the numeric value as a string."""
18+
assert str(FeatureUsageFlag.NONE) == "0"
19+
assert str(FeatureUsageFlag.REDIRECT_HANDLER_ENABLED) == "1"
20+
assert str(FeatureUsageFlag.RETRY_HANDLER_ENABLED) == "2"
21+
assert str(FeatureUsageFlag.AUTH_HANDLER_ENABLED) == "4"
22+
assert str(FeatureUsageFlag.DEFAULT_HTTP_PROVIDER_ENABLED) == "8"
23+
assert str(FeatureUsageFlag.LOGGING_HANDLER_ENABLED) == "16"
24+
25+
26+
def test_feature_usage_flag_is_intflag():
27+
"""FeatureUsageFlag should be an IntFlag for proper bitwise operations."""
28+
assert issubclass(FeatureUsageFlag, IntFlag)
29+
30+
31+
def test_feature_usage_flag_is_int_instance():
32+
"""FeatureUsageFlag members should be instances of int."""
33+
for flag in FeatureUsageFlag:
34+
assert isinstance(flag, int)
35+
36+
37+
def test_feature_usage_flag_is_enum_instance():
38+
"""FeatureUsageFlag members should be instances of Enum."""
39+
for flag in FeatureUsageFlag:
40+
assert isinstance(flag, Enum)
41+
42+
43+
def test_feature_usage_flag_bitwise_or_returns_feature_usage_flag():
44+
"""Bitwise OR should return FeatureUsageFlag, not plain int."""
45+
combined = FeatureUsageFlag.REDIRECT_HANDLER_ENABLED | FeatureUsageFlag.RETRY_HANDLER_ENABLED
46+
assert isinstance(combined, FeatureUsageFlag)
47+
assert combined.value == 3
48+
49+
50+
def test_feature_usage_flag_bitwise_and_returns_feature_usage_flag():
51+
"""Bitwise AND should return FeatureUsageFlag, not plain int."""
52+
combined = FeatureUsageFlag.REDIRECT_HANDLER_ENABLED | FeatureUsageFlag.RETRY_HANDLER_ENABLED
53+
result = combined & FeatureUsageFlag.REDIRECT_HANDLER_ENABLED
54+
assert isinstance(result, FeatureUsageFlag)
55+
assert result.value == 1
56+
57+
58+
def test_feature_usage_flag_bitwise_xor_returns_feature_usage_flag():
59+
"""Bitwise XOR should return FeatureUsageFlag, not plain int."""
60+
combined = FeatureUsageFlag.REDIRECT_HANDLER_ENABLED | FeatureUsageFlag.RETRY_HANDLER_ENABLED
61+
result = combined ^ FeatureUsageFlag.REDIRECT_HANDLER_ENABLED
62+
assert isinstance(result, FeatureUsageFlag)
63+
assert result.value == 2
64+
65+
66+
def test_feature_usage_flag_bitwise_invert_returns_feature_usage_flag():
67+
"""Bitwise invert should return FeatureUsageFlag, not plain int."""
68+
result = ~FeatureUsageFlag.NONE
69+
assert isinstance(result, FeatureUsageFlag)
70+
71+
72+
def test_feature_usage_flag_combined_flags_str():
73+
"""Combined flags should also return string from __str__()."""
74+
combined = FeatureUsageFlag.REDIRECT_HANDLER_ENABLED | FeatureUsageFlag.RETRY_HANDLER_ENABLED
75+
result = str(combined)
76+
assert isinstance(result, str)
77+
assert result == "3"
78+
79+
80+
def test_feature_usage_flag_values_are_powers_of_two():
81+
"""Flag values should be powers of 2 (except NONE=0) for proper bitmask behavior."""
82+
assert FeatureUsageFlag.NONE.value == 0
83+
assert FeatureUsageFlag.REDIRECT_HANDLER_ENABLED.value == 1
84+
assert FeatureUsageFlag.RETRY_HANDLER_ENABLED.value == 2
85+
assert FeatureUsageFlag.AUTH_HANDLER_ENABLED.value == 4
86+
assert FeatureUsageFlag.DEFAULT_HTTP_PROVIDER_ENABLED.value == 8
87+
assert FeatureUsageFlag.LOGGING_HANDLER_ENABLED.value == 16
88+
89+
90+
def test_api_version_str_returns_string_type():
91+
"""__str__() must return str."""
92+
for version in APIVersion:
93+
result = str(version)
94+
assert isinstance(result, str)
95+
96+
97+
def test_api_version_str_returns_value():
98+
"""__str__() should return the enum value."""
99+
assert str(APIVersion.beta) == "beta"
100+
assert str(APIVersion.v1) == "v1.0"
101+
102+
103+
def test_national_clouds_str_returns_string_type():
104+
"""__str__() must return str."""
105+
for cloud in NationalClouds:
106+
result = str(cloud)
107+
assert isinstance(result, str)
108+
109+
110+
def test_national_clouds_str_returns_url_value():
111+
"""__str__() should return the cloud URL."""
112+
assert str(NationalClouds.Global) == "https://graph.microsoft.com"
113+
assert str(NationalClouds.US_GOV) == "https://graph.microsoft.us"
114+
assert str(NationalClouds.China) == "https://microsoftgraph.chinacloudapi.cn"

0 commit comments

Comments
 (0)