Skip to content

Commit 52972b4

Browse files
Replace binary logging with source copy
1 parent 1bfcd3a commit 52972b4

File tree

6 files changed

+419
-13
lines changed

6 files changed

+419
-13
lines changed

internal_filesystem/builtin/apps/com.micropythonos.about/assets/about.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import sys
2+
import logging
23

34
from mpos import Activity, DisplayMetrics, BuildInfo, DeviceInfo
45

56
class About(Activity):
67

8+
logger = logging.getLogger(__file__)
9+
logger.setLevel(logging.INFO)
10+
711
def _add_label(self, parent, text, is_header=False, margin_top=DisplayMetrics.pct_of_height(5)):
812
"""Helper to create and add a label with text."""
913
label = lv.label(parent)
@@ -31,7 +35,7 @@ def _add_disk_info(self, screen, path):
3135
self._add_label(screen, f"Free space {path}: {free_space} bytes")
3236
self._add_label(screen, f"Used space {path}: {used_space} bytes")
3337
except Exception as e:
34-
print(f"About app could not get info on {path} filesystem: {e}")
38+
self.logger.warning(f"About app could not get info on {path} filesystem: {e}")
3539

3640
def onCreate(self):
3741
screen = lv.obj()
@@ -98,7 +102,7 @@ def onCreate(self):
98102
import esp32
99103
self._add_label(screen, f"Temperature: {esp32.mcu_temperature()} °C")
100104
except Exception as e:
101-
print(f"Could not get ESP32 hardware info: {e}")
105+
self.logger.warning(f"Could not get ESP32 hardware info: {e}")
102106

103107
# Partition info (ESP32 only)
104108
try:
@@ -110,12 +114,12 @@ def onCreate(self):
110114
self._add_label(screen, f"Next update partition: {next_partition}")
111115
except Exception as e:
112116
error = f"Could not find partition info because: {e}\nIt's normal to get this error on desktop."
113-
print(error)
117+
self.logger.warning(error)
114118
self._add_label(screen, error)
115119

116120
# Machine info
117121
try:
118-
print("Trying to find out additional board info, not available on every platform...")
122+
self.logger.info("Trying to find out additional board info, not available on every platform...")
119123
self._add_label(screen, f"{lv.SYMBOL.POWER} Machine Info", is_header=True)
120124
import machine
121125
self._add_label(screen, f"machine.freq: {machine.freq()}")
@@ -127,12 +131,12 @@ def onCreate(self):
127131
self._add_label(screen, f"machine.reset_cause(): {machine.reset_cause()}")
128132
except Exception as e:
129133
error = f"Could not find machine info because: {e}\nIt's normal to get this error on desktop."
130-
print(error)
134+
self.logger.warning(error)
131135
self._add_label(screen, error)
132136

133137
# Freezefs info (production builds only)
134138
try:
135-
print("Trying to find out freezefs info")
139+
self.logger.info("Trying to find out freezefs info")
136140
self._add_label(screen, f"{lv.SYMBOL.DOWNLOAD} Frozen Filesystem", is_header=True)
137141
import freezefs_mount_builtin
138142
self._add_label(screen, f"freezefs_mount_builtin.date_frozen: {freezefs_mount_builtin.date_frozen}")
@@ -147,7 +151,7 @@ def onCreate(self):
147151
# BUT which will still have the frozen-inside /lib folder. So the user will be able to install apps into /builtin
148152
# but they will not be able to install libraries into /lib.
149153
error = f"Could not get freezefs_mount_builtin info because: {e}\nIt's normal to get an exception if the internal storage partition contains an overriding /builtin folder."
150-
print(error)
154+
self.logger.warning(error)
151155
self._add_label(screen, error)
152156

153157
# Display info
@@ -159,7 +163,7 @@ def onCreate(self):
159163
dpi = DisplayMetrics.dpi()
160164
self._add_label(screen, f"Dots Per Inch (dpi): {dpi}")
161165
except Exception as e:
162-
print(f"Could not get display info: {e}")
166+
self.logger.warning(f"Could not get display info: {e}")
163167

