From 0dbca137f9b3b35ff67bc56047cebc9a4e75bd61 Mon Sep 17 00:00:00 2001 From: Valerij Talagayev <82884038+talagayev@users.noreply.github.com> Date: Wed, 27 Mar 2024 12:10:51 +0100 Subject: [PATCH 01/14] addition of tests for str and pathlib handling of SingleFrameReaderBase + removal of duplicate import --- testsuite/MDAnalysisTests/coordinates/test_gro.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/testsuite/MDAnalysisTests/coordinates/test_gro.py b/testsuite/MDAnalysisTests/coordinates/test_gro.py index e25bf969fc5..001f0a5d859 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_gro.py +++ b/testsuite/MDAnalysisTests/coordinates/test_gro.py @@ -21,6 +21,7 @@ # J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 # from io import StringIO +from pathlib import Path import MDAnalysis as mda import numpy as np @@ -46,7 +47,6 @@ assert_equal, ) import pytest -from io import StringIO class TestGROReaderOld(RefAdK): @@ -529,3 +529,14 @@ def test_gro_empty_box_write_read(tmpdir): with pytest.warns(UserWarning, match=wmsg): u2 = mda.Universe('test.gro') assert u2.dimensions is None + +def test_pathlib_singleframereaderbase(): + top = Path(GRO) + assert isinstance(top, Path) + u = mda.Universe(top) + assert u.atoms.n_atoms == 47681 + +def test_string_singleframereaderbase(): + assert isinstance(GRO, str) + u = mda.Universe(GRO) + assert u.atoms.n_atoms == 47681 From c2c7c2c305c477213eac5abc2c28177dceef75df Mon Sep 17 00:00:00 2001 From: Valerij Talagayev <82884038+talagayev@users.noreply.github.com> Date: Wed, 27 Mar 2024 13:26:31 +0100 Subject: [PATCH 02/14] renamed tests to specify GRO input as testcase --- testsuite/MDAnalysisTests/coordinates/test_gro.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/MDAnalysisTests/coordinates/test_gro.py b/testsuite/MDAnalysisTests/coordinates/test_gro.py index 001f0a5d859..57fc2798ea1 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_gro.py +++ b/testsuite/MDAnalysisTests/coordinates/test_gro.py @@ -530,13 +530,13 @@ def test_gro_empty_box_write_read(tmpdir): u2 = mda.Universe('test.gro') assert u2.dimensions is None -def test_pathlib_singleframereaderbase(): +def test_gro_pathlib_singleframereaderbase(): top = Path(GRO) assert isinstance(top, Path) u = mda.Universe(top) assert u.atoms.n_atoms == 47681 -def test_string_singleframereaderbase(): +def test_gro_string_singleframereaderbase(): assert isinstance(GRO, str) u = mda.Universe(GRO) assert u.atoms.n_atoms == 47681 From 05ea8dec62496fa5db797b077ae4e0a51fe343a1 Mon Sep 17 00:00:00 2001 From: Valerij Talagayev <82884038+talagayev@users.noreply.github.com> Date: Wed, 27 Mar 2024 13:42:38 +0100 Subject: [PATCH 03/14] Added testcase of LAMMPS str and pathlib handling in class SingleFrameReaderBase --- testsuite/MDAnalysisTests/coordinates/test_lammps.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/testsuite/MDAnalysisTests/coordinates/test_lammps.py b/testsuite/MDAnalysisTests/coordinates/test_lammps.py index 88b4b8c35ee..dd446f55ec5 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_lammps.py +++ b/testsuite/MDAnalysisTests/coordinates/test_lammps.py @@ -30,6 +30,7 @@ from MDAnalysis import NoDataError from numpy.testing import (assert_equal, assert_allclose) +from pathlib import Path from MDAnalysisTests import make_Universe from MDAnalysisTests.coordinates.reference import ( @@ -819,3 +820,14 @@ def test_box(self, u_dump, u_data, reference_box): rtol=1e-5, atol=0) assert_allclose(u_data.dimensions, reference_box, rtol=1e-5, atol=0) + +def test_pathlib_lammps_singleframereaderbase(): + top = Path(LAMMPSdata) + assert isinstance(top, Path) + u = mda.Universe(top) + assert u.atoms.n_atoms == 18364 + +def test_string_lammps_singleframereaderbase(): + assert isinstance(LAMMPSdata, str) + u = mda.Universe(LAMMPSdata) + assert u.atoms.n_atoms == 18364 From 5c0383ca3d2e18018eb59faff5917a83374748cb Mon Sep 17 00:00:00 2001 From: Valerij Talagayev <82884038+talagayev@users.noreply.github.com> Date: Wed, 27 Mar 2024 13:47:19 +0100 Subject: [PATCH 04/14] Update AUTHORS list --- package/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/package/AUTHORS b/package/AUTHORS index 35e4029f776..5c75da76aff 100644 --- a/package/AUTHORS +++ b/package/AUTHORS @@ -236,6 +236,7 @@ Chronological list of authors 2024 - Aditya Keshari - Philipp Stärk + - Valerij Talagayev External code ------------- From 9a4932ba02d5c2a0adaeb2a7fc95d2410cbaefce Mon Sep 17 00:00:00 2001 From: Valerij Talagayev <82884038+talagayev@users.noreply.github.com> Date: Wed, 27 Mar 2024 13:49:16 +0100 Subject: [PATCH 05/14] Update CHANGELOG adding the implementation of tests for str and pathlib handling --- package/CHANGELOG | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package/CHANGELOG b/package/CHANGELOG index 094ec0091ca..4b301cc86d9 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -16,7 +16,7 @@ The rules for this file: ------------------------------------------------------------------------------- ??/??/?? IAlibay, HeetVekariya, marinegor, lilyminium, RMeli, ljwoods2, aditya292002, pstaerk, PicoCentauri, BFedder, - tyler.je.reddy + tyler.je.reddy, talagayev * 2.8.0 @@ -34,6 +34,7 @@ Fixes * Fix deploy action to use the correct version of the pypi upload action. Enhancements + * Implementation of tests for str and pathlib handling of SingleFrameReaderBase (Issue #3937) * Improved performance of PDBWriter (Issue #2785, PR #4472) * Added parsing of arbitrary columns of the LAMMPS dump parser. (Issue #3504) * Documented the r0 attribute in the `Contacts` class and added the From ff2a83279d0662fad6b929f07ef5306a7dcd19ba Mon Sep 17 00:00:00 2001 From: Valerij Talagayev <82884038+talagayev@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:18:27 +0100 Subject: [PATCH 06/14] Adjusting blank lines for PEP8 --- testsuite/MDAnalysisTests/coordinates/test_lammps.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/MDAnalysisTests/coordinates/test_lammps.py b/testsuite/MDAnalysisTests/coordinates/test_lammps.py index dd446f55ec5..3d105131dec 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_lammps.py +++ b/testsuite/MDAnalysisTests/coordinates/test_lammps.py @@ -821,12 +821,14 @@ def test_box(self, u_dump, u_data, reference_box): assert_allclose(u_data.dimensions, reference_box, rtol=1e-5, atol=0) + def test_pathlib_lammps_singleframereaderbase(): top = Path(LAMMPSdata) assert isinstance(top, Path) u = mda.Universe(top) assert u.atoms.n_atoms == 18364 + def test_string_lammps_singleframereaderbase(): assert isinstance(LAMMPSdata, str) u = mda.Universe(LAMMPSdata) From d85defcd21781b35837d01e9f95cfe07d79b0533 Mon Sep 17 00:00:00 2001 From: Valerij Talagayev <82884038+talagayev@users.noreply.github.com> Date: Wed, 27 Mar 2024 14:19:00 +0100 Subject: [PATCH 07/14] adjsuting blank lines for PEP8 --- testsuite/MDAnalysisTests/coordinates/test_gro.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/MDAnalysisTests/coordinates/test_gro.py b/testsuite/MDAnalysisTests/coordinates/test_gro.py index 57fc2798ea1..ee1539d1474 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_gro.py +++ b/testsuite/MDAnalysisTests/coordinates/test_gro.py @@ -530,12 +530,14 @@ def test_gro_empty_box_write_read(tmpdir): u2 = mda.Universe('test.gro') assert u2.dimensions is None + def test_gro_pathlib_singleframereaderbase(): top = Path(GRO) assert isinstance(top, Path) u = mda.Universe(top) assert u.atoms.n_atoms == 47681 + def test_gro_string_singleframereaderbase(): assert isinstance(GRO, str) u = mda.Universe(GRO) From 87f7a95d9bf40cf117294116d7a6fdaf60af4dac Mon Sep 17 00:00:00 2001 From: Valerij Talagayev <82884038+talagayev@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:25:43 +0200 Subject: [PATCH 08/14] removed singleframereader test in test_gro.py --- testsuite/MDAnalysisTests/coordinates/test_gro.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/testsuite/MDAnalysisTests/coordinates/test_gro.py b/testsuite/MDAnalysisTests/coordinates/test_gro.py index ee1539d1474..a4342f3801f 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_gro.py +++ b/testsuite/MDAnalysisTests/coordinates/test_gro.py @@ -21,7 +21,6 @@ # J. Comput. Chem. 32 (2011), 2319--2327, doi:10.1002/jcc.21787 # from io import StringIO -from pathlib import Path import MDAnalysis as mda import numpy as np @@ -529,16 +528,3 @@ def test_gro_empty_box_write_read(tmpdir): with pytest.warns(UserWarning, match=wmsg): u2 = mda.Universe('test.gro') assert u2.dimensions is None - - -def test_gro_pathlib_singleframereaderbase(): - top = Path(GRO) - assert isinstance(top, Path) - u = mda.Universe(top) - assert u.atoms.n_atoms == 47681 - - -def test_gro_string_singleframereaderbase(): - assert isinstance(GRO, str) - u = mda.Universe(GRO) - assert u.atoms.n_atoms == 47681 From 27e9685200e2d582162e14769ea4eab0e6753e9d Mon Sep 17 00:00:00 2001 From: Valerij Talagayev <82884038+talagayev@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:26:50 +0200 Subject: [PATCH 09/14] removed singleframe_reader test in test_lammps.py --- .../MDAnalysisTests/coordinates/test_lammps.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/testsuite/MDAnalysisTests/coordinates/test_lammps.py b/testsuite/MDAnalysisTests/coordinates/test_lammps.py index 3d105131dec..88b4b8c35ee 100644 --- a/testsuite/MDAnalysisTests/coordinates/test_lammps.py +++ b/testsuite/MDAnalysisTests/coordinates/test_lammps.py @@ -30,7 +30,6 @@ from MDAnalysis import NoDataError from numpy.testing import (assert_equal, assert_allclose) -from pathlib import Path from MDAnalysisTests import make_Universe from MDAnalysisTests.coordinates.reference import ( @@ -820,16 +819,3 @@ def test_box(self, u_dump, u_data, reference_box): rtol=1e-5, atol=0) assert_allclose(u_data.dimensions, reference_box, rtol=1e-5, atol=0) - - -def test_pathlib_lammps_singleframereaderbase(): - top = Path(LAMMPSdata) - assert isinstance(top, Path) - u = mda.Universe(top) - assert u.atoms.n_atoms == 18364 - - -def test_string_lammps_singleframereaderbase(): - assert isinstance(LAMMPSdata, str) - u = mda.Universe(LAMMPSdata) - assert u.atoms.n_atoms == 18364 From 567e6ef4e37adef9c087aa24b6cef9c2e1210be6 Mon Sep 17 00:00:00 2001 From: Valerij Talagayev <82884038+talagayev@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:31:20 +0200 Subject: [PATCH 10/14] added test for str and path input for singleframereader in base.py --- testsuite/MDAnalysisTests/coordinates/base.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/testsuite/MDAnalysisTests/coordinates/base.py b/testsuite/MDAnalysisTests/coordinates/base.py index a2a131bbbde..f48e4d1de88 100644 --- a/testsuite/MDAnalysisTests/coordinates/base.py +++ b/testsuite/MDAnalysisTests/coordinates/base.py @@ -25,6 +25,7 @@ import numpy as np import pytest +from pathlib import Path from unittest import TestCase from numpy.testing import (assert_equal, assert_almost_equal, assert_array_almost_equal, assert_allclose) @@ -126,6 +127,12 @@ def test_pickle_singleframe_reader(self): assert_equal(reader.ts, reader_p.ts, "Single-frame timestep is changed after pickling") + def test_pathlib_input_single(self): + path = Path(self.filename) + u_str = mda.Universe(self.filename) + u_path = mda.Universe(path) + assert u_str.atoms.n_atoms == u_path.atoms.n_atoms + class BaseReference(object): def __init__(self): From 5558dda257663dbc25152965847fd9e70b08fc48 Mon Sep 17 00:00:00 2001 From: Valerij Talagayev <82884038+talagayev@users.noreply.github.com> Date: Mon, 15 Apr 2024 11:17:41 +0200 Subject: [PATCH 11/14] Added Baseframe test for singleframes str and path input in base.py --- testsuite/MDAnalysisTests/coordinates/base.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/testsuite/MDAnalysisTests/coordinates/base.py b/testsuite/MDAnalysisTests/coordinates/base.py index f48e4d1de88..11104dc4989 100644 --- a/testsuite/MDAnalysisTests/coordinates/base.py +++ b/testsuite/MDAnalysisTests/coordinates/base.py @@ -32,6 +32,7 @@ import MDAnalysis as mda from MDAnalysis.coordinates.timestep import Timestep +from MDAnalysis.coordinates.memory import MemoryReader from MDAnalysis.transformations import translate @@ -528,6 +529,19 @@ def test_timeseries_atomgroup_asel_mutex(self, reader): atoms = mda.Universe(reader.filename).select_atoms("index 1") with pytest.raises(ValueError, match="Cannot provide both"): timeseries = reader.timeseries(atomgroup=atoms, asel=atoms, order='fac') + + def test_pathlib_input_base(self, reader): + skip_formats = ["DCD", "TNG", "XTC", "TRR"] + if isinstance(reader, MemoryReader) or reader.format in skip_formats: + if isinstance(reader, MemoryReader): + skip_reason = "MemoryReader" + else: + skip_reason = f"{reader.format} file format" + pytest.skip(f"Skipping test for {skip_reason}") + path = Path(reader.filename) + u_str = mda.Universe(reader.filename) + u_path = mda.Universe(path) + assert u_str.atoms.n_atoms == u_path.atoms.n_atoms class MultiframeReaderTest(BaseReaderTest): From e06ae55ad989f45b83a51f3ef84c94b479028a50 Mon Sep 17 00:00:00 2001 From: hmacdope Date: Tue, 28 May 2024 09:42:15 +1000 Subject: [PATCH 12/14] add pathlib checking to topology and universe --- package/MDAnalysis/coordinates/base.py | 6 +++++- package/MDAnalysis/core/universe.py | 4 ++++ package/MDAnalysis/topology/base.py | 8 +++++++- testsuite/MDAnalysisTests/coordinates/base.py | 7 ++----- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/package/MDAnalysis/coordinates/base.py b/package/MDAnalysis/coordinates/base.py index 45befe1c552..68ac6ceb64c 100644 --- a/package/MDAnalysis/coordinates/base.py +++ b/package/MDAnalysis/coordinates/base.py @@ -1663,7 +1663,11 @@ class SingleFrameReaderBase(ProtoReader): def __init__(self, filename, convert_units=True, n_atoms=None, **kwargs): super(SingleFrameReaderBase, self).__init__() - self.filename = filename + if isinstance(filename, NamedStream): + self.filename = filename + else: + self.filename = str(filename) + self.convert_units = convert_units self.n_frames = 1 diff --git a/package/MDAnalysis/core/universe.py b/package/MDAnalysis/core/universe.py index 739e0483395..50b2694daa8 100644 --- a/package/MDAnalysis/core/universe.py +++ b/package/MDAnalysis/core/universe.py @@ -60,6 +60,7 @@ import warnings import contextlib import collections +import pathlib import MDAnalysis import sys @@ -99,6 +100,9 @@ def _check_file_like(topology): else: _name = None return NamedStream(topology, _name) + + elif isinstance(topology, pathlib.Path): + return str(topology) return topology def _topology_from_file_like(topology_file, topology_format=None, diff --git a/package/MDAnalysis/topology/base.py b/package/MDAnalysis/topology/base.py index 260251fb26e..40eaf73e3e1 100644 --- a/package/MDAnalysis/topology/base.py +++ b/package/MDAnalysis/topology/base.py @@ -47,6 +47,7 @@ from ..lib import util + class _Topologymeta(type): """Internal: Topology Parser registration voodoo @@ -115,7 +116,12 @@ class TopologyReaderBase(IOBase, metaclass=_Topologymeta): Added keyword 'universe' to pass to Atom creation. """ def __init__(self, filename): - self.filename = filename + + if isinstance(filename, util.NamedStream): + self.filename = filename + else: + self.filename = str(filename) + def parse(self, **kwargs): # pragma: no cover raise NotImplementedError("Override this in each subclass") diff --git a/testsuite/MDAnalysisTests/coordinates/base.py b/testsuite/MDAnalysisTests/coordinates/base.py index 11104dc4989..21ff6593572 100644 --- a/testsuite/MDAnalysisTests/coordinates/base.py +++ b/testsuite/MDAnalysisTests/coordinates/base.py @@ -531,13 +531,10 @@ def test_timeseries_atomgroup_asel_mutex(self, reader): timeseries = reader.timeseries(atomgroup=atoms, asel=atoms, order='fac') def test_pathlib_input_base(self, reader): - skip_formats = ["DCD", "TNG", "XTC", "TRR"] - if isinstance(reader, MemoryReader) or reader.format in skip_formats: + if isinstance(reader, MemoryReader): if isinstance(reader, MemoryReader): skip_reason = "MemoryReader" - else: - skip_reason = f"{reader.format} file format" - pytest.skip(f"Skipping test for {skip_reason}") + pytest.skip(f"Skipping test for Pathlib input with reason: {skip_reason}") path = Path(reader.filename) u_str = mda.Universe(reader.filename) u_path = mda.Universe(path) From 0aa40cc60a4f6ee4c854009d0be695bd7311c175 Mon Sep 17 00:00:00 2001 From: hmacdope Date: Tue, 28 May 2024 09:49:53 +1000 Subject: [PATCH 13/14] add test for topology Pathlib and fix changelog --- package/CHANGELOG | 4 ++-- testsuite/MDAnalysisTests/topology/base.py | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/package/CHANGELOG b/package/CHANGELOG index 9bc725a549f..11642fc6e79 100644 --- a/package/CHANGELOG +++ b/package/CHANGELOG @@ -17,7 +17,7 @@ The rules for this file: ??/??/?? IAlibay, HeetVekariya, marinegor, lilyminium, RMeli, ljwoods2, aditya292002, pstaerk, PicoCentauri, BFedder, tyler.je.reddy, SampurnaM, leonwehrhan, kainszs, orionarcher, - talagayev + talagayev, hmacdope * 2.8.0 @@ -40,7 +40,7 @@ Fixes * Fix groups.py doctests using sphinx directives (Issue #3925, PR #4374) Enhancements - * Implementation of tests for str and pathlib handling of SingleFrameReaderBase (Issue #3937) + * Handling of Pathlib.Path in SingleFrameReaderBase, Topology and Universe (Issue #3937) * Added a tqdm progress bar for `MDAnalysis.analysis.pca.PCA.transform()` (PR #4531) * Improved performance of PDBWriter (Issue #2785, PR #4472) diff --git a/testsuite/MDAnalysisTests/topology/base.py b/testsuite/MDAnalysisTests/topology/base.py index 7833f0a51ed..acf123b23ed 100644 --- a/testsuite/MDAnalysisTests/topology/base.py +++ b/testsuite/MDAnalysisTests/topology/base.py @@ -100,3 +100,11 @@ def test_creates_universe(self, filename): """Check that Universe works with this Parser""" u = mda.Universe(filename) assert isinstance(u, mda.Universe) + + def test_pathlib_input(self, filename): + """Check that pathlib.Path objects are accepted""" + import pathlib + path = pathlib.Path(filename) + u_str = mda.Universe(filename) + u_path = mda.Universe(path) + assert u_str.atoms.n_atoms == u_path.atoms.n_atoms From 5dafd014830c584b920a49273abada9fed90aff5 Mon Sep 17 00:00:00 2001 From: hmacdope Date: Tue, 28 May 2024 09:51:36 +1000 Subject: [PATCH 14/14] fix spacing chaneg in AUTHORS --- package/AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/package/AUTHORS b/package/AUTHORS index 49c7efdecc6..fb5d5689468 100644 --- a/package/AUTHORS +++ b/package/AUTHORS @@ -242,6 +242,7 @@ Chronological list of authors - Valerij Talagayev + External code -------------