Sfoglia il codice sorgente

new build system but sadly also new dates everywhere. Well, clean commits are so 2020...

master
Nils 3 anni fa
parent
commit
5eb4ded54d
  1. 4
      .gitignore
  2. 24
      Makefile.in
  3. 16
      __main__.py
  4. 4
      configure
  5. 3
      documentation/readme.template
  6. 2
      engine/api.py
  7. 2
      engine/findicons.py
  8. 2
      engine/findprograms.py
  9. 11
      engine/nsmservercontrol.py
  10. 2
      engine/start.py
  11. 102
      engine/watcher.py
  12. 2
      qtgui/addclientprompt.py
  13. 2
      qtgui/descriptiontextwidget.py
  14. 2
      qtgui/eventloop.py
  15. 2
      qtgui/helper.py
  16. 2
      qtgui/mainwindow.py
  17. 2
      qtgui/opensessioncontroller.py
  18. 2
      qtgui/projectname.py
  19. 2
      qtgui/quickopensessioncontroller.py
  20. 2
      qtgui/quicksessioncontroller.py
  21. 2
      qtgui/sessiontreecontroller.py
  22. 2
      qtgui/settings.py
  23. 2
      qtgui/systemtray.py
  24. 2
      qtgui/usermanual.py
  25. 2
      qtgui/waitdialog.py
  26. 2
      tools/nsm-data
  27. 22
      tools/nsmclient.py
  28. 2
      tools/nsmcmdline.py
  29. 2
      tools/nsmservercontrol.py

4
.gitignore

@ -114,8 +114,10 @@ dmypy.json
# Pyre type checker
.pyre/
#nuitka and makefile
#build an makefile
*.bin
*.build
build
buildnsmdata
Makefile
engine/compiledprefix.py

24
Makefile.in

@ -4,21 +4,31 @@
.PHONY: install uninstall clean gitclean resources
all:
#Our Program
printf "prefix = \"$(PREFIX)\"" > compiledprefix.py
python3 -m nuitka --recurse-all --python-flag -O --warn-unusual-code --warn-implicit-exceptions --recurse-not-to=PyQt5 --show-progress --show-modules --file-reference-choice=runtime $(PROGRAM)
rm compiledprefix.py
mkdir -p build
cd build && printf "prefix = \"$(PREFIX)\"" > compiledprefix.py
#Only copy the needed files
cp -r "$(PROGRAM)" __main__.py engine qtgui build
#Clean all pycache in build
cd build && find . -type d -name "__pycache__" -exec rm -r {} +
python -m zipapp "build" --output="$(PROGRAM).bin" --python="/usr/bin/env python3"
rm build/compiledprefix.py
#nsm-data
python3 -m nuitka --recurse-all --python-flag -O --warn-unusual-code --warn-implicit-exceptions --recurse-not-to=PyQt5 --show-progress --show-modules --file-reference-choice=runtime tools/nsm-data
mkdir -p buildnsmdata
cp tools/nsm-data tools/nsmclient.py buildnsmdata
cd buildnsmdata && find . -type d -name "__pycache__" -exec rm -r {} +
python -m zipapp "buildnsmdata" --output="nsm-data.bin" --python="/usr/bin/env python3"
clean:
rm -rf build/
rm -rf buildnsmdata/
rm -f "$(PROGRAM).bin"
rm -rf "$(PROGRAM).build"
rm -f "nsm-data.bin"
rm -rf "nsm-data.build"
rm Makefile
find . -type d -name "__pycache__" -exec rm -r {} +
#Convenience function for developing, not used for the build or install process
gitclean:

16
__main__.py

@ -0,0 +1,16 @@
#!/usr/bin/env python3
# encoding: utf-8
# file: __main__.py
"""
This file is an alternativ to ./agordejo when using zipapp.
Any code changes in ./agordejo must be manually recplicated here.
"""
if __name__ == '__main__':
from engine import start
from qtgui import mainwindow #which in turn imports the engine and starts the engine
mainwindow.MainWindow()
#Program is over. Code here does not get executed.

4
configure

