tmp
/
pip-install-ghxuqwgs
/numpy_78e94bf2b6094bf9a1f3d92042f9bf46
/build
/lib.linux-x86_64-cpython-310
/numpy
/lib
/_iotools.py
| """A collection of functions designed to help I/O with ascii files. | |
| """ | |
| from __future__ import division, absolute_import, print_function | |
| __docformat__ = "restructuredtext en" | |
| import sys | |
| import numpy as np | |
| import numpy.core.numeric as nx | |
| from numpy.compat import asbytes, bytes, asbytes_nested, basestring | |
| if sys.version_info[0] >= 3: | |
| from builtins import bool, int, float, complex, object, str | |
| unicode = str | |
| else: | |
| from __builtin__ import bool, int, float, complex, object, unicode, str | |
| if sys.version_info[0] >= 3: | |
| def _bytes_to_complex(s): | |
| return complex(s.decode('ascii')) | |
| def _bytes_to_name(s): | |
| return s.decode('ascii') | |
| else: | |
| _bytes_to_complex = complex | |
| _bytes_to_name = str | |
| def _is_string_like(obj): | |
| """ | |
| Check whether obj behaves like a string. | |
| """ | |
| try: | |
| obj + '' | |
| except (TypeError, ValueError): | |
| return False | |
| return True | |
| def _is_bytes_like(obj): | |
| """ | |
| Check whether obj behaves like a bytes object. | |
| """ | |
| try: | |
| obj + asbytes('') | |
| except (TypeError, ValueError): | |
| return False | |
| return True | |
| def _to_filehandle(fname, flag='r', return_opened=False): | |
| """ | |
| Returns the filehandle corresponding to a string or a file. | |
| If the string ends in '.gz', the file is automatically unzipped. | |
| Parameters | |
| ---------- | |
| fname : string, filehandle | |
| Name of the file whose filehandle must be returned. | |
| flag : string, optional | |
| Flag indicating the status of the file ('r' for read, 'w' for write). | |
| return_opened : boolean, optional | |
| Whether to return the opening status of the file. | |
| """ | |
| if _is_string_like(fname): | |
| if fname.endswith('.gz'): | |
| import gzip | |
| fhd = gzip.open(fname, flag) | |
| elif fname.endswith('.bz2'): | |
| import bz2 | |
| fhd = bz2.BZ2File(fname) | |
| else: | |
| fhd = file(fname, flag) | |
| opened = True | |
| elif hasattr(fname, 'seek'): | |
| fhd = fname | |
| opened = False | |
| else: | |
| raise ValueError('fname must be a string or file handle') | |
| if return_opened: | |
| return fhd, opened | |
| return fhd | |
| def has_nested_fields(ndtype): | |
| """ | |
| Returns whether one or several fields of a dtype are nested. | |
| Parameters | |
| ---------- | |
| ndtype : dtype | |
| Data-type of a structured array. | |
| Raises | |
| ------ | |
| AttributeError | |
| If `ndtype` does not have a `names` attribute. | |
| Examples | |
| -------- | |
| >>> dt = np.dtype([('name', 'S4'), ('x', float), ('y', float)]) | |
| >>> np.lib._iotools.has_nested_fields(dt) | |
| False | |
| """ | |
| for name in ndtype.names or (): | |
| if ndtype[name].names: | |
| return True | |
| return False | |
| def flatten_dtype(ndtype, flatten_base=False): | |
| """ | |
| Unpack a structured data-type by collapsing nested fields and/or fields | |
| with a shape. | |
| Note that the field names are lost. | |
| Parameters | |
| ---------- | |
| ndtype : dtype | |
| The datatype to collapse | |
| flatten_base : {False, True}, optional | |
| Whether to transform a field with a shape into several fields or not. | |
| Examples | |
| -------- | |
| >>> dt = np.dtype([('name', 'S4'), ('x', float), ('y', float), | |
| ... ('block', int, (2, 3))]) | |
| >>> np.lib._iotools.flatten_dtype(dt) | |
| [dtype('|S4'), dtype('float64'), dtype('float64'), dtype('int32')] | |
| >>> np.lib._iotools.flatten_dtype(dt, flatten_base=True) | |
| [dtype('|S4'), dtype('float64'), dtype('float64'), dtype('int32'), | |
| dtype('int32'), dtype('int32'), dtype('int32'), dtype('int32'), | |
| dtype('int32')] | |
| """ | |
| names = ndtype.names | |
| if names is None: | |
| if flatten_base: | |
| return [ndtype.base] * int(np.prod(ndtype.shape)) | |
| return [ndtype.base] | |
| else: | |
| types = [] | |
| for field in names: | |
| info = ndtype.fields[field] | |
| flat_dt = flatten_dtype(info[0], flatten_base) | |
| types.extend(flat_dt) | |
| return types | |
| class LineSplitter(object): | |
| """ | |
| Object to split a string at a given delimiter or at given places. | |
| Parameters | |
| ---------- | |
| delimiter : str, int, or sequence of ints, optional | |
| If a string, character used to delimit consecutive fields. | |
| If an integer or a sequence of integers, width(s) of each field. | |
| comment : str, optional | |
| Character used to mark the beginning of a comment. Default is '#'. | |
| autostrip : bool, optional | |
| Whether to strip each individual field. Default is True. | |
| """ | |
| def autostrip(self, method): | |
| """ | |
| Wrapper to strip each member of the output of `method`. | |
| Parameters | |
| ---------- | |
| method : function | |
| Function that takes a single argument and returns a sequence of | |
| strings. | |
| Returns | |
| ------- | |
| wrapped : function | |
| The result of wrapping `method`. `wrapped` takes a single input | |
| argument and returns a list of strings that are stripped of | |
| white-space. | |
| """ | |
| return lambda input: [_.strip() for _ in method(input)] | |
| # | |
| def __init__(self, delimiter=None, comments=asbytes('#'), autostrip=True): | |
| self.comments = comments | |
| # Delimiter is a character | |
| if isinstance(delimiter, unicode): | |
| delimiter = delimiter.encode('ascii') | |
| if (delimiter is None) or _is_bytes_like(delimiter): | |
| delimiter = delimiter or None | |
| _handyman = self._delimited_splitter | |
| # Delimiter is a list of field widths | |
| elif hasattr(delimiter, '__iter__'): | |
| _handyman = self._variablewidth_splitter | |
| idx = np.cumsum([0] + list(delimiter)) | |
| delimiter = [slice(i, j) for (i, j) in zip(idx[:-1], idx[1:])] | |
| # Delimiter is a single integer | |
| elif int(delimiter): | |
| (_handyman, delimiter) = ( | |
| self._fixedwidth_splitter, int(delimiter)) | |
| else: | |
| (_handyman, delimiter) = (self._delimited_splitter, None) | |
| self.delimiter = delimiter | |
| if autostrip: | |
| self._handyman = self.autostrip(_handyman) | |
| else: | |
| self._handyman = _handyman | |
| # | |
| def _delimited_splitter(self, line): | |
| if self.comments is not None: | |
| line = line.split(self.comments)[0] | |
| line = line.strip(asbytes(" \r\n")) | |
| if not line: | |
| return [] | |
| return line.split(self.delimiter) | |
| # | |
| def _fixedwidth_splitter(self, line): | |
| if self.comments is not None: | |
| line = line.split(self.comments)[0] | |
| line = line.strip(asbytes("\r\n")) | |
| if not line: | |
| return [] | |
| fixed = self.delimiter | |
| slices = [slice(i, i + fixed) for i in range(0, len(line), fixed)] | |
| return [line[s] for s in slices] | |
| # | |
| def _variablewidth_splitter(self, line): | |
| if self.comments is not None: | |
| line = line.split(self.comments)[0] | |
| if not line: | |
| return [] | |
| slices = self.delimiter | |
| return [line[s] for s in slices] | |
| # | |
| def __call__(self, line): | |
| return self._handyman(line) | |
| class NameValidator(object): | |
| """ | |
| Object to validate a list of strings to use as field names. | |
| The strings are stripped of any non alphanumeric character, and spaces | |
| are replaced by '_'. During instantiation, the user can define a list | |
| of names to exclude, as well as a list of invalid characters. Names in | |
| the exclusion list are appended a '_' character. | |
| Once an instance has been created, it can be called with a list of | |
| names, and a list of valid names will be created. The `__call__` | |
| method accepts an optional keyword "default" that sets the default name | |
| in case of ambiguity. By default this is 'f', so that names will | |
| default to `f0`, `f1`, etc. | |
| Parameters | |
| ---------- | |
| excludelist : sequence, optional | |
| A list of names to exclude. This list is appended to the default | |
| list ['return', 'file', 'print']. Excluded names are appended an | |
| underscore: for example, `file` becomes `file_` if supplied. | |
| deletechars : str, optional | |
| A string combining invalid characters that must be deleted from the | |
| names. | |
| casesensitive : {True, False, 'upper', 'lower'}, optional | |
| * If True, field names are case-sensitive. | |
| * If False or 'upper', field names are converted to upper case. | |
| * If 'lower', field names are converted to lower case. | |
| The default value is True. | |
| replace_space : '_', optional | |
| Character(s) used in replacement of white spaces. | |
| Notes | |
| ----- | |
| Calling an instance of `NameValidator` is the same as calling its | |
| method `validate`. | |
| Examples | |
| -------- | |
| >>> validator = np.lib._iotools.NameValidator() | |
| >>> validator(['file', 'field2', 'with space', 'CaSe']) | |
| ['file_', 'field2', 'with_space', 'CaSe'] | |
| >>> validator = np.lib._iotools.NameValidator(excludelist=['excl'], | |
| deletechars='q', | |
| case_sensitive='False') | |
| >>> validator(['excl', 'field2', 'no_q', 'with space', 'CaSe']) | |
| ['excl_', 'field2', 'no_', 'with_space', 'case'] | |
| """ | |
| # | |
| defaultexcludelist = ['return', 'file', 'print'] | |
| defaultdeletechars = set("""~!@#$%^&*()-=+~\|]}[{';: /?.>,<""") | |
| # | |
| def __init__(self, excludelist=None, deletechars=None, | |
| case_sensitive=None, replace_space='_'): | |
| # Process the exclusion list .. | |
| if excludelist is None: | |
| excludelist = [] | |
| excludelist.extend(self.defaultexcludelist) | |
| self.excludelist = excludelist | |
| # Process the list of characters to delete | |
| if deletechars is None: | |
| delete = self.defaultdeletechars | |
| else: | |
| delete = set(deletechars) | |
| delete.add('"') | |
| self.deletechars = delete | |
| # Process the case option ..... | |
| if (case_sensitive is None) or (case_sensitive is True): | |
| self.case_converter = lambda x: x | |
| elif (case_sensitive is False) or ('u' in case_sensitive): | |
| self.case_converter = lambda x: x.upper() | |
| elif 'l' in case_sensitive: | |
| self.case_converter = lambda x: x.lower() | |
| else: | |
| self.case_converter = lambda x: x | |
| # | |
| self.replace_space = replace_space | |
| def validate(self, names, defaultfmt="f%i", nbfields=None): | |
| """ | |
| Validate a list of strings as field names for a structured array. | |
| Parameters | |
| ---------- | |
| names : sequence of str | |
| Strings to be validated. | |
| defaultfmt : str, optional | |
| Default format string, used if validating a given string | |
| reduces its length to zero. | |
| nboutput : integer, optional | |
| Final number of validated names, used to expand or shrink the | |
| initial list of names. | |
| Returns | |
| ------- | |
| validatednames : list of str | |
| The list of validated field names. | |
| Notes | |
| ----- | |
| A `NameValidator` instance can be called directly, which is the | |
| same as calling `validate`. For examples, see `NameValidator`. | |
| """ | |
| # Initial checks .............. | |
| if (names is None): | |
| if (nbfields is None): | |
| return None | |
| names = [] | |
| if isinstance(names, basestring): | |
| names = [names, ] | |
| if nbfields is not None: | |
| nbnames = len(names) | |
| if (nbnames < nbfields): | |
| names = list(names) + [''] * (nbfields - nbnames) | |
| elif (nbnames > nbfields): | |
| names = names[:nbfields] | |
| # Set some shortcuts ........... | |
| deletechars = self.deletechars | |
| excludelist = self.excludelist | |
| case_converter = self.case_converter | |
| replace_space = self.replace_space | |
| # Initializes some variables ... | |
| validatednames = [] | |
| seen = dict() | |
| nbempty = 0 | |
| # | |
| for item in names: | |
| item = case_converter(item).strip() | |
| if replace_space: | |
| item = item.replace(' ', replace_space) | |
| item = ''.join([c for c in item if c not in deletechars]) | |
| if item == '': | |
| item = defaultfmt % nbempty | |
| while item in names: | |
| nbempty += 1 | |
| item = defaultfmt % nbempty | |
| nbempty += 1 | |
| elif item in excludelist: | |
| item += '_' | |
| cnt = seen.get(item, 0) | |
| if cnt > 0: | |
| validatednames.append(item + '_%d' % cnt) | |
| else: | |
| validatednames.append(item) | |
| seen[item] = cnt + 1 | |
| return tuple(validatednames) | |
| # | |
| def __call__(self, names, defaultfmt="f%i", nbfields=None): | |
| return self.validate(names, defaultfmt=defaultfmt, nbfields=nbfields) | |
| def str2bool(value): | |
| """ | |
| Tries to transform a string supposed to represent a boolean to a boolean. | |
| Parameters | |
| ---------- | |
| value : str | |
| The string that is transformed to a boolean. | |
| Returns | |
| ------- | |
| boolval : bool | |
| The boolean representation of `value`. | |
| Raises | |
| ------ | |
| ValueError | |
| If the string is not 'True' or 'False' (case independent) | |
| Examples | |
| -------- | |
| >>> np.lib._iotools.str2bool('TRUE') | |
| True | |
| >>> np.lib._iotools.str2bool('false') | |
| False | |
| """ | |
| value = value.upper() | |
| if value == asbytes('TRUE'): | |
| return True | |
| elif value == asbytes('FALSE'): | |
| return False | |
| else: | |
| raise ValueError("Invalid boolean") | |
| class ConverterError(Exception): | |
| """ | |
| Exception raised when an error occurs in a converter for string values. | |
| """ | |
| pass | |
| class ConverterLockError(ConverterError): | |
| """ | |
| Exception raised when an attempt is made to upgrade a locked converter. | |
| """ | |
| pass | |
| class ConversionWarning(UserWarning): | |
| """ | |
| Warning issued when a string converter has a problem. | |
| Notes | |
| ----- | |
| In `genfromtxt` a `ConversionWarning` is issued if raising exceptions | |
| is explicitly suppressed with the "invalid_raise" keyword. | |
| """ | |
| pass | |
| class StringConverter(object): | |
| """ | |
| Factory class for function transforming a string into another object | |
| (int, float). | |
| After initialization, an instance can be called to transform a string | |
| into another object. If the string is recognized as representing a | |
| missing value, a default value is returned. | |
| Attributes | |
| ---------- | |
| func : function | |
| Function used for the conversion. | |
| default : any | |
| Default value to return when the input corresponds to a missing | |
| value. | |
| type : type | |
| Type of the output. | |
| _status : int | |
| Integer representing the order of the conversion. | |
| _mapper : sequence of tuples | |
| Sequence of tuples (dtype, function, default value) to evaluate in | |
| order. | |
| _locked : bool | |
| Holds `locked` parameter. | |
| Parameters | |
| ---------- | |
| dtype_or_func : {None, dtype, function}, optional | |
| If a `dtype`, specifies the input data type, used to define a basic | |
| function and a default value for missing data. For example, when | |
| `dtype` is float, the `func` attribute is set to `float` and the | |
| default value to `np.nan`. If a function, this function is used to | |
| convert a string to another object. In this case, it is recommended | |
| to give an associated default value as input. | |
| default : any, optional | |
| Value to return by default, that is, when the string to be | |
| converted is flagged as missing. If not given, `StringConverter` | |
| tries to supply a reasonable default value. | |
| missing_values : sequence of str, optional | |
| Sequence of strings indicating a missing value. | |
| locked : bool, optional | |
| Whether the StringConverter should be locked to prevent automatic | |
| upgrade or not. Default is False. | |
| """ | |
| # | |
| _mapper = [(nx.bool_, str2bool, False), | |
| (nx.integer, int, -1), | |
| (nx.floating, float, nx.nan), | |
| (complex, _bytes_to_complex, nx.nan + 0j), | |
| (nx.string_, bytes, asbytes('???'))] | |
| (_defaulttype, _defaultfunc, _defaultfill) = zip(*_mapper) | |
| # | |
| def _getdtype(cls, val): | |
| """Returns the dtype of the input variable.""" | |
| return np.array(val).dtype | |
| # | |
| def _getsubdtype(cls, val): | |
| """Returns the type of the dtype of the input variable.""" | |
| return np.array(val).dtype.type | |
| # | |
| # This is a bit annoying. We want to return the "general" type in most | |
| # cases (ie. "string" rather than "S10"), but we want to return the | |
| # specific type for datetime64 (ie. "datetime64[us]" rather than | |
| # "datetime64"). | |
| def _dtypeortype(cls, dtype): | |
| """Returns dtype for datetime64 and type of dtype otherwise.""" | |
| if dtype.type == np.datetime64: | |
| return dtype | |
| return dtype.type | |
| # | |
| def upgrade_mapper(cls, func, default=None): | |
| """ | |
| Upgrade the mapper of a StringConverter by adding a new function and | |
| its corresponding default. | |
| The input function (or sequence of functions) and its associated | |
| default value (if any) is inserted in penultimate position of the | |
| mapper. The corresponding type is estimated from the dtype of the | |
| default value. | |
| Parameters | |
| ---------- | |
| func : var | |
| Function, or sequence of functions | |
| Examples | |
| -------- | |
| >>> import dateutil.parser | |
| >>> import datetime | |
| >>> dateparser = datetustil.parser.parse | |
| >>> defaultdate = datetime.date(2000, 1, 1) | |
| >>> StringConverter.upgrade_mapper(dateparser, default=defaultdate) | |
| """ | |
| # Func is a single functions | |
| if hasattr(func, '__call__'): | |
| cls._mapper.insert(-1, (cls._getsubdtype(default), func, default)) | |
| return | |
| elif hasattr(func, '__iter__'): | |
| if isinstance(func[0], (tuple, list)): | |
| for _ in func: | |
| cls._mapper.insert(-1, _) | |
| return | |
| if default is None: | |
| default = [None] * len(func) | |
| else: | |
| default = list(default) | |
| default.append([None] * (len(func) - len(default))) | |
| for (fct, dft) in zip(func, default): | |
| cls._mapper.insert(-1, (cls._getsubdtype(dft), fct, dft)) | |
| # | |
| def __init__(self, dtype_or_func=None, default=None, missing_values=None, | |
| locked=False): | |
| # Convert unicode (for Py3) | |
| if isinstance(missing_values, unicode): | |
| missing_values = asbytes(missing_values) | |
| elif isinstance(missing_values, (list, tuple)): | |
| missing_values = asbytes_nested(missing_values) | |
| # Defines a lock for upgrade | |
| self._locked = bool(locked) | |
| # No input dtype: minimal initialization | |
| if dtype_or_func is None: | |
| self.func = str2bool | |
| self._status = 0 | |
| self.default = default or False | |
| dtype = np.dtype('bool') | |
| else: | |
| # Is the input a np.dtype ? | |
| try: | |
| self.func = None | |
| dtype = np.dtype(dtype_or_func) | |
| except TypeError: | |
| # dtype_or_func must be a function, then | |
| if not hasattr(dtype_or_func, '__call__'): | |
| errmsg = ("The input argument `dtype` is neither a" | |
| " function nor a dtype (got '%s' instead)") | |
| raise TypeError(errmsg % type(dtype_or_func)) | |
| # Set the function | |
| self.func = dtype_or_func | |
| # If we don't have a default, try to guess it or set it to | |
| # None | |
| if default is None: | |
| try: | |
| default = self.func(asbytes('0')) | |
| except ValueError: | |
| default = None | |
| dtype = self._getdtype(default) | |
| # Set the status according to the dtype | |
| _status = -1 | |
| for (i, (deftype, func, default_def)) in enumerate(self._mapper): | |
| if np.issubdtype(dtype.type, deftype): | |
| _status = i | |
| if default is None: | |
| self.default = default_def | |
| else: | |
| self.default = default | |
| break | |
| if _status == -1: | |
| # We never found a match in the _mapper... | |
| _status = 0 | |
| self.default = default | |
| self._status = _status | |
| # If the input was a dtype, set the function to the last we saw | |
| if self.func is None: | |
| self.func = func | |
| # If the status is 1 (int), change the function to | |
| # something more robust. | |
| if self.func == self._mapper[1][1]: | |
| if issubclass(dtype.type, np.uint64): | |
| self.func = np.uint64 | |
| elif issubclass(dtype.type, np.int64): | |
| self.func = np.int64 | |
| else: | |
| self.func = lambda x: int(float(x)) | |
| # Store the list of strings corresponding to missing values. | |
| if missing_values is None: | |
| self.missing_values = set([asbytes('')]) | |
| else: | |
| if isinstance(missing_values, bytes): | |
| missing_values = missing_values.split(asbytes(",")) | |
| self.missing_values = set(list(missing_values) + [asbytes('')]) | |
| # | |
| self._callingfunction = self._strict_call | |
| self.type = self._dtypeortype(dtype) | |
| self._checked = False | |
| self._initial_default = default | |
| # | |
| def _loose_call(self, value): | |
| try: | |
| return self.func(value) | |
| except ValueError: | |
| return self.default | |
| # | |
| def _strict_call(self, value): | |
| try: | |
| return self.func(value) | |
| except ValueError: | |
| if value.strip() in self.missing_values: | |
| if not self._status: | |
| self._checked = False | |
| return self.default | |
| raise ValueError("Cannot convert string '%s'" % value) | |
| # | |
| def __call__(self, value): | |
| return self._callingfunction(value) | |
| # | |
| def upgrade(self, value): | |
| """ | |
| Find the best converter for a given string, and return the result. | |
| The supplied string `value` is converted by testing different | |
| converters in order. First the `func` method of the | |
| `StringConverter` instance is tried, if this fails other available | |
| converters are tried. The order in which these other converters | |
| are tried is determined by the `_status` attribute of the instance. | |
| Parameters | |
| ---------- | |
| value : str | |
| The string to convert. | |
| Returns | |
| ------- | |
| out : any | |
| The result of converting `value` with the appropriate converter. | |
| """ | |
| self._checked = True | |
| try: | |
| self._strict_call(value) | |
| except ValueError: | |
| # Raise an exception if we locked the converter... | |
| if self._locked: | |
| errmsg = "Converter is locked and cannot be upgraded" | |
| raise ConverterLockError(errmsg) | |
| _statusmax = len(self._mapper) | |
| # Complains if we try to upgrade by the maximum | |
| _status = self._status | |
| if _status == _statusmax: | |
| errmsg = "Could not find a valid conversion function" | |
| raise ConverterError(errmsg) | |
| elif _status < _statusmax - 1: | |
| _status += 1 | |
| (self.type, self.func, default) = self._mapper[_status] | |
| self._status = _status | |
| if self._initial_default is not None: | |
| self.default = self._initial_default | |
| else: | |
| self.default = default | |
| self.upgrade(value) | |
| def iterupgrade(self, value): | |
| self._checked = True | |
| if not hasattr(value, '__iter__'): | |
| value = (value,) | |
| _strict_call = self._strict_call | |
| try: | |
| for _m in value: | |
| _strict_call(_m) | |
| except ValueError: | |
| # Raise an exception if we locked the converter... | |
| if self._locked: | |
| errmsg = "Converter is locked and cannot be upgraded" | |
| raise ConverterLockError(errmsg) | |
| _statusmax = len(self._mapper) | |
| # Complains if we try to upgrade by the maximum | |
| _status = self._status | |
| if _status == _statusmax: | |
| raise ConverterError( | |
| "Could not find a valid conversion function" | |
| ) | |
| elif _status < _statusmax - 1: | |
| _status += 1 | |
| (self.type, self.func, default) = self._mapper[_status] | |
| if self._initial_default is not None: | |
| self.default = self._initial_default | |
| else: | |
| self.default = default | |
| self._status = _status | |
| self.iterupgrade(value) | |
| def update(self, func, default=None, testing_value=None, | |
| missing_values=asbytes(''), locked=False): | |
| """ | |
| Set StringConverter attributes directly. | |
| Parameters | |
| ---------- | |
| func : function | |
| Conversion function. | |
| default : any, optional | |
| Value to return by default, that is, when the string to be | |
| converted is flagged as missing. If not given, | |
| `StringConverter` tries to supply a reasonable default value. | |
| testing_value : str, optional | |
| A string representing a standard input value of the converter. | |
| This string is used to help defining a reasonable default | |
| value. | |
| missing_values : sequence of str, optional | |
| Sequence of strings indicating a missing value. | |
| locked : bool, optional | |
| Whether the StringConverter should be locked to prevent | |
| automatic upgrade or not. Default is False. | |
| Notes | |
| ----- | |
| `update` takes the same parameters as the constructor of | |
| `StringConverter`, except that `func` does not accept a `dtype` | |
| whereas `dtype_or_func` in the constructor does. | |
| """ | |
| self.func = func | |
| self._locked = locked | |
| # Don't reset the default to None if we can avoid it | |
| if default is not None: | |
| self.default = default | |
| self.type = self._dtypeortype(self._getdtype(default)) | |
| else: | |
| try: | |
| tester = func(testing_value or asbytes('1')) | |
| except (TypeError, ValueError): | |
| tester = None | |
| self.type = self._dtypeortype(self._getdtype(tester)) | |
| # Add the missing values to the existing set | |
| if missing_values is not None: | |
| if _is_bytes_like(missing_values): | |
| self.missing_values.add(missing_values) | |
| elif hasattr(missing_values, '__iter__'): | |
| for val in missing_values: | |
| self.missing_values.add(val) | |
| else: | |
| self.missing_values = [] | |
| def easy_dtype(ndtype, names=None, defaultfmt="f%i", **validationargs): | |
| """ | |
| Convenience function to create a `np.dtype` object. | |
| The function processes the input `dtype` and matches it with the given | |
| names. | |
| Parameters | |
| ---------- | |
| ndtype : var | |
| Definition of the dtype. Can be any string or dictionary recognized | |
| by the `np.dtype` function, or a sequence of types. | |
| names : str or sequence, optional | |
| Sequence of strings to use as field names for a structured dtype. | |
| For convenience, `names` can be a string of a comma-separated list | |
| of names. | |
| defaultfmt : str, optional | |
| Format string used to define missing names, such as ``"f%i"`` | |
| (default) or ``"fields_%02i"``. | |
| validationargs : optional | |
| A series of optional arguments used to initialize a | |
| `NameValidator`. | |
| Examples | |
| -------- | |
| >>> np.lib._iotools.easy_dtype(float) | |
| dtype('float64') | |
| >>> np.lib._iotools.easy_dtype("i4, f8") | |
| dtype([('f0', '<i4'), ('f1', '<f8')]) | |
| >>> np.lib._iotools.easy_dtype("i4, f8", defaultfmt="field_%03i") | |
| dtype([('field_000', '<i4'), ('field_001', '<f8')]) | |
| >>> np.lib._iotools.easy_dtype((int, float, float), names="a,b,c") | |
| dtype([('a', '<i8'), ('b', '<f8'), ('c', '<f8')]) | |
| >>> np.lib._iotools.easy_dtype(float, names="a,b,c") | |
| dtype([('a', '<f8'), ('b', '<f8'), ('c', '<f8')]) | |
| """ | |
| try: | |
| ndtype = np.dtype(ndtype) | |
| except TypeError: | |
| validate = NameValidator(**validationargs) | |
| nbfields = len(ndtype) | |
| if names is None: | |
| names = [''] * len(ndtype) | |
| elif isinstance(names, basestring): | |
| names = names.split(",") | |
| names = validate(names, nbfields=nbfields, defaultfmt=defaultfmt) | |
| ndtype = np.dtype(dict(formats=ndtype, names=names)) | |
| else: | |
| nbtypes = len(ndtype) | |
| # Explicit names | |
| if names is not None: | |
| validate = NameValidator(**validationargs) | |
| if isinstance(names, basestring): | |
| names = names.split(",") | |
| # Simple dtype: repeat to match the nb of names | |
| if nbtypes == 0: | |
| formats = tuple([ndtype.type] * len(names)) | |
| names = validate(names, defaultfmt=defaultfmt) | |
| ndtype = np.dtype(list(zip(names, formats))) | |
| # Structured dtype: just validate the names as needed | |
| else: | |
| ndtype.names = validate(names, nbfields=nbtypes, | |
| defaultfmt=defaultfmt) | |
| # No implicit names | |
| elif (nbtypes > 0): | |
| validate = NameValidator(**validationargs) | |
| # Default initial names : should we change the format ? | |
| if ((ndtype.names == tuple("f%i" % i for i in range(nbtypes))) and | |
| (defaultfmt != "f%i")): | |
| ndtype.names = validate([''] * nbtypes, defaultfmt=defaultfmt) | |
| # Explicit initial names : just validate | |
| else: | |
| ndtype.names = validate(ndtype.names, defaultfmt=defaultfmt) | |
| return ndtype | |