Skip to content

Commit

Permalink
Update and add support for 3.11 and 3.12 (#902)
Browse files Browse the repository at this point in the history
Fix python/cpython#100458

Fix a pandas incompatibility

commit-id:f0b690de
  • Loading branch information
dhalperi authored Dec 16, 2023
1 parent ea524b3 commit e238298
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 86 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/reusable-precommit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ jobs:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
integration_tests:
runs-on: ubuntu-latest
needs:
Expand Down Expand Up @@ -148,6 +150,8 @@ jobs:
- "3.8"
- "3.9"
- "3.10"
- "3.11"
- "3.12"
doc_tests:
runs-on: ubuntu-latest
needs:
Expand Down
17 changes: 4 additions & 13 deletions pybatfish/client/asserts.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,20 +134,11 @@ def _get_duplicate_router_ids(
.frame()
)
if ignore_same_node:
# Maps Router_ID to whether multiple nodes have that Router_ID
router_id_on_duplicate_nodes = (
df.drop_duplicates(["Node", "Router_ID"])
.value_counts(["Router_ID"])
.map(lambda x: x > 1)
return df.groupby("Router_ID").filter(
lambda x: x["Node"].nunique() > 1 and x["Node"].nunique() != len(x)
)
df_duplicate = df[
df.apply(lambda x: router_id_on_duplicate_nodes[x["Router_ID"]], axis=1)
].sort_values(["Router_ID"])
else:
df_duplicate = df[df.duplicated(["Router_ID"], keep=False)].sort_values(
["Router_ID"]
)
return df_duplicate
return df[df.duplicated(["Router_ID"], keep=False)].sort_values(["Router_ID"])


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

supported_protocols = {"bgp", "ospf"}
protocols_to_fetch = (
supported_protocols if protocols is None else set(map(str.lower, protocols))
supported_protocols if protocols is None else set(p.lower() for p in protocols)
)
if not protocols_to_fetch.issubset(supported_protocols):
raise ValueError(
Expand Down
2 changes: 1 addition & 1 deletion pybatfish/client/restv2helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ def auto_complete(
if session.snapshot
else "",
CoordConstsV2.RSC_AUTOCOMPLETE,
completion_type,
completion_type.value,
)
params = {} # type: Dict[str, Any]
if query:
Expand Down
87 changes: 46 additions & 41 deletions pybatfish/question/question.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,7 @@ def _validate(questionJson):
else:
for i in range(0, len(value)):
valueElement = value[i]
typeValid = _validateType(valueElement, variableType)
typeValid = _validate_type(valueElement, variableType)
if not typeValid:
valid = False
errorMessage += (
Expand Down Expand Up @@ -750,7 +750,7 @@ def _validate(questionJson):
)

else:
typeValid, typeValidErrorMessage = _validateType(
typeValid, typeValidErrorMessage = _validate_type(
value, variableType
)
if not typeValid:
Expand Down Expand Up @@ -796,7 +796,9 @@ def _validate(questionJson):
return True


def _validateType(value, expectedType):
def _validate_type(
value: Any, expected_type: Union[str, VariableType]
) -> Tuple[bool, Optional[str]]:
"""
Check if the input `value` have contents that matches the requirements specified by `expectedType`.
Expand All @@ -805,28 +807,31 @@ def _validateType(value, expectedType):
:raises QuestionValidationException
"""
if expectedType == VariableType.BOOLEAN:
if not isinstance(expected_type, VariableType):
expected_type = VariableType(expected_type)

if expected_type == VariableType.BOOLEAN:
return isinstance(value, bool), None
elif expectedType == VariableType.COMPARATOR:
validComparators = ["<", "<=", "==", ">=", ">", "!="]
if value not in validComparators:
elif expected_type == VariableType.COMPARATOR:
valid_comparators = ["<", "<=", "==", ">=", ">", "!="]
if value not in valid_comparators:
return (
False,
"'{}' is not a known comparator. Valid options are: '{}'".format(
value, ", ".join(validComparators)
value, ", ".join(valid_comparators)
),
)
return True, None
elif expectedType == VariableType.INTEGER:
elif expected_type == VariableType.INTEGER:
INT32_MIN = -(2**32)
INT32_MAX = 2**32 - 1
valid = isinstance(value, int) and INT32_MIN <= value <= INT32_MAX
return valid, None
elif expectedType == VariableType.FLOAT:
elif expected_type == VariableType.FLOAT:
return isinstance(value, float), None
elif expectedType == VariableType.DOUBLE:
elif expected_type == VariableType.DOUBLE:
return isinstance(value, float), None
elif expectedType in [
elif expected_type in [
VariableType.ADDRESS_GROUP_NAME,
VariableType.APPLICATION_SPEC,
VariableType.BGP_PEER_PROPERTY_SPEC,
Expand Down Expand Up @@ -868,46 +873,46 @@ def _validateType(value, expectedType):
VariableType.ZONE,
]:
if not isinstance(value, str):
return False, f"A Batfish {expectedType} must be a string"
return False, f"A Batfish {expected_type.value} must be a string"
return True, None
elif expectedType == VariableType.IP:
elif expected_type == VariableType.IP:
if not isinstance(value, str):
return False, f"A Batfish {expectedType} must be a string"
return False, f"A Batfish {expected_type.value} must be a string"
else:
return _isIp(value)
elif expectedType == VariableType.IP_WILDCARD:
elif expected_type == VariableType.IP_WILDCARD:
if not isinstance(value, str):
return False, f"A Batfish {expectedType} must be a string"
return False, f"A Batfish {expected_type.value} must be a string"
else:
return _isIpWildcard(value)
elif expectedType == VariableType.JSON_PATH:
elif expected_type == VariableType.JSON_PATH:
return _isJsonPath(value)
elif expectedType == VariableType.LONG:
elif expected_type == VariableType.LONG:
INT64_MIN = -(2**64)
INT64_MAX = 2**64 - 1
valid = isinstance(value, int) and INT64_MIN <= value <= INT64_MAX
return valid, None
elif expectedType == VariableType.PREFIX:
elif expected_type == VariableType.PREFIX:
if not isinstance(value, str):
return False, f"A Batfish {expectedType} must be a string"
return False, f"A Batfish {expected_type.value} must be a string"
else:
return _isPrefix(value)
elif expectedType == VariableType.PREFIX_RANGE:
elif expected_type == VariableType.PREFIX_RANGE:
if not isinstance(value, str):
return False, f"A Batfish {expectedType} must be a string"
return False, f"A Batfish {expected_type.value} must be a string"
else:
return _isPrefixRange(value)
elif expectedType == VariableType.QUESTION:
elif expected_type == VariableType.QUESTION:
return isinstance(value, QuestionBase), None
elif expectedType == VariableType.BGP_ROUTES:
elif expected_type == VariableType.BGP_ROUTES:
if not isinstance(value, list) or not all(
isinstance(r, BgpRoute) for r in value
):
return False, f"A Batfish {expectedType} must be a list of BgpRoute"
return False, f"A Batfish {expected_type.value} must be a list of BgpRoute"
return True, None
elif expectedType == VariableType.STRING:
elif expected_type == VariableType.STRING:
return isinstance(value, str), None
elif expectedType == VariableType.SUBRANGE:
elif expected_type == VariableType.SUBRANGE:
if isinstance(value, int):
return True, None
elif isinstance(value, str):
Expand All @@ -916,12 +921,12 @@ def _validateType(value, expectedType):
return (
False,
"A Batfish {} must either be a string or an integer".format(
expectedType
expected_type.value
),
)
elif expectedType == VariableType.PROTOCOL:
elif expected_type == VariableType.PROTOCOL:
if not isinstance(value, str):
return False, f"A Batfish {expectedType} must be a string"
return False, f"A Batfish {expected_type.value} must be a string"
else:
validProtocols = ["dns", "ssh", "tcp", "udp"]
if not value.lower() in validProtocols:
Expand All @@ -932,9 +937,9 @@ def _validateType(value, expectedType):
),
)
return True, None
elif expectedType == VariableType.IP_PROTOCOL:
elif expected_type == VariableType.IP_PROTOCOL:
if not isinstance(value, str):
return False, f"A Batfish {expectedType} must be a string"
return False, f"A Batfish {expected_type.value} must be a string"
else:
try:
intValue = int(value)
Expand All @@ -947,7 +952,7 @@ def _validateType(value, expectedType):
except ValueError:
# TODO: Should be validated at server side
return True, None
elif expectedType in [
elif expected_type in [
VariableType.ANSWER_ELEMENT,
VariableType.BGP_ROUTE_CONSTRAINTS,
VariableType.HEADER_CONSTRAINT,
Expand All @@ -957,13 +962,13 @@ def _validateType(value, expectedType):
else:
logging.getLogger(__name__).warning(
"WARNING: skipping validation for unknown argument type {}".format(
expectedType
expected_type.value
)
)
return True, None


def _isJsonPath(value):
def _isJsonPath(value: Any) -> Tuple[bool, Optional[str]]:
"""
Check if the input string represents a valid jsonPath.
Expand Down Expand Up @@ -991,7 +996,7 @@ def _isJsonPath(value):
return True, None


def _isIp(value):
def _isIp(value: str) -> Tuple[bool, Optional[str]]:
"""
Check if the input string represents a valid IP address.
Expand Down Expand Up @@ -1040,7 +1045,7 @@ def _isIp(value):
return True, None


def _isSubRange(value):
def _isSubRange(value: str) -> Tuple[bool, Optional[str]]:
"""
Check if the input string represents a valid subRange.
Expand All @@ -1061,7 +1066,7 @@ def _isSubRange(value):
return True, None


def _isPrefix(value):
def _isPrefix(value: str) -> Tuple[bool, Optional[str]]:
"""
Check if the input string represents a valid prefix.
Expand All @@ -1081,7 +1086,7 @@ def _isPrefix(value):
return _isIp(contents[0])


def _isPrefixRange(value):
def _isPrefixRange(value: str) -> Tuple[bool, Optional[str]]:
"""
Check if the input string represents a valid prefix range.
Expand All @@ -1105,7 +1110,7 @@ def _isPrefixRange(value):
return True, None


def _isIpWildcard(value):
def _isIpWildcard(value: str) -> Tuple[bool, Optional[str]]:
"""
Check if the input string represents a valid ipWildCard.
Expand Down
2 changes: 2 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
],
python_requires=">=3.8",
# What does your project relate to?
Expand Down
Loading

0 comments on commit e238298

Please sign in to comment.