@ -46,10 +46,6 @@ python3 -c 'import PyQt5' >/dev/null 2>&1 || { echo >&2 "PyQt for Python3 >= $re
PYQTVERSION=$(python3 -c 'from PyQt5.QtCore import QT_VERSION_STR; print(QT_VERSION_STR)')
if version_gt $required_version_pyqt $PYQTVERSION; then echo "PyQt must be version >= $required_version_pyqt but is $PYQTVERSION. Aborting."; exit 1; fi
command -v nuitka3 >/dev/null 2>&1 || { echo >&2 "Nuitka3 is required but it's not installed. Aborting."; exit 1; }
NUITKAVERSION=$(python3 -c 'import nuitka.Version; print(nuitka.Version.getNuitkaVersion())')
if version_gt $required_version_nuitka $NUITKAVERSION; then echo "Nuitka3 must be version >= $required_version_nuitka but is $NUITKAVERSION. Aborting."; exit 1; fi
echo "generating makefile"
printf "PREFIX=$prefix\nPROGRAM=$program\nVERSION=$version\n" >Makefile

3
documentation/readme.template

@ -37,7 +37,6 @@ It is possible to clone a git repository.
#### Build Dependencies
* Bash
* Nuitka >= 0.6 (maybe earlier. Optional when running from source dir)
* GCC (development is done on 8.2, but most likely you can use a much earlier version)
### Environment:
@ -58,4 +57,4 @@ You can also run <name> after extracting the release archive or cloning from git
installation. If you did so, for additional features please link tools/nsm-data to your executable PATH.
Use the manpage `man <shortname>` or run `<shortname> --help` (or local variant `./<shortname> --help` )
to see available command line parameters.
to see available command line parameters.

2
engine/api.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org )

2
engine/findicons.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),

2
engine/findprograms.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),

11
engine/nsmservercontrol.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
The Non-Session-Manager by Jonathan Moore Liles <male@tuxfamily.org>: http://non.tuxfamily.org/nsm/
New Session Manager, by LinuxAudio.org: https://github.com/linuxaudio/new-session-manager
@ -1448,11 +1448,16 @@ class NsmServerControl(object):
basePath = pathlib.Path(self.sessionRoot, nsmSessionName)
assert basePath.exists()
if not self._checkIfLocked(nsmSessionName):
logger.info(f"Deleting session {nsmSessionName}: {self.getSessionFiles(nsmSessionName)}")
shutilrmtree(basePath)
try:
logger.info(f"Deleting session {nsmSessionName}: {self.getSessionFiles(nsmSessionName)}")
shutilrmtree(basePath)
except PermissionError:
logger.warning(f"Tried to delete {basePath} but permission was denied.")
else:
logger.warning(f"Tried to delete {basePath} but it is locked")
self._updateSessionListBlocking() #if we don't update our internal representation the watchdog will go mad.
def renameSession(self, nsmSessionName:str, newName:str):
"""Only works if session is not locked and dir does not exist yet"""
self._updateSessionListBlocking()

2
engine/start.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),

102
engine/watcher.py

