This commit is contained in:
emdee@spm.plastiras.org 2024-02-05 14:58:00 +00:00
parent 3ce822fc27
commit 7cebe9cd9f
12 changed files with 182 additions and 2441 deletions

View file

@ -4,4 +4,5 @@ find * -name \*.py | xargs grep -l '[ ]*$' | xargs sed -i -e 's/[ ]*$//'
rsync "$@" -vax --include \*.py \
--exclude Toxygen.egg-info --exclude build \
--exclude \*.pyc --exclude .pyl\* --exclude \*~ \
--exclude __pycache__ --exclude \*.egg-info --exclude \*.new \
./ ../toxygen.git/|grep -v /$

53
pyproject.toml Normal file
View file

@ -0,0 +1,53 @@
[project]
name = "toxygen"
description = "examples of using stem"
authors = [{ name = "emdee", email = "emdee@spm.plastiras.org" } ]
requires-python = ">=3.7"
keywords = ["stem", "python3", "tox"]
classifiers = [
# How mature is this project? Common values are
# 3 - Alpha
# 4 - Beta
# 5 - Production/Stable
"Development Status :: 4 - Beta",
# Indicate who your project is intended for
"Intended Audience :: Developers",
# Specify the Python versions you support here.
"Programming Language :: Python :: 3",
"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", "dependencies"] # cannot be dynamic ['license']
[project.scripts]
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 = "toxygen.app.__version__"}
readme = {file = ["README.md", "ToDo.txt"]}
dependencies = {file = ["requirements.txt"]}
[tool.setuptools]
packages = ["toxygen"]

View file

@ -1,11 +1,16 @@
PyQt5
PyAudio
numpy
opencv-python
pydenticon
cv2
gevent
greenlet
pydenticon
pyqtconsole
toxygen_wrapper
# the versions are the current ones tested - may work with earlier versions
# choose one of PyQt5 PyQt6 PySide2 PySide6
PyAudio >= 0.2.13
numpy >= 1.26.1
opencv_python >= 4.8.0
pydenticon >= 0.3.1
pillow >= 10.2.0
gevent >= 23.9.1
greenlet >= 2.0.2
# this is optional
coloredlogs >= 15.0.1
# this is optional
# qtconsole >= 5.4.3
# this is not on pypi yet - get it from
# https://git.plastiras.org/emdee/toxygen_wrapper
# toxygen_wrapper == 1.0.0

54
setup.cfg Normal file
View file

@ -0,0 +1,54 @@
[metadata]
classifiers =
License :: OSI Approved
License :: OSI Approved :: BSD 1-clause
Intended Audience :: Web Developers
Operating System :: Microsoft :: Windows
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
[options]
zip_safe = false
python_requires = ~=3.6
include_package_data =
"*" = ["*.ui", "*.txt"]
[options.entry_points]
console_scripts =
toxygen = toxygen.__main__:iMain
[easy_install]
zip_ok = false
[flake8]
jobs = 1
max-line-length = 88
ignore =
E111
E114
E128
E225
E261
E302
E305
E402
E501
E502
E541
E701
E702
E704
E722
E741
F508
F541
W503
W601

53
setup.py.dst Normal file
View file

@ -0,0 +1,53 @@
import sys
import os
from setuptools import setup
from setuptools.command.install import install
version = '1.0.0'
MODULES = open('requirements.txt', 'rt').readlines()
def get_packages():
directory = os.path.join(os.path.dirname(__file__), 'tox_wrapper')
for root, dirs, files in os.walk(directory):
packages = map(lambda d: 'toxygen.' + d, dirs)
packages = ['toxygen'] + list(packages)
return packages
class InstallScript(install):
"""This class configures Toxygen after installation"""
def run(self):
install.run(self)
setup(name='Toxygen',
version=version,
description='Toxygen - Tox client',
long_description='Toxygen is powerful Tox client written in Python3',
url='https://git.plastiras.org/emdee/toxygen/',
keywords='toxygen Tox messenger',
author='Ingvar',
maintainer='',
license='GPL3',
packages=get_packages(),
install_requires=MODULES,
include_package_data=True,
classifiers=[
'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',
],
entry_points={
'console_scripts': ['toxygen=toxygen.main:main']
},
package_data={"": ["*.ui"],},
cmdclass={
'install': InstallScript,
},
zip_safe=False
)

