]> Repositories - Adafruit_Blinka-hackapet.git/blob - src/adafruit_blinka/__init__.py
fix wrongly assuming "of_node/compatible" will always exist for all gpiochips
[Adafruit_Blinka-hackapet.git] / src / adafruit_blinka / __init__.py
1 # SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
2 #
3 # SPDX-License-Identifier: MIT
4 """
5 `adafruit_blinka` - Runtime utility objects for re-implementation of CircuitPython API
6 ======================================================================================
7
8 * Author(s): cefn
9 """
10
11 import os
12
13 try:
14     import tomllib
15 except ImportError:
16     import toml as tomllib
17
18
19 class Enum:
20     """
21     Object supporting CircuitPython-style of static symbols
22     as seen with Direction.OUTPUT, Pull.UP
23     """
24
25     def __repr__(self):
26         """
27         Assumes instance will be found as attribute of own class.
28         Returns dot-subscripted path to instance
29         (assuming absolute import of containing package)
30         """
31         cls = type(self)
32         for key in dir(cls):
33             if getattr(cls, key) is self:
34                 return "{}.{}.{}".format(cls.__module__, cls.__qualname__, key)
35         return repr(self)
36
37     @classmethod
38     def iteritems(cls):
39         """
40         Inspects attributes of the class for instances of the class
41         and returns as key,value pairs mirroring dict#iteritems
42         """
43         for key in dir(cls):
44             val = getattr(cls, key)
45             if isinstance(cls, val):
46                 yield (key, val)
47
48
49 class ContextManaged:
50     """An object that automatically deinitializes hardware with a context manager."""
51
52     def __enter__(self):
53         return self
54
55     def __exit__(self, exc_type, exc_value, traceback):
56         self.deinit()
57
58     # pylint: disable=no-self-use
59     def deinit(self):
60         """Free any hardware used by the object."""
61         return
62
63     # pylint: enable=no-self-use
64
65
66 class Lockable(ContextManaged):
67     """An object that must be locked to prevent collisions on a microcontroller resource."""
68
69     _locked = False
70
71     def try_lock(self):
72         """Attempt to grab the lock. Return True on success, False if the lock is already taken."""
73         if self._locked:
74             return False
75         self._locked = True
76         return True
77
78     def unlock(self):
79         """Release the lock so others may use the resource."""
80         if self._locked:
81             self._locked = False
82
83
84 def load_settings_toml():
85     """Load values from settings.toml into os.environ, so that os.getenv returns them."""
86     if not os.path.isfile("settings.toml"):
87         raise FileNotFoundError("settings.toml not cound in current directory.")
88
89     print("settings.toml found. Updating environment variables:")
90     with open("settings.toml", "rb") as toml_file:
91         try:
92             settings = tomllib.load(toml_file)
93         except tomllib.TOMLDecodeError as e:
94             raise tomllib.TOMLDecodeError("Error with settings.toml file.") from e
95
96     invalid_types = set()
97     for key, value in settings.items():
98         if not isinstance(value, (bool, int, float, str)):
99             invalid_types.add(type(value).__name__)
100     if invalid_types:
101         invalid_types_string = ", ".join(invalid_types)
102         raise ValueError(
103             f"The types: '{invalid_types_string}' are not supported in settings.toml."
104         )
105
106     for key, value in settings.items():
107         key = str(key)
108         if key in os.environ:
109             print(f" - {key} already exists in environment")
110             continue
111         os.environ[key] = str(value)
112         print(f" - {key} added")
113
114     return settings
115
116
117 def patch_system():
118     """Patch modules that may be different due to the platform."""
119     # pylint: disable=import-outside-toplevel
120     import sys
121     from adafruit_blinka.agnostic import time
122
123     # pylint: enable=import-outside-toplevel
124
125     sys.modules["time"] = time