@ -1,7 +1,7 @@
#! /usr/bi n/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),
@ -28,15 +28,15 @@ import os
#Our Modules
from engine.start import PATHS
def fast_scandir(dir):
def fast_scandir(dir):
"""
Get all subdirectories recursively.
https://stackoverflow.com/questions/973473/getting-a-list-of-all-subdirectories-in-the-current-directory"""
https://stackoverflow.com/questions/973473/getting-a-list-of-all-subdirectories-in-the-current-directory"""
try:
subfolders= [f.path for f in os.scandir(dir) if f.is_dir()]
except PermissionError:
subfolders = []
subfolders= [f.path for f in os.scandir(dir) if f.is_dir()]
except PermissionError:
subfolders = []
for dir in list(subfolders):
subfolders.extend(fast_scandir(dir))
return subfolders
@ -54,13 +54,13 @@ class Watcher(object):
"new" signal, and then our watcher will notice the change itself. However, this happens only so
often and can be accepted, so the program does not need more checks and exceptions.
Inform you via callback when:
Inform you via callback when:
a) a session dir was deleted
b) a new directory got created.
c) session directory renamed or moved
d) session.nsm changed timestamp
e) A lockfile appeared or disappeared
e) A lockfile appeared or disappeared
We cannot poll nsmServerControl.exportSessionsAsDicts() because that triggers an nsmd response
including log message and will flood their console. Instead this class only offers incremental
@ -73,7 +73,7 @@ class Watcher(object):
it goes wrong a bit, at least in the new-session-manager GUI. They will leave a zombie lockfile.
However, it still is possible to open a second nsmd instance. In this case the lockfile prevents
opening a session twice. And we are reflecting the opened state of the project, no matter from
which daemon. Horray for us :)
which daemon. Horray for us :)
Clients can only be added or removed while a session is locked. We do not check nor update
number of clients or symlinks. Therefore we advice a GUI to deactivate the display of
@ -82,17 +82,17 @@ class Watcher(object):
def __init__(self, nsmServerControl):
self.active = True
self._nsmServerControl = nsmServerControl
assert self._nsmServerControl.sessionRoot
self._directories = fast_scandir(self._nsmServerControl.sessionRoot)
logger.info("Requestion our own copy of the session list. Don't worry about the apparent redundant call :)")
self._lastExport = self._nsmServerControl.exportSessionsAsDicts()
self._lastTimestamp = {d["nsmSessionName"]:d["lastSavedDate"] for d in self._lastExport} #str:str
#Init all values with None will send the initial state via callback on program start, which is what the user wants to know.
self._lastExport = self._nsmServerControl.exportSessionsAsDicts() #list of dicts
self._lastTimestamp = {d["nsmSessionName"]:d["lastSavedDate"] for d in self._lastExport} #str:str
#Init all values with None will send the initial state via callback on program start, which is what the user wants to know.
self._lastLockfile = {d["nsmSessionName"]:None for d in self._lastExport} #str:bool
self.timeStampHook = None # a single function that gets informed of changes, most likely the api callback
@ -103,17 +103,26 @@ class Watcher(object):
"""For api callbacks"""
self.active = True
#If we returned from an open session that will surely have changed. Trigger a single poll
self.process()
self.process()
logger.info("Watcher resumed")
def suspend(self, *args):
"""For api callbacks"""
self.active = False
logger.info("Watcher suspended")
def _update(self):
current_directories = fast_scandir(self._nsmServerControl.sessionRoot)
if not self._directories == current_directories:
self._directories = current_directories
self._lastExport = self.sessionsChangedHook() #will gather its own data, send it to api callbacks, but also return for us.
self._lastTimestamp = {d["nsmSessionName"]:d["lastSavedDate"] for d in self._lastExport} #str:str
self._lastLockfile = {d["nsmSessionName"]:None for d in self._lastExport} #str:bool
def process(self):
"""Add this to your event loop.
We look for any changes in the directory structure.
If we detect any we simply trigger a new NSM export and a new NSM generated project
list via callback. We do not expect this to happen often.
@ -123,35 +132,42 @@ class Watcher(object):
"""
if not self.active:
return
if self.sessionsChangedHook:
current_directories = fast_scandir(self._nsmServerControl.sessionRoot)
if not self._directories == current_directories:
self._directories = current_directories
self._lastExport = self.sessionsChangedHook() #will gather its own data, send it to api callbacks, but also return for us.
self._lastTimestamp = {d["nsmSessionName"]:d["lastSavedDate"] for d in self._lastExport} #str:str
self._lastLockfile = {d["nsmSessionName"]:None for d in self._lastExport} #str:bool
self._update()
#Now check the incremental hooks.
#No hooks, no reason to process
if not (self.timeStampHook or self.lockFileHook):
if not (self.timeStampHook or self.lockFileHook):
logger.info("No watcher-hooks to process")
return
return
for entry in self._lastExport:
for entry in self._lastExport:
nsmSessionName = entry["nsmSessionName"]
#Timestamp of session.nsm
if self.timeStampHook:
timestamp = datetime.fromtimestamp(entry["sessionFile"].stat().st_mtime).isoformat(sep=" ", timespec='minutes') #same format as server control export
if not timestamp == self._lastTimestamp[nsmSessionName]: #This will only trigger on a minute-based slot, which is all we want and need. This is for relaying information to the user, not for advanced processing.
self._lastTimestamp[nsmSessionName] = timestamp
self.timeStampHook(nsmSessionName, timestamp)
#Lockfiles
if self.lockFileHook:
lockfileState = entry["lockFile"].is_file()
if not self._lastLockfile[nsmSessionName] == lockfileState:
self._lastLockfile[nsmSessionName] = lockfileState
self.lockFileHook(nsmSessionName, lockfileState)
try:
#Timestamp of session.nsm
if self.timeStampHook:
timestamp = datetime.fromtimestamp(entry["sessionFile"].stat().st_mtime).isoformat(sep=" ", timespec='minutes') #same format as server control export
if not timestamp == self._lastTimestamp[nsmSessionName]: #This will only trigger on a minute-based slot, which is all we want and need. This is for relaying information to the user, not for advanced processing.
self._lastTimestamp[nsmSessionName] = timestamp
self.timeStampHook(nsmSessionName, timestamp)
#Lockfiles
if self.lockFileHook:
lockfileState = entry["lockFile"].is_file()
if not self._lastLockfile[nsmSessionName] == lockfileState:
self._lastLockfile[nsmSessionName] = lockfileState
self.lockFileHook(nsmSessionName, lockfileState)
except PermissionError:
logger.warning(f"File Permission error for {entry}")
self._lastExport.remove(entry) #avoid stumbling upon this again
self._update()
except FileNotFoundError:
logger.warning(f"File not found error for {entry}")
self._lastExport.remove(entry) #avoid stumbling upon this again
self._update()

