ya2 · news · projects · code · about

housekeeping: ya2 module
[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 platform import system
5 from pathlib import Path
6 from glob import glob
7 # from datetime import datetime
8 from pprint import pprint
9 from os import getcwd, environ
10 from os.path import exists
11 from traceback import print_stack
12 from sys import version_info
13 # from platform import system, release, architecture, platform, processor, \
14 # version, machine
15 # from multiprocessing import cpu_count
16 from panda3d.core import Filename, GraphicsWindow, PandaSystem
17 from panda3d.bullet import get_bullet_version
18 from ya2.utils.logics import LogicsTools
19
20
21 class LogManagerBase: # headless log manager
22
23 @staticmethod
24 def pre_init_logging():
25 opt_path = LogManagerBase.__get_option_file_path()
26 LogManagerBase.__log_info_debug_messages(opt_path)
27
28 @staticmethod
29 def __get_option_file_path():
30 opt_path = ''
31 if platform in ['win32', 'linux'] and not exists('main.py'):
32 # it is the deployed version for windows
33 opt_path = str(Filename.get_user_appdata_directory()) + '/pmachines'
34 opath = LogicsTools.fixpath(opt_path + '/options.ini') if opt_path else \
35 'options.ini'
36 return opath
37
38 @staticmethod
39 def __log_info_debug_messages(opath):
40 lev = INFO
41 if exists(opath):
42 with open(opath):# as json_file:
43 # optfile = load(json_file)
44 optfile = ConfigParser()
45 optfile.read(opath)
46 # optfile['development']['verbose']
47 # and int(optfile['development']['verbose']) or \
48 if optfile['development']['verbose_log'] and \
49 int(optfile['development']['verbose_log']):
50 lev = DEBUG
51
52 basicConfig(level=lev, format='%(asctime)s %(message)s', datefmt='%H:%M:%S')
53 getLogger().setLevel(lev) # it doesn't work otherwise
54
55 @staticmethod
56 def init_cls():
57 return LogMgr if base.win else LogManagerBase
58
59 def __init__(self):
60 self.log_cfg()
61
62 def log(self, msg, verbose=False):
63 if verbose and not self.eng.cfg.dev_cfg.verbose_log:
64 return
65 info(msg)
66
67 @property
68 def is_appimage(self):
69 par_path = str(Path(__file__).parent.absolute())
70 is_appimage = par_path.startswith('/tmp/.mount_Pmachi')
71 return is_appimage and par_path.endswith('/usr/bin')
72
73 # @property
74 # def curr_path(self):
75 # # this is different from the music's one since it does not work
76 # # with the version in windows
77 # if sys.platform == 'darwin':
78 # return dirname(__file__) + '/../Resources/'
79 # # return dirname(__file__)
80 # par_path = str(Path(__file__).parent.absolute())
81 # if self.is_appimage:
82 # return str(Path(par_path).absolute())
83 # is_snap = par_path.startswith('/snap/')
84 # is_snap = is_snap and par_path.endswith('/x1')
85 # if is_snap:
86 # return str(Path(par_path).absolute())
87 # #return getcwd()
88 # #curr_path = dirname(__file__)
89 # curr_path = str(Path(__file__).parent.parent.parent.absolute())
90 # info('current path: %s' % curr_path)
91 # return curr_path
92
93 @property
94 def curr_path(self):
95 if system() == 'Windows':
96 return ''
97 if exists('main.py'):
98 return ''
99 else:
100 par_path = str(Path(__file__).parent.absolute())
101 if self.is_appimage:
102 par_path = str(Path(par_path).absolute())
103 par_path += '/'
104 return par_path
105
106 @property
107 def build_version(self):
108 appimg_mnt = glob('/tmp/.mount_Pmachi*')
109 if appimg_mnt:
110 # with open(
111 # appimg_mnt[0] + '/usr/bin/appimage_version.txt') as fver:
112 with open(self.curr_path + 'assets/bld_version.txt') as fver:
113 return fver.read().strip()
114 try:
115 with open(self.curr_path + 'assets/bld_version.txt') as fver:
116 return fver.read().strip()
117 except FileNotFoundError:
118 info('not found ' + self.curr_path + 'assets/bld_version.txt')
119 return 'notfound'
120
121 def log_cfg(self):
122 if '--version' in argv:
123 path = str(Filename.get_user_appdata_directory())
124 home = '/home/flavio' # we must force this for wine
125 if path.startswith('/c/users/') and exists(home + '/.wine/'):
126 path = home + '/.wine/drive_' + path[1:]
127 info('writing %s' % path + '/pmachines/obs_version.txt')
128 with open(path + '/pmachines/obs_version.txt', 'w') as f:
129 # f.write(self.eng.logic.version)
130 f.write(self.build_version)
131 if not platform.startswith('win'):
132 from os import ttyname
133 # here because it doesn't work on windows
134 import sys
135 try:
136 with open(ttyname(0), 'w') as fout:
137 sys.stdout = fout
138 print('version: ' + self.build_version)
139 # self.eng.logic.version)
140 except OSError: # it doesn't work with crontab
141 print('version: ' + self.build_version)
142 messages = ['version: ' + self.build_version]
143 # self.eng.logic.version]
144 messages += ['argv[0]: %s' % argv[0]]
145 messages += ['getcwd: %s' % getcwd()]
146 messages += ['__file__: %s' % __file__]
147 for elm in environ.items():
148 messages += ['env::%s: %s' % elm]
149 # os_info = (system(), release(), version())
150 # messages += ['operative system: %s %s %s' % os_info]
151 # messages += ['architecture: ' + str(architecture())]
152 # messages += ['machine: ' + machine()]
153 # messages += ['platform: ' + platform()]
154 # messages += ['processor: ' + processor()]
155 # try:
156 # messages += ['cores: ' + str(cpu_count())]
157 # except NotImplementedError: # on Windows
158 # messages += ['cores: not implemented']
159 lib_ver = PandaSystem.get_version_string()
160 try:
161 import psutil
162 mem = psutil.virtual_memory().total / 1000000000.0
163 messages += ['memory: %s GB' % round(mem, 2)]
164 except ImportError:
165 info("can't import psutil") # windows
166 lib_commit = PandaSystem.get_git_commit()
167 py_ver = [str(elm) for elm in version_info[:3]]
168 messages += ['python version: %s' % '.'.join(py_ver)]
169 messages += ['panda version: %s %s' % (lib_ver, lib_commit)]
170 messages += ['bullet version: ' + str(get_bullet_version())]
171 messages += ['appdata: ' + str(Filename.get_user_appdata_directory())]
172 if base.win and isinstance(base.win, GraphicsWindow):
173 # not headless
174 print(base.win.get_keyboard_map())
175 list(map(self.log, messages))
176
177 @staticmethod
178 def log_tasks():
179 info('tasks: %s' % taskMgr.getAllTasks())
180 info('do-laters: %s' % taskMgr.getDoLaters())
181
182 @staticmethod
183 def plog(obj):
184 print('\n\n')
185 print_stack()
186 pprint(obj)
187 print('\n\n')
188
189
190 class LogMgr(LogManagerBase):
191
192 def log_cfg(self):
193 LogManagerBase.log_cfg(self)
194 messages = [base.win.get_gsg().get_driver_vendor()]
195 messages += [base.win.get_gsg().get_driver_renderer()]
196 shad_maj = base.win.get_gsg().\
197 get_driver_shader_version_major()
198 shad_min = base.win.get_gsg().\
199 get_driver_shader_version_minor()
200 messages += ['shader: {maj}.{min}'.format(maj=shad_maj, min=shad_min)]
201 messages += [base.win.get_gsg().get_driver_version()]
202 drv_maj = base.win.get_gsg().get_driver_version_major()
203 drv_min = base.win.get_gsg().get_driver_version_minor()
204 drv = 'driver version: {maj}.{min}'
205 messages += [drv.format(maj=drv_maj, min=drv_min)]
206 fullscreen = None
207 if isinstance(base.win, GraphicsWindow):
208 fullscreen = base.win.get_properties().get_fullscreen()
209 messages += ['fullscreen: ' + str(fullscreen)]
210
211 def resolution():
212 if not isinstance(base.win, GraphicsWindow):
213 return 800, 600
214 win_prop = base.win.get_properties()
215 return win_prop.get_x_size(), win_prop.get_y_size()
216 res_x, res_y = resolution()
217 res_tmpl = 'resolution: {res_x}x{res_y}'
218 messages += [res_tmpl.format(res_x=res_x, res_y=res_y)]
219 list(map(self.log, messages))