This commit is contained in:
emdee@spm.plastiras.org 2024-02-03 04:34:10 +00:00
parent e4b1b9c4d8
commit 3ce822fc27
18 changed files with 198 additions and 68 deletions

View File

@ -85,3 +85,7 @@ Work on Tox on this project is suspended until the
This will probably be ported to Qt6 using qtpy This will probably be ported to Qt6 using qtpy
https://github.com/spyder-ide/qtpy . https://github.com/spyder-ide/qtpy .
Up-to-date code is on https://git.plastiras.org/emdee/toxygen
Work on this project is suspended until the
[MultiDevice](https://git.plastiras.org/emdee/tox_profile/wiki/MultiDevice-Announcements-POC) problem is solved. Fork me!

51
pyproject.tom Normal file
View File

@ -0,0 +1,51 @@
[project]
name = "stem_examples"
description = "examples of using stem"
authors = [{ name = "emdee", email = "emdee@spm.plastiras.org" } ]
requires-python = ">=3.6"
dependencies = [
'stem',
]
keywords = ["stem", "python3", "tor"]
classifiers = [
"License :: OSI Approved",
"Operating System :: POSIX :: BSD :: FreeBSD",
"Operating System :: POSIX :: Linux",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: Implementation :: CPython",
]
#
dynamic = ["version", "readme", ] # cannot be dynamic ['license']
[project.scripts]
toxygen = "toxygen.toxygen.main:main"
#[project.license]
#file = "LICENSE.md"
[project.urls]
repository = "https://git.plastiras.org/emdee/toxygen"
[build-system]
requires = ["setuptools >= 61.0"]
build-backend = "setuptools.build_meta"
[tool.setuptools.dynamic]
version = {attr = "stem_examples.__version__"}
readme = {file = ["README.md", "ToDo.txt"]}
[tool.setuptools]
packages = ["toxygen"]
[tool.setuptools.packages.find]
where = "toxygen"
[tool.setuptools.packages.package-data]
"*" = ["*.ui"]

View File

@ -4,3 +4,8 @@ numpy
opencv-python opencv-python
pydenticon pydenticon
cv2 cv2
gevent
greenlet
pydenticon
pyqtconsole
toxygen_wrapper

View File

@ -5,8 +5,7 @@ from setuptools.command.install import install
version = '1.0.0' version = '1.0.0'
MODULES = ['argparse', 'PyQt5', 'PyAudio', 'numpy', 'opencv-python', 'cv2', MODULES = open('requirements.txt', 'rt').readlines()
'pydenticon', 'pyqtconsole', 'toxygen_wrapper'] # qweechat
def get_packages(): def get_packages():
directory = os.path.join(os.path.dirname(__file__), 'tox_wrapper') directory = os.path.join(os.path.dirname(__file__), 'tox_wrapper')
@ -35,11 +34,18 @@ setup(name='Toxygen',
include_package_data=True, include_package_data=True,
classifiers=[ classifiers=[
'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: 3 :: Only',
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.11',
], ],
entry_points={ entry_points={
'console_scripts': ['toxygen=toxygen.main:main'] 'console_scripts': ['toxygen=toxygen.main:main']
}, },
package_data={"": ["*.ui"],},
cmdclass={ cmdclass={
'install': InstallScript, 'install': InstallScript,
}, },

View File

@ -1,5 +1,4 @@
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- # -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
import pyaudio
import time import time
import threading import threading
import itertools import itertools
@ -8,6 +7,8 @@ from tox_wrapper.toxav_enums import *
from tox_wrapper.tests import support_testing as ts from tox_wrapper.tests import support_testing as ts
from tox_wrapper.tests.support_testing import LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG, LOG_TRACE from tox_wrapper.tests.support_testing import LOG_ERROR, LOG_WARN, LOG_INFO, LOG_DEBUG, LOG_TRACE
with ts.ignoreStderr():
import pyaudio
from av import screen_sharing from av import screen_sharing
from av.call import Call from av.call import Call
import common.tox_save import common.tox_save

View File

@ -161,6 +161,12 @@ class BaseContact:
# Widgets # Widgets
def init_widget(self): def init_widget(self):
# File "/mnt/o/var/local/src/toxygen/toxygen/contacts/contacts_manager.py", line 252, in filtration_and_sorting
# contact.set_widget(item_widget)
# File "/mnt/o/var/local/src/toxygen/toxygen/contacts/contact.py", line 320, in set_widget
if not self._widget:
LOG_WARN("BC.init_widget self._widget is NULL")
return
self._widget.name.setText(self._name) self._widget.name.setText(self._name)
self._widget.status_message.setText(self._status_message) self._widget.status_message.setText(self._status_message)
if hasattr(self._widget, 'kind'): if hasattr(self._widget, 'kind'):

View File

@ -33,9 +33,11 @@ class ContactProvider(tox_save.ToxSave):
if friend is not None: if friend is not None:
return friend return friend
friend = self._friend_factory.create_friend_by_public_key(public_key) friend = self._friend_factory.create_friend_by_public_key(public_key)
self._add_to_cache(public_key, friend) if friend is None:
LOG_INFO(f"CP.get_friend_by_public_key ADDED {friend} ") LOG_WARN(f"CP.get_friend_by_public_key NULL {friend} ")
else:
self._add_to_cache(public_key, friend)
LOG_DEBUG(f"CP.get_friend_by_public_key ADDED {friend} ")
return friend return friend
def get_all_friends(self): def get_all_friends(self):
@ -72,7 +74,7 @@ class ContactProvider(tox_save.ToxSave):
def get_group_by_number(self, group_number): def get_group_by_number(self, group_number):
group = None group = None
try: try:
LOG_INFO(f"CP.CP.group_get_number {group_number} ") # LOG_DEBUG(f"CP.CP.group_get_number {group_number} ")
# original code # original code
chat_id = self._tox.group_get_chat_id(group_number) chat_id = self._tox.group_get_chat_id(group_number)
if chat_id is None: if chat_id is None:
@ -110,7 +112,7 @@ class ContactProvider(tox_save.ToxSave):
return group return group
group = self._group_factory.create_group_by_public_key(public_key) group = self._group_factory.create_group_by_public_key(public_key)
if group is None: if group is None:
LOG_ERROR(f"get_group_by_public_key NULL group public_key={public_key}") LOG_WARN(f"get_group_by_public_key NULL group public_key={public_key}")
else: else:
self._add_to_cache(public_key, group) self._add_to_cache(public_key, group)
@ -123,13 +125,17 @@ class ContactProvider(tox_save.ToxSave):
def get_group_peer_by_id(self, group, peer_id): def get_group_peer_by_id(self, group, peer_id):
peer = group.get_peer_by_id(peer_id) peer = group.get_peer_by_id(peer_id)
if peer: if peer is not None:
return self._get_group_peer(group, peer) return self._get_group_peer(group, peer)
LOG_WARN(f"get_group_peer_by_id peer_id={peer_id}")
return None
def get_group_peer_by_public_key(self, group, public_key): def get_group_peer_by_public_key(self, group, public_key):
peer = group.get_peer_by_public_key(public_key) peer = group.get_peer_by_public_key(public_key)
if peer: if peer is not None:
return self._get_group_peer(group, peer) return self._get_group_peer(group, peer)
LOG_WARN(f"get_group_peer_by_public_key public_key={public_key}")
return None
# All contacts # All contacts

View File

@ -99,6 +99,10 @@ class ContactsManager(ToxSave):
LOG.warn(f"ERROR NULL {self._contacts[self._active_contact]} {contact.tox_id}") LOG.warn(f"ERROR NULL {self._contacts[self._active_contact]} {contact.tox_id}")
return False return False
if not hasattr(contact, 'tox_id'):
LOG.warn(f"ERROR is_contact_active no contact.tox_id {type(contact)} contact={contact}")
return False
return self._contacts[self._active_contact].tox_id == contact.tox_id return self._contacts[self._active_contact].tox_id == contact.tox_id
# Reconnection support # Reconnection support
@ -142,7 +146,11 @@ class ContactsManager(ToxSave):
current_contact.curr_text = self._screen.messageEdit.toPlainText() current_contact.curr_text = self._screen.messageEdit.toPlainText()
except: except:
pass pass
# IndexError: list index out of range # IndexError: list index out of range
if value >= len(self._contacts):
LOG.warn("CM.set_active value too big: {{self._contacts}}")
return
contact = self._contacts[value] contact = self._contacts[value]
self._subscribe_to_events(contact) self._subscribe_to_events(contact)
contact.remove_invalid_unsent_files() contact.remove_invalid_unsent_files()
@ -171,9 +179,8 @@ class ContactsManager(ToxSave):
# self._screen.call_finished() # self._screen.call_finished()
self._set_current_contact_data(contact) self._set_current_contact_data(contact)
self._active_contact_changed(contact) self._active_contact_changed(contact)
except Exception as ex: # no friend found. ignore except Exception as e: # no friend found. ignore
LOG.warn(f"no friend found. Friend value: {value!s}") LOG.warn(f"CM.set_active EXCEPTION value:{value} len={len(self._contacts)} {e}")
LOG.error('in set active: ' + str(ex))
# gulp raise # gulp raise
active_contact = property(get_active, set_active) active_contact = property(get_active, set_active)
@ -249,6 +256,9 @@ class ContactsManager(ToxSave):
for index, contact in enumerate(self._contacts): for index, contact in enumerate(self._contacts):
list_item = self._screen.friends_list.item(index) list_item = self._screen.friends_list.item(index)
item_widget = self._screen.friends_list.itemWidget(list_item) item_widget = self._screen.friends_list.itemWidget(list_item)
if not item_widget:
LOG_WARN("CM.filtration_and_sorting( item_widget is NULL")
continue
contact.set_widget(item_widget) contact.set_widget(item_widget)
for index, friend in enumerate(self._contacts): for index, friend in enumerate(self._contacts):
@ -287,16 +297,16 @@ class ContactsManager(ToxSave):
def get_or_create_group_peer_contact(self, group_number, peer_id): def get_or_create_group_peer_contact(self, group_number, peer_id):
group = self.get_group_by_number(group_number) group = self.get_group_by_number(group_number)
peer = group.get_peer_by_id(peer_id) peer = group.get_peer_by_id(peer_id)
if peer is None: # broken? is 0 allowed? if peer is None:
if not hasattr(peer, 'public_key') or not peer.public_key: LOG.warn(f'get_or_create_group_peer_contact group_number={group_number} peer_id={peer_id} peer={peer}')
LOG.error(f'no peer public_key ' + repr(dir(peer))) return None
else: LOG.debug(f'get_or_create_group_peer_contact group_number={group_number} peer_id={peer_id} peer={peer}')
if not self.check_if_contact_exists(peer.public_key): if not self.check_if_contact_exists(peer.public_key):
self.add_group_peer(group, peer) contact = self.add_group_peer(group, peer)
return self.get_contact_by_tox_id(peer.public_key) # dunno
else: return contact
LOG.warn(f'no peer group_number={group_number} peer_id={peer_id}') # me - later wrong kind of object?
return peer return self.get_contact_by_tox_id(peer.public_key)
def check_if_contact_exists(self, tox_id): def check_if_contact_exists(self, tox_id):
return any(filter(lambda c: c.tox_id == tox_id, self._contacts)) return any(filter(lambda c: c.tox_id == tox_id, self._contacts))
@ -436,6 +446,7 @@ class ContactsManager(ToxSave):
self._contacts.append(contact) self._contacts.append(contact)
contact.reset_avatar(self._settings['identicons']) contact.reset_avatar(self._settings['identicons'])
self._save_profile() self._save_profile()
return contact
def remove_group_peer_by_id(self, group, peer_id): def remove_group_peer_by_id(self, group, peer_id):
peer = group.get_peer_by_id(peer_id) peer = group.get_peer_by_id(peer_id)

View File

@ -107,7 +107,7 @@ class GroupChat(contact.Contact, ToxSave):
return peers[0] return peers[0]
else: else:
LOG_WARN(f"get_peer_by_id empty peers for {peer_id}") LOG_WARN(f"get_peer_by_id empty peers for {peer_id}")
return [] return None
def get_peer_by_public_key(self, public_key): def get_peer_by_public_key(self, public_key):
peers = list(filter(lambda p: p.public_key == public_key, self._peers)) peers = list(filter(lambda p: p.public_key == public_key, self._peers))
@ -117,7 +117,7 @@ class GroupChat(contact.Contact, ToxSave):
return peers[0] return peers[0]
else: else:
LOG_WARN(f"get_peer_by_public_key empty peers for {public_key}") LOG_WARN(f"get_peer_by_public_key empty peers for {public_key}")
return [] return None
def remove_all_peers_except_self(self): def remove_all_peers_except_self(self):
self._peers = self._peers[:1] self._peers = self._peers[:1]

View File

@ -72,7 +72,11 @@ def setup_default_audio():
def setup_video(oArgs): def setup_video(oArgs):
video = setup_default_video() video = setup_default_video()
if oArgs.video_input == '-1': # this is messed up - no video_input in oArgs
# parser.add_argument('--video_input', type=str,)
if not hasattr(oArgs, 'video_input'):
video['device'] = video['output_devices'][0]
elif oArgs.video_input == '-1':
video['device'] = video['output_devices'][1] video['device'] = video['output_devices'][1]
else: else:
video['device'] = oArgs.video_input video['device'] = oArgs.video_input
@ -165,7 +169,7 @@ def setup_audio(oArgs):
def setup_default_video(): def setup_default_video():
default_video = ["-1"] default_video = ["-1"]
default_video.extend(ts.get_video_indexes()) default_video.extend(ts.get_video_indexes())
LOG.info(f"Video input choices: {default_video!r}") LOG.info(f"Video input choices: {default_video}")
video = {'device': -1, 'width': 320, 'height': 240, 'x': 0, 'y': 0} video = {'device': -1, 'width': 320, 'height': 240, 'x': 0, 'y': 0}
video['output_devices'] = default_video video['output_devices'] = default_video
return video return video
@ -179,7 +183,7 @@ def main_parser(_=None, iMode=2):
lIpV6Choices=[bIpV6, 'False'] lIpV6Choices=[bIpV6, 'False']
audio = setup_default_audio() audio = setup_default_audio()
default_video = setup_default_video() default_video = setup_default_video()['output_devices']
parser = ts.oMainArgparser() parser = ts.oMainArgparser()
parser.add_argument('--version', action='store_true', help='Prints Toxygen version') parser.add_argument('--version', action='store_true', help='Prints Toxygen version')
@ -225,7 +229,7 @@ def main_parser(_=None, iMode=2):
help='Update program (broken)') help='Update program (broken)')
parser.add_argument('--video_input', type=str, parser.add_argument('--video_input', type=str,
default=-1, default=-1,
choices=default_video['output_devices'], choices=default_video,
help="Video input device number - /dev/video?") help="Video input device number - /dev/video?")
parser.add_argument('--audio_input', type=str, parser.add_argument('--audio_input', type=str,
default=oPYA.get_default_input_device_info()['name'], default=oPYA.get_default_input_device_info()['name'],
@ -266,6 +270,8 @@ lKEEP_SETTINGS = ['uri',
'ipv6_enabled', 'ipv6_enabled',
'udp_enabled', 'udp_enabled',
'local_discovery_enabled', 'local_discovery_enabled',
'trace_enabled',
'theme', 'theme',
'network', 'network',
'message_font_size', 'message_font_size',
@ -283,9 +289,11 @@ lKEEP_SETTINGS = ['uri',
class A(): pass class A(): pass
def main(lArgs): def main(lArgs=None):
global oPYA global oPYA
from argparse import Namespace from argparse import Namespace
if lArgs is None:
lArgs = sys.argv[1:]
parser = main_parser() parser = main_parser()
default_ns = parser.parse_args([]) default_ns = parser.parse_args([])
oArgs = parser.parse_args(lArgs) oArgs = parser.parse_args(lArgs)
@ -328,7 +336,10 @@ def main(lArgs):
oApp = app.App(__version__, oArgs) oApp = app.App(__version__, oArgs)
# for pyqtconsole # for pyqtconsole
__builtins__.app = oApp try:
setattr(__builtins__, 'app', oApp)
except Exception as e:
pass
i = oApp.iMain() i = oApp.iMain()
return i return i

View File

@ -192,21 +192,33 @@ class Messenger(tox_save.ToxSave):
return return
if group.number < 0: if group.number < 0:
return return
if peer_id and peer_id < 0: if peer_id is not None and peer_id < 0:
return return
assert_main_thread() assert_main_thread()
# FixMe: peer_id is None?
group_peer_contact = self._contacts_manager.get_or_create_group_peer_contact(group_number, peer_id)
# group_peer_contact now may be None
group = self._get_group_by_number(group_number) group = self._get_group_by_number(group_number)
messages = self._split_message(text.encode('utf-8')) messages = self._split_message(text.encode('utf-8'))
# FixMe: peer_id is None?
group_peer_contact = self._contacts_manager.get_or_create_group_peer_contact(group_number, peer_id)
if group_peer_contact is None:
LOG.warn("M.group_send_private_message group_peer_contact is None")
return
# group_peer_contact now may be None
t = util.get_unix_time() t = util.get_unix_time()
for message in messages: for message in messages:
self._tox.group_send_private_message(group_number, peer_id, message_type, message) bRet = self._tox.group_send_private_message(group_number, peer_id, message_type, message)
if not bRet:
LOG.warn("M.group_send_private_messag failed")
continue
message_author = MessageAuthor(group.get_self_name(), MESSAGE_AUTHOR['GC_PEER']) message_author = MessageAuthor(group.get_self_name(), MESSAGE_AUTHOR['GC_PEER'])
message = OutgoingTextMessage(text, message_author, t, message_type) message = OutgoingTextMessage(text, message_author, t, message_type)
group_peer_contact.append_message(message) # AttributeError: 'GroupChatPeer' object has no attribute 'append_message'
if not hasattr(group_peer_contact, 'append_message'):
LOG.warn("M. group_peer_contact has no append_message group_peer_contact={group_peer_contact}")
else:
group_peer_contact.append_message(message)
if not self._contacts_manager.is_contact_active(group_peer_contact): if not self._contacts_manager.is_contact_active(group_peer_contact):
return return
self._create_message_item(message) self._create_message_item(message)

View File

@ -473,7 +473,11 @@ def group_private_message(window, tray, tox, messenger, settings, profile):
if window.isActiveWindow(): if window.isActiveWindow():
return return
bl = settings['notify_all_gc'] or profile.name in message bl = settings['notify_all_gc'] or profile.name in message
name = tox.group_peer_get_name(group_number, peer_id) try:
name = tox.group_peer_get_name(group_number, peer_id)
except Exception as e:
LOG_WARN("tox.group_peer_get_name {group_number} {peer_id}")
name = ''
if settings['notifications'] and settings['tray_icon'] \ if settings['notifications'] and settings['tray_icon'] \
and profile.status != TOX_USER_STATUS['BUSY'] \ and profile.status != TOX_USER_STATUS['BUSY'] \
and (not settings.locked) and bl: and (not settings.locked) and bl:

View File

@ -69,12 +69,9 @@ def tox_factory(data=None, settings=None, args=None, app=None):
if 'trace_enabled' in settings and not settings['trace_enabled']: if 'trace_enabled' in settings and not settings['trace_enabled']:
LOG_DEBUG("settings['trace_enabled' disabled" ) LOG_DEBUG("settings['trace_enabled' disabled" )
elif tox_options._options_pointer: elif tox_options._options_pointer and \
c_callback = CFUNCTYPE(None, c_void_p, c_int, c_char_p, c_int, c_char_p, c_char_p, c_void_p) 'trace_enabled' in settings and settings['trace_enabled']:
tox_options.self_logger_cb = c_callback(ts.tox_log_cb) ts.vAddLoggerCallback(tox_options)
tox_wrapper.tox.Tox.libtoxcore.tox_options_set_log_callback(
tox_options._options_pointer,
tox_options.self_logger_cb)
LOG_INFO("c-toxcore trace_enabled enabled" ) LOG_INFO("c-toxcore trace_enabled enabled" )
else: else:
LOG_WARN("No tox_options._options_pointer to add self_logger_cb" ) LOG_WARN("No tox_options._options_pointer to add self_logger_cb" )

View File

@ -1,7 +1,10 @@
import os.path
import utils.util import utils.util
import wave import wave
import pyaudio
import os.path import tox_wrapper.tests.support_testing as ts
with ts.ignoreStderr():
import pyaudio
global LOG global LOG
import logging import logging

View File

@ -1756,7 +1756,7 @@ class ToxSuite(unittest.TestCase):
else: else:
LOG.info("passed test_tox_savedata") LOG.info("passed test_tox_savedata")
def vOargsToxPreamble(oArgs, Tox, ToxTest): def vOargsToxPreamble(oArgs, Tox, ToxTest) -> None:
ts.vSetupLogging(oArgs) ts.vSetupLogging(oArgs)

View File

@ -1,12 +1,13 @@
import threading import threading
from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets
import pyaudio
import wave import wave
from ui import widgets from ui import widgets
import utils.util as util import utils.util as util
import tox_wrapper.tests.support_testing as ts import tox_wrapper.tests.support_testing as ts
with ts.ignoreStderr():
import pyaudio
global LOG global LOG
import logging import logging

View File

@ -1,6 +1,6 @@
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*- # -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
from PyQt5 import QtCore, QtGui, QtWidgets, uic from PyQt5 import QtCore, QtGui, QtWidgets, uic
import pyaudio
from user_data.settings import * from user_data.settings import *
from utils.util import * from utils.util import *
@ -8,6 +8,8 @@ from ui.widgets import CenteredWidget, DataLabel, LineEdit, RubberBandWindow
import updater.updater as updater import updater.updater as updater
import utils.ui as util_ui import utils.ui as util_ui
import tox_wrapper.tests.support_testing as ts import tox_wrapper.tests.support_testing as ts
with ts.ignoreStderr():
import pyaudio
from user_data import settings from user_data import settings
global LOG global LOG

View File

@ -17,7 +17,6 @@ LOG = logging.getLogger('settings')
def merge_args_into_settings(args, settings): def merge_args_into_settings(args, settings):
if args: if args:
print(repr(args.__dict__.keys()))
if not hasattr(args, 'audio'): if not hasattr(args, 'audio'):
LOG.warn('No audio ' +repr(args)) LOG.warn('No audio ' +repr(args))
settings['audio'] = getattr(args, 'audio') settings['audio'] = getattr(args, 'audio')
@ -131,17 +130,17 @@ class Settings(dict):
Settings of current profile + global app settings Settings of current profile + global app settings
""" """
def __init__(self, toxes, path, app): def __init__(self, toxes, json_path, app):
self._path = path
self._profile_path = path.replace('.json', '.tox')
self._toxes = toxes self._toxes = toxes
self._app = app self._app = app
self._path = app._path self._path = app._path
self._args = app._args self._args = app._args
self._oArgs = app._args self._oArgs = app._args
self._log = lambda l: LOG.log(self._oArgs.loglevel, l) self._log = lambda l: LOG.log(self._oArgs.loglevel, l)
self._profile_path = app._path # json_path.replace('.json', '.tox')
self._settings_saved_event = Event() self._settings_saved_event = Event()
path = json_path.replace('.tox', '.json')
if path and os.path.isfile(path): if path and os.path.isfile(path):
try: try:
with open(path, 'rb') as fl: with open(path, 'rb') as fl:
@ -151,9 +150,9 @@ class Settings(dict):
info = json.loads(str(data, 'utf-8')) info = json.loads(str(data, 'utf-8'))
LOG.debug('Parsed settings from: ' + str(path)) LOG.debug('Parsed settings from: ' + str(path))
except Exception as ex: except Exception as ex:
title = 'Error opening/parsing settings file: ' title = f"Error opening/parsing settings file:"
text = title + path text = title +f"\n{path}\n"
LOG.error(title +str(ex)) LOG.error(text +str(ex))
util_ui.message_box(text, title) util_ui.message_box(text, title)
info = Settings.get_default_settings(app._args) info = Settings.get_default_settings(app._args)
user_data.settings.clean_settings(info) user_data.settings.clean_settings(info)
@ -161,7 +160,7 @@ class Settings(dict):
LOG.debug('get_default_settings for: ' + repr(path)) LOG.debug('get_default_settings for: ' + repr(path))
info = Settings.get_default_settings(app._args) info = Settings.get_default_settings(app._args)
if not os.path.exists(path): if not path or not os.path.exists(path):
merge_args_into_settings(app._args, info) merge_args_into_settings(app._args, info)
else: else:
aC = self._changed(app._args, info) aC = self._changed(app._args, info)
@ -178,12 +177,16 @@ class Settings(dict):
merge_args_into_settings(app._args, info) merge_args_into_settings(app._args, info)
info['audio'] = getattr(app._args, 'audio') info['audio'] = getattr(app._args, 'audio')
info['video'] = getattr(app._args, 'video') info['video'] = getattr(app._args, 'video')
info['trace_enabled'] = getattr(app._args, 'trace_enabled') if getattr(app._args, 'trace_enabled'):
info['trace_enabled'] = getattr(app._args, 'trace_enabled')
else:
LOG.warn("app._args, 'trace_enabled")
info['trace_enabled'] = False
super().__init__(info) super().__init__(info)
self._upgrade() self._upgrade()
LOG.info('Parsed settings from: ' + str(path)) LOG.info('Parsed settings from: ' + str(path))
ex = f"self=id(self) {self!r}" ex = f"self=id(self) {self}"
LOG.debug(ex) LOG.debug(ex)
self.save() self.save()
@ -206,10 +209,16 @@ class Settings(dict):
text = bytes(self._toxes.pass_encrypt(bytes(text, 'utf-8'))) text = bytes(self._toxes.pass_encrypt(bytes(text, 'utf-8')))
else: else:
text = bytes(text, 'utf-8') text = bytes(text, 'utf-8')
if not self._path:
#?
self._path = os.path.join(get_user_config_path(), 'toxygen.json')
tmp = self._path + str(os.getpid()) tmp = self._path + str(os.getpid())
try: try:
with open(tmp, 'wb') as fl: with open(tmp, 'wb') as fl:
fl.write(text) fl.write(text)
if os.path.exists(self._path+'.bak'):
os.remove(self._path+'.bak')
os.rename(self._path, self._path+'.bak')
os.rename(tmp, self._path) os.rename(tmp, self._path)
except Exception as e: except Exception as e:
LOG.warn(f'Error saving to {self._path} ' +str(e)) LOG.warn(f'Error saving to {self._path} ' +str(e))
@ -221,17 +230,17 @@ class Settings(dict):
if os.path.isfile(path): if os.path.isfile(path):
os.remove(path) os.remove(path)
def set_active_profile(self): def set_active_profile(self, profile_path):
""" """
Mark current profile as active Mark current profile as active
""" """
path = self._profile_path + '.lock' path = profile_path + '.lock'
try: try:
import shutil import shutil
except: except:
pass pass
else: else:
shutil.copy2(self._profile_path, path) shutil.copy2(profile_path, path)
# need to open this with the same perms as _profile_path # need to open this with the same perms as _profile_path
# copy profile_path and then write? # copy profile_path and then write?
with open(path, 'wb') as fl: with open(path, 'wb') as fl:
@ -250,9 +259,9 @@ class Settings(dict):
# Static methods # Static methods
@staticmethod @staticmethod
def get_auto_profile(): def get_auto_profile(appdir):
# self._path = # self._path =
p = os.path.join(os.path.dirname(self._app._path), 'toxygen.json') p = os.path.join(appdir, 'toxygen.json')
if not os.path.isfile(p): if not os.path.isfile(p):
return None return None
with open(p) as fl: with open(p) as fl:
@ -260,14 +269,15 @@ class Settings(dict):
try: try:
auto = json.loads(data) auto = json.loads(data)
except Exception as ex: except Exception as ex:
LOG.warn(f"json.loads {data}: {ex!s}") LOG.warn(f"json.loads {data}: {ex}")
auto = {} auto = {}
if 'profile_path' in auto: if 'profile_path' in auto:
path = str(auto['profile_path']) path = str(auto['profile_path'])
if not os.path.isabs(path): if not os.path.isabs(path):
path = join_path(path, curr_directory(__file__)) path = join_path(path, os.path.dirname(os.path.realpath(__file__)))
if os.path.isfile(path): if os.path.isfile(path):
return path return path
return None
@staticmethod @staticmethod
def supported_languages(): def supported_languages():
@ -276,7 +286,7 @@ class Settings(dict):
@staticmethod @staticmethod
def set_auto_profile(path): def set_auto_profile(path):
p = os.path.join(os.path.dirname(self._app._path), 'toxygen.json') p = os.path.join(os.path.dirname(path), 'toxygen.json')
if os.path.isfile(p): if os.path.isfile(p):
with open(p) as fl: with open(p) as fl:
data = fl.read() data = fl.read()
@ -289,7 +299,7 @@ class Settings(dict):
@staticmethod @staticmethod
def reset_auto_profile(): def reset_auto_profile():
p = os.path.join(os.path.dirname(self._app._path), 'toxygen.json') p = os.path.join(os.path.dirname(app._path), 'toxygen.json')
if os.path.isfile(p): if os.path.isfile(p):
with open(p) as fl: with open(p) as fl:
data = fl.read() data = fl.read()