2
qtgui/addclientprompt.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ).

2
qtgui/descriptiontextwidget.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org )

2
qtgui/eventloop.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ).

2
qtgui/helper.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of Laborejo ( https://www.laborejo.org )

2
qtgui/mainwindow.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ).

2
qtgui/opensessioncontroller.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),

2
qtgui/projectname.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),

2
qtgui/quickopensessioncontroller.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ).

2
qtgui/quicksessioncontroller.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ).

2
qtgui/sessiontreecontroller.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ).

2
qtgui/settings.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),

2
qtgui/systemtray.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),

2
qtgui/usermanual.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),

2
qtgui/waitdialog.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org )

2
tools/nsm-data

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
This file is part of the Laborejo Software Suite ( https://www.laborejo.org ),
more specifically its template base application.

22
tools/nsmclient.py

@ -9,7 +9,7 @@ With help from code fragments from https://github.com/attwad/python-osc ( DO WHA
MIT License
Copyright 2014-2020 Nils Hilbricht https://www.laborejo.org
Copyright (c) since 2014: Laborejo Software Suite <info@laborejo.org>, All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
@ -548,18 +548,14 @@ class NSMClient(object):
"""If you want a very strict client you can block any non-NSM quit-attempts, like ignoring a
qt closeEvent, and instead send the NSM Server a request to close this client.
This method is a shortcut to do just that.
Using this method will not result in a NSM-"client died unexpectedly" message that usually
happens a client quits on its own. This message is harmless but may confuse a user."""
logger.info("instructing the NSM-Server to send SIGTERM to ourselves.")
if "server-control" in self.serverFeatures:
message = _OutgoingMessage("/nsm/server/stop")
message.add_arg("{}".format(self.ourClientId))
self.sock.sendto(message.build(), self.nsmOSCUrl)
else:
logger.warning("...but the NSM-Server does not support server control. Quitting on our own. Server only supports: {}".format(self.serverFeatures))
kill(getpid(), SIGTERM) #this calls the exit callback but nsm will output something like "client died unexpectedly."
"""
logger.info("Sending SIGTERM to ourselves to trigger the exit callback.")
#if "server-control" in self.serverFeatures:
# message = _OutgoingMessage("/nsm/server/stop")
# message.add_arg("{}".format(self.ourClientId))
# self.sock.sendto(message.build(), self.nsmOSCUrl)
#else:
kill(getpid(), SIGTERM) #this calls the exit callback
def serverSendSaveToSelf(self):
"""Some clients want to offer a manual Save function, mostly for psychological reasons.

2
tools/nsmcmdline.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
The Non-Session-Manager by Jonathan Moore Liles <male@tuxfamily.org>: http://non.tuxfamily.org/nsm/
With help from code fragments from https://github.com/attwad/python-osc ( DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE v2 )

2
tools/nsmservercontrol.py

@ -1,7 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Copyright 2020, Nils Hilbricht, Germany ( https://www.hilbricht.net )
Copyright 2021, Nils Hilbricht, Germany ( https://www.hilbricht.net )
The Non-Session-Manager by Jonathan Moore Liles <male@tuxfamily.org>: http://non.tuxfamily.org/nsm/
New Session Manager, by LinuxAudio.org: https://github.com/linuxaudio/new-session-manager

Caricamento…
Annulla
Salva