Merge branch 'main' into testing

This commit is contained in:
Veronica K. B. Olsen
2021-04-18 17:33:29 +02:00
6 changed files with 298 additions and 14 deletions
+35
View File
@@ -51,6 +51,41 @@ This is a beta release. Use with caution on live project.
----
## Version 1.2.3 [2021-04-18]
### Release Notes
This patch fixes a bug where the user's word list (personal dictionary) was not saved properly for
new projects. The added words were thus "forgotten" the next time the project was opened.
In addition, uninstall commands have been added to the main setup script to make it easier to clean
up icons (Linux and Windows) and registry keys (Windows) if the user wishes to uninstall
novelWriter.
### Detailed Changelog
**Bugfixes**
* Fixed an issue where the initial file for the user dictionary for a new project would not be
created the first time a word was added to it. This caused the words the user added to the
dictionary to not be loaded the next time the project was opened. Issue #733. PR #734.
* Some of the `setup.py` commands could not run if the PyQt5 packages were missing due to an import
command extracting the version number from the main `nw` package. This was not technically a bug
as the choice to do it this way was made deliberately, but a function has been added to the
`setup.py` script to allow reading the version number without having to import the `nw` package.
PR #749.
**Installation**
* An `xdg-uninstall` option has been added to `setup.py` to uninstall the icons installed into the
system by the `xdg-install` command. PR #736.
* Likewise, a `win-uninstall` option has been added to `setup.py` to uninstall the icons installed
into the system by the `win-install` command. Issue #743 and discussion #739. PR #749.
* Improvements have also been made to the `setup_windows.bat` script, and a complementary
`uninstall_windows.bat` has been added as well. PR #749.
----
## Version 1.2.2 [2021-03-28]
### Release Notes
+41 -2
View File
@@ -75,10 +75,13 @@ Step 2: Dependencies and Icons
**Alternative A: By Script**
Open the folder where you extracted the novelWriter source, and double-click the file named
Open the folder where you extracted novelWriter, and double-click the file named
``setup_windows.bat``. This should open a command line window and run the setup script to install
dependencies, and add desktop and start menu icons.
.. note::
If you downloaded the full source package, the file may be in the ``setup`` subfolder.
The script will also check that it can find Python on your system and alert you if it cannot run
it. If you are sure you have installed it, but the script cannot find it, you probably didn't
install it with the "Add Python to PATH" option mentioned in Step 1.
@@ -100,7 +103,7 @@ and run the following commands:
.. code-block:: console
python setup.py pip
pip install --user pywin32 -r requirements.txt
python setup.py win-install
The first command will install the dependencies on your system from the `Python Package Index`_,
@@ -108,3 +111,39 @@ and the second command will create a desktop icon and a start menu icon. That sh
you need.
.. _Python Package Index: https://pypi.org/
Uninstalling
============
**Alternative A: By Script**
Open the folder where you keep the novelWriter files, and double-click the file named
``uninstall_windows.bat``. This should open a command line window and run the setup script to
remove the main dependency packages and remove desktop and start menu icons.
.. note::
If you downloaded the full source package, the file may be in the ``setup`` subfolder.
If you plan to also remove Python from your system, you must run the above script first as it needs
Python in order to run.
.. note::
Due to limitations of the ``pip`` installer, dependencies of the dependencies will not be
removed, only the ones the setup script directly installed.
**Alternative B: Manual Uninstallation**
Like for the install process, the script just runs two commands. You can of course run them
yourself if you wish. They are:
.. code-block:: console
python setup.py win-uninstall
pip uninstall -r requirements.txt
There may be other packages on your system installed by ``pip``. To list all packages, run:
.. code-block:: console
pip freeze --user
+144 -11
View File
@@ -35,6 +35,30 @@ OS_LINUX = 1
OS_WIN = 2
OS_DARWIN = 3
# =============================================================================================== #
# Utilities
# =============================================================================================== #
def extractVersion():
"""Extract the novelWriter version number without having to import
anything else from the main package.
"""
def getValue(theString):
theBits = theString.partition("=")
return theBits[2].strip().strip('"')
numVers = "Unknown"
hexVers = "Unknown"
initFile = os.path.join("nw", "__init__.py")
with open(initFile, mode="r") as inFile:
for aLine in inFile:
if aLine.startswith("__version__"):
numVers = getValue((aLine))
if aLine.startswith("__hexversion__"):
hexVers = getValue((aLine))
return numVers, hexVers
# =============================================================================================== #
# General
# =============================================================================================== #
@@ -263,9 +287,11 @@ def buildSampleZip():
def makeMinimalPackage(targetOS):
"""Pack the core source file in a single zip file.
"""
from nw import __version__
from zipfile import ZipFile, ZIP_DEFLATED
# Get the version
numVers, _ = extractVersion()
# Make sample.zip first
try:
buildSampleZip()
@@ -285,21 +311,24 @@ def makeMinimalPackage(targetOS):
print("")
print("Building Minimal ZIP File")
print("=========================")
print("")
if not os.path.isdir("dist"):
os.mkdir("dist")
if targetOS == OS_LINUX:
targName = "-linux"
print("Target OS: Linux")
elif targetOS == OS_DARWIN:
targName = "-darwin"
print("Target OS: Darwin")
elif targetOS == OS_WIN:
targName = "-win"
print("Target OS: Windows")
else:
targName = ""
print("")
zipFile = f"novelWriter-{__version__}-minimal{targName}.zip"
zipFile = f"novelWriter-{numVers}-minimal{targName}.zip"
outFile = os.path.join("dist", zipFile)
if os.path.isfile(outFile):
os.unlink(outFile)
@@ -338,8 +367,10 @@ def makeMinimalPackage(targetOS):
if targetOS == OS_WIN:
zipObj.write("novelWriter.py", "novelWriter.pyw")
print("Adding File: novelWriter.pyw")
zipObj.write("setup_windows.bat")
zipObj.write(os.path.join("setup", "setup_windows.bat"), "setup_windows.bat")
print("Adding File: setup_windows.bat")
zipObj.write(os.path.join("setup", "uninstall_windows.bat"), "uninstall_windows.bat")
print("Adding File: uninstall_windows.bat")
else:
zipObj.write("novelWriter.py")
print("Adding File: novelWriter.py")
@@ -747,14 +778,13 @@ def xdgUninstall():
return
##
# WIN Installation (win-install, launcher)
# WIN Installation (win-install)
##
def winInstall():
"""Will attempt to install icons and make a launcher for Windows.
"""
import winreg
from nw import __version__, __hexversion__
try:
import win32com.client
except ImportError:
@@ -770,13 +800,14 @@ def winInstall():
print("===============")
print("")
nwTesting = not __hexversion__[-2] == "f"
numVers, hexVers = extractVersion()
nwTesting = not hexVers[-2] == "f"
wShell = win32com.client.Dispatch("WScript.Shell")
if nwTesting:
linkName = "novelWriter Testing %s.lnk" % __version__
linkName = "novelWriter Testing %s.lnk" % numVers
else:
linkName = "novelWriter %s.lnk" % __version__
linkName = "novelWriter %s.lnk" % numVers
desktopDir = wShell.SpecialFolders("Desktop")
desktopIcon = os.path.join(desktopDir, linkName)
@@ -870,6 +901,92 @@ def winInstall():
return
##
# WIN Uninstallation (win-uninstall)
##
def winUninstall():
"""Will attempt to uninstall icons previously installed.
"""
import winreg
try:
import win32com.client
except ImportError:
print(
"ERROR: Package 'pywin32' is missing on this system.\n"
" Please run 'pip install --user pywin32' to install it."
)
sys.exit(1)
print("")
print("Windows Uninstall")
print("=================")
print("")
numVers, hexVers = extractVersion()
nwTesting = not hexVers[-2] == "f"
wShell = win32com.client.Dispatch("WScript.Shell")
if nwTesting:
linkName = "novelWriter Testing %s.lnk" % numVers
else:
linkName = "novelWriter %s.lnk" % numVers
desktopDir = wShell.SpecialFolders("Desktop")
desktopIcon = os.path.join(desktopDir, linkName)
startMenuDir = wShell.SpecialFolders("StartMenu")
startMenuProg = os.path.join(startMenuDir, "Programs", "novelWriter")
startMenuIcon = os.path.join(startMenuProg, linkName)
print("Deleting Links ...")
if os.path.isfile(desktopIcon):
os.unlink(desktopIcon)
print("Deleted: %s" % desktopIcon)
else:
print("Not Found: %s" % desktopIcon)
if os.path.isfile(startMenuIcon):
os.unlink(startMenuIcon)
print("Deleted: %s" % startMenuIcon)
else:
print("Not Found: %s" % startMenuIcon)
if os.path.isdir(startMenuProg):
if not os.listdir(startMenuProg):
os.rmdir(startMenuProg)
print("Deleted: %s" % startMenuProg)
else:
print("Not Empty: %s" % startMenuProg)
print("")
print("Removing registry keys ...")
theKeys = [
r"Software\Classes\novelWriterProject.nwx\shell\open\command",
r"Software\Classes\novelWriterProject.nwx\shell\open",
r"Software\Classes\novelWriterProject.nwx\shell",
r"Software\Classes\novelWriterProject.nwx\DefaultIcon",
r"Software\Classes\novelWriterProject.nwx",
r"Software\Classes\.nwx\OpenWithProgids",
r"Software\Classes\.nwx",
r"Software\Classes\Applications\novelWriter.pyw\SupportedTypes",
r"Software\Classes\Applications\novelWriter.pyw",
]
for aKey in theKeys:
try:
winreg.DeleteKey(winreg.HKEY_CURRENT_USER, aKey)
print("Deleted: HKEY_CURRENT_USER\\%s" % aKey)
except WindowsError:
print("Not Found: HKEY_CURRENT_USER\\%s" % aKey)
print("")
print("Done!")
print("")
return
# =============================================================================================== #
# Windows Installers
# =============================================================================================== #
@@ -891,8 +1008,8 @@ def innoSetup():
with open(os.path.join("setup", "win_setup_pyz.iss"), mode="r") as inFile:
issData = inFile.read()
import nw # noqa: E402
issData = issData.replace(r"%%version%%", nw.__version__)
numVers, _ = extractVersion()
issData = issData.replace(r"%%version%%", numVers)
issData = issData.replace(r"%%dir%%", os.getcwd())
with open("setup.iss", mode="w+") as outFile:
@@ -982,6 +1099,7 @@ if __name__ == "__main__":
" with sudo for system-wide install, or as user for single user install.\n"
" Running 'xdg-uninstall' will remove the icons.\n"
" win-install Install desktop and start menu icons for Windows systems.\n"
" Running 'win-uninstall' will remove the icons.\n"
)
# Flags and Variables
@@ -997,6 +1115,13 @@ if __name__ == "__main__":
print(helpMsg)
sys.exit(0)
if "version" in sys.argv:
sys.argv.remove("version")
numVers, hexVers = extractVersion()
print("Semantic Version: %s" % numVers)
print("Hexadecimal Version: %s" % hexVers)
sys.exit(0)
if "pip" in sys.argv:
sys.argv.remove("pip")
installPackages(hostOS)
@@ -1064,6 +1189,14 @@ if __name__ == "__main__":
print("ERROR: Command 'win-install' can only be used on Windows")
sys.exit(1)
if "win-uninstall" in sys.argv:
sys.argv.remove("win-uninstall")
if hostOS == OS_WIN:
winUninstall()
else:
print("ERROR: Command 'win-uninstall' can only be used on Windows")
sys.exit(1)
# Windows Setup Installer
# =======================
+1
View File
@@ -53,3 +53,4 @@ or with sudo for system-wide install, or as user for single user install.
Running `xdg-uninstall` will remove the icons.
`win-install` Install desktop and start menu icons for Windows systems.
Running `win-uninstall` will remove the icons.
+20 -1
View File
@@ -6,10 +6,21 @@ echo Looking for Python
python --version 2>NUL
if errorlevel 1 goto errorNoPython
echo Python found. OK.
if exist setup.py (
echo setup.py found. OK.
) else (
cd ..
if exist setup.py (
echo setup.py found. OK.
) else (
goto errorNoSetup
)
)
echo.
:: Install the PyQt5, lxml and pyenchant dependencies
python setup.py pip
pip install --user pywin32 -r requirements.txt
:: Create the desktop and start menu icons
python setup.py win-install
@@ -24,5 +35,13 @@ echo.
echo Please download and install it from https://www.python.org/downloads/
echo Also make sure the "Add Python to PATH" option is selected during installation.
echo.
goto:eof
:errorNoSetup
echo.
echo ERROR^: Could not find the setup.py script.
echo.
echo Make sure you run setup.py from the novelWriter root folder.
echo.
pause
+57
View File
@@ -0,0 +1,57 @@
@echo off
:: Check for Python Installation
echo.
echo Looking for Python
python --version 2>NUL
if errorlevel 1 goto errorNoPython
echo Python found. OK.
if exist setup.py (
echo setup.py found. OK.
) else (
cd ..
if exist setup.py (
echo setup.py found. OK.
) else (
goto errorNoSetup
)
)
echo.
echo Ready to remove the novelWriter icons, registry keys, and package dependencies.
set /P c=Are you sure you want to continue [y/n]?
if /I "%c%" EQU "y" goto doUninst
goto afterUninst
:doUninst
:: Remove the desktop and start menu icons
python setup.py win-uninstall
:: Remove the PyQt5, lxml and pyenchant dependencies
pip uninstall --yes -r requirements.txt
:afterUninst
echo.
pause
goto:eof
:errorNoPython
echo.
echo ERROR^: Python is not installed on your system, or cannot be found.
echo.
echo Please download and install it from https://www.python.org/downloads/
echo Also make sure the "Add Python to PATH" option is selected during installation.
echo.
goto:eof
:errorNoSetup
echo.
echo ERROR^: Could not find the setup.py script.
echo.
echo Make sure you run setup.py from the novelWriter root folder.
echo.
pause