示例#1
0
def test_numpy_nan_like_lengths():
    """ Test that a strange int length with bad behaviour is correctly handled """

    # Actually the test below shows that in current versions of python it is not possible to create a len

    class NanInt(int):
        """
        An int that behaves like numpy NaN (comparison always returns false)
        """
        def __le__(self, other):
            return False

        def __lt__(self, other):
            return False

        def __gt__(self, other):
            return False

        def __ge__(self, other):
            return False

    nanlength = NanInt()

    class Foo:
        def __len__(self):
            return nanlength

    if isinstance(len(Foo()), NanInt):
        # in current version of python this does not happen, but the test is ready for future evolutions
        with pytest.raises(ValidationError) as exc_info:
            validate('Foo()', Foo(), min_len=0, max_len=10)
示例#2
0
def test_numpy_nan():
    """ Test that a numpy nan is correctly handled """

    import numpy as np

    with pytest.raises(ValidationError) as exc_info:
        validate('np.nan', np.nan, min_value=5.1, max_value=5.2)
示例#3
0
    def yield_helper(
        self,
    ) -> Generator["GameInputRequest", "GameInputRequest", "GameInputRequest"]:
        """
        A helper generator that yields this input request with validation.

        It yields a single object ``self``. When execution resumes, it checks that
        ``self`` was sent back and was fulfilled. Finally, if validation completes
        successfully, the return value of the generator is, again, ``self``.
        """
        completed = yield self
        valid8.validate(
            "completed_step",
            completed,
            custom=lambda o: o is self,
            help_msg=(
                f"Did not receive the same GameInputRequest that was yielded: "
                f"expected {self}, got {completed}"),
        )
        valid8.validate(
            "completed_step",
            completed,
            custom=lambda r: r.fulfilled,
            help_msg="Received an unfulfilled GameInputRequest step",
        )
        return completed
示例#4
0
    def validate(
            cls,
            name,  # type: str
            val):
        """
        Class method that can be used to check if some value is valid. A name should be provided so that the
        error messages are human-friendly.

        :param name:
        :param val:
        :return:
        """
        # validate type
        for typ in cls.__type__:
            validate(name,
                     val,
                     instance_of=typ,
                     help_msg=cls.__help_msg__,
                     error_type=cls.__error_type__)

        # apply validators
        if cls._validator is not None:
            cls._validator.assert_valid(name,
                                        val,
                                        help_msg=cls.__help_msg__,
                                        error_type=cls.__error_type__)
示例#5
0
    def start(self, first_player: RoundPlayer = None) -> "Turn":
        """
        Start the round: hand out one card to each player and start the first turn.

        Can only be called once in the lifetime of a round object. If there aren't
        sufficient cards to start the round or the end condition is met immediately
        after starting, an error is raised.

        :param first_player: First player that will play in this round. None means
                             choose at random.
        """
        super().start()

        if first_player is None:
            first_player = random.choice(self.players)
        else:
            valid8.validate(
                "first_player",
                first_player,
                is_in=self.players,
                help_msg="Not a player of this round",
            )

        with valid8.validation(
                "round",
                self,
                help_msg="Invalid initial state for starting the round"):
            for player in itertools.islice(
                    cycle_from(self.players, first_player), None,
                    self.num_players + 1):
                self.deal_card(player)
            self._check_post_start()

        self.state = turn = Turn(first_player, turn_no=1)
        return turn
示例#6
0
def test_validate_():
    """ Tests the validate function """

    # nominal
    surf = 2
    validate('surface', surf, instance_of=int, min_value=0)
    validate('surface', surf, instance_of=(int, ), min_value=0)
    validate('surface', surf, instance_of=(int, str), min_value=0)

    # error wrong value
    surf = -1
    with pytest.raises(ValidationError) as exc_info:
        validate('surface', surf, instance_of=int, min_value=0)
    e = exc_info.value
    assert str(e) == "Error validating [surface=-1]. " \
                     "TooSmall: x >= 0 does not hold for x=-1. Wrong value: -1."

    # error wrong type
    surf = 1j
    with pytest.raises(ValidationError) as exc_info:
        # note: we use a length-1 tuple on purpose to see if the error msg takes length into account
        validate('surface', surf, instance_of=(int, ), min_value=0)
    e = exc_info.value
    assert str(e) == "Error validating [surface=1j]. " \
                     "HasWrongType: Value should be an instance of %r. Wrong value: 1j." % int
