ya2 · news · projects · code · about

7330b90e0b3c2624a0f81162366693a537d46b8b
[pmachines.git] / ya2 / utils / log.py
1 from logging import basicConfig, info, INFO, DEBUG, getLogger
2 from configparser import ConfigParser
3 from sys import platform, argv
4 from glob import glob
5 from os import getcwd, environ
6 from os.path import exists
7 from sys import version_info
8 # from platform import system, release, architecture, platform, processor, \
9 # version, machine
10 # from multiprocessing import cpu_count
11 from panda3d.core import Filename, PandaSystem
12 from panda3d.bullet import get_bullet_version
13 from ya2.utils.logics import LogicsTools, class_property
14 import sys
15
16
17 class LogManager:
18
19 @staticmethod
20 def before_init_setup(app_name):
21 LogManager.__app_name = app_name
22 o = LogManager.option_file_path
23 LogManager.__set_level(o)
24
25 @class_property
26 def option_file_path(cls):
27 r = 'options.ini'
28 path = ''
29 if LogicsTools.in_build:
30 path = str(Filename.get_user_appdata_directory()) + '/pmachines'
31 if path:
32 r = LogicsTools.platform_specific_path(path + '/options.ini')
33 return r
34
35 @staticmethod
36 def __set_level(options_file_path):
37 l = LogManager.__set_level_from_settings(options_file_path)
38 basicConfig(level=l, format='%(asctime)s %(message)s', datefmt='%H:%M:%S')
39 getLogger().setLevel(l)
40
41 @staticmethod
42 def __set_level_from_settings(options_file_path):
43 l = INFO
44 if exists(options_file_path):
45 with open(options_file_path):
46 o = ConfigParser()
47 o.read(options_file_path)
48 v = o['development']['verbose_log']
49 if v and int(v):
50 l = DEBUG
51 return l
52
53 @class_property
54 def init_cls(cls):
55 return WindowedLogManager if base.win else LogManager
56
57 def __init__(self):
58 self.log_configuration()
59
60 def log(self, message, verbose=False):
61 if verbose and not self.eng.cfg.dev_cfg.verbose_log: return
62 info(message)
63
64 @property
65 def build_version(self):
66 appimage_version = self.__build_version_appimage()
67 if appimage_version: return appimage_version
68 return self.__build_version_from_file
69
70 def __build_version_appimage(self):
71 appimage_mounted = glob(f'{LogicsTools.appimage_path(self.__app_name)}*')
72 if appimage_mounted:
73 with open(LogicsTools.current_path(self.__app_name) + 'assets/build_version.txt') as f:
74 return f.read().strip()
75
76 @property
77 def __build_version_from_file(self):
78 try: return self.__load_version_from_file()
79 except FileNotFoundError:
80 info('not found ' + LogicsTools.current_path(self.__app_name) + 'assets/build_version.txt')
81 return 'notfound'
82
83 def __load_version_from_file(self):
84 with open(LogicsTools.current_path(self.__app_name) + 'assets/build_version.txt') as f:
85 return f.read().strip()
86
87 def log_configuration(self):
88 if '--version' in argv:
89 self.__write_observed_version()
90 self.__print_version()
91 self.__messages = [f'version: {self.build_version}',
92 f'argv[0]: {argv[0]}',
93 f'getcwd: {getcwd()}',
94 f'__file__: {__file__}']
95 for e in environ.items():
96 self.__messages += [f'env::{e[0]}: {e[1]}']
97 # os_info = (system(), release(), version())
98 # messages += ['operative system: %s %s %s' % os_info]
99 # messages += ['architecture: ' + str(architecture())]
100 # messages += ['machine: ' + machine()]
101 # messages += ['platform: ' + platform()]
102 # messages += ['processor: ' + processor()]
103 # try:
104 # messages += ['cores: ' + str(cpu_count())]
105 # except NotImplementedError: # on Windows
106 # messages += ['cores: not implemented']
107 lib_ver = PandaSystem.get_version_string()
108 self.__log_system_memory()
109 lib_commit = PandaSystem.get_git_commit()
110 py_ver = [str(e) for e in version_info[:3]]
111 self.__messages += [f'python version: {".".join(py_ver)}',
112 f'panda version: {lib_ver} {lib_commit}',
113 f'bullet version: {str(get_bullet_version())}',
114 f'appdata: {str(Filename.get_user_appdata_directory())}']
115 if LogicsTools.windowed:
116 # not headless
117 print(base.win.get_keyboard_map())
118 list(map(self.log, self.__messages))
119
120 def __write_observed_version(self):
121 info(f'writing {LogicsTools.appdata_path}/{self.__appname}/observed_version.txt')
122 with open(LogicsTools.appdata_path + '/pmachines/observed_version.txt', 'w') as f:
123 f.write(self.build_version)
124
125 def __print_version(self):
126 if not platform.startswith('win'):
127 from os import ttyname # here because it doesn't work on windows
128 try:
129 with open(ttyname(0), 'w') as f:
130 sys.stdout = f
131 print(f'version: {self.build_version}')
132 except OSError: # it doesn't work with crontab
133 print('version: ' + self.build_version)
134
135 def __log_system_memory(self):
136 try:
137 import psutil
138 mem = psutil.virtual_memory().total / 1000000000
139 self.__messages += [f'memory: {round(mem, 2)} GB']
140 except ImportError:
141 info("can't import psutil") # windows
142
143
144 class WindowedLogManager(LogManager):
145
146 def log_configuration(self):
147 super().log_configuration()
148 self.__messages = [base.win.get_gsg().get_driver_vendor()]
149 self.__messages += [base.win.get_gsg().get_driver_renderer()]
150 shad_maj = base.win.get_gsg().\
151 get_driver_shader_version_major()
152 shad_min = base.win.get_gsg().\
153 get_driver_shader_version_minor()
154 self.__messages += ['shader: {maj}.{min}'.format(maj=shad_maj, min=shad_min)]
155 self.__messages += [base.win.get_gsg().get_driver_version()]
156 drv_maj = base.win.get_gsg().get_driver_version_major()
157 drv_min = base.win.get_gsg().get_driver_version_minor()
158 drv = 'driver version: {maj}.{min}'
159 self.__messages += [drv.format(maj=drv_maj, min=drv_min)]
160 self.__log_fullscreen()
161 self.__log_resolution()
162 list(map(self.log, self.__messages))
163
164 def __log_fullscreen(self):
165 fullscreen = None
166 if LogicsTools.windowed:
167 fullscreen = base.win.get_properties().get_fullscreen()
168 self.__messages += ['fullscreen: ' + str(fullscreen)]
169
170 def __log_resolution(self):
171 def resolution():
172 if not LogicsTools.windowed:
173 return 800, 600
174 w = base.win.get_properties()
175 return w.get_x_size(), w.get_y_size()
176 self.__messages += [f'resolution: {(r := resolution())[0]}x{r[1]}']