Repository: pybamm-team/PyBaMM

Issue:
`pybamm.citations.register` does not work on Google Colab
 I have been using PyBaMM for most of 2022 with no issues, but since Google Colab was updated to Python 3.8, I have not been able to run any simulations. 

I have tried the following fixes to no avail:
1. Installed PyBaMM on Colab with `pip install git+https://github.com/pybamm-team/PyBaMM@develop` as suggested by @Saransh-cpp 
- Allows installing/importing  pybamm, but throws an error when defining the model or the parameter_values
- `model = pybamm.lithium_ion.DFN(options={"thermal":"lumped"})` or `parameter_values = pybamm.ParameterValues('Chen2020')`
- Error1: KeyError: 'Not a bibtex citation or known citation: Ai2019'
- Error2: KeyError: 'Not a bibtex citation or known citation: Chen2020'
2. Attempted installation on my local environment (desktop) with `pip install pybamm` 
- Throws an ERROR during installation 
- ERROR: PluginNotFound: plugin pybtex.database.input.bibtex not found
3. Installed PyBaMM on my local environment (desktop) with `pip install git+https://github.com/pybamm-team/PyBaMM@develop`
- Allows installation but throws an ERROR during `import pybamm`
- ERROR: PluginNotFound: plugin pybtex.database.input.bibtex not found

Any other suggestions?

_Originally posted by @renatorod in https://github.com/pybamm-team/PyBaMM/issues/2524#issuecomment-1345971134_
      

Discussion:

Patch:
diff --git a/.github/workflows/periodic_benchmarks.yml b/.github/workflows/periodic_benchmarks.yml
index d9fab3302..53371d2a4 100644
--- a/.github/workflows/periodic_benchmarks.yml
+++ b/.github/workflows/periodic_benchmarks.yml
@@ -25,7 +25,7 @@ jobs:
         with:
           python-version: 3.8
       - name: Install tox and asv
-        run: pip install -U pip tox asv
+        run: pip install -U pip "tox<4" asv
       - name: Run benchmarks
         run: |
           asv machine --machine "GitHubRunner"
diff --git a/.github/workflows/run_benchmarks_over_history.yml b/.github/workflows/run_benchmarks_over_history.yml
index 41cae77f9..9deb04169 100644
--- a/.github/workflows/run_benchmarks_over_history.yml
+++ b/.github/workflows/run_benchmarks_over_history.yml
@@ -28,7 +28,7 @@ jobs:
         with:
           python-version: 3.8
       - name: Install tox and asv
-        run: pip install -U pip tox asv
+        run: pip install -U pip "tox<4" asv
       - name: Fetch develop branch
         # Not required when worklow trigerred
         # on develop, but useful when
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b8d695b6a..3f5a43d40 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
 # [Unreleased](https://github.com/pybamm-team/PyBaMM/)
 
+# [v22.11.1](https://github.com/pybamm-team/PyBaMM/tree/v22.11.1) - 2022-12-13
+
+## Bug fixes
+
+- Fixed installation on Google Colab (`pybtex` issues) ([#2547](https://github.com/pybamm-team/PyBaMM/pull/2547/files))
+
 # [v22.11](https://github.com/pybamm-team/PyBaMM/tree/v22.11) - 2022-11-30
 
 ## Features
diff --git a/CITATION.cff b/CITATION.cff
index e4cce984a..d8e390a3d 100644
--- a/CITATION.cff
+++ b/CITATION.cff
@@ -24,6 +24,6 @@ keywords:
   - "expression tree"
   - "python"
   - "symbolic differentiation"
-version: "22.11"
+version: "22.11.1"
 repository-code: "https://github.com/pybamm-team/PyBaMM"
 title: "Python Battery Mathematical Modelling (PyBaMM)"
diff --git a/docs/conf.py b/docs/conf.py
index f39e6d8e8..a3323be46 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -27,7 +27,7 @@ copyright = "2018-2022, The PyBaMM Team"
 author = "The PyBaMM Team"
 
 # The short X.Y version
-version = "22.11"
+version = "22.11.1"
 # The full version, including alpha/beta/rc tags
 release = version
 
diff --git a/docs/install/install-from-source.rst b/docs/install/install-from-source.rst
index c320d9ac7..c6789da63 100644
--- a/docs/install/install-from-source.rst
+++ b/docs/install/install-from-source.rst
@@ -50,7 +50,7 @@ You can install it with
 
 .. code:: bash
 
-	  python3.X -m pip install --user tox
+	  python3.X -m pip install --user "tox<4"
 
 Depending on your operating system, you may or may not have ``pip`` installed along python.
 If ``pip`` is not found, you probably want to install the ``python3-pip`` package.
diff --git a/pybamm/citations.py b/pybamm/citations.py
index 756de395f..113aaac11 100644
--- a/pybamm/citations.py
+++ b/pybamm/citations.py
@@ -35,8 +35,14 @@ class Citations:
         # Dict mapping citations keys to BibTex entries
         self._all_citations: dict[str, str] = dict()
 
-        self.read_citations()
-        self._reset()
+        # store citation error
+        self._citation_err_msg = None
+
+        try:
+            self.read_citations()
+            self._reset()
+        except Exception as e:  # pragma: no cover
+            self._citation_err_msg = e
 
     def _reset(self):
         """Reset citations to default only (only for testing purposes)"""
@@ -91,27 +97,27 @@ class Citations:
             - The citation key for an entry in `pybamm/CITATIONS.txt` or
             - One or more BibTex formatted citations
         """
-
-        # Check if citation is a known key
-        if key in self._all_citations:
-            self._papers_to_cite.add(key)
-            return
-
-        # Try to parse the citation using pybtex
-        try:
-            # Parse string as a bibtex citation, and check that a citation was found
-            bib_data = parse_string(key, bib_format="bibtex")
-            if not bib_data.entries:
-                raise PybtexError("no entries found")
-
-            # Add and register all citations
-            for key, entry in bib_data.entries.items():
-                self._add_citation(key, entry)
-                self.register(key)
+        if self._citation_err_msg is None:
+            # Check if citation is a known key
+            if key in self._all_citations:
+                self._papers_to_cite.add(key)
                 return
-        except PybtexError:
-            # Unable to parse / unknown key
-            raise KeyError(f"Not a bibtex citation or known citation: {key}")
+
+            # Try to parse the citation using pybtex
+            try:
+                # Parse string as a bibtex citation, and check that a citation was found
+                bib_data = parse_string(key, bib_format="bibtex")
+                if not bib_data.entries:
+                    raise PybtexError("no entries found")
+
+                # Add and register all citations
+                for key, entry in bib_data.entries.items():
+                    self._add_citation(key, entry)
+                    self.register(key)
+                    return
+            except PybtexError:
+                # Unable to parse / unknown key
+                raise KeyError(f"Not a bibtex citation or known citation: {key}")
 
     def print(self, filename=None, output_format="text"):
         """Print all citations that were used for running simulations.
@@ -143,7 +149,17 @@ class Citations:
 
 def print_citations(filename=None, output_format="text"):
     """See :meth:`Citations.print`"""
-    pybamm.citations.print(filename, output_format)
+    if citations._citation_err_msg is not None:
+        raise ImportError(
+            f"Citations could not be registered. If you are on Google Colab - "
+            "pybtex does not work with Google Colab due to a known bug - "
+            "https://bitbucket.org/pybtex-devs/pybtex/issues/148/. "
+            "Please manually cite all the references."
+            "\nError encountered -\n"
+            f"{citations._citation_err_msg}"
+        )
+    else:
+        pybamm.citations.print(filename, output_format)
 
 
 citations = Citations()
diff --git a/pybamm/version.py b/pybamm/version.py
index 969639bd2..bf687dda7 100644
--- a/pybamm/version.py
+++ b/pybamm/version.py
@@ -1,1 +1,1 @@
-__version__ = "22.11"
+__version__ = "22.11.1"
diff --git a/vcpkg.json b/vcpkg.json
index d812052bb..62a7bfc2f 100644
--- a/vcpkg.json
+++ b/vcpkg.json
@@ -1,6 +1,6 @@
 {
   "name": "pybamm",
-  "version-string": "22.11",
+  "version-string": "22.11.1",
   "dependencies": [
     "casadi",
     {


Test patch:
diff --git a/.github/workflows/test_on_push.yml b/.github/workflows/test_on_push.yml
index c892aa312..44e5b86fe 100644
--- a/.github/workflows/test_on_push.yml
+++ b/.github/workflows/test_on_push.yml
@@ -36,7 +36,7 @@ jobs:
 
       - name: Check style
         run: |
-          python -m pip install tox
+          python -m pip install "tox<4"
           tox -e flake8
 
   build:
@@ -80,7 +80,7 @@ jobs:
       - name: Install standard python dependencies
         run: |
           python -m pip install --upgrade pip wheel setuptools
-          python -m pip install tox
+          python -m pip install "tox<4"
 
       - name: Install SuiteSparse and Sundials
         if: matrix.os == 'ubuntu-latest'
diff --git a/tests/unit/test_citations.py b/tests/unit/test_citations.py
index 015a20bfd..d2241badf 100644
--- a/tests/unit/test_citations.py
+++ b/tests/unit/test_citations.py
@@ -64,6 +64,11 @@ class TestCitations(unittest.TestCase):
         with self.assertRaisesRegex(pybamm.OptionError, "'text' or 'bibtex'"):
             pybamm.print_citations("test_citations.txt", "bad format")
 
+        pybamm.citations._citation_err_msg = "Error"
+        with self.assertRaisesRegex(ImportError, "Error"):
+            pybamm.print_citations()
+        pybamm.citations._citation_err_msg = None
+
     def test_overwrite_citation(self):
         # Unknown citation
         fake_citation = r"@article{NotACitation, title = {This Doesn't Exist}}"