示例#7
0
def _get_valid_blob_path_prefix(blob_path_prefix  # type: str
                                ):
    # type: (...) -> str
    """
    Utility method to get a valid blob path prefix from a provided one. A trailing slash is added if non-empty

    :param blob_path_prefix:
    :return:
    """
    validate('blob_path_prefix',
             blob_path_prefix,
             instance_of=str,
             enforce_not_none=False)

    if blob_path_prefix is None:
        blob_path_prefix = ''
    elif isinstance(blob_path_prefix, str):
        if len(blob_path_prefix) > 0 and not blob_path_prefix.endswith('/'):
            blob_path_prefix = blob_path_prefix + '/'
    else:
        raise TypeError(
            "Blob path prefix should be a valid string or not be provided (default is empty string)"
        )

    return blob_path_prefix
def csv_to_df(
        csv_buffer_or_str_or_filepath,  # type: Union[str, StringIO, BytesIO]
        csv_name=None  # type: str
):
    # type: (...) -> pandas.DataFrame
    """
    Converts the provided csv to a DatFrame, typically to read it from blob storage for Batch AzureML calls.
    Helper method to ensure consistent reading in particular for timezones and datetime parsing

    :param csv_buffer_or_str_or_filepath:
    :param csv_name: the name of the DataFrame, for error messages
    :return:
    """
    validate(csv_name, csv_buffer_or_str_or_filepath)

    # pandas does not accept string. create a buffer
    if isinstance(csv_buffer_or_str_or_filepath, str):
        csv_buffer_or_str_or_filepath = create_reading_buffer(
            csv_buffer_or_str_or_filepath)

    # read without parsing dates
    res = pandas.read_csv(csv_buffer_or_str_or_filepath, sep=',',
                          decimal='.')  # infer_dt_format=True, parse_dates=[0]

    # -- try to infer datetime columns
    convert_all_datetime_columns(res)

    # -- additionally we automatically configure the timezone as UTC
    localize_all_datetime_columns(res)

    return res
def dfs_to_azmltables(
        dfs,  # type: Dict[str, pandas.DataFrame]
        swagger_format=False,  # type: bool
        mimic_azml_output=False,  # type: bool
        replace_NaN_with=None,  # type: Any
        replace_NaT_with=None,  # type: Any
):
    # type: (...) -> Dict[str, Dict[str, Union[str, Dict[str, List]]]]
    """
    Converts a dictionary of DataFrames into a dictionary of dictionaries following the structure
    required for AzureML JSON conversion

    :param dfs: a dictionary containing input names and input content (each input content is a DataFrame)
    :param swagger_format: a boolean (default: False) indicating if the 'swagger' azureml format should be used
    :return: a dictionary of tables represented as dictionaries
    """
    validate('dfs', dfs, instance_of=dict)

    # resultsDict = {}
    # for dfName, df in DataFramesDict.items():
    #     resultsDict[dfName] = Df_to_AzmlTable(df, dfName)
    # return resultsDict

    return {
        df_name: df_to_azmltable(df,
                                 table_name=df_name,
                                 swagger_format=swagger_format,
                                 mimic_azml_output=mimic_azml_output,
                                 replace_NaN_with=replace_NaN_with,
                                 replace_NaT_with=replace_NaT_with)
        for df_name, df in dfs.items()
    }
def df_to_csv(
        df,  # type: pandas.DataFrame
        df_name=None,  # type: str
        charset=None  # type: str
):
    # type: (...) -> str
    """
    Converts the provided DataFrame to a csv, typically to store it on blob storage for Batch AzureML calls.
    WARNING: datetime columns are converted in ISO format but the milliseconds are ignored and set to zero.

    :param df:
    :param df_name: the name of the DataFrame, for error messages
    :param charset: the charset to use for encoding
    :return:
    """
    validate(df_name, df, instance_of=pandas.DataFrame)

    # TODO what about timezone detail if not present, will the %z be ok ?
    return df.to_csv(path_or_buf=None,
                     sep=',',
                     decimal='.',
                     na_rep='',
                     encoding=charset,
                     index=False,
                     date_format='%Y-%m-%dT%H:%M:%S.000%z')
