Skip to content

Commit d5d54df

Browse files
committed
CI: try with 3.11 and 3.12
Fix python/cpython#100458 Fix a pandas incompatibility commit-id:f0b690de
1 parent ea524b3 commit d5d54df

6 files changed

Lines changed: 88 additions & 86 deletions

File tree

.github/workflows/reusable-precommit.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,8 @@ jobs:
101101
- "3.8"
102102
- "3.9"
103103
- "3.10"
104+
- "3.11"
105+
- "3.12"
104106
integration_tests:
105107
runs-on: ubuntu-latest
106108
needs:
@@ -148,6 +150,8 @@ jobs:
148150
- "3.8"
149151
- "3.9"
150152
- "3.10"
153+
- "3.11"
154+
- "3.12"
151155
doc_tests:
152156
runs-on: ubuntu-latest
153157
needs:

pybatfish/client/asserts.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -134,20 +134,11 @@ def _get_duplicate_router_ids(
134134
.frame()
135135
)
136136
if ignore_same_node:
137-
# Maps Router_ID to whether multiple nodes have that Router_ID
138-
router_id_on_duplicate_nodes = (
139-
df.drop_duplicates(["Node", "Router_ID"])
140-
.value_counts(["Router_ID"])
141-
.map(lambda x: x > 1)
137+
return df.groupby("Router_ID").filter(
138+
lambda x: x["Node"].nunique() > 1 and x["Node"].nunique() != len(x)
142139
)
143-
df_duplicate = df[
144-
df.apply(lambda x: router_id_on_duplicate_nodes[x["Router_ID"]], axis=1)
145-
].sort_values(["Router_ID"])
146140
else:
147-
df_duplicate = df[df.duplicated(["Router_ID"], keep=False)].sort_values(
148-
["Router_ID"]
149-
)
150-
return df_duplicate
141+
return df[df.duplicated(["Router_ID"], keep=False)].sort_values(["Router_ID"])
151142

152143

153144
def _is_dict_match(actual: Dict[str, Any], expected: Dict[str, Any]) -> bool:
@@ -782,7 +773,7 @@ def assert_no_duplicate_router_ids(
782773

783774
supported_protocols = {"bgp", "ospf"}
784775
protocols_to_fetch = (
785-
supported_protocols if protocols is None else set(map(str.lower, protocols))
776+
supported_protocols if protocols is None else set(p.lower() for p in protocols)
786777
)
787778
if not protocols_to_fetch.issubset(supported_protocols):
788779
raise ValueError(

pybatfish/client/restv2helper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ def auto_complete(
630630
if session.snapshot
631631
else "",
632632
CoordConstsV2.RSC_AUTOCOMPLETE,
633-
completion_type,
633+
completion_type.value,
634634
)
635635
params = {} # type: Dict[str, Any]
636636
if query:

pybatfish/question/question.py

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ def _validate(questionJson):
712712
else:
713713
for i in range(0, len(value)):
714714
valueElement = value[i]
715-
typeValid = _validateType(valueElement, variableType)
715+
typeValid = _validate_type(valueElement, variableType)
716716
if not typeValid:
717717
valid = False
718718
errorMessage += (
@@ -750,7 +750,7 @@ def _validate(questionJson):
750750
)
751751

752752
else:
753-
typeValid, typeValidErrorMessage = _validateType(
753+
typeValid, typeValidErrorMessage = _validate_type(
754754
value, variableType
755755
)
756756
if not typeValid:
@@ -796,7 +796,9 @@ def _validate(questionJson):
796796
return True
797797

798798

799-
def _validateType(value, expectedType):
799+
def _validate_type(
800+
value: Any, expected_type: Union[str, VariableType]
801+
) -> Tuple[bool, Optional[str]]:
800802
"""
801803
Check if the input `value` have contents that matches the requirements specified by `expectedType`.
802804
@@ -805,28 +807,31 @@ def _validateType(value, expectedType):
805807
806808
:raises QuestionValidationException
807809
"""
808-
if expectedType == VariableType.BOOLEAN:
810+
if not isinstance(expected_type, VariableType):
811+
expected_type = VariableType(expected_type)
812+
813+
if expected_type == VariableType.BOOLEAN:
809814
return isinstance(value, bool), None
810-
elif expectedType == VariableType.COMPARATOR:
811-
validComparators = ["<", "<=", "==", ">=", ">", "!="]
812-
if value not in validComparators:
815+
elif expected_type == VariableType.COMPARATOR:
816+
valid_comparators = ["<", "<=", "==", ">=", ">", "!="]
817+
if value not in valid_comparators:
813818
return (
814819
False,
815820
"'{}' is not a known comparator. Valid options are: '{}'".format(
816-
value, ", ".join(validComparators)
821+
value, ", ".join(valid_comparators)
817822
),
818823
)
819824
return True, None
820-
elif expectedType == VariableType.INTEGER:
825+
elif expected_type == VariableType.INTEGER:
821826
INT32_MIN = -(2**32)
822827
INT32_MAX = 2**32 - 1
823828
valid = isinstance(value, int) and INT32_MIN <= value <= INT32_MAX
824829
return valid, None
825-
elif expectedType == VariableType.FLOAT:
830+
elif expected_type == VariableType.FLOAT:
826831
return isinstance(value, float), None
827-
elif expectedType == VariableType.DOUBLE:
832+
elif expected_type == VariableType.DOUBLE:
828833
return isinstance(value, float), None
829-
elif expectedType in [
834+
elif expected_type in [
830835
VariableType.ADDRESS_GROUP_NAME,
831836
VariableType.APPLICATION_SPEC,
832837
VariableType.BGP_PEER_PROPERTY_SPEC,
@@ -868,46 +873,46 @@ def _validateType(value, expectedType):
868873
VariableType.ZONE,
869874
]:
870875
if not isinstance(value, str):
871-
return False, f"A Batfish {expectedType} must be a string"
876+
return False, f"A Batfish {expected_type.value} must be a string"
872877
return True, None
873-
elif expectedType == VariableType.IP:
878+
elif expected_type == VariableType.IP:
874879
if not isinstance(value, str):
875-
return False, f"A Batfish {expectedType} must be a string"
880+
return False, f"A Batfish {expected_type.value} must be a string"
876881
else:
877882
return _isIp(value)
878-
elif expectedType == VariableType.IP_WILDCARD:
883+
elif expected_type == VariableType.IP_WILDCARD:
879884
if not isinstance(value, str):
880-
return False, f"A Batfish {expectedType} must be a string"
885+
return False, f"A Batfish {expected_type.value} must be a string"
881886
else:
882887
return _isIpWildcard(value)
883-
elif expectedType == VariableType.JSON_PATH:
888+
elif expected_type == VariableType.JSON_PATH:
884889
return _isJsonPath(value)
885-
elif expectedType == VariableType.LONG:
890+
elif expected_type == VariableType.LONG:
886891
INT64_MIN = -(2**64)
887892
INT64_MAX = 2**64 - 1
888893
valid = isinstance(value, int) and INT64_MIN <= value <= INT64_MAX
889894
return valid, None
890-
elif expectedType == VariableType.PREFIX:
895+
elif expected_type == VariableType.PREFIX:
891896
if not isinstance(value, str):
892-
return False, f"A Batfish {expectedType} must be a string"
897+
return False, f"A Batfish {expected_type.value} must be a string"
893898
else:
894899
return _isPrefix(value)
895-
elif expectedType == VariableType.PREFIX_RANGE:
900+
elif expected_type == VariableType.PREFIX_RANGE:
896901
if not isinstance(value, str):
897-
return False, f"A Batfish {expectedType} must be a string"
902+
return False, f"A Batfish {expected_type.value} must be a string"
898903
else:
899904
return _isPrefixRange(value)
900-
elif expectedType == VariableType.QUESTION:
905+
elif expected_type == VariableType.QUESTION:
901906
return isinstance(value, QuestionBase), None
902-
elif expectedType == VariableType.BGP_ROUTES:
907+
elif expected_type == VariableType.BGP_ROUTES:
903908
if not isinstance(value, list) or not all(
904909
isinstance(r, BgpRoute) for r in value
905910
):
906-
return False, f"A Batfish {expectedType} must be a list of BgpRoute"
911+
return False, f"A Batfish {expected_type.value} must be a list of BgpRoute"
907912
return True, None
908-
elif expectedType == VariableType.STRING:
913+
elif expected_type == VariableType.STRING:
909914
return isinstance(value, str), None
910-
elif expectedType == VariableType.SUBRANGE:
915+
elif expected_type == VariableType.SUBRANGE:
911916
if isinstance(value, int):
912917
return True, None
913918
elif isinstance(value, str):
@@ -916,12 +921,12 @@ def _validateType(value, expectedType):
916921
return (
917922
False,
918923
"A Batfish {} must either be a string or an integer".format(
919-
expectedType
924+
expected_type.value
920925
),
921926
)
922-
elif expectedType == VariableType.PROTOCOL:
927+
elif expected_type == VariableType.PROTOCOL:
923928
if not isinstance(value, str):
924-
return False, f"A Batfish {expectedType} must be a string"
929+
return False, f"A Batfish {expected_type.value} must be a string"
925930
else:
926931
validProtocols = ["dns", "ssh", "tcp", "udp"]
927932
if not value.lower() in validProtocols:
@@ -932,9 +937,9 @@ def _validateType(value, expectedType):
932937
),
933938
)
934939
return True, None
935-
elif expectedType == VariableType.IP_PROTOCOL:
940+
elif expected_type == VariableType.IP_PROTOCOL:
936941
if not isinstance(value, str):
937-
return False, f"A Batfish {expectedType} must be a string"
942+
return False, f"A Batfish {expected_type.value} must be a string"
938943
else:
939944
try:
940945
intValue = int(value)
@@ -947,7 +952,7 @@ def _validateType(value, expectedType):
947952
except ValueError:
948953
# TODO: Should be validated at server side
949954
return True, None
950-
elif expectedType in [
955+
elif expected_type in [
951956
VariableType.ANSWER_ELEMENT,
952957
VariableType.BGP_ROUTE_CONSTRAINTS,
953958
VariableType.HEADER_CONSTRAINT,
@@ -957,13 +962,13 @@ def _validateType(value, expectedType):
957962
else:
958963
logging.getLogger(__name__).warning(
959964
"WARNING: skipping validation for unknown argument type {}".format(
960-
expectedType
965+
expected_type.value
961966
)
962967
)
963968
return True, None
964969

965970

966-
def _isJsonPath(value):
971+
def _isJsonPath(value: Any) -> Tuple[bool, Optional[str]]:
967972
"""
968973
Check if the input string represents a valid jsonPath.
969974
@@ -991,7 +996,7 @@ def _isJsonPath(value):
991996
return True, None
992997

993998

994-
def _isIp(value):
999+
def _isIp(value: str) -> Tuple[bool, Optional[str]]:
9951000
"""
9961001
Check if the input string represents a valid IP address.
9971002
@@ -1040,7 +1045,7 @@ def _isIp(value):
10401045
return True, None
10411046

10421047

1043-
def _isSubRange(value):
1048+
def _isSubRange(value: str) -> Tuple[bool, Optional[str]]:
10441049
"""
10451050
Check if the input string represents a valid subRange.
10461051
@@ -1061,7 +1066,7 @@ def _isSubRange(value):
10611066
return True, None
10621067

10631068

1064-
def _isPrefix(value):
1069+
def _isPrefix(value: str) -> Tuple[bool, Optional[str]]:
10651070
"""
10661071
Check if the input string represents a valid prefix.
10671072
@@ -1081,7 +1086,7 @@ def _isPrefix(value):
10811086
return _isIp(contents[0])
10821087

10831088

1084-
def _isPrefixRange(value):
1089+
def _isPrefixRange(value: str) -> Tuple[bool, Optional[str]]:
10851090
"""
10861091
Check if the input string represents a valid prefix range.
10871092
@@ -1105,7 +1110,7 @@ def _isPrefixRange(value):
11051110
return True, None
11061111

11071112

1108-
def _isIpWildcard(value):
1113+
def _isIpWildcard(value: str) -> Tuple[bool, Optional[str]]:
11091114
"""
11101115
Check if the input string represents a valid ipWildCard.
11111116

setup.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@
7474
"Programming Language :: Python :: 3.8",
7575
"Programming Language :: Python :: 3.9",
7676
"Programming Language :: Python :: 3.10",
77+
"Programming Language :: Python :: 3.11",
78+
"Programming Language :: Python :: 3.12",
7779
],
7880
python_requires=">=3.8",
7981
# What does your project relate to?

0 commit comments

Comments
 (0)