Skip to content

Commit 093d559

Browse files
committed
More pylint issues squashed
1 parent eb658fc commit 093d559

17 files changed

Lines changed: 255 additions & 229 deletions

File tree

‎Stoner/core/__init__.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@
2424
from . import Typing, array, base, exceptions, utils
2525
from .array import DataArray
2626
from .base import RegexpDict, TypeHintedDict, metadataObject, string_to_type
27-
from .setas import setas as _setas
27+
from .setas import Setas as _setas

‎Stoner/core/array.py‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@
99
import copy
1010

1111
import numpy as np
12-
import numpy.ma as ma
13-
12+
from numpy import ma
1413
from ..compat import int_types
1514
from ..tools import AttributeStore, all_size, all_type, isiterable, isnone
1615
from .exceptions import StonerSetasError
17-
from .setas import setas as _setas
16+
from .setas import Setas as _setas
1817

1918

2019
class DataArray(ma.MaskedArray):

‎Stoner/core/data.py‎

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
from ..analysis.fitting import functions as fitting
5656
from ..plot import PlotMixin
5757
from ..tools.decorators import class_modifier
58+
from ..tools.file import best_saver
5859
from . import methods
5960

6061

@@ -963,3 +964,52 @@ def load(cls, *args, **kargs):
963964
copy_into(ret, datafile)
964965
datafile.filetype = filetype
965966
return datafile
967+
968+
def save(self, filename=None, as_loaded=None, filetype=False, **kwargs):
969+
"""Save a string representation of the current self object into the file 'filename'.
970+
971+
Args:
972+
self (Data):
973+
Data object to work with if not being used as a bound method.
974+
975+
Keyword Arguments:
976+
filename (string, bool or None):
977+
Filename to save data as, if this is None then the current filename for the object is used. If this
978+
is not set, then then a file dialog is used. If filename is False then a file dialog is forced.
979+
as_loaded (bool,str):
980+
If True, then the *Loaded as* key is inspected to see what the original class of the self was
981+
and then this class' save method is used to save the data. If a str then
982+
the keyword value is interpreted as the name of a subclass of the the current self.
983+
filetype (bool):
984+
Fallback is as_loaded is not provided.
985+
**kwargs:
986+
Other keyword arguments are ignored.
987+
988+
Returns:
989+
self:
990+
The current :py:class:`self` object
991+
"""
992+
as_loaded = filetype if as_loaded is None else as_loaded
993+
if filename is None:
994+
filename = self.filename
995+
if filename is None or (isinstance(filename, bool) and not filename):
996+
# now go and ask for one
997+
filename = file_dialog("w", self.filename, "Data")
998+
if not filename:
999+
raise RuntimeError("Cannot get filename to save")
1000+
match as_loaded:
1001+
case False:
1002+
saver = best_saver(filename, name=None, what="Data")
1003+
ret = saver(self, filename)
1004+
self.filename = ret.filename
1005+
return self
1006+
case True:
1007+
as_loaded = self.get("Loaded as", "self")
1008+
case str():
1009+
pass
1010+
case _:
1011+
raise TypeError("Unable to use loadtype to work out best saving routine.")
1012+
saver = best_saver(filename, name=as_loaded, what="Data")
1013+
ret = saver(self, filename)
1014+
self.filename = ret.filename
1015+
return self

‎Stoner/core/methods.py‎

Lines changed: 57 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
from ..compat import _pattern_type, int_types, str2bytes
1515
from ..tools import all_type, format_error, isiterable, operator, make_Class
16-
from ..tools.file import HDFFileManager, best_saver, file_dialog
16+
from ..tools.file import HDFFileManager, file_dialog
1717
from ..tools.widgets import RangeSelect
1818
from .array import DataArray
1919

@@ -673,6 +673,59 @@ def unique(datafile, col, return_index=False, return_inverse=False):
673673
return np.unique(datafile.column(col), return_index, return_inverse)
674674

675675

