use _data instead of data in MutableSeq to be consistent with Seq (#3311)

* use _data instead of data in MutableSeq to be consistent with Seq

* adding a .data getter/setter with a deprecation warning

* travis

* travis
This commit is contained in:
mdehoon
2020-10-17 10:05:13 +09:00
committed by GitHub
parent e1d7194b38
commit eacd368d47
2 changed files with 72 additions and 48 deletions

View File

@ -24,7 +24,7 @@ import array
import sys
import warnings
from Bio import BiopythonWarning
from Bio import BiopythonWarning, BiopythonDeprecationWarning
from Bio.Data.IUPACData import ambiguous_dna_complement, ambiguous_rna_complement
from Bio.Data.IUPACData import ambiguous_dna_letters as _ambiguous_dna_letters
from Bio.Data.IUPACData import ambiguous_rna_letters as _ambiguous_rna_letters
@ -1699,14 +1699,36 @@ class MutableSeq:
def __init__(self, data):
"""Initialize the class."""
if isinstance(data, str): # TODO - What about unicode?
self.data = array.array("u", data)
self._data = array.array("u", data)
elif isinstance(data, (Seq, int, float)):
raise TypeError(
"The sequence data given to a MutableSeq object "
"should be a string or an array (not a Seq object etc)"
)
else:
self.data = data # assumes the input is an array
self._data = data # assumes the input is an array
@property
def data(self):
"""Get the data."""
warnings.warn(
"Accessing MutableSeq.data has been deprecated, as it is now a private "
"attribute. Please use indexing to access the sequence contents of "
"a MutableSeq object.",
BiopythonDeprecationWarning,
)
return self._data
@data.setter
def data(self, value):
"""Set the data."""
warnings.warn(
"Accessing MutableSeq.data has been deprecated, as it is now a private "
"attribute. Please use indexing to access the sequence contents of "
"a MutableSeq object.",
BiopythonDeprecationWarning,
)
self._data = value
def __repr__(self):
"""Return (truncated) representation of the sequence for debugging."""
@ -1727,7 +1749,7 @@ class MutableSeq:
should continue to use my_seq.tostring() rather than str(my_seq).
"""
# See test_GAQueens.py for an historic usage of a non-string alphabet!
return "".join(self.data)
return "".join(self._data)
def __eq__(self, other):
"""Compare the sequence to another sequence or a string.
@ -1757,13 +1779,13 @@ class MutableSeq:
"""
if isinstance(other, MutableSeq):
return self.data == other.data
return self._data == other._data
return str(self) == str(other)
def __lt__(self, other):
"""Implement the less-than operand."""
if isinstance(other, MutableSeq):
return self.data < other.data
return self._data < other._data
if isinstance(other, (str, Seq, UnknownSeq)):
return str(self) < str(other)
raise TypeError(
@ -1774,7 +1796,7 @@ class MutableSeq:
def __le__(self, other):
"""Implement the less-than or equal operand."""
if isinstance(other, MutableSeq):
return self.data <= other.data
return self._data <= other._data
if isinstance(other, (str, Seq, UnknownSeq)):
return str(self) <= str(other)
raise TypeError(
@ -1785,7 +1807,7 @@ class MutableSeq:
def __gt__(self, other):
"""Implement the greater-than operand."""
if isinstance(other, MutableSeq):
return self.data > other.data
return self._data > other._data
if isinstance(other, (str, Seq, UnknownSeq)):
return str(self) > str(other)
raise TypeError(
@ -1796,7 +1818,7 @@ class MutableSeq:
def __ge__(self, other):
"""Implement the greater-than or equal operand."""
if isinstance(other, MutableSeq):
return self.data >= other.data
return self._data >= other._data
if isinstance(other, (str, Seq, UnknownSeq)):
return str(self) >= str(other)
raise TypeError(
@ -1806,7 +1828,7 @@ class MutableSeq:
def __len__(self):
"""Return the length of the sequence, use len(my_seq)."""
return len(self.data)
return len(self._data)
def __getitem__(self, index):
"""Return a subsequence of single letter, use my_seq[index].
@ -1817,10 +1839,10 @@ class MutableSeq:
"""
if isinstance(index, int):
# Return a single letter as a string
return self.data[index]
return self._data[index]
else:
# Return the (sub)sequence as another Seq object
return MutableSeq(self.data[index])
return MutableSeq(self._data[index])
def __setitem__(self, index, value):
"""Set a subsequence of single letter via value parameter.
@ -1832,15 +1854,15 @@ class MutableSeq:
"""
if isinstance(index, int):
# Replacing a single letter with a new string
self.data[index] = value
self._data[index] = value
else:
# Replacing a sub-sequence
if isinstance(value, MutableSeq):
self.data[index] = value.data
elif isinstance(value, type(self.data)):
self.data[index] = value
self._data[index] = value._data
elif isinstance(value, type(self._data)):
self._data[index] = value
else:
self.data[index] = array.array("u", str(value))
self._data[index] = array.array("u", str(value))
def __delitem__(self, index):
"""Delete a subsequence of single letter.
@ -1851,7 +1873,7 @@ class MutableSeq:
MutableSeq('CTCGACGTCG')
"""
# Could be deleting a single letter, or a slice
del self.data[index]
del self._data[index]
def __add__(self, other):
"""Add another sequence or string to this sequence.
@ -1861,7 +1883,7 @@ class MutableSeq:
if isinstance(other, MutableSeq):
# See test_GAQueens.py for an historic usage of a non-string
# alphabet! Adding the arrays should support this.
return self.__class__(self.data + other.data)
return self.__class__(self._data + other._data)
elif isinstance(other, (str, Seq)):
return self.__class__(str(self) + str(other))
else:
@ -1877,7 +1899,7 @@ class MutableSeq:
if isinstance(other, MutableSeq):
# See test_GAQueens.py for an historic usage of a non-string
# alphabet! Adding the arrays should support this.
return self.__class__(other.data + self.data)
return self.__class__(other._data + self._data)
elif isinstance(other, (str, Seq)):
return self.__class__(str(other) + str(self))
else:
@ -1895,7 +1917,7 @@ class MutableSeq:
"""
if not isinstance(other, int):
raise TypeError(f"can't multiply {self.__class__.__name__} by non-int type")
return self.__class__(self.data * other)
return self.__class__(self._data * other)
def __rmul__(self, other):
"""Multiply integer by MutableSeq.
@ -1909,7 +1931,7 @@ class MutableSeq:
"""
if not isinstance(other, int):
raise TypeError(f"can't multiply {self.__class__.__name__} by non-int type")
return self.__class__(self.data * other)
return self.__class__(self._data * other)
def __imul__(self, other):
"""Multiply MutableSeq in-place.
@ -1922,7 +1944,7 @@ class MutableSeq:
"""
if not isinstance(other, int):
raise TypeError(f"can't multiply {self.__class__.__name__} by non-int type")
return self.__class__(self.data * other)
return self.__class__(self._data * other)
def append(self, c):
"""Add a subsequence to the mutable sequence object.
@ -1934,7 +1956,7 @@ class MutableSeq:
No return value.
"""
self.data.append(c)
self._data.append(c)
def insert(self, i, c):
"""Add a subsequence to the mutable sequence object at a given index.
@ -1949,7 +1971,7 @@ class MutableSeq:
No return value.
"""
self.data.insert(i, c)
self._data.insert(i, c)
def pop(self, i=(-1)):
"""Remove a subsequence of a single letter at given index.
@ -1966,8 +1988,8 @@ class MutableSeq:
Returns the last character of the sequence.
"""
c = self.data[i]
del self.data[i]
c = self._data[i]
del self._data[i]
return c
def remove(self, item):
@ -1983,9 +2005,9 @@ class MutableSeq:
No return value.
"""
for i in range(len(self.data)):
if self.data[i] == item:
del self.data[i]
for i in range(len(self._data)):
if self._data[i] == item:
del self._data[i]
return
raise ValueError("MutableSeq.remove(x): x not in list")
@ -2042,7 +2064,7 @@ class MutableSeq:
if len(search) == 1:
# Try and be efficient and work directly from the array.
count = 0
for c in self.data[start:end]:
for c in self._data[start:end]:
if c == search:
count += 1
return count
@ -2127,9 +2149,9 @@ class MutableSeq:
subsequences are not supported. Instead this acts like an array or
a list of the entries. There is therefore no ``.rindex()`` method.
"""
# TODO?: return self.data.index(i)
for i in range(len(self.data)):
if self.data[i] == item:
# TODO?: return self._data.index(i)
for i in range(len(self._data)):
if self._data[i] == item:
return i
raise ValueError("MutableSeq.index(x): x not in list")
@ -2138,7 +2160,7 @@ class MutableSeq:
No return value.
"""
self.data.reverse()
self._data.reverse()
def complement(self):
"""Modify the mutable sequence to take on its complement.
@ -2150,16 +2172,16 @@ class MutableSeq:
If the sequence contains both T and U, an exception is raised.
"""
if "U" in self.data and "T" in self.data:
if "U" in self._data and "T" in self._data:
raise ValueError("Mixed RNA/DNA found")
elif "U" in self.data:
elif "U" in self._data:
d = ambiguous_rna_complement
else:
d = ambiguous_dna_complement
mixed = d.copy() # We're going to edit this to be mixed case!
mixed.update((x.lower(), y.lower()) for x, y in d.items())
self.data = [mixed[_] for _ in self.data]
self.data = array.array("u", self.data)
self._data = [mixed[_] for _ in self._data]
self._data = array.array("u", self._data)
def reverse_complement(self):
"""Modify the mutable sequence to take on its reverse complement.
@ -2167,7 +2189,7 @@ class MutableSeq:
No return value.
"""
self.complement()
self.data.reverse()
self._data.reverse()
def extend(self, other):
"""Add a sequence to the original mutable sequence object.
@ -2183,11 +2205,11 @@ class MutableSeq:
No return value.
"""
if isinstance(other, MutableSeq):
for c in other.data:
self.data.append(c)
for c in other._data:
self._data.append(c)
else:
for c in other:
self.data.append(c)
self._data.append(c)
def toseq(self):
"""Return the full sequence as a new immutable Seq object.
@ -2199,7 +2221,7 @@ class MutableSeq:
>>> my_mseq.toseq()
Seq('MKQHKAMIVALIVICITAVVAAL')
"""
return Seq("".join(self.data))
return Seq("".join(self._data))
def join(self, other):
"""Return a merge of the sequences in other, spaced by the sequence from self.

View File

@ -427,13 +427,15 @@ Numeric support
Following the Release of 1.48, Numeric support in Biopython is discontinued.
Please move to NumPy for Biopython 1.49 or later.
Bio.Seq and the data property
-----------------------------
Bio.Seq, Bio.MutableSeq and the data property
---------------------------------------------
Direct use of the Seq object (and MutableSeq object) .data property is
deprecated. As of Release 1.49, writing to the Seq object's .data property
triggered a warning, and this property was made read only in Release 1.53. In
Release 1.55 final, accessing the .data property gives a DeprecationWarning.
The Seq object's .data property was removed in Release 1.61.
Release 1.55 final, accessing the .data property of a Seq object gives a
DeprecationWarning. The Seq object's .data property was removed in Release
1.61. Starting from Release 1.78, accessing the .data property of a MutableSeq
object similarly gives a deprecation warning.
Bio.Transcribe and Bio.Translate
--------------------------------