Esempio n. 1
0
    def _check_parity(cls, parities):

        try:
            cls._check_negative_values(parities)
            cls._check_parity_values(parities)
            cls._check_parity_length(parities)
        except (ValueError, IndexError) as e:
            _error(f'Parities={parities} raised an error')
            raise SystemExit(e)
Esempio n. 2
0
    def _check_masses(cls, masses):

        cls._check_type_iterable(masses)

        try:
            cls._check_negative_values(masses)
        except ValueError as ve:
            _error(f'Masses={masses} raised an error')
            raise SystemExit(ve)
Esempio n. 3
0
    def _check_type_iterable(cls, iterable):

        try:
            _ = iter(iterable)
        except TypeError as te:
            _error(f'The type of {iterable} raised an error')
            raise SystemExit(te)
        else:
            if isinstance(iterable, str):
                raise SystemExit(
                    f'The type of {iterable} must not be a string.')
Esempio n. 4
0
    def validate(cls,
                 molecule_data=None,
                 grid=None,
                 channels=None,
                 couplings=None,
                 fitting=None):

        if molecule_data is not None:

            if molecule_data.masses is None and molecule_data.molecule is None:
                _error(f'At least one of the required parameters '
                       f'{molecule_data.massses} or {molecule_data.molecule}'
                       f'should be set.')
                raise SystemExit()

            if molecule_data.masses is not None:
                cls._check_masses(molecule_data.masses)

            if molecule_data.molecule is not None:
                cls._check_molecule(molecule_data.molecule)

            if molecule_data.nisotopes is None:
                _error('The required parameter "nisotopes" is missing.')
                raise SystemExit()

            if molecule_data.jrange is not None:
                cls._check_jrange(molecule_data.rot_range)
                cls._check_jqnumbers(molecule_data.jqnumbers)

            if molecule_data.jvalues is not None:
                cls._check_jvalues(molecule_data.rot_values)
                cls._check_jqnumbers(molecule_data.jqnumbers)

            if molecule_data.referencej is not None:
                cls._check_referencej(molecule_data.referencej)

            if molecule_data.parities is not None:
                cls._check_parity(molecule_data.parities)
        if grid is not None:
            # TODO: split this to several methods
            cls._check_grid_data(grid.rgrid, grid.npoints, grid.alpha,
                                 grid.rbar)
        if channels is not None:
            cls._check_channel_data(channels)
        if couplings is not None:
            cls._check_couplings_data(couplings)
        if fitting is not None:
            cls._check_fitting_data(fitting)
Esempio n. 5
0
    def _check_channel_data(cls, channels):

        for ch in channels:
            if ch.model == 'pointwise':
                if not _exists(ch.filep):
                    raise FileNotFoundError(
                        f'The file {ch.filep} does not exist.')
                if _stat(ch.filep).st_size == 0:
                    raise OSError(f'The file {ch.filep} is empty.')

                pot_data = np.loadtxt(ch.filep, skiprows=1)

                msg_init = 'The pointwise potential file'
                if pot_data.shape[0] < 5:
                    _warning(
                        f'{msg_init} {ch.filep} has less than 5 parameters')
                if pot_data.shape[0] < 2:
                    _error(f'{msg_init} {ch.filep} has less than 2 parameters')
                if pot_data.shape[1] == 2:
                    _warning(f'{msg_init} {ch.filep} has 2 columns')
                if pot_data.shape[1] < 2:
                    _error(f'{msg_init} {ch.filep} has less than 2 columns')

            if ch.model == 'custom':
                if not hasattr(ch, '__call__'):
                    _error('Model is set to custum but ' +
                           'custom function is not provided')
Esempio n. 6
0
    def _check_grid_data(cls, rrange, ngrid, alpha, rbar):

        cls._check_type_iterable(rrange)

        try:
            cls._check_rrange_len(rrange)
        except IndexError as ie:
            print(ie)

        rmin, rmax = rrange[0], rrange[1]

        try:
            for x in [ngrid, rmin, rmax, rbar]:
                cls._check_type_int_or_float(x)
        except TypeError as te:
            _error('Incorrect type for parameters "rrange" and/or "npoints".')
            raise SystemExit(te)

        try:
            cls._check_negative_values([rmax, rmin, ngrid, rbar])  # rbar?
            cls._check_grid_values(rmin, rmax)
        except ValueError as ve:
            _error(f'Incorrect values for {rmin}//{rmax}//{ngrid}.')
            raise SystemExit(ve)