676+
def _validate_index(datafile, index, replace):
677+
match index:
678+
case None | True:
679+
index = datafile.shape[1]
680+
replace = False
681+
case int() if index == datafile.shape[1]:
682+
replace = False
683+
case _:
684+
index = datafile.find_col(index)
685+
return index, replace
686+
687+
688+
def _normalise_column_data(datafile, column_data, header, func_args):
689+
"""Sort out the data and get it into an array of values."""
690+
if isinstance(column_data, list):
691+
column_data = np.array(column_data)
692+
693+
if isinstance(column_data, DataArray) and header is None:
694+
header = column_data.column_headers
695+
696+
match column_data:
697+
case np.ndarray():
698+
np_data = column_data
699+
case _ if callable(column_data) and isinstance(func_args, dict):
700+
new_data = [column_data(x, **func_args) for x in datafile]
701+
np_data = np.array(new_data)
702+
case _ if callable(column_data):
703+
new_data = [column_data(x) for x in datafile]
704+
np_data = np.array(new_data)
705+
case _:
706+
raise NotImplementedError
707+
708+
return np_data, header
709+
710+
711+
def _data_make_setas(setas, cw):
712+
"""Make setas based on the existing setas and the one supplied."""
713+
setas = "." * cw if setas is None else setas
714+
715+
if isiterable(setas) and len(setas) == cw:
716+
for s in setas:
717+
if s not in ".-xyzuvwdefpqr":
718+
raise TypeError(
719+
f"setas parameter should be a string or list of letter in the set xyzdefuvw.-, not {setas}"
720+
)
721+
else:
722+
raise TypeError(
723+
f"""setas parameter should be a string or list of letter the same length as the number of columns
724+
being added in the set xyzdefuvw.-, not {setas}"""
725+
)
726+
return setas
727+
728+
676729
def add_column(datafile, column_data, header=None, index=None, func_args=None, replace=False, setas=None):
677730
"""Append a column of data or inserts a column to a datafile instance.
678731
@@ -704,50 +757,14 @@ def add_column(datafile, column_data, header=None, index=None, func_args=None, r
704757
Like most :py:class:`DataFile` methods, this method operates in-place in that it also modifies
705758
the original DataFile Instance as well as returning it.
706759
"""
707-
if index is None or isinstance(index, bool) and index: # Enure index is set
708-
index = datafile.shape[1]
709-
replace = False
710-
elif isinstance(index, int_types) and index == datafile.shape[1]:
711-
replace = False
712-
else:
713-
index = datafile.find_col(index)
714-
715-
# Sort out the data and get it into an array of values.
716-
if isinstance(column_data, list):
717-
column_data = np.array(column_data)
718-
719-
if isinstance(column_data, DataArray) and header is None:
720-
header = column_data.column_headers
721760

722-
if isinstance(column_data, np.ndarray):
723-
np_data = column_data
724-
elif callable(column_data):
725-
if isinstance(func_args, dict):
726-
new_data = [column_data(x, **func_args) for x in datafile]
727-
else:
728-
new_data = [column_data(x) for x in datafile]
729-
np_data = np.array(new_data)
730-
else:
731-
return NotImplemented
761+
index, replace = _validate_index(datafile, index, replace)
762+
np_data, header = _normalise_column_data(datafile, column_data, header, func_args)
732763

733764
# Sort out the sizes of the arrays
734765
np_data = np.atleast_2d(np_data).T
735766
cl, cw = np_data.shape
736-
737-
# Make setas
738-
setas = "." * cw if setas is None else setas
739-
740-
if isiterable(setas) and len(setas) == cw:
741-
for s in setas:
742-
if s not in ".-xyzuvwdefpqr":
743-
raise TypeError(
744-
f"setas parameter should be a string or list of letter in the set xyzdefuvw.-, not {setas}"
745-
)
746-
else:
747-
raise TypeError(
748-
f"""setas parameter should be a string or list of letter the same length as the number of columns
749-
being added in the set xyzdefuvw.-, not {setas}"""
750-
)
767+
setas = _data_make_setas(setas, cw)
751768

752769
# Make sure our current data is at least 2D and get its size
753770
match datafile.data.shape:
@@ -1161,52 +1178,6 @@ def rows(datafile, not_masked=False, reset=False):
11611178
yield row
11621179

11631180

