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)
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)
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.')
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)
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')
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)
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)
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