Esempio n. 7
0
    def _check_jrange(cls, jrange):

        cls._check_type_iterable(jrange)

        try:
            cls._check_jrange_length(jrange)
        except IndexError as ie:
            print(ie)

        jmin, jmax = jrange[0], jrange[1]

        try:
            for x in [jmin, jmax]:
                cls._check_type_int_or_float(x)
        except TypeError as te:
            _error('The type of "jrange" raised an error')
            raise SystemExit(te)

        try:
            cls._check_negative_values(jrange)
            cls._check_jrange_values(jmin, jmax)
        except ValueError as ve:
            _error(f'jrange data {jmin}, {jmax} raised an error')
            raise SystemExit(ve)
Esempio n. 8
0
def voicetext(environ, start_response):
    """
    After validating the incoming request, retrieve the audio file from
    the upstream VoiceText service, check it, and return it.
    """

    remote_addr = environ.get('REMOTE_ADDR', '')
    if not remote_addr:
        _warn("Relay denied -- no remote IP address")
        start_response(_CODE_403, _HEADERS_JSON)
        return _MSG_DENIED

    if not environ.get('HTTP_USER_AGENT', '').startswith(_AWESOMETTS):
        _warn("Relay denied -- unauthorized user agent")
        start_response(_CODE_403, _HEADERS_JSON)
        return _MSG_DENIED

    if environ.get('REQUEST_METHOD') != 'GET':
        _warn("Relay denied -- unacceptable request method")
        start_response(_CODE_405, _HEADERS_JSON)
        return _MSG_UNACCEPTABLE

    data = environ.get('QUERY_STRING')

    # do a very rough sanity check without generating a bunch of junk objects;
    # remember that most Japanese characters encode to 9-byte strings and we
    # allow up to 100 Japanese characters (or 900 bytes) in the client
    if not (data and len(data) < 1000 and data.count('&') > 4
            and data.count('=') < 8 and 'format=' in data and 'format=wav'
            not in data and 'pitch=' in data and 'speaker=' in data
            and 'speed=' in data and 'text=' in data and 'volume=' in data):
        _warn("Relay denied -- unacceptable query string")
        start_response(_CODE_400, _HEADERS_JSON)
        return _MSG_UNACCEPTABLE

    # apply rate-limiting
    with _limit_lock:
        now = int(_time())

        # remove expired entries
        for level in _limit_levels:
            expired = now - level.within
            lookup = level.lookup
            for addr, info in lookup.items():
                if info['created'] < expired:
                    del lookup[addr]

        # check maximum levels
        for level in _limit_levels:
            lookup = level.lookup
            try:
                info = lookup[remote_addr]
            except KeyError:
                total = len(lookup)
                if total >= level.max_total:
                    _warn(
                        "Relay denied -- already have %d total callers "
                        "within the last %d seconds", total, level.within)
                    start_response(_CODE_503, _HEADERS_JSON)
                    return _MSG_CAPACITY
            else:
                calls = info['calls']
                if calls >= level.max_single:
                    _warn(
                        "Relay denied -- already had %d individual calls "
                        "from %s within the last %d seconds", calls,
                        remote_addr, level.within)
                    start_response(_CODE_429, _HEADERS_JSON)
                    return _MSG_TOO_MANY

        # caller is good to go; update their call counts
        summaries = []
        for level in _limit_levels:
            lookup = level.lookup
            try:
                info = lookup[remote_addr]
            except KeyError:
                lookup[remote_addr] = info = {'created': now, 'calls': 1}
            else:
                info['calls'] += 1
            summaries.append("%d-second window has %d/%d individual calls for "
                             "%s and %d/%d total unique callers" %
                             (level.within, info['calls'], level.max_single,
                              remote_addr, len(lookup), level.max_total))
        _info("Relay accepted -- %s", "; ".join(summaries))

    try:
        response = _url_open(_Request(_API_VOICETEXT_ENDPOINT, data,
                                      _API_VOICETEXT_AUTH),
                             timeout=_API_VOICETEXT_TIMEOUT)

        if response.getcode() != 200:
            raise IOError("non-200 status code from upstream service")

        mime = response.info().gettype()
        if not mime.startswith('audio/'):
            raise IOError("non-audio format from upstream service")

        payload = [response.read()]

    except Exception as exception:  # catch all, pylint:disable=broad-except
        _error("Relay failed -- %s", exception)
        start_response(_CODE_502, _HEADERS_JSON)
        return _MSG_UPSTREAM

    else:
        start_response(_CODE_200, [('Content-Type', mime)])
        return payload

    finally:
        try:
            response.close()
        except Exception:  # catch all, pylint:disable=broad-except
            pass