Repository: biopython/biopython

Issue:
TypeError when get structure using MMCIFParser with parameter auth_residues=False
### Setup

Hi, I am reporting a problem with Biopython version, Python version, and operating
system as follows:

```python
import sys; print(sys.version)
import platform; print(platform.python_implementation()); print(platform.platform())
import Bio; print(Bio.__version__)
```

```
3.10.8 | packaged by conda-forge | (main, Nov 24 2022, 14:07:00) [MSC v.1916 64 bit (AMD64)]
CPython
Windows-10-10.0.19044-SP0
1.80
```

### Expected behaviour

I want to exact the residues of `1FE4.cif` with mmcif-style residue index, so I look up the document and run the code
```
from Bio.PDB.MMCIFParser import MMCIFParser
parser = MMCIFParser(auth_chains=False, auth_residues=False)
pdb_structure = parser.get_structure("1FE4", "1fe4.cif")
```

### Actual behaviour

The code can run well with parameter auth_residues=True, but when I set auth_residues=False, it seems to be some mistakes with the usage of warning.warn in `_build_structure` of `\Bio\PDB\MMCIFParser.py` for the type of input
```
Traceback (most recent call last):
  File "c:\Users\86153\Desktop\ai\bio\code\bio.py", line 19, in <module>
    pdb_structure = parser.get_structure("1FE4", "1fe4.cif")
  File "C:\Users\86153\miniconda3\envs\bio\lib\site-packages\Bio\PDB\MMCIFParser.py", line 74, in get_structure
    self._build_structure(structure_id)
  File "C:\Users\86153\miniconda3\envs\bio\lib\site-packages\Bio\PDB\MMCIFParser.py", line 241, in _build_structure
    warnings.warn(
TypeError: 'type' object cannot be interpreted as an integer
```

The error happens in line 234-246 of `\Bio\PDB\MMCIFParser.py`
```python
if resseq == ".":
    # Non-existing residue ID
    try:
        msg_resseq = mmcif_dict["_atom_site.auth_seq_id"][i]
        msg = "Non-existing residue ID in chain '{}', residue '{}'".format(
            chainid, msg_resseq
        )
    except (KeyError, IndexError):
        msg = f"Non-existing residue ID in chain '{chainid}'"
    warnings.warn(
        "PDBConstructionWarning: ",
        msg,
        PDBConstructionWarning,
    )
    continue
```

I look up the usage of warnings.warn in python 3.10, and I find the third parameters of warnings.warn should be a interger of stack level, but in the code mentioned above, the type is `PDBConstructionWarning`. I guess the code want to concat the string "PDBConstructionWarning: " and msg, and let `PDBConstructionWarning` to be the second parameter which indicates the category of warning. I make some minor changes and it works
```
if resseq == ".":
    # Non-existing residue ID
    try:
        msg_resseq = mmcif_dict["_atom_site.auth_seq_id"][i]
        msg = "Non-existing residue ID in chain '{}', residue '{}'".format(
            chainid, msg_resseq
        )
    except (KeyError, IndexError):
        msg = f"Non-existing residue ID in chain '{chainid}'"
    warnings.warn(
        "PDBConstructionWarning: " +
        msg,
        PDBConstructionWarning,
    )
    continue
```
In addition, I find the same mistakes appear in `\Bio\PDB\MMCIFParser.py`. May you check the code and fix the minor mistakes in your latest version? Thank you!

can't set auth_residues=False in MMCIFParser
### Setup

I am reporting a problem with Biopython version, Python version, and operating
system as follows:

```python
parser = PDB.MMCIFParser(QUIET=True,auth_residues=False)
strure = parser.get_structure("",'../../../datasets/PDBs/1ab9.cif')
```

### Expected behaviour