示例#11
0
    def call_azureml(
            self,
            service_id,  # type: str
            service_config,  # type: ServiceConfig
            ws_inputs,  # type: Dict[str, pd.DataFrame]
            ws_params=None,  # type: Dict[str, str]
            ws_output_names=None,  # type: List[str]
            session=None,  # type: Session
    ):
        """
        (See super for base description)
        :return:
        """
        validate("%s:base_url" % service_id, service_config.base_url)
        validate("%s:api_key" % service_id, service_config.api_key)
        validate("%s:blob_account" % service_id, service_config.blob_account)
        validate("%s:blob_api_key" % service_id, service_config.blob_api_key)
        validate("%s:blob_container" % service_id,
                 service_config.blob_container)

        return execute_bes(
            # all of this is filled using the `service_config`
            api_key=service_config.api_key,
            base_url=service_config.base_url,
            blob_storage_account=service_config.blob_account,
            blob_storage_apikey=service_config.blob_api_key,
            blob_container=service_config.blob_container,
            blob_path_prefix=service_config.blob_path_prefix,
            # blob_charset=None,
            # -------
            inputs=ws_inputs,
            params=ws_params,
            output_names=ws_output_names,
            nb_seconds_between_status_queries=self.polling_period_seconds,
            requests_session=session)
示例#12
0
 def _add_entry(self, value: Entry, create_key: Any) -> None:
     validate('create_key', create_key, custom=Menu.Builder.is_valid_key)
     validate('value.key',
              value.key,
              custom=lambda v: v not in self.__key2entry)
     self.__entries.append(value)
     self.__key2entry[value.key] = value
示例#13
0
 def _validate_choice(self, value):
     valid8.validate(
         "choice",
         value,
         is_in=self.options,
         help_msg="This card is not an option",
     )
示例#14
0
 def __post_init__(self):
     validate_dataclass(self)
     validate('MenuDescription.value',
              self.value,
              min_len=1,
              max_len=1000,
              custom=pattern(r'[0-9A-Za-z ;.,_-]*'))
示例#15
0
 def __post_init__(self):
     validate_dataclass(self)
     validate('Key.value',
              self.value,
              min_len=1,
              max_len=10,
              custom=pattern(r'[0-9A-Za-z_-]*'))
示例#16
0
 def _validate_choice(self, value):
     valid8.validate(
         "target",
         value,
         is_in=self._valid_choices,
         help_msg="Must target a living, non-immune player from the round",
     )
示例#17
0
    def __fetch(self) -> None:
        res = requests.get(url=f'{api_server}shopping-list/', headers={'Authorization': f'Token {self.__key}'})

        if res.status_code != 200:
            raise RuntimeError()

        json = res.json()
        for item in json:
            validate('row length', item, length=7)

            item_id = int(item['id'])
            name = Name(str(item['name']))
            category = str(item['category'])
            manufacturer = Manufacturer(str(item['manufacturer']))
            price = Price.create(int(int(item['price']) / 100), int(item['price']) % 100)
            quantity = Quantity(int(item['quantity']))

            self.__id_dictionary.append([item_id, name.value, manufacturer.value])

            description = Description(str(item['description']))

            if category == 'Smartphone':
                self.__shoppinglist.add_smartphone(Smartphone(name, manufacturer, price, quantity, description))
            elif category == 'Computer':
                self.__shoppinglist.add_computer(Computer(name, manufacturer, price, quantity, description))
            else:
                raise ValueError('Unknown item category in your shopping list')
示例#18
0
 def _validate_choice(self, value):
     valid8.validate(
         "choice",
         value,
         is_in=self.round.players,
         help_msg="Not a player of the round",
     )
示例#19
0
def inline_validate_3(s):
    from valid8 import validate
    # we create a custom mini_lambda variable, since the name 's' is already used
    from mini_lambda import InputVar

    txt = InputVar('txt', str)
    validate('s', s, instance_of=str, min_len=1, custom=txt.islower())
