diff options
author | Arun Isaac | 2023-12-29 18:55:37 +0000 |
---|---|---|
committer | Arun Isaac | 2023-12-29 19:01:46 +0000 |
commit | 204a308be0f741726b9a620d88fbc22b22124c81 (patch) | |
tree | b3cf66906674020b530c844c2bb4982c8a0e2d39 /gn2/utility/monads.py | |
parent | 83062c75442160427b50420161bfcae2c5c34c84 (diff) | |
download | genenetwork2-204a308be0f741726b9a620d88fbc22b22124c81.tar.gz |
Namespace all modules under gn2.
We move all modules under a gn2 directory. This is important for
"correct" packaging and deployment as a Guix service.
Diffstat (limited to 'gn2/utility/monads.py')
-rw-r--r-- | gn2/utility/monads.py | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/gn2/utility/monads.py b/gn2/utility/monads.py new file mode 100644 index 00000000..2d708261 --- /dev/null +++ b/gn2/utility/monads.py @@ -0,0 +1,114 @@ +"""Monadic utilities + +This module is a collection of monadic utilities for use in +GeneNetwork. It includes: + +* MonadicDict - monadic version of the built-in dictionary +* MonadicDictCursor - monadic version of MySQLdb.cursors.DictCursor + that returns a MonadicDict instead of the built-in dictionary +""" + +from collections import UserDict +from functools import partial + +from MySQLdb.cursors import DictCursor +from pymonad.maybe import Just, Nothing + +class MonadicDict(UserDict): + """ + Monadic version of the built-in dictionary. + + Keys in this dictionary can be any python object, but values must + be monadic values. + + from pymonad.maybe import Just, Nothing + + Initialize by setting individual keys to monadic values. + >>> d = MonadicDict() + >>> d["foo"] = Just(1) + >>> d["bar"] = Nothing + >>> d + {'foo': 1} + + Initialize by converting a built-in dictionary object. + >>> MonadicDict({"foo": 1}) + {'foo': 1} + >>> MonadicDict({"foo": 1, "bar": None}) + {'foo': 1} + + Initialize from a built-in dictionary object with monadic values. + >>> MonadicDict({"foo": Just(1)}, convert=False) + {'foo': 1} + >>> MonadicDict({"foo": Just(1), "bar": Nothing}, convert=False) + {'foo': 1} + + Get values. For non-existent keys, Nothing is returned. Else, a + Just value is returned. + >>> d["foo"] + Just 1 + >>> d["bar"] + Nothing + + Convert MonadicDict object to a built-in dictionary object. + >>> d.data + {'foo': 1} + >>> type(d) + <class 'utility.monads.MonadicDict'> + >>> type(d.data) + <class 'dict'> + + Delete keys. Deleting non-existent keys does nothing. + >>> del d["bar"] + >>> d + {'foo': 1} + >>> del d["foo"] + >>> d + {} + """ + def __init__(self, d={}, convert=True): + """Initialize monadic dictionary. + + If convert is False, values in dictionary d must be + monadic. If convert is True, values in dictionary d are + converted to monadic values. + """ + if convert: + super().__init__({key:Just(value) for key, value in d.items() + if value is not None}) + else: + super().__init__(d) + def __getitem__(self, key): + """Get key from dictionary. + + If key exists in the dictionary, return a Just value. Else, + return Nothing. + """ + try: + return Just(self.data[key]) + except KeyError: + return Nothing + def __setitem__(self, key, value): + """Set key in dictionary. + + value must be a monadic value---either Nothing or a Just + value. If value is a Just value, set it in the dictionary. If + value is Nothing, do nothing. + """ + value.bind(partial(super().__setitem__, key)) + def __delitem__(self, key): + """Delete key from dictionary. + + If key exists in the dictionary, delete it. Else, do nothing. + """ + try: + super().__delitem__(key) + except KeyError: + pass + + +def sql_query_mdict(conn, query): + """Execute SQL query and return a generator of MonadicDict objects.""" + with conn.cursor(DictCursor) as cursor: + cursor.execute(query) + while (row := cursor.fetchone()): + yield MonadicDict(row) |