Repository: biopython/biopython

Issue:
Explaining the SeqRecord letter_annotations length limit
### Setup

I am reporting a problem with Biopython version 1.79, Python version  3.9.12, and operating
system as follows windows 10 Pro:

```python
import sys; print(sys.version)
import platform; print(platform.python_implementation()); print(platform.platform())
import Bio; print(Bio.__version__)
```

from Bio.Seq import Seq
from Bio.SeqRecord import SeqRecord
from Bio.SeqFeature import SeqFeature

my_sequence = Seq("GATCGATCGATCGATCGATCGATCGATCGATC")
my_sequence_record = SeqRecord(my_sequence)
my_sequence_record.letter_annotations["phred_quality"] = [4, 4, 3, 30]

output
(base) C:\Users\dror\OneDrive - ariel.ac.il\teaching\biopython\week5>python test.py
Traceback (most recent call last):
  File "C:\Users\dror\OneDrive - ariel.ac.il\teaching\biopython\week5\test.py", line 7, in <module>
    my_sequence_record.letter_annotations["phred_quality"] = [4, 4, 3, 30]
  File "C:\Users\dror\anaconda3\lib\site-packages\Bio\SeqRecord.py", line 86, in __setitem__
    raise TypeError(
TypeError: We only allow python sequences (lists, tuples or strings) of length 32.

### Expected behaviour
none

### Actual behaviour

(*Please fill this in, and provide any exception message in full*)

### Steps to reproduce

(*Please fill this in *)



Discussion:
The number of quality scores has to match the sequence length, one score
for each base.

Thanks, Is it possible to make the error massage more explanatory?

Yes - What would you suggest here?

The number of annotation values has to match the sequence length.
The exception is raised here:

https://github.com/biopython/biopython/blob/biopython-181/Bio/SeqRecord.py#L87

```python
            raise TypeError(
                "We only allow python sequences (lists, tuples or strings) "
                f"of length {self._length}."
            )
```

While in principle anyone might be using the ``_RestrictedDict`` class, it is private (leading underscore), so we can make the exception message more specific to the ``SeqRecord`` usage.

So maybe:

```python
            raise TypeError(
                "Any per-letter annotation should be a Python sequence "
                "(list, tuple or string) of the same length as the "
                "biological sequence, here {self._length}"
            )
```
Looks good, Thanks

Resolving patch:
diff --git a/Bio/SeqRecord.py b/Bio/SeqRecord.py
--- a/Bio/SeqRecord.py
+++ b/Bio/SeqRecord.py
@@ -1,6 +1,6 @@
 # Copyright 2000-2002 Andrew Dalke.  All rights reserved.
 # Copyright 2002-2004 Brad Chapman.  All rights reserved.
-# Copyright 2006-2020 by Peter Cock.  All rights reserved.
+# Copyright 2006-2023 by Peter Cock.  All rights reserved.
 #
 # This file is part of the Biopython distribution and governed by your
 # choice of the "Biopython License Agreement" or the "BSD 3-Clause License".
@@ -41,7 +41,7 @@ class _RestrictedDict(dict):
     >>> x["test"] = "hello world"
     Traceback (most recent call last):
     ...
-    TypeError: We only allow python sequences (lists, tuples or strings) of length 5.
+    TypeError: Any per-letter annotation should be a Python sequence (list, tuple or string) of the same length as the biological sequence, here 5.
 
     The expected length is stored as a private attribute,
 
@@ -85,8 +85,9 @@ def __setitem__(self, key, value):
             or (hasattr(self, "_length") and len(value) != self._length)
         ):
             raise TypeError(
-                "We only allow python sequences (lists, tuples or strings) "
-                f"of length {self._length}."
+                "Any per-letter annotation should be a Python sequence "
+                "(list, tuple or string) of the same length as the "
+                f"biological sequence, here {self._length}."
             )
         dict.__setitem__(self, key, value)
 


Test patch: