We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Fix git SHA on website + status page (dupe?)
<!-- What problem are we solving? What does the experience look like today? What are the symptoms? -->

The footer + https://openlibrary.org/status should both show the website's git sha. Somewhere down the road we had a regression.

### Evidence / Screenshot (if possible)

### Relevant url?
<!-- `https://openlibrary.org/...` -->

### Steps to Reproduce
<!-- What steps caused you to find the bug? -->
1. Go to ...
2. Do ...

<!-- What actually happened after these steps? What did you expect to happen? -->
* Actual:
* Expected:

### Details

- **Logged in (Y/N)?**
- **Browser type/version?**
- **Operating system?**
- **Environment (prod/dev/local)?** prod
<!-- If not sure, put prod -->

### Proposal & Constraints
<!-- What is the proposed solution / implementation? Is there a precedent of this approach succeeding elsewhere? -->

### Related files
<!-- Files related to this issue; this is super useful for new contributors who might want to help! If you're not sure, leave this blank; a maintainer will add them. -->

### Stakeholders
<!-- @ tag stakeholders of this bug -->


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `openlibrary/utils/__init__.py`
Content:
```
1 """Generic utilities"""
2 
3 from enum import Enum
4 import re
5 from subprocess import run
6 from typing import TypeVar, Literal, Optional
7 from collections.abc import Iterable, Callable
8 
9 to_drop = set(''';/?:@&=+$,<>#%"{}|\\^[]`\n\r''')
10 
11 
12 def str_to_key(s: str) -> str:
13     """
14     >>> str_to_key("?H$e##l{o}[0] -world!")
15     'helo0_-world!'
16     >>> str_to_key("".join(to_drop))
17     ''
18     >>> str_to_key("")
19     ''
20     """
21     return ''.join(c if c != ' ' else '_' for c in s.lower() if c not in to_drop)
22 
23 
24 def finddict(dicts, **filters):
25     """Find a dictionary that matches given filter conditions.
26 
27     >>> dicts = [{"x": 1, "y": 2}, {"x": 3, "y": 4}]
28     >>> sorted(finddict(dicts, x=1).items())
29     [('x', 1), ('y', 2)]
30     """
31     for d in dicts:
32         if all(d.get(k) == v for k, v in filters.items()):
33             return d
34 
35 
36 T = TypeVar('T')
37 
38 
39 def uniq(values: Iterable[T], key=None) -> list[T]:
40     """Returns the unique entries from the given values in the original order.
41 
42     The value of the optional `key` parameter should be a function that takes
43     a single argument and returns a key to test the uniqueness.
44     TODO: Moved this to core/utils.py
45 
46     >>> uniq("abcbcddefefg")
47     ['a', 'b', 'c', 'd', 'e', 'f', 'g']
48     >>> uniq("011223344556677889")
49     ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
50     """
51     key = key or (lambda x: x)
52     s = set()
53     result = []
54     for v in values:
55         k = key(v)
56         if k not in s:
57             s.add(k)
58             result.append(v)
59     return result
60 
61 
62 def take_best(
63     items: list[T],
64     optimization: Literal["min", "max"],
65     scoring_fn: Callable[[T], float],
66 ) -> list[T]:
67     """
68     >>> take_best([], 'min', lambda x: x)
69     []
70     >>> take_best([3, 2, 1], 'min', lambda x: x)
71     [1]
72     >>> take_best([3, 4, 5], 'max', lambda x: x)
73     [5]
74     >>> take_best([4, 1, -1, -1], 'min', lambda x: x)
75     [-1, -1]
76     """
77     best_score = float("-inf") if optimization == "max" else float("inf")
78     besties = []
79     for item in items:
80         score = scoring_fn(item)
81         if (optimization == "max" and score > best_score) or (
82             optimization == "min" and score < best_score
83         ):
84             best_score = score
85             besties = [item]
86         elif score == best_score:
87             besties.append(item)
88         else:
89             continue
90     return besties
91 
92 
93 def multisort_best(
94     items: list[T], specs: list[tuple[Literal["min", "max"], Callable[[T], float]]]
95 ) -> Optional[T]:
96     """
97     Takes the best item, taking into account the multisorts
98 
99     >>> multisort_best([], [])
100 
101     >>> multisort_best([3,4,5], [('max', lambda x: x)])
102     5
103 
104     >>> multisort_best([
105     ...     {'provider': 'ia', 'size': 4},
106     ...     {'provider': 'ia', 'size': 12},
107     ...     {'provider': None, 'size': 42},
108     ... ], [
109     ...     ('min', lambda x: 0 if x['provider'] == 'ia' else 1),
110     ...     ('max', lambda x: x['size']),
111     ... ])
112     {'provider': 'ia', 'size': 12}
113     """
114     if not items:
115         return None
116     pool = items
117     for optimization, fn in specs:
118         # Shrink the pool down each time
119         pool = take_best(pool, optimization, fn)
120     return pool[0]
121 
122 
123 def dicthash(d):
124     """Dictionaries are not hashable. This function converts dictionary into nested
125     tuples, so that it can hashed.
126     """
127     if isinstance(d, dict):
128         return tuple((k, dicthash(d[k])) for k in sorted(d))
129     elif isinstance(d, list):
130         return tuple(dicthash(v) for v in d)
131     else:
132         return d
133 
134 
135 author_olid_embedded_re = re.compile(r'OL\d+A', re.IGNORECASE)
136 
137 
138 def find_author_olid_in_string(s):
139     """
140     >>> find_author_olid_in_string("ol123a")
141     'OL123A'
142     >>> find_author_olid_in_string("/authors/OL123A/edit")
143     'OL123A'
144     >>> find_author_olid_in_string("some random string")
145     """
146     found = re.search(author_olid_embedded_re, s)
147     return found and found.group(0).upper()
148 
149 
150 work_olid_embedded_re = re.compile(r'OL\d+W', re.IGNORECASE)
151 
152 
153 def find_work_olid_in_string(s):
154     """
155     >>> find_work_olid_in_string("ol123w")
156     'OL123W'
157     >>> find_work_olid_in_string("/works/OL123W/Title_of_book")
158     'OL123W'
159     >>> find_work_olid_in_string("some random string")
160     """
161     found = re.search(work_olid_embedded_re, s)
162     return found and found.group(0).upper()
163 
164 
165 def extract_numeric_id_from_olid(olid):
166     """
167     >>> extract_numeric_id_from_olid("OL123W")
168     '123'
169     >>> extract_numeric_id_from_olid("/authors/OL123A")
170     '123'
171     """
172     if '/' in olid:
173         olid = olid.split('/')[-1]
174     if olid.lower().startswith('ol'):
175         olid = olid[2:]
176     if not is_number(olid[-1].lower()):
177         olid = olid[:-1]
178     return olid
179 
180 
181 def is_number(s):
182     """
183     >>> all(is_number(n) for n in (1234, "1234", -1234, "-1234", 123.4, -123.4))
184     True
185     >>> not any(is_number(n) for n in ("123.4", "-123.4", "123a", "--1234"))
186     True
187     """
188     try:
189         int(s)
190         return True
191     except ValueError:
192         return False
193 
194 
195 def get_software_version() -> str:
196     cmd = "git rev-parse --short HEAD --".split()
197     return run(cmd, text=True).stdout
198 
199 
200 # See https://docs.python.org/3/library/enum.html#orderedenum
201 class OrderedEnum(Enum):
202     def __ge__(self, other):
203         if self.__class__ is other.__class__:
204             return self.value >= other.value
205         return NotImplemented
206 
207     def __gt__(self, other):
208         if self.__class__ is other.__class__:
209             return self.value > other.value
210         return NotImplemented
211 
212     def __le__(self, other):
213         if self.__class__ is other.__class__:
214             return self.value <= other.value
215         return NotImplemented
216 
217     def __lt__(self, other):
218         if self.__class__ is other.__class__:
219             return self.value < other.value
220         return NotImplemented
221
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/openlibrary/utils/__init__.py b/openlibrary/utils/__init__.py
--- a/openlibrary/utils/__init__.py
+++ b/openlibrary/utils/__init__.py
@@ -193,8 +193,11 @@
 
 
 def get_software_version() -> str:
+    """
+    assert get_software_version()  # Should never return a falsy value
+    """
     cmd = "git rev-parse --short HEAD --".split()
-    return run(cmd, text=True).stdout
+    return run(cmd, capture_output=True, text=True).stdout.strip()
 
 
 # See https://docs.python.org/3/library/enum.html#orderedenum

{"golden_diff": "diff --git a/openlibrary/utils/__init__.py b/openlibrary/utils/__init__.py\n--- a/openlibrary/utils/__init__.py\n+++ b/openlibrary/utils/__init__.py\n@@ -193,8 +193,11 @@\n \n \n def get_software_version() -> str:\n+    \"\"\"\n+    assert get_software_version()  # Should never return a falsy value\n+    \"\"\"\n     cmd = \"git rev-parse --short HEAD --\".split()\n-    return run(cmd, text=True).stdout\n+    return run(cmd, capture_output=True, text=True).stdout.strip()\n \n \n # See https://docs.python.org/3/library/enum.html#orderedenum\n", "issue": "Fix git SHA on website + status page (dupe?)\n<!-- What problem are we solving? What does the experience look like today? What are the symptoms? -->\r\n\r\nThe footer + https://openlibrary.org/status should both show the website's git sha. Somewhere down the road we had a regression.\r\n\r\n### Evidence / Screenshot (if possible)\r\n\r\n### Relevant url?\r\n<!-- `https://openlibrary.org/...` -->\r\n\r\n### Steps to Reproduce\r\n<!-- What steps caused you to find the bug? -->\r\n1. Go to ...\r\n2. Do ...\r\n\r\n<!-- What actually happened after these steps? What did you expect to happen? -->\r\n* Actual:\r\n* Expected:\r\n\r\n### Details\r\n\r\n- **Logged in (Y/N)?**\r\n- **Browser type/version?**\r\n- **Operating system?**\r\n- **Environment (prod/dev/local)?** prod\r\n<!-- If not sure, put prod -->\r\n\r\n### Proposal & Constraints\r\n<!-- What is the proposed solution / implementation? Is there a precedent of this approach succeeding elsewhere? -->\r\n\r\n### Related files\r\n<!-- Files related to this issue; this is super useful for new contributors who might want to help! If you're not sure, leave this blank; a maintainer will add them. -->\r\n\r\n### Stakeholders\r\n<!-- @ tag stakeholders of this bug -->\r\n\n", "before_files": [{"content": "\"\"\"Generic utilities\"\"\"\n\nfrom enum import Enum\nimport re\nfrom subprocess import run\nfrom typing import TypeVar, Literal, Optional\nfrom collections.abc import Iterable, Callable\n\nto_drop = set(''';/?:@&=+$,<>#%\"{}|\\\\^[]`\\n\\r''')\n\n\ndef str_to_key(s: str) -> str:\n    \"\"\"\n    >>> str_to_key(\"?H$e##l{o}[0] -world!\")\n    'helo0_-world!'\n    >>> str_to_key(\"\".join(to_drop))\n    ''\n    >>> str_to_key(\"\")\n    ''\n    \"\"\"\n    return ''.join(c if c != ' ' else '_' for c in s.lower() if c not in to_drop)\n\n\ndef finddict(dicts, **filters):\n    \"\"\"Find a dictionary that matches given filter conditions.\n\n    >>> dicts = [{\"x\": 1, \"y\": 2}, {\"x\": 3, \"y\": 4}]\n    >>> sorted(finddict(dicts, x=1).items())\n    [('x', 1), ('y', 2)]\n    \"\"\"\n    for d in dicts:\n        if all(d.get(k) == v for k, v in filters.items()):\n            return d\n\n\nT = TypeVar('T')\n\n\ndef uniq(values: Iterable[T], key=None) -> list[T]:\n    \"\"\"Returns the unique entries from the given values in the original order.\n\n    The value of the optional `key` parameter should be a function that takes\n    a single argument and returns a key to test the uniqueness.\n    TODO: Moved this to core/utils.py\n\n    >>> uniq(\"abcbcddefefg\")\n    ['a', 'b', 'c', 'd', 'e', 'f', 'g']\n    >>> uniq(\"011223344556677889\")\n    ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']\n    \"\"\"\n    key = key or (lambda x: x)\n    s = set()\n    result = []\n    for v in values:\n        k = key(v)\n        if k not in s:\n            s.add(k)\n            result.append(v)\n    return result\n\n\ndef take_best(\n    items: list[T],\n    optimization: Literal[\"min\", \"max\"],\n    scoring_fn: Callable[[T], float],\n) -> list[T]:\n    \"\"\"\n    >>> take_best([], 'min', lambda x: x)\n    []\n    >>> take_best([3, 2, 1], 'min', lambda x: x)\n    [1]\n    >>> take_best([3, 4, 5], 'max', lambda x: x)\n    [5]\n    >>> take_best([4, 1, -1, -1], 'min', lambda x: x)\n    [-1, -1]\n    \"\"\"\n    best_score = float(\"-inf\") if optimization == \"max\" else float(\"inf\")\n    besties = []\n    for item in items:\n        score = scoring_fn(item)\n        if (optimization == \"max\" and score > best_score) or (\n            optimization == \"min\" and score < best_score\n        ):\n            best_score = score\n            besties = [item]\n        elif score == best_score:\n            besties.append(item)\n        else:\n            continue\n    return besties\n\n\ndef multisort_best(\n    items: list[T], specs: list[tuple[Literal[\"min\", \"max\"], Callable[[T], float]]]\n) -> Optional[T]:\n    \"\"\"\n    Takes the best item, taking into account the multisorts\n\n    >>> multisort_best([], [])\n\n    >>> multisort_best([3,4,5], [('max', lambda x: x)])\n    5\n\n    >>> multisort_best([\n    ...     {'provider': 'ia', 'size': 4},\n    ...     {'provider': 'ia', 'size': 12},\n    ...     {'provider': None, 'size': 42},\n    ... ], [\n    ...     ('min', lambda x: 0 if x['provider'] == 'ia' else 1),\n    ...     ('max', lambda x: x['size']),\n    ... ])\n    {'provider': 'ia', 'size': 12}\n    \"\"\"\n    if not items:\n        return None\n    pool = items\n    for optimization, fn in specs:\n        # Shrink the pool down each time\n        pool = take_best(pool, optimization, fn)\n    return pool[0]\n\n\ndef dicthash(d):\n    \"\"\"Dictionaries are not hashable. This function converts dictionary into nested\n    tuples, so that it can hashed.\n    \"\"\"\n    if isinstance(d, dict):\n        return tuple((k, dicthash(d[k])) for k in sorted(d))\n    elif isinstance(d, list):\n        return tuple(dicthash(v) for v in d)\n    else:\n        return d\n\n\nauthor_olid_embedded_re = re.compile(r'OL\\d+A', re.IGNORECASE)\n\n\ndef find_author_olid_in_string(s):\n    \"\"\"\n    >>> find_author_olid_in_string(\"ol123a\")\n    'OL123A'\n    >>> find_author_olid_in_string(\"/authors/OL123A/edit\")\n    'OL123A'\n    >>> find_author_olid_in_string(\"some random string\")\n    \"\"\"\n    found = re.search(author_olid_embedded_re, s)\n    return found and found.group(0).upper()\n\n\nwork_olid_embedded_re = re.compile(r'OL\\d+W', re.IGNORECASE)\n\n\ndef find_work_olid_in_string(s):\n    \"\"\"\n    >>> find_work_olid_in_string(\"ol123w\")\n    'OL123W'\n    >>> find_work_olid_in_string(\"/works/OL123W/Title_of_book\")\n    'OL123W'\n    >>> find_work_olid_in_string(\"some random string\")\n    \"\"\"\n    found = re.search(work_olid_embedded_re, s)\n    return found and found.group(0).upper()\n\n\ndef extract_numeric_id_from_olid(olid):\n    \"\"\"\n    >>> extract_numeric_id_from_olid(\"OL123W\")\n    '123'\n    >>> extract_numeric_id_from_olid(\"/authors/OL123A\")\n    '123'\n    \"\"\"\n    if '/' in olid:\n        olid = olid.split('/')[-1]\n    if olid.lower().startswith('ol'):\n        olid = olid[2:]\n    if not is_number(olid[-1].lower()):\n        olid = olid[:-1]\n    return olid\n\n\ndef is_number(s):\n    \"\"\"\n    >>> all(is_number(n) for n in (1234, \"1234\", -1234, \"-1234\", 123.4, -123.4))\n    True\n    >>> not any(is_number(n) for n in (\"123.4\", \"-123.4\", \"123a\", \"--1234\"))\n    True\n    \"\"\"\n    try:\n        int(s)\n        return True\n    except ValueError:\n        return False\n\n\ndef get_software_version() -> str:\n    cmd = \"git rev-parse --short HEAD --\".split()\n    return run(cmd, text=True).stdout\n\n\n# See https://docs.python.org/3/library/enum.html#orderedenum\nclass OrderedEnum(Enum):\n    def __ge__(self, other):\n        if self.__class__ is other.__class__:\n            return self.value >= other.value\n        return NotImplemented\n\n    def __gt__(self, other):\n        if self.__class__ is other.__class__:\n            return self.value > other.value\n        return NotImplemented\n\n    def __le__(self, other):\n        if self.__class__ is other.__class__:\n            return self.value <= other.value\n        return NotImplemented\n\n    def __lt__(self, other):\n        if self.__class__ is other.__class__:\n            return self.value < other.value\n        return NotImplemented\n", "path": "openlibrary/utils/__init__.py"}], "after_files": [{"content": "\"\"\"Generic utilities\"\"\"\n\nfrom enum import Enum\nimport re\nfrom subprocess import run\nfrom typing import TypeVar, Literal, Optional\nfrom collections.abc import Iterable, Callable\n\nto_drop = set(''';/?:@&=+$,<>#%\"{}|\\\\^[]`\\n\\r''')\n\n\ndef str_to_key(s: str) -> str:\n    \"\"\"\n    >>> str_to_key(\"?H$e##l{o}[0] -world!\")\n    'helo0_-world!'\n    >>> str_to_key(\"\".join(to_drop))\n    ''\n    >>> str_to_key(\"\")\n    ''\n    \"\"\"\n    return ''.join(c if c != ' ' else '_' for c in s.lower() if c not in to_drop)\n\n\ndef finddict(dicts, **filters):\n    \"\"\"Find a dictionary that matches given filter conditions.\n\n    >>> dicts = [{\"x\": 1, \"y\": 2}, {\"x\": 3, \"y\": 4}]\n    >>> sorted(finddict(dicts, x=1).items())\n    [('x', 1), ('y', 2)]\n    \"\"\"\n    for d in dicts:\n        if all(d.get(k) == v for k, v in filters.items()):\n            return d\n\n\nT = TypeVar('T')\n\n\ndef uniq(values: Iterable[T], key=None) -> list[T]:\n    \"\"\"Returns the unique entries from the given values in the original order.\n\n    The value of the optional `key` parameter should be a function that takes\n    a single argument and returns a key to test the uniqueness.\n    TODO: Moved this to core/utils.py\n\n    >>> uniq(\"abcbcddefefg\")\n    ['a', 'b', 'c', 'd', 'e', 'f', 'g']\n    >>> uniq(\"011223344556677889\")\n    ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']\n    \"\"\"\n    key = key or (lambda x: x)\n    s = set()\n    result = []\n    for v in values:\n        k = key(v)\n        if k not in s:\n            s.add(k)\n            result.append(v)\n    return result\n\n\ndef take_best(\n    items: list[T],\n    optimization: Literal[\"min\", \"max\"],\n    scoring_fn: Callable[[T], float],\n) -> list[T]:\n    \"\"\"\n    >>> take_best([], 'min', lambda x: x)\n    []\n    >>> take_best([3, 2, 1], 'min', lambda x: x)\n    [1]\n    >>> take_best([3, 4, 5], 'max', lambda x: x)\n    [5]\n    >>> take_best([4, 1, -1, -1], 'min', lambda x: x)\n    [-1, -1]\n    \"\"\"\n    best_score = float(\"-inf\") if optimization == \"max\" else float(\"inf\")\n    besties = []\n    for item in items:\n        score = scoring_fn(item)\n        if (optimization == \"max\" and score > best_score) or (\n            optimization == \"min\" and score < best_score\n        ):\n            best_score = score\n            besties = [item]\n        elif score == best_score:\n            besties.append(item)\n        else:\n            continue\n    return besties\n\n\ndef multisort_best(\n    items: list[T], specs: list[tuple[Literal[\"min\", \"max\"], Callable[[T], float]]]\n) -> Optional[T]:\n    \"\"\"\n    Takes the best item, taking into account the multisorts\n\n    >>> multisort_best([], [])\n\n    >>> multisort_best([3,4,5], [('max', lambda x: x)])\n    5\n\n    >>> multisort_best([\n    ...     {'provider': 'ia', 'size': 4},\n    ...     {'provider': 'ia', 'size': 12},\n    ...     {'provider': None, 'size': 42},\n    ... ], [\n    ...     ('min', lambda x: 0 if x['provider'] == 'ia' else 1),\n    ...     ('max', lambda x: x['size']),\n    ... ])\n    {'provider': 'ia', 'size': 12}\n    \"\"\"\n    if not items:\n        return None\n    pool = items\n    for optimization, fn in specs:\n        # Shrink the pool down each time\n        pool = take_best(pool, optimization, fn)\n    return pool[0]\n\n\ndef dicthash(d):\n    \"\"\"Dictionaries are not hashable. This function converts dictionary into nested\n    tuples, so that it can hashed.\n    \"\"\"\n    if isinstance(d, dict):\n        return tuple((k, dicthash(d[k])) for k in sorted(d))\n    elif isinstance(d, list):\n        return tuple(dicthash(v) for v in d)\n    else:\n        return d\n\n\nauthor_olid_embedded_re = re.compile(r'OL\\d+A', re.IGNORECASE)\n\n\ndef find_author_olid_in_string(s):\n    \"\"\"\n    >>> find_author_olid_in_string(\"ol123a\")\n    'OL123A'\n    >>> find_author_olid_in_string(\"/authors/OL123A/edit\")\n    'OL123A'\n    >>> find_author_olid_in_string(\"some random string\")\n    \"\"\"\n    found = re.search(author_olid_embedded_re, s)\n    return found and found.group(0).upper()\n\n\nwork_olid_embedded_re = re.compile(r'OL\\d+W', re.IGNORECASE)\n\n\ndef find_work_olid_in_string(s):\n    \"\"\"\n    >>> find_work_olid_in_string(\"ol123w\")\n    'OL123W'\n    >>> find_work_olid_in_string(\"/works/OL123W/Title_of_book\")\n    'OL123W'\n    >>> find_work_olid_in_string(\"some random string\")\n    \"\"\"\n    found = re.search(work_olid_embedded_re, s)\n    return found and found.group(0).upper()\n\n\ndef extract_numeric_id_from_olid(olid):\n    \"\"\"\n    >>> extract_numeric_id_from_olid(\"OL123W\")\n    '123'\n    >>> extract_numeric_id_from_olid(\"/authors/OL123A\")\n    '123'\n    \"\"\"\n    if '/' in olid:\n        olid = olid.split('/')[-1]\n    if olid.lower().startswith('ol'):\n        olid = olid[2:]\n    if not is_number(olid[-1].lower()):\n        olid = olid[:-1]\n    return olid\n\n\ndef is_number(s):\n    \"\"\"\n    >>> all(is_number(n) for n in (1234, \"1234\", -1234, \"-1234\", 123.4, -123.4))\n    True\n    >>> not any(is_number(n) for n in (\"123.4\", \"-123.4\", \"123a\", \"--1234\"))\n    True\n    \"\"\"\n    try:\n        int(s)\n        return True\n    except ValueError:\n        return False\n\n\ndef get_software_version() -> str:\n    \"\"\"\n    assert get_software_version()  # Should never return a falsy value\n    \"\"\"\n    cmd = \"git rev-parse --short HEAD --\".split()\n    return run(cmd, capture_output=True, text=True).stdout.strip()\n\n\n# See https://docs.python.org/3/library/enum.html#orderedenum\nclass OrderedEnum(Enum):\n    def __ge__(self, other):\n        if self.__class__ is other.__class__:\n            return self.value >= other.value\n        return NotImplemented\n\n    def __gt__(self, other):\n        if self.__class__ is other.__class__:\n            return self.value > other.value\n        return NotImplemented\n\n    def __le__(self, other):\n        if self.__class__ is other.__class__:\n            return self.value <= other.value\n        return NotImplemented\n\n    def __lt__(self, other):\n        if self.__class__ is other.__class__:\n            return self.value < other.value\n        return NotImplemented\n", "path": "openlibrary/utils/__init__.py"}]}