I would expect this to make it so that I can index the structure as ``structure[model#][chain_name][index]`` with index being the 2 in  TRP B 2 126  instead of 141 from 141 TRP B from below
```
ATOM   1008 C CH2 . TRP B 2 126 ? 14.801 1.309   29.870 1.00 11.99 ? 141 TRP B CH2 1 
```
or make it so that residue.get_id can parse similarly 

### Actual behaviour

returns type error upon file parsing

```
TypeError                                 Traceback (most recent call last)
parser = PDB.MMCIFParser(QUIET=True,auth_residues=False)
----> structure = parser.get_structure("",f'../../../datasets/PDBs/1ab9.cif)

~/anaconda3/envs/data/lib/python3.10/site-packages/Bio/PDB/MMCIFParser.py:74), in MMCIFParser.get_structure(self, structure_id, filename)
     72         warnings.filterwarnings("ignore", category=PDBConstructionWarning)
     73     self._mmcif_dict = MMCIF2Dict(filename)
---> 74     self._build_structure(structure_id)
     75     self._structure_builder.set_header(self._get_header())
     77 return self._structure_builder.get_structure()

~/anaconda3/envs/data/lib/python3.10/site-packages/Bio/PDB/MMCIFParser.py:241), in MMCIFParser._build_structure(self, structure_id)
    239     except (KeyError, IndexError):
    240         msg = f"Non-existing residue ID in chain '{chainid}'"
--> 241     warnings.warn(
    242         "PDBConstructionWarning: ",
    243         msg,
    244         PDBConstructionWarning,
    245     )
    246     continue
    247 int_resseq = int(resseq)

TypeError: 'type' object cannot be interpreted as an integer
```

### Steps to reproduce

parsing a structure with ``PDB.MMCIFParser(auth_residues=False)``



Discussion:
You change looks good - could you submit this as a pull request please? You can do a small edit like this entirely within GitHub's web interface. Thank you.
Ok, I will soon close the issue and submit PR.
Normally we'd leave the issue open until the pull request is merged, otherwise the problem might be forgotten in between - or someone might open a duplicate if by bad luck they find the same problem.
Issue edited to use markup to show indentation etc.

I am not familiar with this area of the code. Maybe @jgreener64 or @JoaoRodrigues might be able to advise?
Looks like a repeat of https://github.com/biopython/biopython/issues/4216, I'll submit a PR to fix.

Looks like we don't test the `auth_residues` or `auth_chains` options, ideally we would.

Resolving patch:
diff --git a/Bio/PDB/MMCIFParser.py b/Bio/PDB/MMCIFParser.py
--- a/Bio/PDB/MMCIFParser.py
+++ b/Bio/PDB/MMCIFParser.py
@@ -215,8 +215,7 @@ def _build_structure(self, structure_id):
             except ValueError:
                 serial = atom_serial_list[i]
                 warnings.warn(
-                    "PDBConstructionWarning: "
-                    "Some atom serial numbers are not numerical",
+                    "PDBConstructionWarning: Some atom serial numbers are not numerical",
                     PDBConstructionWarning,
                 )
 
@@ -239,8 +238,7 @@ def _build_structure(self, structure_id):
                 except (KeyError, IndexError):
                     msg = f"Non-existing residue ID in chain '{chainid}'"
                 warnings.warn(
-                    "PDBConstructionWarning: ",
-                    msg,
+                    "PDBConstructionWarning: " + msg,
                     PDBConstructionWarning,
                 )
                 continue
@@ -530,8 +528,7 @@ def _build_structure(self, structure_id, filehandle):
                 except (KeyError, IndexError):
                     msg = f"Non-existing residue ID in chain '{chainid}'"
                 warnings.warn(
-                    "PDBConstructionWarning: ",
-                    msg,
+                    "PDBConstructionWarning: " + msg,
                     PDBConstructionWarning,
                 )
                 continue


Test patch:
diff --git a/Tests/test_PDB_MMCIFParser.py b/Tests/test_PDB_MMCIFParser.py
--- a/Tests/test_PDB_MMCIFParser.py
+++ b/Tests/test_PDB_MMCIFParser.py
@@ -54,6 +54,21 @@ def test_parsers(self):
         self.assertEqual(len(structure), 1)
         self.assertEqual(len(f_structure), 1)
 
+        parser_lab_res = MMCIFParser(auth_residues=False, QUIET=True)
+        fast_parser_lab_res = FastMMCIFParser(auth_residues=False, QUIET=True)
+        parser_lab_chain = MMCIFParser(auth_chains=False, QUIET=True)
+        fast_parser_lab_chain = FastMMCIFParser(auth_chains=False, QUIET=True)
+
+        structure_lr = parser_lab_res.get_structure("example", "PDB/1A8O.cif")
+        f_structure_lr = fast_parser_lab_res.get_structure("example", "PDB/1A8O.cif")
+        structure_lc = parser_lab_chain.get_structure("example", "PDB/1A8O.cif")
+        f_structure_lc = fast_parser_lab_chain.get_structure("example", "PDB/1A8O.cif")
+
+        self.assertEqual(len(list(structure_lr.get_atoms())), 556)
+        self.assertEqual(len(list(f_structure_lr.get_atoms())), 556)
+        self.assertEqual(len(list(structure_lc.get_atoms())), 644)
+        self.assertEqual(len(list(f_structure_lc.get_atoms())), 644)
+
         for ppbuild in [PPBuilder(), CaPPBuilder()]:
             # ==========================================================
             # Check that serial_num (model column) is stored properly