def test_altitude_ok():
    """
    Assert that an impossible altitude is invalid.
    """
    fields = src_fields.copy()
    fields["altitude"] = 9000
    with pytest.raises(ValidationError):
        School.parse_obj(fields)
def test_required_fields():
    """
    Assert that removing a required field is invalid.
    """
    src_missing_fields = src_fields.copy()
    src_missing_fields["provider"] = None  # clear a required field
    with pytest.raises(ValidationError):
        School.parse_obj(src_missing_fields)
def test_tower_location_not_null_island():
    """
   Assert that tower_latitude, lower_longitude of 0,0 is never valid.
   """
    fields = src_fields.copy()
    fields["tower_latitude"] = 0.0
    fields["tower_longitude"] = 0.0
    with pytest.raises(ValidationError):
        School.parse_obj(fields)
def test_location_not_null_island():
    """
    Assert that lat,lng of 0,0 is never valid.
    """
    fields = src_fields.copy()
    fields["lat"] = 0.0
    fields["lon"] = 0.0
    with pytest.raises(ValidationError):
        School.parse_obj(fields)
def _dataframe_filter(row: Series) -> Optional[Series]:
    """
    Pandas filter for schools data cleaning. Use with DataFrame.apply(func=)
    Note: returns Series of dtype=object so it is recommended to call dataframe.convert_dtypes() or other method of
    restoring correct dtypes in Pandas.

    :param row: pandas series of one school row
    :return: validated School record
    """
    try:
        s = School.parse_obj(row.to_dict())
        s.is_invalid = False
        s.is_invalid_reason = None
        data = s.dict()
        return Series(data=data, dtype=object)
    except ValidationError as err:
        invalid_row = row.copy()
        invalid_row["is_invalid"] = True
        invalid_row["is_invalid_reason"] = str(err)
        return invalid_row
def test_latency_connectivity():
    """
    Assert that an impossible Internet latency value is invalid.
    """
    fields = src_fields.copy()
    fields["latency_connectivity"] = 100  # ms
    School.parse_obj(fields)

    fields["latency_connectivity"] = -100
    with pytest.raises(ValidationError):
        School.parse_obj(fields)

    fields["latency_connectivity"] = 6000
    with pytest.raises(ValidationError):
        School.parse_obj(fields)
def test_country_code():
    """
    Assert that an bad ISO country code is invalid.
    """
    fields = src_fields.copy()
    fields["country_code"] = "MX"  # Mexico
    School.parse_obj(fields)

    fields[
        "country_code"] = "ZY"  # unassigned code per https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#ES
    with pytest.raises(ValidationError):
        School.parse_obj(fields)

    fields["country_code"] = "*(&"
    with pytest.raises(ValidationError):
        School.parse_obj(fields)
def test_speed_connectivity():
    """
    Assert that an impossible Internet bandwidth value is invalid.
    """
    fields = src_fields.copy()
    fields["speed_connectivity"] = 99999
    School.parse_obj(fields)

    fields["speed_connectivity"] = 10000000
    School.parse_obj(fields)

    # 0 is coerced to None
    fields["speed_connectivity"] = 0.0
    school = School.parse_obj(fields)
    assert school.speed_connectivity is None

    # out of range is invalid
    fields["speed_connectivity"] = 99900000
    with pytest.raises(ValidationError):
        School.parse_obj(fields)
def test_enumerated_field():
    src = src_fields.copy()
    src["type_connectivity"] = "2G"  # set enumerated value field to something legit
    School.parse_obj(src)
def test_school_constructor():
    """
    Assert the School constructor basically works.
    """
    School.parse_obj(src_fields)