1164-
def save(datafile, filename=None, as_loaded=None, filetype=False):
1165-
"""Save a string representation of the current DataFile object into the file 'filename'.
1166-
1167-
Args:
1168-
datafile (Data):
1169-
Data object to work with if not being used as a bound method.
1170-
filename (string, bool or None):
1171-
Filename to save data as, if this is None then the current filename for the object is used. If this
1172-
is not set, then then a file dialog is used. If filename is False then a file dialog is forced.
1173-
as_loaded (bool,str):
1174-
If True, then the *Loaded as* key is inspected to see what the original class of the DataFile was
1175-
and then this class' save method is used to save the data. If a str then
1176-
the keyword value is interpreted as the name of a subclass of the the current DataFile.
1177-
filetype (bool):
1178-
Fallback is as_loaded is not provided.
1179-
1180-
Returns:
1181-
datafile:
1182-
The current :py:class:`DataFile` object
1183-
"""
1184-
as_loaded = filetype if as_loaded is None else as_loaded
1185-
if filename is None:
1186-
filename = datafile.filename
1187-
if filename is None or (isinstance(filename, bool) and not filename):
1188-
# now go and ask for one
1189-
filename = file_dialog("w", datafile.filename, "Data")
1190-
if not filename:
1191-
raise RuntimeError("Cannot get filename to save")
1192-
match as_loaded:
1193-
case False:
1194-
saver = best_saver(filename, name=None, what="Data")
1195-
ret = saver(datafile, filename)
1196-
datafile.filename = ret.filename
1197-
return datafile
1198-
case True:
1199-
as_loaded = datafile.get("Loaded as", "DataFile")
1200-
case str():
1201-
pass
1202-
case _:
1203-
raise TypeError("Unable to use loadtype to work out best saving routine.")
1204-
saver = best_saver(filename, name=as_loaded, what="Data")
1205-
ret = saver(datafile, filename)
1206-
datafile.filename = ret.filename
1207-
return datafile
1208-
1209-
12101181
def swap_column(datafile, *swp, headers_too=True, **kwargs):
12111182
"""Swap pairs of columns in the data.
12121183

‎Stoner/core/operators.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,7 @@ def __read_iterable(self, reader):
257257
readline = reader.__next__
258258

259259
else:
260-
return NotImplemented
260+
raise NotImplementedError
261261
row = readline().split("\t")
262262
if row[0].strip() == "TDI Format 1.5":
263263
fmt = 1.5

‎Stoner/core/property.py‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,7 @@ def filename(self):
123123
self.filename = "Untitled"
124124
if isinstance(self._filename, path_types):
125125
return str(self._filename)
126-
else:
127-
return self._filename
126+
return self._filename
128127

129128
@filename.setter
130129
def filename(self, filename):

‎Stoner/core/setas.py‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
33
"""setas module provides the setas class for DataFile and friends."""
4-
__all__ = ["setas"]
4+
__all__ = ["Setas"]
55
import copy
66
import re
77
from collections.abc import Iterable, MutableMapping
@@ -13,7 +13,7 @@
1313
from .utils import decode_string
1414

1515

16-
class setas(MutableMapping):
16+
class Setas(MutableMapping):
1717
"""A Class that provides a mechanism for managing the column assignments in a DataFile like object.
1818
1919
Implements a MutableMapping bsed on the column_headers as the keys (with a few tweaks!).
@@ -163,9 +163,9 @@ def clone(self):
163163
"""Create an exact copy of the current object."""
164164
cls = type(self)
165165
new = cls()
166-
for attr in self.__dict__:
167-
if not callable(self.__dict__[attr]):
168-
new.__dict__[attr] = copy.deepcopy(self.__dict__[attr])
166+
for attr, val in self.__dict__.items():
167+
if not callable(val):
168+
new.__dict__[attr] = copy.deepcopy(val)
169169
return new
170170

171171
@property
@@ -281,10 +281,10 @@ def __call__(self, *args, **kargs):
281281
return_self = kargs.pop("_self", False)
282282
if not (args or kargs): # New - bare call to setas will return the current value.
283283
return self.setas
284-
if len(args) == 1 and isinstance(args[0], setas):
284+
if len(args) == 1 and isinstance(args[0], Setas):
285285
args = list(args)
286286
args[0] = args[0].to_list()
287-
if len(args) == 1 and not (isinstance(args[0], string_types + (setas,)) or isiterable(args[0])):
287+
if len(args) == 1 and not (isinstance(args[0], string_types + (Setas,)) or isiterable(args[0])):
288288
raise SyntaxError(
289289
f"setas should be called with eother a string, iterable object or setas object, not a {type(args[0])}"
290290
)
@@ -311,7 +311,7 @@ def __call__(self, *args, **kargs):
311311
if len(value) > self._size:
312312
value = value[: self._size]
313313
elif len(value) < self._size:
314-
value = [v for v in value] # Ensure value is now a list
314+
value = list(value) # Ensure value is now a list
315315
value.extend(list("." * (self._size - len(value))))
316316
value = value[: self._size]
317317
for i, v in enumerate(value):
@@ -347,8 +347,8 @@ def __eq__(self, other):
347347
"""Check to see if this is the same object, or has the same headers and the same setas values."""
348348
ret = False
349349
if isinstance(other, string_types): # Expand strings and convert to list
350-
other = [c for c in decode_string(other)]
351-
if not isinstance(other, setas): # Ok, need to check whether items match
350+
other = list(decode_string(other))
351+
if not isinstance(other, Setas): # Ok, need to check whether items match
352352
if isiterable(other) and len(other) <= self._size:
353353
for m in self.setas[len(other) :]: # Check that if other is short we don't have assignments there
354354
if m != ".":
@@ -714,7 +714,7 @@ def unset(self, what=None):
714714

715715
def update(self, other=(), **kwds): # pylint: disable=arguments-differ
716716
"""Replace any assignments in self with assignments from other."""
717-
if isinstance(other, setas):
717+
if isinstance(other, Setas):
718718
other = other.to_dict()
719719
elif isinstance(other, tuple) and len(other) == 0:
720720
other = kwds

0 commit comments

Comments
 (0)