示例#20
0
def test_numpy_bool_is_ok():
    """ Tests that numpy booleans can be used as success result by validation functions"""

    # a numpy float is not a python float
    np_float = np.float_(1.0)

    # numpy bools are not python bools
    assert np_float > 0 is not True
    assert 'numpy' in "%s" % (np_float > 0).__class__

    # simple checker
    validate('np_float', np_float, min_value=1)

    # more complex checker
    @validate_arg('a', lambda x: x >= 1)
    def foo(a):
        return

    foo(np_float)

    # even more complex checker
    @validate_arg('a', and_(x > 0, lambda x: x >= 1))
    def foo(a):
        return

    foo(np_float)
示例#21
0
def create_blob_refs(
        blob_service,  # type: BlockBlobService
        blob_container,  # type: str
        blob_names,  # type: List[str]
        blob_path_prefix=None,  # type: str
        blob_name_prefix=None  # type: str
):
    # type: (...) -> Dict[str, AzmlBlobTable]
    """
    Utility method to create one or several blob references on the same container on the same blob storage service.

    :param blob_service:
    :param blob_container:
    :param blob_names:
    :param blob_path_prefix: optional prefix to the blob names
    :param blob_name_prefix:
    :return:
    """
    validate('blob_names', blob_names, instance_of=list)
    if blob_name_prefix is None:
        blob_name_prefix = ""
    else:
        validate('blob_name_prefix', blob_name_prefix, instance_of=str)

    # convert all and return in a dict
    return {
        blob_name: create_blob_ref(blob_service,
                                   blob_container,
                                   blob_name_prefix + blob_name,
                                   blob_path_prefix=blob_path_prefix)[0]
        for blob_name in blob_names
    }
示例#22
0
 def _validate_choice(self, value):
     valid8.validate("choice", value, instance_of=tuple)
     valid8.validate(
         "choice",
         Counter(value),
         equals=Counter(self.cards),
         help_msg="Chosen cards don't match cards to be ordered",
     )
示例#23
0
 def __post_init__(self):
     validate_dataclass(self)
     validate('neighbourhood',
              self.neighbourhood,
              is_in={
                  'NRV', 'MTA', 'MTB', 'MLA', 'MLB', 'MSN', 'CH1', 'CH2',
                  'MON', 'SNG'
              })
     validate('room_type', self.room, is_in={'SIN', 'DBL'})
示例#24
0
 def to_serializable(self) -> Serializable:
     """Return a serializable value representing this choice."""
     valid8.validate(
         "fulfilled",
         self.fulfilled,
         equals=True,
         help_msg="Choice hasn't been set yet",
     )
     return self.choice
示例#25
0
def test_enum_isinstance():
    """Tests that enum can be used in validate/instance_of"""
    from enum import Enum

    class MyEnum(Enum):
        a = 1
        b = 2

    validate('a', MyEnum.a, instance_of=MyEnum)
示例#26
0
 def __enter__(self):
     valid8.validate(
         "turn.stage",
         self.stage,
         equals=Turn.Stage.START,
         help_msg=
         f"Can't start another move; turn is already {self.stage.name}",
     )
     self._set_stage(Turn.Stage.IN_PROGRESS)
示例#27
0
 def check_move(self, owner, card):
     disallowed = {CardType.PRINCE, CardType.KING}
     card_type = CardType(card)
     valid8.validate(
         "card",
         card_type,
         custom=lambda t: t not in disallowed,
         help_msg=f"Can't play a {card_type.name.title()} with a Countess in hand",
     )
示例#28
0
 def nb_floors(
         self,
         nb_floors  # type: Optional[Integral]
 ):
     validate('nb_floors',
              nb_floors,
              instance_of=Integral,
              enforce_not_none=False)
     self._surface = nb_floors  # !**
示例#29
0
    def _validate_choice(self, value):
        from loveletter.cards import CardType

        card_type = CardType(value)
        valid8.validate(
            "card_type",
            card_type,
            custom=lambda t: t != CardType.GUARD,  # TODO: use minilambda
            help_msg="You can't guess a Guard",
        )
示例#30
0
 def replace(self, card: Card):
     """Replace the current (only) card in the hand; return the old card"""
     valid8.validate(
         "hand",
         self._cards,
         length=1,
         help_msg="Can't replace hand with more than one card",
     )
     old, self._cards[0] = self._cards[0], card
     return old