diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 85b32f10f..c39a14f66 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -6,7 +6,7 @@ This pull request fixes issue #? * I confirm that I have merged the latest version of `devel` into this branch before issuing this pull request (e.g. by running `git pull origin devel`): [y/n] * I confirm that I have added a changelog entry to the changelog (we will add a link to this PR as part of the review): [y/n] -* I confirm that I have permission to release this code under the LGPLv3+ license: [y/n] +* I confirm that I have permission to release this code under the MIT license (the Python API) or the LGPLv3+ license (everything else), as described in the `LICENSE` file: [y/n] ## If this introduces new functionality... @@ -16,7 +16,7 @@ Changes proposed in this pull request: * I confirm that I have added a test for any new functionality in this pull request: [y/n] * I confirm that I have added documentation (e.g. a new tutorial page or detailed guide) for any new functionality in this pull request: [y/n] * I confirm that I have added a changelog entry to the changelog (we will add a link to this PR as part of the review): [y/n] -* I confirm that I have permission to release this code under the LGPLv3+ license: [y/n] +* I confirm that I have permission to release this code under the MIT license (the Python API) or the LGPLv3+ license (everything else), as described in the `LICENSE` file: [y/n] ## Suggested reviewers: @chryswoods, @lohedges diff --git a/LICENSE b/LICENSE index 8bc842a26..c83fbfb18 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,41 @@ -Sire is licensed under the GNU Lesser General Public License, version 3 -or (at your option) any later version. The LGPL is a set of additional +Sire is distributed under two licenses. + +The Python API is licensed under the MIT License. This covers the Python +source in the src directory, plus the following files that implement the +OpenMM layer used by the Python API: + + wrapper/Convert/SireOpenMM/_perturbablemol.py + wrapper/Convert/SireOpenMM/_sommcontext.py + +Everything else, including the C++ libraries and their Python wrappers, +is licensed under the GNU Lesser General Public License, version 3 or +(at your option) any later version. The LGPL is a set of additional permissions on top of the GNU General Public License, version 3, so the -full text of both licenses is included below. +full text of both licenses is included below, after the MIT License. + +------------------------------------------------------------------------ + + MIT License + +Copyright (c) The Sire contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. ------------------------------------------------------------------------ diff --git a/README.rst b/README.rst index d0a664588..1af2f520a 100644 --- a/README.rst +++ b/README.rst @@ -174,6 +174,26 @@ This is intended as a local development tweak only and shouldn't be committed, since ``actions/generate_recipe.py`` reads the ``[dependencies]`` section when generating the conda recipe, so the pin would also end up in our packages. +License +======= + +Sire is distributed under two licenses: + +* The Python API is licensed under the + `MIT License `__. This covers the + Python source in ``src/``, plus + ``wrapper/Convert/SireOpenMM/_perturbablemol.py`` and + ``wrapper/Convert/SireOpenMM/_sommcontext.py``. You are free to adapt, + extend, or include this code in your own projects, provided the copyright + and license notice is kept. +* Everything else, including the C++ libraries and their Python wrappers, is + licensed under the + `GNU Lesser General Public License, version 3 or later `__ + (LGPLv3+). You can use Sire as a library from software under any license, + but changes to these parts of Sire must be shared under the LGPL. + +See the `LICENSE `__ file for the full terms. + Support and Development ======================= diff --git a/actions/generate_recipe.py b/actions/generate_recipe.py index 7633a3a51..d60056fdf 100644 --- a/actions/generate_recipe.py +++ b/actions/generate_recipe.py @@ -401,7 +401,7 @@ def generate_recipe(data, features, git_remote, git_branch, git_version, git_num # About lines.append("about:") lines.append(" homepage: https://github.com/openbiosim/sire") - lines.append(" license: LGPL-3.0-or-later") + lines.append(" license: LGPL-3.0-or-later AND MIT") lines.append(" license_file: LICENSE") lines.append(' summary: "An advanced molecular modelling framework."') lines.append(" repository: https://github.com/openbiosim/sire") diff --git a/doc/source/acknowledgements.rst b/doc/source/acknowledgements.rst index 60a7039c3..446c0efcc 100644 --- a/doc/source/acknowledgements.rst +++ b/doc/source/acknowledgements.rst @@ -62,9 +62,10 @@ which can be found below. The software will be installed automatically as part of the installing the :mod:`sire` conda package, so you shouldn't have to do anything yourself. -:mod:`sire` is itself distributed under the terms of the GNU Lesser -General Public License, version 3 or (at your option) any later version -(LGPLv3+). Some optional dependencies are licensed differently, e.g. +:mod:`sire` itself is distributed under the terms of the MIT License (the +Python API) and the GNU Lesser General Public License, version 3 or (at your +option) any later version (everything else). See the :doc:`license ` +page for details. Some optional dependencies are licensed differently, e.g. `emle-engine `__ (GPLv2), which is conditionally imported for QM/MM calculations if it is installed. These are not distributed with :mod:`sire` and are used under their own license terms. diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst index 946bc3af9..664b9988b 100644 --- a/doc/source/changelog.rst +++ b/doc/source/changelog.rst @@ -121,6 +121,10 @@ organisation on `GitHub `__. * Fixed reading a DCD frame reading the coordinates, space and time from the file twice. +* Relicensed the Python API, i.e. the Python source in ``src`` and the two Python files in + ``wrapper/Convert/SireOpenMM`` that implement its OpenMM layer, from the LGPLv3+ to the MIT + License. The rest of :mod:`sire` remains LGPLv3+. + `2026.2.0 `__ - September 2026 ---------------------------------------------------------------------------------------------- diff --git a/doc/source/index.rst b/doc/source/index.rst index f5577315a..854c87b47 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -105,6 +105,14 @@ Changelog changelog +License +======= + +.. toctree:: + :maxdepth: 1 + + license + Acknowledgements ================ .. toctree:: diff --git a/doc/source/license.rst b/doc/source/license.rst new file mode 100644 index 000000000..38af34bfc --- /dev/null +++ b/doc/source/license.rst @@ -0,0 +1,24 @@ +======= +License +======= + +:mod:`sire` is distributed under two licenses: + +* The Python API is licensed under the + `MIT License `__. This covers the + Python source in ``src/``, plus + ``wrapper/Convert/SireOpenMM/_perturbablemol.py`` and + ``wrapper/Convert/SireOpenMM/_sommcontext.py``. You are free to adapt, + extend, or include this code in your own projects, provided the copyright + and license notice is kept. +* Everything else, including the C++ libraries and their Python wrappers, is + licensed under the + `GNU Lesser General Public License, version 3 or later `__ + (LGPLv3+). You can use :mod:`sire` as a library from software under any + license, but changes to these parts of :mod:`sire` must be shared under the + LGPL. + +The full terms are in the +`LICENSE `__ file. +Details of the licenses of the third party software that :mod:`sire` depends +on can be found in the :doc:`acknowledgements `. diff --git a/recipes/sire/LICENSE b/recipes/sire/LICENSE index 8bc842a26..c83fbfb18 100644 --- a/recipes/sire/LICENSE +++ b/recipes/sire/LICENSE @@ -1,7 +1,41 @@ -Sire is licensed under the GNU Lesser General Public License, version 3 -or (at your option) any later version. The LGPL is a set of additional +Sire is distributed under two licenses. + +The Python API is licensed under the MIT License. This covers the Python +source in the src directory, plus the following files that implement the +OpenMM layer used by the Python API: + + wrapper/Convert/SireOpenMM/_perturbablemol.py + wrapper/Convert/SireOpenMM/_sommcontext.py + +Everything else, including the C++ libraries and their Python wrappers, +is licensed under the GNU Lesser General Public License, version 3 or +(at your option) any later version. The LGPL is a set of additional permissions on top of the GNU General Public License, version 3, so the -full text of both licenses is included below. +full text of both licenses is included below, after the MIT License. + +------------------------------------------------------------------------ + + MIT License + +Copyright (c) The Sire contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. ------------------------------------------------------------------------ diff --git a/setup.py b/setup.py index 9646c1252..069ff13c7 100644 --- a/setup.py +++ b/setup.py @@ -756,7 +756,7 @@ def install(ncores: int = 1, npycores: int = 1): "build_number": 0, "channel": "local", "size": 0, - "license": "LGPL-3.0-or-later", + "license": "LGPL-3.0-or-later AND MIT", "subdir": platform_string, } metadata_file = os.path.join( diff --git a/src/sire/__init__.py b/src/sire/__init__.py index 92488d7b7..1548ae528 100644 --- a/src/sire/__init__.py +++ b/src/sire/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + from . import config import os as _os diff --git a/src/sire/_colname.py b/src/sire/_colname.py index 77a4f4420..ebebd4649 100644 --- a/src/sire/_colname.py +++ b/src/sire/_colname.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["colname", "colnames"] _col_funcs = None diff --git a/src/sire/_lazy_import.py b/src/sire/_lazy_import.py index b820e2290..3af0a3025 100644 --- a/src/sire/_lazy_import.py +++ b/src/sire/_lazy_import.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + """ A minimal, standard-library-only replacement for the third-party `lazy_import` package (GPLv3), used to defer importing submodules until diff --git a/src/sire/_load.py b/src/sire/_load.py index 300470f1b..4cdc7f08e 100644 --- a/src/sire/_load.py +++ b/src/sire/_load.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + from typing import Union as _Union from typing import List as _List diff --git a/src/sire/_match.py b/src/sire/_match.py index 7ecffb8d4..f31b2043f 100644 --- a/src/sire/_match.py +++ b/src/sire/_match.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["match_atoms"] diff --git a/src/sire/_measure.py b/src/sire/_measure.py index a4e8c790b..1479a5dd5 100644 --- a/src/sire/_measure.py +++ b/src/sire/_measure.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["measure", "minimum_distance"] diff --git a/src/sire/_parallel.py b/src/sire/_parallel.py index c398a893b..1ebc0cf7e 100644 --- a/src/sire/_parallel.py +++ b/src/sire/_parallel.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "get_max_num_threads", "set_default_num_threads", diff --git a/src/sire/_pythonize.py b/src/sire/_pythonize.py index 5f637a24e..44a98b191 100644 --- a/src/sire/_pythonize.py +++ b/src/sire/_pythonize.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["use_old_api", "use_new_api", "use_mixed_api"] diff --git a/src/sire/analysis/__init__.py b/src/sire/analysis/__init__.py index a3675a299..f77d2246b 100644 --- a/src/sire/analysis/__init__.py +++ b/src/sire/analysis/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [] # Need to import the module to pythonize it diff --git a/src/sire/base/__init__.py b/src/sire/base/__init__.py index ccc91ab86..8f905d185 100644 --- a/src/sire/base/__init__.py +++ b/src/sire/base/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "create_map", "wrap", diff --git a/src/sire/base/_pagecache.py b/src/sire/base/_pagecache.py index 09523c299..1d970be3a 100644 --- a/src/sire/base/_pagecache.py +++ b/src/sire/base/_pagecache.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["PageCache"] from ..legacy.Base import PageCache @@ -24,7 +26,6 @@ def __fetch__(obj): """ Fetch the object from the cache and return it """ - from ..legacy.Qt import QByteArray from pickle import loads data = obj.__orig__fetch__() diff --git a/src/sire/base/_progressbar.py b/src/sire/base/_progressbar.py index 870234fde..2ce64b648 100644 --- a/src/sire/base/_progressbar.py +++ b/src/sire/base/_progressbar.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["ProgressBar"] from ..legacy.Base import ProgressBar as _ProgressBar diff --git a/src/sire/cas/__init__.py b/src/sire/cas/__init__.py index 59ebd8f14..3c8fe4f53 100644 --- a/src/sire/cas/__init__.py +++ b/src/sire/cas/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["Expression", "lam", "Symbol", "x", "y", "LambdaSchedule"] from ..legacy import CAS as _CAS diff --git a/src/sire/cluster/__init__.py b/src/sire/cluster/__init__.py index 7d93d0678..1cb189695 100644 --- a/src/sire/cluster/__init__.py +++ b/src/sire/cluster/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [] # Need to import so it is pythonized diff --git a/src/sire/config/__init__.py b/src/sire/config/__init__.py index 3d73aa1c2..790a868fe 100644 --- a/src/sire/config/__init__.py +++ b/src/sire/config/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "binary_directory", "include_directory", diff --git a/src/sire/convert/__init__.py b/src/sire/convert/__init__.py index a21ac6fd2..1c971cc18 100644 --- a/src/sire/convert/__init__.py +++ b/src/sire/convert/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "biosimspace_to_sire", "gemmi_to_sire", diff --git a/src/sire/convert/openmm/__init__.py b/src/sire/convert/openmm/__init__.py index 328c5ad56..d6e66a1b8 100644 --- a/src/sire/convert/openmm/__init__.py +++ b/src/sire/convert/openmm/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "LambdaLever", "OpenMMMetaData", diff --git a/src/sire/convert/openmm/_pme.py b/src/sire/convert/openmm/_pme.py index 0abd83843..f975fd726 100644 --- a/src/sire/convert/openmm/_pme.py +++ b/src/sire/convert/openmm/_pme.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["tune_pme"] diff --git a/src/sire/error/__init__.py b/src/sire/error/__init__.py index b73435de6..071812be9 100644 --- a/src/sire/error/__init__.py +++ b/src/sire/error/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "disable_backtrace_exceptions", "enable_backtrace_exceptions", diff --git a/src/sire/ff/__init__.py b/src/sire/ff/__init__.py index 26147a09e..d4401dce8 100644 --- a/src/sire/ff/__init__.py +++ b/src/sire/ff/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [] # Need to import so the module is pythonized diff --git a/src/sire/id/__init__.py b/src/sire/id/__init__.py index e67906225..1d67504af 100644 --- a/src/sire/id/__init__.py +++ b/src/sire/id/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["CaseInsensitive", "CaseSensitive"] from ..legacy import ID as _ID diff --git a/src/sire/io/__init__.py b/src/sire/io/__init__.py index c2098ebc7..ce0bac1ef 100644 --- a/src/sire/io/__init__.py +++ b/src/sire/io/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["get_coords_array", "resolve_path"] from ..legacy import IO as _IO diff --git a/src/sire/io/parser/__init__.py b/src/sire/io/parser/__init__.py index 38d1c7693..8541df499 100644 --- a/src/sire/io/parser/__init__.py +++ b/src/sire/io/parser/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "DCD", "G87", diff --git a/src/sire/maths/__init__.py b/src/sire/maths/__init__.py index 56f6c0e3d..bcb10e1e4 100644 --- a/src/sire/maths/__init__.py +++ b/src/sire/maths/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "align", "create_quaternion", diff --git a/src/sire/maths/_sphere.py b/src/sire/maths/_sphere.py index 7fd4b4838..62e2d3ae9 100644 --- a/src/sire/maths/_sphere.py +++ b/src/sire/maths/_sphere.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + from ..legacy.Maths import Sphere as _Sphere diff --git a/src/sire/maths/_vector.py b/src/sire/maths/_vector.py index 79edd1286..936dd2594 100644 --- a/src/sire/maths/_vector.py +++ b/src/sire/maths/_vector.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + from ..legacy.Maths import Vector as _Vector diff --git a/src/sire/mm/__init__.py b/src/sire/mm/__init__.py index 37948fb44..b330bd12f 100644 --- a/src/sire/mm/__init__.py +++ b/src/sire/mm/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "AmberBond", "AmberAngle", diff --git a/src/sire/mol/__init__.py b/src/sire/mol/__init__.py index 77409ac90..060aea198 100644 --- a/src/sire/mol/__init__.py +++ b/src/sire/mol/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "get_alignment", "is_water", diff --git a/src/sire/mol/_cursor.py b/src/sire/mol/_cursor.py index 600c12ffa..c3accf9dd 100644 --- a/src/sire/mol/_cursor.py +++ b/src/sire/mol/_cursor.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + from typing import List as _List __all__ = ["Cursor", "Cursors", "CursorsM"] @@ -968,7 +970,7 @@ def residue(self, i=None): return c except Exception: raise TypeError( - f"There is no residue that contains {self.type()}:" f"{self.id()}" + f"There is no residue that contains {self.type()}:{self.id()}" ) self._update() @@ -995,7 +997,7 @@ def chain(self, i=None): return c except Exception: raise TypeError( - f"There is no chain that contains {self.type()}:" f"{self.id()}" + f"There is no chain that contains {self.type()}:{self.id()}" ) self._update() @@ -1022,7 +1024,7 @@ def segment(self, i=None): return c except Exception: raise TypeError( - f"There is no segment that contains {self.type()}:" f"{self.id()}" + f"There is no segment that contains {self.type()}:{self.id()}" ) self._update() @@ -1057,8 +1059,7 @@ def bond(self, *args, **kwargs): if "map" in kwargs: raise ValueError( - "The 'map' parameter is not allowed when creating a " - "Cursor for a bond" + "The 'map' parameter is not allowed when creating a Cursor for a bond" ) return c @@ -1075,8 +1076,7 @@ def angle(self, *args, **kwargs): if "map" in kwargs: raise ValueError( - "The 'map' parameter is not allowed when creating a " - "Cursor for an angle" + "The 'map' parameter is not allowed when creating a Cursor for an angle" ) return c @@ -1175,7 +1175,7 @@ def get_name(self): if self.is_internal(): raise TypeError( - "An internal (bond/angle/dihedral/improper) does not have " "a name!" + "An internal (bond/angle/dihedral/improper) does not have a name!" ) return self._view.name().value() @@ -1186,7 +1186,7 @@ def set_name(self, name): if self.is_internal(): raise TypeError( - "An internal (bond/angle/dihedral/improper) does not have " "a name!" + "An internal (bond/angle/dihedral/improper) does not have a name!" ) # get the type right... @@ -1209,7 +1209,7 @@ def get_number(self): if self.is_internal(): raise TypeError( - "An internal (bond/angle/dihedral/improper) does not have " "a number!" + "An internal (bond/angle/dihedral/improper) does not have a number!" ) try: @@ -1223,7 +1223,7 @@ def set_number(self, number): if self.is_internal(): raise TypeError( - "An internal (bond/angle/dihedral/improper) does not have " "a number!" + "An internal (bond/angle/dihedral/improper) does not have a number!" ) try: @@ -1244,7 +1244,7 @@ def get_index(self): if self.is_internal(): raise TypeError( - "An internal (bond/angle/dihedral/improper) does not have " "an index!" + "An internal (bond/angle/dihedral/improper) does not have an index!" ) return self._view.index().value() @@ -1799,15 +1799,15 @@ def __str__(self): if n <= 10: for i in range(0, n): - lines.append(f"{i+1}: {self._cursors[i]}") + lines.append(f"{i + 1}: {self._cursors[i]}") else: for i in range(0, 5): - lines.append(f"{i+1}: {self._cursors[i]}") + lines.append(f"{i + 1}: {self._cursors[i]}") lines.append("...") for i in range(n - 5, n): - lines.append(f"{i+1}: {self._cursors[i]}") + lines.append(f"{i + 1}: {self._cursors[i]}") lines = "\n".join(lines) @@ -3496,15 +3496,15 @@ def __str__(self): if n <= 10: for i in range(0, n): - lines.append(f"{i+1}: {self._cursors[i]}") + lines.append(f"{i + 1}: {self._cursors[i]}") else: for i in range(0, 5): - lines.append(f"{i+1}: {self._cursors[i]}") + lines.append(f"{i + 1}: {self._cursors[i]}") lines.append("...") for i in range(n - 5, n): - lines.append(f"{i+1}: {self._cursors[i]}") + lines.append(f"{i + 1}: {self._cursors[i]}") lines = "\n".join(lines) diff --git a/src/sire/mol/_dynamics.py b/src/sire/mol/_dynamics.py index 53bc74b14..bda70b88d 100644 --- a/src/sire/mol/_dynamics.py +++ b/src/sire/mol/_dynamics.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["Dynamics"] diff --git a/src/sire/mol/_element.py b/src/sire/mol/_element.py index 0a15bee56..d26e57e03 100644 --- a/src/sire/mol/_element.py +++ b/src/sire/mol/_element.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["Element"] from ..legacy.Mol import Element diff --git a/src/sire/mol/_minimisation.py b/src/sire/mol/_minimisation.py index 088256d36..804bf115d 100644 --- a/src/sire/mol/_minimisation.py +++ b/src/sire/mol/_minimisation.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["Minimisation"] diff --git a/src/sire/mol/_smiles.py b/src/sire/mol/_smiles.py index 5c537871b..999052341 100644 --- a/src/sire/mol/_smiles.py +++ b/src/sire/mol/_smiles.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "_to_smiles", "_to_smarts", diff --git a/src/sire/mol/_trajectory.py b/src/sire/mol/_trajectory.py index 13b6a8971..456fdfc12 100644 --- a/src/sire/mol/_trajectory.py +++ b/src/sire/mol/_trajectory.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["TrajectoryIterator"] # make sure that GeneralUnit has been modernised @@ -723,7 +725,7 @@ def _custom_measures(self, func, to_pandas): if self._view is None: return {} - if not type(func) is dict: + if type(func) is not dict: func = {"custom": func} import numpy as np diff --git a/src/sire/mol/_view.py b/src/sire/mol/_view.py index 1111153a7..7fd476f1d 100644 --- a/src/sire/mol/_view.py +++ b/src/sire/mol/_view.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["view"] _nglview_import_error = None @@ -196,9 +198,7 @@ def get_selection_string(self, selection): except Exception as e: from ..utils import Console - Console.warning( - f"Unrecognised selection '{selection}'\n" f"Error is {e}" - ) + Console.warning(f"Unrecognised selection '{selection}'\nError is {e}") return "*" def add(self, selection, rep): diff --git a/src/sire/morph/__init__.py b/src/sire/morph/__init__.py index caf66cb84..21f587895 100644 --- a/src/sire/morph/__init__.py +++ b/src/sire/morph/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "shrink_ghost_atoms", "replica_exchange", diff --git a/src/sire/morph/_alchemy.py b/src/sire/morph/_alchemy.py index b66689524..3f8776344 100644 --- a/src/sire/morph/_alchemy.py +++ b/src/sire/morph/_alchemy.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["to_alchemlyb"] diff --git a/src/sire/morph/_decouple.py b/src/sire/morph/_decouple.py index e8f2c3e3b..45b873079 100644 --- a/src/sire/morph/_decouple.py +++ b/src/sire/morph/_decouple.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["annihilate", "decouple"] diff --git a/src/sire/morph/_ghost_atoms.py b/src/sire/morph/_ghost_atoms.py index bb1955309..21a2cdb99 100644 --- a/src/sire/morph/_ghost_atoms.py +++ b/src/sire/morph/_ghost_atoms.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["shrink_ghost_atoms"] diff --git a/src/sire/morph/_hmr.py b/src/sire/morph/_hmr.py index 6a6d30c9f..4d616e4bc 100644 --- a/src/sire/morph/_hmr.py +++ b/src/sire/morph/_hmr.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["repartition_hydrogen_masses"] diff --git a/src/sire/morph/_merge.py b/src/sire/morph/_merge.py index b31383b29..f3e7d33a5 100644 --- a/src/sire/morph/_merge.py +++ b/src/sire/morph/_merge.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["merge"] diff --git a/src/sire/morph/_mutate.py b/src/sire/morph/_mutate.py index 5613b1bed..673a7a833 100644 --- a/src/sire/morph/_mutate.py +++ b/src/sire/morph/_mutate.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["mutate"] diff --git a/src/sire/morph/_pertfile.py b/src/sire/morph/_pertfile.py index bc210401e..6f5dab205 100644 --- a/src/sire/morph/_pertfile.py +++ b/src/sire/morph/_pertfile.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["create_from_pertfile"] diff --git a/src/sire/morph/_perturbation.py b/src/sire/morph/_perturbation.py index a42153d07..db2c71581 100644 --- a/src/sire/morph/_perturbation.py +++ b/src/sire/morph/_perturbation.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "Perturbation", "link_to_reference", @@ -124,12 +126,12 @@ def __init__(self, mol, map=None): if not mol.has_property(map["is_perturbable"]): raise ValueError( - "You can only create a `Perturbation` from a " "perturbable molecule!" + "You can only create a `Perturbation` from a perturbable molecule!" ) if not mol.property(map["is_perturbable"]): raise ValueError( - "You can only create a `Perturbation` from a " "perturbable molecule!" + "You can only create a `Perturbation` from a perturbable molecule!" ) # construct the perturbation objects that can move the diff --git a/src/sire/morph/_repex.py b/src/sire/morph/_repex.py index 8edbd6057..32f291cc0 100644 --- a/src/sire/morph/_repex.py +++ b/src/sire/morph/_repex.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["replica_exchange"] diff --git a/src/sire/morph/_xml.py b/src/sire/morph/_xml.py index 29bee2a1d..0b2fa60d7 100644 --- a/src/sire/morph/_xml.py +++ b/src/sire/morph/_xml.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["evaluate_xml_force"] diff --git a/src/sire/move/__init__.py b/src/sire/move/__init__.py index bffa62730..11ca3f2a4 100644 --- a/src/sire/move/__init__.py +++ b/src/sire/move/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [] from ..legacy import Move as _Move diff --git a/src/sire/options/__init__.py b/src/sire/options/__init__.py index b0f3b52be..86334c983 100644 --- a/src/sire/options/__init__.py +++ b/src/sire/options/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "Option", "Integrator", diff --git a/src/sire/options/_dynamics_options.py b/src/sire/options/_dynamics_options.py index 1f0fd35f8..f154c767b 100644 --- a/src/sire/options/_dynamics_options.py +++ b/src/sire/options/_dynamics_options.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "Integrator", "Constraint", diff --git a/src/sire/options/_option.py b/src/sire/options/_option.py index b2ab02fb4..dbc48177a 100644 --- a/src/sire/options/_option.py +++ b/src/sire/options/_option.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["Option"] from enum import Enum as _Enum diff --git a/src/sire/qm/__init__.py b/src/sire/qm/__init__.py index 090c31f22..ffcd66d1c 100644 --- a/src/sire/qm/__init__.py +++ b/src/sire/qm/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["create_engine", "emle", "zero_charge"] from .. import use_new_api as _use_new_api diff --git a/src/sire/qm/_emle.py b/src/sire/qm/_emle.py index 0e619ae46..c1ce56e22 100644 --- a/src/sire/qm/_emle.py +++ b/src/sire/qm/_emle.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["emle"] from ..legacy import Convert as _Convert diff --git a/src/sire/qm/_utils.py b/src/sire/qm/_utils.py index ddd7e8b79..bd00f0ae7 100644 --- a/src/sire/qm/_utils.py +++ b/src/sire/qm/_utils.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: MIT + + def _zero_charge(mols, qm_atoms, map=None): """ Zero the charge for the QM atoms in the system. diff --git a/src/sire/qt/__init__.py b/src/sire/qt/__init__.py index 63c37177f..fcfeb982c 100644 --- a/src/sire/qt/__init__.py +++ b/src/sire/qt/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [] # Imported so that it is pythonized diff --git a/src/sire/restraints/__init__.py b/src/sire/restraints/__init__.py index 6afff5aea..161ae52f6 100644 --- a/src/sire/restraints/__init__.py +++ b/src/sire/restraints/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "angle", "positional", diff --git a/src/sire/restraints/_boresch_search.py b/src/sire/restraints/_boresch_search.py index 0674e8aff..868d42ba1 100644 --- a/src/sire/restraints/_boresch_search.py +++ b/src/sire/restraints/_boresch_search.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + """ Automatic Boresch restraint generation for ABFE simulations. """ diff --git a/src/sire/restraints/_restraints.py b/src/sire/restraints/_restraints.py index 246eadece..df3162614 100644 --- a/src/sire/restraints/_restraints.py +++ b/src/sire/restraints/_restraints.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "angle", "boresch", diff --git a/src/sire/restraints/_standard_state_correction.py b/src/sire/restraints/_standard_state_correction.py index 5366c8344..7bb582cf3 100644 --- a/src/sire/restraints/_standard_state_correction.py +++ b/src/sire/restraints/_standard_state_correction.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["get_standard_state_correction"] import numpy as _np diff --git a/src/sire/search/__init__.py b/src/sire/search/__init__.py index 224f44fbf..b901d2f5c 100644 --- a/src/sire/search/__init__.py +++ b/src/sire/search/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "approx_equal", "approx_greater", diff --git a/src/sire/squire/__init__.py b/src/sire/squire/__init__.py index 361cd5985..860d86626 100644 --- a/src/sire/squire/__init__.py +++ b/src/sire/squire/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [] # Imported so that it is pythonized diff --git a/src/sire/stream/__init__.py b/src/sire/stream/__init__.py index 9112fc387..e909e84ca 100644 --- a/src/sire/stream/__init__.py +++ b/src/sire/stream/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "save", "load", diff --git a/src/sire/system/__init__.py b/src/sire/system/__init__.py index 58ede02d6..89eeb482b 100644 --- a/src/sire/system/__init__.py +++ b/src/sire/system/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "System", "ForceFieldInfo", diff --git a/src/sire/system/_system.py b/src/sire/system/_system.py index 9638c4680..232e285bd 100644 --- a/src/sire/system/_system.py +++ b/src/sire/system/_system.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["System"] diff --git a/src/sire/units/__init__.py b/src/sire/units/__init__.py index 7db6573c2..06a8ccdd4 100644 --- a/src/sire/units/__init__.py +++ b/src/sire/units/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "angle", "convert", diff --git a/src/sire/utils/__init__.py b/src/sire/utils/__init__.py index 346aa984f..ca85cdf4e 100644 --- a/src/sire/utils/__init__.py +++ b/src/sire/utils/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = [ "Console", "NullProfiler", diff --git a/src/sire/utils/_console.py b/src/sire/utils/_console.py index 53156ac8f..e4a9625d2 100644 --- a/src/sire/utils/_console.py +++ b/src/sire/utils/_console.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + from typing import Union as _Union from typing import List as _List from typing import IO as _IO @@ -200,17 +202,6 @@ def debugging_enabled(level: int = None): else: return level is None - @staticmethod - def _retrieve_name(variable): - # thanks to scohe001 on stackoverflow - # https://stackoverflow.com/questions/18425225/getting-the-name-of-a-variable-as-a-string - import inspect - - callers_local_vars = inspect.currentframe().f_back.f_back.f_locals.items() - return [ - var_name for var_name, var_val in callers_local_vars if var_val is variable - ][-1] - @staticmethod def debug( text: str, @@ -255,23 +246,18 @@ def debug( import inspect # get the local variables in the caller's scope - callers_local_vars = inspect.currentframe().f_back.f_locals.items() + callers_locals = list(inspect.currentframe().f_back.f_locals.items()) table = Table(box=box.MINIMAL_DOUBLE_HEAD, style="on magenta") table.add_column("Name", justify="right", style="cyan", no_wrap=True) table.add_column("Value", justify="left", style="green") for variable in variables: - # get the name of the variable in the caller - try: - # go for the last matching variable in the caller's scope - name = [ - var_name - for var_name, var_val in callers_local_vars - if var_val is variable - ][-1] - except Exception: - name = "variable" + # use the last name bound to this object in the caller's scope + name = next( + (k for k, v in reversed(callers_locals) if v is variable), + "variable", + ) table.add_row(name, str(variable)) diff --git a/src/sire/utils/_profiler.py b/src/sire/utils/_profiler.py index e214b1ab1..9d539d408 100644 --- a/src/sire/utils/_profiler.py +++ b/src/sire/utils/_profiler.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + import time __all__ = ["Profiler", "NullProfiler"] @@ -140,7 +142,7 @@ def stop(self): from ._console import Console Console.warning( - f"You cannot stop profiler {self._name} as " f"it has not been started!" + f"You cannot stop profiler {self._name} as it has not been started!" ) elif self._end is not None: from ._console import Console diff --git a/src/sire/utils/_simple.py b/src/sire/utils/_simple.py index 7c952a3e9..5f9197fae 100644 --- a/src/sire/utils/_simple.py +++ b/src/sire/utils/_simple.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + from dataclasses import dataclass as _dataclass from dataclasses import field as _field from typing import List as _List diff --git a/src/sire/utils/_spring_flowers.py b/src/sire/utils/_spring_flowers.py index d4c1ee611..e89b0b9ab 100644 --- a/src/sire/utils/_spring_flowers.py +++ b/src/sire/utils/_spring_flowers.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + from dataclasses import dataclass as _dataclass from dataclasses import field as _field from typing import List as _List diff --git a/src/sire/utils/_try_import.py b/src/sire/utils/_try_import.py index b6a927f92..c4eff619f 100644 --- a/src/sire/utils/_try_import.py +++ b/src/sire/utils/_try_import.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["try_import", "try_import_from", "assert_imported", "have_imported"] _module_to_package = {} @@ -156,7 +158,7 @@ def try_import(name, package_registry=_module_to_package, version=None): except Exception as e: error_string = str(e) - if not (package_registry is None): + if package_registry is not None: _install_package(name, package_registry, version=version) return try_import(name, package_registry=None) @@ -206,7 +208,7 @@ def try_import_from(name, fromlist, package_registry=_module_to_package, version is_loaded = False if not is_loaded: - if not (package_registry is None): + if package_registry is not None: _install_package(name, package_registry, version=version) return try_import_from(name, fromlist, package_registry=None) else: diff --git a/src/sire/vol/__init__.py b/src/sire/vol/__init__.py index 413f270dc..7f499784c 100644 --- a/src/sire/vol/__init__.py +++ b/src/sire/vol/__init__.py @@ -1,3 +1,5 @@ +# SPDX-License-Identifier: MIT + __all__ = ["Cartesian", "PeriodicBox", "TriclinicBox", "CoordGroup"] from ..legacy import Vol as _Vol diff --git a/wrapper/Convert/SireOpenMM/_perturbablemol.py b/wrapper/Convert/SireOpenMM/_perturbablemol.py index 135e44cdc..282dea54f 100644 --- a/wrapper/Convert/SireOpenMM/_perturbablemol.py +++ b/wrapper/Convert/SireOpenMM/_perturbablemol.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: MIT +# Part of the Python API, so MIT rather than LGPL like the rest of wrapper. + __all__ = [ "_changed_atoms", "_changed_bonds", diff --git a/wrapper/Convert/SireOpenMM/_sommcontext.py b/wrapper/Convert/SireOpenMM/_sommcontext.py index 54289232c..0c3bc85db 100644 --- a/wrapper/Convert/SireOpenMM/_sommcontext.py +++ b/wrapper/Convert/SireOpenMM/_sommcontext.py @@ -1,3 +1,6 @@ +# SPDX-License-Identifier: MIT +# Part of the Python API, so MIT rather than LGPL like the rest of wrapper. + __all__ = ["SOMMContext"] from openmm import Context as _Context