View file

@ -4,6 +4,7 @@ import os
import app
import logging
import signal
import time
import faulthandler
faulthandler.enable()
@ -11,7 +12,6 @@ faulthandler.enable()
import warnings
warnings.filterwarnings('ignore')
import tox_wrapper.tests.support_testing as ts
try:
from trepan.interfaces import server as Mserver
from trepan.api import debug
@ -28,13 +28,13 @@ from user_data.settings import *
from user_data.settings import Settings
from user_data import settings
import utils.util as util
import tox_wrapper.tests.support_testing as ts
with ts.ignoreStderr():
import pyaudio
__maintainer__ = 'Ingvar'
__version__ = '0.5.0+'
import time
sleep = time.sleep
def reset():

View file

@ -14,6 +14,8 @@ from PyQt5 import QtWidgets, QtGui, QtCore
from qtpy.QtCore import QTimer
from qtpy.QtWidgets import QApplication
__version__ = "1.0.0"
try:
import coloredlogs
if 'COLOREDLOGS_LEVEL_STYLES' not in os.environ:

View file

@ -1,87 +0,0 @@
# toxygen_wrapper
[ctypes](https://docs.python.org/3/library/ctypes.html)
wrapping of [Tox](https://tox.chat/)
[```libtoxcore```](https://github.com/TokTok/c-toxcore) into Python.
Taken from the ```wrapper``` directory of the now abandoned
<https://github.com/toxygen-project/toxygen> ```next_gen``` branch
by Ingvar.
The basics of NGC groups are supported, as well as AV and toxencryptsave.
There is no coverage of conferences as they are not used in ```toxygen```
and the list of still unwrapped calls as of Sept. 2022 can be found in
```tox.c-toxcore.missing```. The code still needs double-checking
that every call in ```tox.py``` has the right signature, but it runs
```toxygen``` with no apparent issues.
It has been tested with UDP and TCP proxy (Tor). It has ***not*** been
tested on Windows, and there may be some minor breakage, which should be
easy to fix. There is a good coverage integration testsuite in ```wrapper_tests```.
Change to that directory and run ```tests_wrapper.py --help```; the test
suite gives a good set of examples of usage.
## Install
Put the parent of the wrapper directory on your PYTHONPATH and
touch a file called `__init__.py` in its parent directory.
Then you need a ```libs``` directory beside the `wrapper` directory
and you need to link your ```libtoxcore.so``` and ```libtoxav.so```
and ```libtoxencryptsave.so``` into it. Link all 3 filenames
to ```libtoxcore.so``` if you have only ```libtoxcore.so```
(which is usually the case if you built ```c-toxcore``` with ```cmake```
rather than ```autogen/configure```). If you want to be different,
the environment variable TOXCORE_LIBS overrides the location of ```libs```.
As is, the code in ```tox.py``` is very verbose. Edit the file to change
```
def LOG_ERROR(a): print('EROR> '+a)
def LOG_WARN(a): print('WARN> '+a)
def LOG_INFO(a): print('INFO> '+a)
def LOG_DEBUG(a): print('DBUG> '+a)
def LOG_TRACE(a): pass # print('TRAC> '+a)
```
to all ```pass #``` or use ```logging.logger``` to suite your tastes.
```logging.logger``` can be dangerous in callbacks in ```Qt``` applications,
so we use simple print statements as default. The same applies to
```wrapper/tests_wrapper.py```.
## Prerequisites
No prerequisites in Python3.
## Other wrappers
There are a number of other wrappings into Python of Tox core.
This one uses [ctypes](https://docs.python.org/3/library/ctypes.html)
which has its merits - there is no need to recompile anything as with
Cython - change the Python file and it's done. And you can follow things
in a Python debugger, or with the utterly stupendous Python feature of
```gdb``` (```gdb -ex r --args /usr/bin/python3.9 <pyfile>```).
CTYPES code can be brittle, segfaulting if you've got things wrong,
but if your wrapping is right, it is very efficient and easy to work on.
The [faulthandler](https://docs.python.org/3/library/faulthandler.html)
module can be helpful in debugging crashes
(e.g. from segmentation faults produced by erroneous C library wrapping).
Others include:
* <https://github.com/TokTok/py-toxcore-c> Cython bindings.
Incomplete and not really actively supported. Maybe it will get
worked on in the future, but TokTok seems to be working on
java, rust, scalla, go, etc. bindings instead.
No support for NGC groups or toxencryptsave.
* <https://github.com/oxij/PyTox>
forked from https://github.com/aitjcize/PyTox
by Wei-Ning Huang <aitjcize@gmail.com>.
Hardcore C wrapping which is not easy to keep up to date.
No support for NGC or toxencryptsave. Abandonned.
This was the basis for the TokTok/py-toxcore-c code until recently.
To our point of view, the ability of CTYPEs to follow code in the
debugger is a crucial advantage.
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!

1
toxygen/tests/README.txt Normal file
View file

@ -0,0 +1 @@
unused

View file

@ -1,439 +0,0 @@
#!/var/local/bin/python3.bash
#
""" echo.py features
- accept friend request
- echo back friend message
- accept and answer friend call request
- send back friend audio/video data
- send back files friend sent
"""
from __future__ import print_function
import sys
import os
import traceback
import random
from ctypes import *
import argparse
import time
from os.path import exists
# LOG=util.log
global LOG
import logging
# log = lambda x: LOG.info(x)
LOG = logging.getLogger('app')
def LOG_error(a): print('EROR_ '+a)
def LOG_warn(a): print('WARN_ '+a)
def LOG_info(a): print('INFO_ '+a)
def LOG_debug(a): print('DBUG_ '+a)
def LOG_trace(a): pass # print('TRAC_ '+a)
from middleware.tox_factory import tox_factory
import tox_wrapper
import tox_wrapper.toxcore_enums_and_consts as enums
from tox_wrapper.toxcore_enums_and_consts import TOX_CONNECTION, TOX_USER_STATUS, \
TOX_MESSAGE_TYPE, TOX_PUBLIC_KEY_SIZE, TOX_FILE_CONTROL
import user_data
from tox_wrapper.libtox import LibToxCore
import tox_wrapper.tests.support_testing as ts
from tox_wrapper.tests.support_testing import oMainArgparser
from tox_wrapper.tests.support_testing import logging_toxygen_echo
def sleep(fSec):
if 'QtCore' in globals():
if fSec > .000001: globals['QtCore'].QThread.msleep(fSec)
globals['QtCore'].QCoreApplication.processEvents()
else:
time.sleep(fSec)
try:
import coloredlogs
if 'COLOREDLOGS_LEVEL_STYLES' not in os.environ:
os.environ['COLOREDLOGS_LEVEL_STYLES'] = 'spam=22;debug=28;verbose=34;notice=220;warning=202;success=118,bold;error=124;critical=background=red'
except ImportError as e:
# logging.log(logging.DEBUG, f"coloredlogs not available: {e}")
coloredlogs = None
import tox_wrapper.tests.support_testing as ts
if 'USER' in os.environ:
sDATA_FILE = '/tmp/logging_toxygen_' +os.environ['USER'] +'.tox'
elif 'USERNAME' in os.environ:
sDATA_FILE = '/tmp/logging_toxygen_' +os.environ['USERNAME'] +'.tox'
else:
sDATA_FILE = '/tmp/logging_toxygen_' +'data' +'.tox'
bHAVE_AV = True
iDHT_TRIES = 100
iDHT_TRY = 0
#?SERVER = lLOCAL[-1]
class AV(tox_wrapper.tox.ToxAV):
def __init__(self, core):
super(AV, self).__init__(core)
self.core = self.get_tox()
def on_call(self, fid, audio_enabled, video_enabled):
LOG.info("Incoming %s call from %d:%s ..." % (
"video" if video_enabled else "audio", fid,
self.core.friend_get_name(fid)))
bret = self.answer(fid, 48, 64)
LOG.info(f"Answered, in call... {bret!s}")
def on_call_state(self, fid, state):
LOG.info('call state:fn=%d, state=%d' % (fid, state))
def on_audio_bit_rate(self, fid, audio_bit_rate):
LOG.info('audio bit rate status: fn=%d, abr=%d' %
(fid, audio_bit_rate))
def on_video_bit_rate(self, fid, video_bit_rate):
LOG.info('video bit rate status: fn=%d, vbr=%d' %
(fid, video_bit_rate))
def on_audio_receive_frame(self, fid, pcm, sample_count,
channels, sampling_rate):
# LOG.info('audio frame: %d, %d, %d, %d' %
# (fid, sample_count, channels, sampling_rate))
# LOG.info('pcm len:%d, %s' % (len(pcm), str(type(pcm))))
sys.stdout.write('.')
sys.stdout.flush()
bret = self.audio_send_frame(fid, pcm, sample_count,
channels, sampling_rate)
if bret is False:
LOG.error('on_audio_receive_frame error.')
def on_video_receive_frame(self, fid, width, height, frame, u, v):
LOG.info('video frame: %d, %d, %d, ' % (fid, width, height))
sys.stdout.write('*')
sys.stdout.flush()
bret = self.video_send_frame(fid, width, height, frame, u, v)
if bret is False:
LOG.error('on_video_receive_frame error.')
def witerate(self):
self.iterate()
def save_to_file(tox, fname):
data = tox.get_savedata()
with open(fname, 'wb') as f:
f.write(data)
def load_from_file(fname):
assert os.path.exists(fname)
return open(fname, 'rb').read()
class EchoBot():
def __init__(self, oTox):
self._tox = oTox
self._tox.self_set_name("EchoBot")
LOG.info('ID: %s' % self._tox.self_get_address())
self.files = {}
self.av = None
self.on_connection_status = None
def start(self):
self.connect()
if bHAVE_AV:
# RuntimeError: Attempted to create a second session for the same Tox instance.
self.av = True # AV(self._tox_pointer)
def bobs_on_friend_request(iTox,
public_key,
message_data,
message_data_size,
*largs):
key = ''.join(chr(x) for x in public_key[:TOX_PUBLIC_KEY_SIZE])
sPk = tox_wrapper.tox.bin_to_string(key, TOX_PUBLIC_KEY_SIZE)
sMd = str(message_data, 'UTF-8')
LOG.debug('on_friend_request ' +sPk +' ' +sMd)
self.on_friend_request(sPk, sMd)
LOG.info('setting bobs_on_friend_request')
self._tox.callback_friend_request(bobs_on_friend_request)
def bobs_on_friend_message(iTox,
iFriendNum,
iMessageType,
message_data,
message_data_size,
*largs):
sMd = str(message_data, 'UTF-8')
LOG_debug(f"on_friend_message {iFriendNum}" +' ' +sMd)
self.on_friend_message(iFriendNum, iMessageType, sMd)
LOG.info('setting bobs_on_friend_message')
self._tox.callback_friend_message(bobs_on_friend_message)
def bobs_on_file_chunk_request(iTox, fid, filenumber, position, length, *largs):
if length == 0:
return
data = self.files[(fid, filenumber)]['f'][position:(position + length)]
self._tox.file_send_chunk(fid, filenumber, position, data)
self._tox.callback_file_chunk_request(bobs_on_file_chunk_request)
def bobs_on_file_recv(iTox, fid, filenumber, kind, size, filename, *largs):
LOG_info(f"on_file_recv {fid!s} {filenumber!s} {kind!s} {size!s} {filename}")
if size == 0:
return
self.files[(fid, filenumber)] = {
'f': bytes(),
'filename': filename,
'size': size
}
self._tox.file_control(fid, filenumber, TOX_FILE_CONTROL['RESUME'])
def connect(self):
if not self.on_connection_status:
def on_connection_status(iTox, iCon, *largs):
LOG_info('ON_CONNECTION_STATUS - CONNECTED ' + repr(iCon))
self._tox.callback_self_connection_status(on_connection_status)
LOG.info('setting on_connection_status callback ')
self.on_connection_status = on_connection_status
if self._oargs.network in ['newlocal', 'local']:
LOG.info('connecting on the new network ')
sNet = 'newlocal'
elif self._oargs.network == 'new':
LOG.info('connecting on the new network ')
sNet = 'new'
else: # main old
LOG.info('connecting on the old network ')
sNet = 'old'
sFile = self._oargs.nodes_json
lNodes = generate_nodes_from_file(sFile)
lElts = lNodes
random.shuffle(lElts)
for lElt in lElts[:10]:
status = self._tox.self_get_connection_status()
try:
if self._tox.bootstrap(*lElt):
LOG.info('connected to ' + lElt[0]+' '+repr(status))
else:
LOG.warn('failed connecting to ' + lElt[0])
except Exception as e:
LOG.warn('error connecting to ' + lElt[0])
if self._oargs.proxy_type > 0:
random.shuffle(ts.lRELAYS)
for lElt in ts.lRELAYS[:10]:
status = self._tox.self_get_connection_status()
try:
if self._tox.add_tcp_relay(*lElt):
LOG.info('relayed to ' + lElt[0] +' '+repr(status))
else:
LOG.warn('failed relay to ' + lElt[0])
except Exception as e:
LOG.warn('error relay to ' + lElt[0])
def loop(self):
if not self.av:
self.start()
checked = False
save_to_file(self._tox, sDATA_FILE)
LOG.info('Starting loop.')
while True:
status = self._tox.self_get_connection_status()
if not checked and status:
LOG.info('Connected to DHT.')
checked = True
if not checked and not status:
global iDHT_TRY
iDHT_TRY += 10
self.connect()
self.iterate(100)
if iDHT_TRY >= iDHT_TRIES:
raise RuntimeError("Failed to connect to the DHT.")
LOG.warn(f"NOT Connected to DHT. {iDHT_TRY}")
checked = True
if checked and not status:
LOG.info('Disconnected from DHT.')
self.connect()
checked = False
if bHAVE_AV:
True # self.av.witerate()
self.iterate(100)
LOG.info('Ending loop.')
def iterate(self, n=100):
interval = self._tox.iteration_interval()
for i in range(n):
self._tox.iterate()
sleep(interval / 1000.0)
self._tox.iterate()
def on_friend_request(self, pk, message):
LOG.debug('Friend request from %s: %s' % (pk, message))
self._tox.friend_add_norequest(pk)
LOG.info('on_friend_request Accepted.')
save_to_file(self._tox, sDATA_FILE)
def on_friend_message(self, friendId, type, message):
name = self._tox.friend_get_name(friendId)
LOG.debug('%s: %s' % (name, message))
yMessage = bytes(message, 'UTF-8')
self._tox.friend_send_message(friendId, TOX_MESSAGE_TYPE['NORMAL'], yMessage)
LOG.info('EchoBot sent: %s' % message)
def on_file_recv_chunk(self, fid, filenumber, position, data):
filename = self.files[(fid, filenumber)]['filename']
size = self.files[(fid, filenumber)]['size']
LOG.debug(f"on_file_recv_chunk {fid!s} {filenumber!s} {filename} {position/float(size)*100!s}")
if data is None:
msg = "I got '{}', sending it back right away!".format(filename)
self._tox.friend_send_message(fid, TOX_MESSAGE_TYPE['NORMAL'], msg)
self.files[(fid, 0)] = self.files[(fid, filenumber)]
length = self.files[(fid, filenumber)]['size']
self.file_send(fid, 0, length, filename, filename)
del self.files[(fid, filenumber)]
return
self.files[(fid, filenumber)]['f'] += data
def iMain(oArgs):
global sDATA_FILE
# oTOX_OPTIONS = ToxOptions()
global oTOX_OPTIONS
oTOX_OPTIONS = oToxygenToxOptions(oArgs)
opts = oTOX_OPTIONS
if coloredlogs:
coloredlogs.install(
level=oArgs.loglevel,
logger=LOG,
# %(asctime)s,%(msecs)03d %(hostname)s [%(process)d]
fmt='%(name)s %(levelname)s %(message)s'
)
else:
if 'logfile' in oArgs:
logging.basicConfig(filename=oArgs.logfile,
level=oArgs.loglevel,
format='%(levelname)-8s %(message)s')
else:
logging.basicConfig(level=oArgs.loglevel,
format='%(levelname)-8s %(message)s')
iRet = 0
if hasattr(oArgs,'profile') and oArgs.profile and os.path.isfile(oArgs.profile):
sDATA_FILE = oArgs.profile
LOG.info(f"loading from {sDATA_FILE}")
opts.savedata_data = load_from_file(sDATA_FILE)
opts.savedata_length = len(opts.savedata_data)
opts.savedata_type = enums.TOX_SAVEDATA_TYPE['TOX_SAVE']
else:
opts.savedata_data = None
try:
if False:
oTox = tox_factory(data=opts.savedata_data,
settings=opts, args=oArgs, app=None)
else:
oTox = tox_wrapper.tox.Tox(opts)
t = EchoBot(oTox)
t._oargs = oArgs
t.start()
t.loop()
save_to_file(t._tox, sDATA_FILE)
except KeyboardInterrupt:
save_to_file(t._tox, sDATA_FILE)
except RuntimeError as e:
LOG.error(f"exiting with {e}")
iRet = 1
except Exception as e:
LOG.error(f"exiting with {e}")
LOG.warn(' iMain(): ' \
+'\n' + traceback.format_exc())
iRet = 1
return iRet
def oToxygenToxOptions(oArgs, data=None):
tox_options = tox_wrapper.tox.Tox.options_new()
tox_options.contents.local_discovery_enabled = False
tox_options.contents.dht_announcements_enabled = False
tox_options.contents.hole_punching_enabled = False
tox_options.contents.experimental_thread_safety = False
tox_options.contents.ipv6_enabled = False
tox_options.contents.tcp_port = 3390
if oArgs.proxy_type > 0:
tox_options.contents.proxy_type = int(oArgs.proxy_type)
tox_options.contents.proxy_host = bytes(oArgs.proxy_host, 'UTF-8')
tox_options.contents.proxy_port = int(oArgs.proxy_port)
tox_options.contents.udp_enabled = False
LOG.debug('setting oArgs.proxy_host = ' +oArgs.proxy_host)
else:
tox_options.contents.udp_enabled = True
if data: # load existing profile
tox_options.contents.savedata_type = enums.TOX_SAVEDATA_TYPE['TOX_SAVE']
tox_options.contents.savedata_data = c_char_p(data)
tox_options.contents.savedata_length = len(data)
else: # create new profile
tox_options.contents.savedata_type = enums.TOX_SAVEDATA_TYPE['NONE']
tox_options.contents.savedata_data = None
tox_options.contents.savedata_length = 0
if tox_options._options_pointer:
ts.vAddLoggerCallback(tox_options, ts.on_log)
else:
logging.warn("No tox_options._options_pointer " +repr(tox_options._options_pointer))
return tox_options
def oArgparse(lArgv):
parser = ts.oMainArgparser()
parser.add_argument('profile', type=str, nargs='?',
default=sDATA_FILE,
help='Path to Tox profile to save')
oArgs = parser.parse_args(lArgv)
if hasattr(oArgs, 'sleep') and oArgs.sleep == 'qt':
pass # broken
else:
oArgs.sleep = 'time'
for key in ts.lBOOLEANS:
if key not in oArgs: continue
val = getattr(oArgs, key)
if val in ['False', 'false', 0]:
setattr(oArgs, key, False)
else:
setattr(oArgs, key, True)
if not os.path.exists('/proc/sys/net/ipv6') and oArgs.ipv6_enabled:
LOG.warn('setting oArgs.ipv6_enabled = False')
oArgs.ipv6_enabled = False
return oArgs
def main(largs=None):
if largs is None: largs = []
oArgs = oArgparse(largs)
global oTOX_OARGS
oTOX_OARGS = oArgs
print(oArgs)
if coloredlogs:
logger = logging.getLogger()
# https://pypi.org/project/coloredlogs/
coloredlogs.install(level=oArgs.loglevel,
logger=logger,
# %(asctime)s,%(msecs)03d %(hostname)s [%(process)d]
fmt='%(name)s %(levelname)s %(message)s'
)
else:
logging.basicConfig(level=oArgs.loglevel) # logging.INFO
return iMain(oArgs)
if __name__ == '__main__':
sys.exit(main(sys.argv[1:]))

File diff suppressed because it is too large Load diff

View file

@ -1,17 +0,0 @@
# -*- mode: python; indent-tabs-mode: nil; py-indent-offset: 4; coding: utf-8 -*-
from notifications import sound
from notifications.sound import SOUND_NOTIFICATION
from time import sleep
if True:
def test_sound_notification(self):
"""
Plays sound notification
:param type of notification
"""
sound.sound_notification( SOUND_NOTIFICATION['MESSAGE'] )
sleep(10)
sound.sound_notification( SOUND_NOTIFICATION['FILE_TRANSFER'] )
sleep(10)
sound.sound_notification( None )