164168
# Disk usage info
165169
self._add_label(screen, f"{lv.SYMBOL.DRIVE} Storage", is_header=True)
-2.76 KB
Binary file not shown.

internal_filesystem/lib/logging.py

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
from micropython import const
2+
import io
3+
import sys
4+
import time
5+
6+
CRITICAL = const(50)
7+
ERROR = const(40)
8+
WARNING = const(30)
9+
INFO = const(20)
10+
DEBUG = const(10)
11+
NOTSET = const(0)
12+
13+
_DEFAULT_LEVEL = const(WARNING)
14+
15+
_level_dict = {
16+
CRITICAL: "CRITICAL",
17+
ERROR: "ERROR",
18+
WARNING: "WARNING",
19+
INFO: "INFO",
20+
DEBUG: "DEBUG",
21+
NOTSET: "NOTSET",
22+
}
23+
24+
_loggers = {}
25+
_stream = sys.stderr
26+
_default_fmt = "%(levelname)s:%(name)s:%(message)s"
27+
_default_datefmt = "%Y-%m-%d %H:%M:%S"
28+
29+
30+
class LogRecord:
31+
def set(self, name, level, message):
32+
self.name = name
33+
self.levelno = level
34+
self.levelname = _level_dict[level]
35+
self.message = message
36+
self.ct = time.time()
37+
self.msecs = int((self.ct - int(self.ct)) * 1000)
38+
self.asctime = None
39+
40+
41+
class Handler:
42+
def __init__(self, level=NOTSET):
43+
self.level = level
44+
self.formatter = None
45+
46+
def close(self):
47+
pass
48+
49+
def setLevel(self, level):
50+
self.level = level
51+
52+
def setFormatter(self, formatter):
53+
self.formatter = formatter
54+
55+
def format(self, record):
56+
return self.formatter.format(record)
57+
58+
59+
class StreamHandler(Handler):
60+
def __init__(self, stream=None):
61+
super().__init__()
62+
self.stream = _stream if stream is None else stream
63+
self.terminator = "\n"
64+
65+
def close(self):
66+
if hasattr(self.stream, "flush"):
67+
self.stream.flush()
68+
69+
def emit(self, record):
70+
if record.levelno >= self.level:
71+
self.stream.write(self.format(record) + self.terminator)
72+
73+
74+
class FileHandler(StreamHandler):
75+
def __init__(self, filename, mode="a", encoding="UTF-8"):
76+
super().__init__(stream=open(filename, mode=mode, encoding=encoding))
77+
78+
def close(self):
79+
super().close()
80+
self.stream.close()
81+
82+
83+
class Formatter:
84+
def __init__(self, fmt=None, datefmt=None):
85+
self.fmt = _default_fmt if fmt is None else fmt
86+
self.datefmt = _default_datefmt if datefmt is None else datefmt
87+
88+
def usesTime(self):
89+
return "asctime" in self.fmt
90+
91+
def formatTime(self, datefmt, record):
92+
if hasattr(time, "strftime"):
93+
return time.strftime(datefmt, time.localtime(record.ct))
94+
return None
95+
96+
def format(self, record):
97+
if self.usesTime():
98+
record.asctime = self.formatTime(self.datefmt, record)
99+
return self.fmt % {
100+
"name": record.name,
101+
"message": record.message,
102+
"msecs": record.msecs,
103+
"asctime": record.asctime,
104+
"levelname": record.levelname,
105+
}
106+
107+
108+
class Logger:
109+
def __init__(self, name, level=NOTSET):
110+
self.name = name
111+
self.level = level
112+
self.handlers = []
113+
self.record = LogRecord()
114+
115+
def setLevel(self, level):
116+
self.level = level
117+
118+
def isEnabledFor(self, level):
119+
return level >= self.getEffectiveLevel()
120+
121+
def getEffectiveLevel(self):
122+
return self.level or getLogger().level or _DEFAULT_LEVEL
123+
124+
def log(self, level, msg, *args):
125+
if self.isEnabledFor(level):
126+
if args:
127+
if isinstance(args[0], dict):
128+
args = args[0]
129+
msg = msg % args
130+
self.record.set(self.name, level, msg)
131+
handlers = self.handlers
132+
if not handlers:
133+
handlers = getLogger().handlers
134+
for h in handlers:
135+
h.emit(self.record)
136+
137+
def debug(self, msg, *args):
138+
self.log(DEBUG, msg, *args)
139+
140+
def info(self, msg, *args):
141+
self.log(INFO, msg, *args)
142+
143+
def warning(self, msg, *args):
144+
self.log(WARNING, msg, *args)
145+
146+
def error(self, msg, *args):
147+
self.log(ERROR, msg, *args)
148+
149+
def critical(self, msg, *args):
150+
self.log(CRITICAL, msg, *args)
151+
152+
def exception(self, msg, *args, exc_info=True):
153+
self.log(ERROR, msg, *args)
154+
tb = None
155+
if isinstance(exc_info, BaseException):
156+
tb = exc_info
157+
elif hasattr(sys, "exc_info"):
158+
tb = sys.exc_info()[1]
159+
if tb:
160+
buf = io.StringIO()
161+
sys.print_exception(tb, buf)
162+
self.log(ERROR, buf.getvalue())
163+
164+
def addHandler(self, handler):
165+
self.handlers.append(handler)
166+
167+
def hasHandlers(self):
168+
return len(self.handlers) > 0
169+
170+
171+
def getLogger(name=None):
172+
if name is None:
173+
name = "root"
174+
if name not in _loggers:
175+
_loggers[name] = Logger(name)
176+
if name == "root":
177+
basicConfig()
178+
return _loggers[name]
179+
180+
181+
def log(level, msg, *args):
182+
getLogger().log(level, msg, *args)
183+
184+
185+
def debug(msg, *args):
186+
getLogger().debug(msg, *args)
187+
188+
189+
def info(msg, *args):
190+
getLogger().info(msg, *args)
191+
192+
193+
def warning(msg, *args):
194+
getLogger().warning(msg, *args)
195+
196+
197+
def error(msg, *args):
198+
getLogger().error(msg, *args)
199+
200+
201+
def critical(msg, *args):
202+
getLogger().critical(msg, *args)
203+
204+
205+
def exception(msg, *args, exc_info=True):
206+
getLogger().exception(msg, *args, exc_info=exc_info)
207+
208+
209+
def shutdown():
210+
for k, logger in _loggers.items():
211+
for h in logger.handlers:
212+
h.close()
213+
_loggers.pop(logger, None)
214+
215+
216+
def addLevelName(level, name):
217+
_level_dict[level] = name
218+
219+
220+
def basicConfig(
221+
filename=None,
222+
filemode="a",
223+
format=None,
224+
datefmt=None,
225+
level=WARNING,
226+
stream=None,
227+
encoding="UTF-8",
228+
force=False,
229+
):
230+
if "root" not in _loggers:
231+
_loggers["root"] = Logger("root")
232+
233+
logger = _loggers["root"]
234+
235+
if force or not logger.handlers:
236+
for h in logger.handlers:
237+
h.close()
238+
logger.handlers = []
239+
240+
if filename is None:
241+
handler = StreamHandler(stream)
242+
else:
243+
handler = FileHandler(filename, filemode, encoding)
244+
245+
# Fix from https://github.com/micropython/micropython-lib/pull/1077 is on the line below:
246+
handler.setLevel(NOTSET)
247+
handler.setFormatter(Formatter(format, datefmt))
248+
249+
logger.setLevel(level)
250+
logger.addHandler(handler)
251+
252+
253+
if hasattr(sys, "atexit"):
254+
sys.atexit(shutdown)

internal_filesystem/lib/mpos/content/app_manager.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,8 @@ def execute_script(script_source, is_file, classname, cwd=None):
252252
print(f"execute_script: reading script_source took {read_time}ms")
253253
script_globals = {
254254
'lv': lv,
255-
'__name__': "__main__"
255+
'__name__': "__main__", # in case the script wants this
256+
'__file__': compile_name
256257
}
257258
print(f"Thread {thread_id}: starting script")
258259
import sys

manifests/manifest_fri3d-2024.py

Lines changed: 0 additions & 4 deletions
This file was deleted.

0 commit comments

Comments
 (0)