Merge branch 'main' into fix_docs
This commit is contained in:
@@ -6,27 +6,28 @@ jobs:
|
|||||||
buildAssets:
|
buildAssets:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Python Setup
|
- name: Checkout Source
|
||||||
uses: actions/setup-python@v6
|
uses: actions/checkout@v5
|
||||||
with:
|
|
||||||
python-version: "3.13"
|
|
||||||
architecture: x64
|
|
||||||
|
|
||||||
- name: Install Packages (apt)
|
- name: Install System Packages
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install qttools5-dev-tools latexmk texlive texlive-latex-extra
|
sudo apt install qttools5-dev-tools latexmk texlive texlive-latex-extra
|
||||||
|
|
||||||
- name: Checkout Source
|
- name: Install UV and Python
|
||||||
uses: actions/checkout@v5
|
uses: astral-sh/setup-uv@v6
|
||||||
|
with:
|
||||||
|
python-version: "3.13"
|
||||||
|
enable-cache: true
|
||||||
|
|
||||||
- name: Install Packages (pip)
|
- name: Sync UV
|
||||||
run: pip install -U -r requirements.txt -r docs/requirements.txt
|
run: |
|
||||||
|
uv sync --no-dev --group docs
|
||||||
|
|
||||||
- name: Build Assets
|
- name: Build Assets
|
||||||
run: |
|
run: |
|
||||||
python pkgutils.py build-assets
|
uv run --no-sync pkgutils.py build-assets
|
||||||
python pkgutils.py icons optional
|
uv run --no-sync pkgutils.py icons optional
|
||||||
|
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|||||||
@@ -14,14 +14,18 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
python-version: "3.13"
|
python-version: "3.13"
|
||||||
architecture: x64
|
architecture: x64
|
||||||
- name: Install Packages (apt)
|
|
||||||
|
- name: Checkout Source
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
|
||||||
|
- name: Install System Packages
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install qttools5-dev-tools
|
sudo apt install qttools5-dev-tools
|
||||||
- name: Checkout Source
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
- name: Build Assets
|
- name: Build Assets
|
||||||
run: python pkgutils.py qtlrelease
|
run: python pkgutils.py qtlrelease
|
||||||
|
|
||||||
- name: Upload Artifacts
|
- name: Upload Artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -14,24 +14,29 @@ jobs:
|
|||||||
checkSyntax:
|
checkSyntax:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Python Setup
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: 3
|
|
||||||
architecture: x64
|
|
||||||
- name: Checkout Source
|
- name: Checkout Source
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
- name: Install Dependencies
|
|
||||||
run: pip install -r requirements.txt -r requirements-dev.txt
|
- name: Install UV and Python
|
||||||
|
uses: astral-sh/setup-uv@v6
|
||||||
|
with:
|
||||||
|
enable-cache: true
|
||||||
|
|
||||||
|
- name: Sync UV
|
||||||
|
run: |
|
||||||
|
uv sync --no-dev --group lint
|
||||||
|
|
||||||
- name: Ruff Check
|
- name: Ruff Check
|
||||||
run: |
|
run: |
|
||||||
ruff --version
|
uv run --no-sync ruff --version
|
||||||
ruff check
|
uv run --no-sync ruff check
|
||||||
|
|
||||||
- name: Pyright Check
|
- name: Pyright Check
|
||||||
run: |
|
run: |
|
||||||
pyright --version
|
uv run --no-sync pyright --version
|
||||||
pyright
|
uv run --no-sync pyright
|
||||||
|
|
||||||
- name: Isort Check
|
- name: Isort Check
|
||||||
run: |
|
run: |
|
||||||
isort --version
|
uv run --no-sync isort --version
|
||||||
isort --check .
|
uv run --no-sync isort --check .
|
||||||
|
|||||||
@@ -14,33 +14,44 @@ jobs:
|
|||||||
testLinux:
|
testLinux:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
python-version:
|
||||||
|
- "3.11"
|
||||||
|
- "3.12"
|
||||||
|
- "3.13"
|
||||||
|
- "3.14"
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Python Setup
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: ${{ matrix.python-version }}
|
|
||||||
architecture: x64
|
|
||||||
- name: Install Packages (apt)
|
|
||||||
run: |
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install libenchant-2-dev qttools5-dev-tools
|
|
||||||
- name: Checkout Source
|
- name: Checkout Source
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
- name: Install Dependencies (pip)
|
|
||||||
|
- name: Install System Packages
|
||||||
run: |
|
run: |
|
||||||
pip install -U -r requirements.txt -r tests/requirements.txt
|
sudo apt update
|
||||||
- name: Run Build Commands
|
sudo apt install qttools5-dev-tools
|
||||||
|
|
||||||
|
- name: Install UV and Python
|
||||||
|
uses: astral-sh/setup-uv@v6
|
||||||
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
|
- name: Sync UV
|
||||||
run: |
|
run: |
|
||||||
python pkgutils.py qtlrelease
|
uv sync --no-dev --group test
|
||||||
python pkgutils.py sample
|
|
||||||
|
- name: Build Assets
|
||||||
|
run: |
|
||||||
|
uv run --no-sync pkgutils.py qtlrelease
|
||||||
|
uv run --no-sync pkgutils.py sample
|
||||||
|
|
||||||
- name: Run Tests
|
- name: Run Tests
|
||||||
run: |
|
run: |
|
||||||
export QT_QPA_PLATFORM=offscreen
|
export QT_QPA_PLATFORM=offscreen
|
||||||
python -m pytest -v --cov=novelwriter --timeout=60
|
uv run --no-sync coverage run -m pytest -v --timeout=60
|
||||||
|
uv run --no-sync coverage xml
|
||||||
|
|
||||||
- name: Upload to Codecov
|
- name: Upload to Codecov
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v5
|
||||||
env:
|
with:
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
fail_ci_if_error: true
|
||||||
|
|||||||
@@ -14,24 +14,30 @@ jobs:
|
|||||||
testMac:
|
testMac:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Python Setup
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: "3.13"
|
|
||||||
architecture: x64
|
|
||||||
- name: Install Packages (brew)
|
|
||||||
run: |
|
|
||||||
brew install enchant
|
|
||||||
- name: Checkout Source
|
- name: Checkout Source
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
- name: Install Dependencies (pip)
|
|
||||||
|
- name: Install System Packages
|
||||||
run: |
|
run: |
|
||||||
pip install -U pyobjc -r requirements.txt -r tests/requirements.txt
|
brew install enchant
|
||||||
|
|
||||||
|
- name: Install UV and Python
|
||||||
|
uses: astral-sh/setup-uv@v6
|
||||||
|
with:
|
||||||
|
python-version: "3.13"
|
||||||
|
|
||||||
|
- name: Sync UV
|
||||||
|
run: |
|
||||||
|
uv sync --no-dev --group test --group macos
|
||||||
|
|
||||||
- name: Run Tests
|
- name: Run Tests
|
||||||
run: |
|
run: |
|
||||||
export QT_QPA_PLATFORM=offscreen
|
export QT_QPA_PLATFORM=offscreen
|
||||||
python -m pytest -v --cov=novelwriter --timeout=60
|
uv run --no-sync coverage run -m pytest -v --timeout=60
|
||||||
|
uv run --no-sync coverage xml
|
||||||
|
|
||||||
- name: Upload to Codecov
|
- name: Upload to Codecov
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v5
|
||||||
env:
|
with:
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
fail_ci_if_error: true
|
||||||
|
|||||||
@@ -14,20 +14,25 @@ jobs:
|
|||||||
testWin:
|
testWin:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Python Setup
|
|
||||||
uses: actions/setup-python@v6
|
|
||||||
with:
|
|
||||||
python-version: "3.13"
|
|
||||||
architecture: x64
|
|
||||||
- name: Checkout Source
|
- name: Checkout Source
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v5
|
||||||
- name: Install Dependencies (pip)
|
|
||||||
|
- name: Install UV and Python
|
||||||
|
uses: astral-sh/setup-uv@v6
|
||||||
|
with:
|
||||||
|
python-version: "3.13"
|
||||||
|
|
||||||
|
- name: Sync UV
|
||||||
run: |
|
run: |
|
||||||
pip install -U -r requirements.txt -r tests/requirements.txt
|
uv sync --no-dev --group test
|
||||||
|
|
||||||
- name: Run Tests
|
- name: Run Tests
|
||||||
run: |
|
run: |
|
||||||
python -m pytest -v --cov=novelwriter --timeout=60
|
uv run --no-sync coverage run -m pytest -v --timeout=60
|
||||||
|
uv run --no-sync coverage xml
|
||||||
|
|
||||||
- name: Upload to Codecov
|
- name: Upload to Codecov
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v5
|
||||||
env:
|
with:
|
||||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
fail_ci_if_error: true
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ setup.iss
|
|||||||
/setup/macos/Info.plist
|
/setup/macos/Info.plist
|
||||||
/setup/windows/build
|
/setup/windows/build
|
||||||
.venv
|
.venv
|
||||||
|
/uv.lock
|
||||||
|
|
||||||
# Translations
|
# Translations
|
||||||
/novelwriter/assets/i18n/*.qm
|
/novelwriter/assets/i18n/*.qm
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
docutils>=0.17.1
|
|
||||||
pygments>=2.7
|
|
||||||
sphinx-book-theme
|
|
||||||
sphinx-copybutton
|
|
||||||
sphinx-design
|
|
||||||
sphinx-favicon
|
|
||||||
sphinx-intl
|
|
||||||
sphinx>=5.0
|
|
||||||
@@ -7,6 +7,7 @@ Running from Source
|
|||||||
.. _GitHub: https://github.com/vkbo/novelWriter/releases
|
.. _GitHub: https://github.com/vkbo/novelWriter/releases
|
||||||
.. _PyPi: https://pypi.org/project/novelWriter/
|
.. _PyPi: https://pypi.org/project/novelWriter/
|
||||||
.. _Sphinx Docs: https://www.sphinx-doc.org/
|
.. _Sphinx Docs: https://www.sphinx-doc.org/
|
||||||
|
.. _uv: https://docs.astral.sh/uv/
|
||||||
|
|
||||||
This chapter describes various ways of running novelWriter directly from the source code, and how
|
This chapter describes various ways of running novelWriter directly from the source code, and how
|
||||||
to build the various components like the translation files and documentation.
|
to build the various components like the translation files and documentation.
|
||||||
@@ -28,6 +29,7 @@ by running:
|
|||||||
|
|
||||||
.. _docs_technical_source_depend:
|
.. _docs_technical_source_depend:
|
||||||
|
|
||||||
|
|
||||||
Dependencies
|
Dependencies
|
||||||
============
|
============
|
||||||
|
|
||||||
@@ -43,11 +45,20 @@ The following Python packages are needed to run all features of novelWriter:
|
|||||||
If you want spell checking, you must install the ``PyEnchant`` package. The spell check library
|
If you want spell checking, you must install the ``PyEnchant`` package. The spell check library
|
||||||
must be at least 3.0 to work with Windows. On Linux, 2.0 also works fine.
|
must be at least 3.0 to work with Windows. On Linux, 2.0 also works fine.
|
||||||
|
|
||||||
If you install from PyPi, these dependencies should be installed automatically. If you install from
|
If you install novelWriter from PyPi, these dependencies should be installed automatically.
|
||||||
source, dependencies can still be installed from PyPi with:
|
|
||||||
|
You can run novelWriter directly from source with uv_:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
|
uv run novelwriter
|
||||||
|
|
||||||
|
If you prefer to install dependencies using ``pip``, you must first generate the
|
||||||
|
``requirements.txt`` file:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
python pkgutils.py gen-req
|
||||||
pip install -r requirements.txt
|
pip install -r requirements.txt
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
@@ -136,12 +147,14 @@ running:
|
|||||||
Building the Documentation
|
Building the Documentation
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
A local copy of this documentation can be generated as HTML. This requires installing some Python
|
A local copy of this documentation can be generated as HTML.
|
||||||
packages from PyPi:
|
|
||||||
|
If you're using ``pip``, you must first generate the ``requirements.txt`` file:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
pip install -r docs/requirements.txt
|
python pkgutils.py gen-req docs
|
||||||
|
pip install -r requirements.txt
|
||||||
|
|
||||||
The documentation can then be built from the root folder in the source code by running:
|
The documentation can then be built from the root folder in the source code by running:
|
||||||
|
|
||||||
@@ -149,6 +162,12 @@ The documentation can then be built from the root folder in the source code by r
|
|||||||
|
|
||||||
make -C docs html
|
make -C docs html
|
||||||
|
|
||||||
|
Or you can run directly with uv_:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
uv run make -C docs html
|
||||||
|
|
||||||
If successful, the documentation should be available in the ``docs/build/html`` folder and you can
|
If successful, the documentation should be available in the ``docs/build/html`` folder and you can
|
||||||
open the ``index.html`` file in your browser.
|
open the ``index.html`` file in your browser.
|
||||||
|
|
||||||
|
|||||||
@@ -4,23 +4,12 @@
|
|||||||
Running Tests
|
Running Tests
|
||||||
*************
|
*************
|
||||||
|
|
||||||
|
.. _uv: https://docs.astral.sh/uv/
|
||||||
|
|
||||||
The novelWriter source code is well covered by tests. The test framework used for the development
|
The novelWriter source code is well covered by tests. The test framework used for the development
|
||||||
is ``pytest`` with the use of an extension for Qt.
|
is ``pytest`` with the use of an extension for Qt.
|
||||||
|
|
||||||
|
|
||||||
Dependencies
|
|
||||||
============
|
|
||||||
|
|
||||||
The dependencies for running the tests can be installed with:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
pip install -r tests/requirements.txt
|
|
||||||
|
|
||||||
This will install a couple of extra packages for coverage and test management. The minimum
|
|
||||||
requirement is ``pytest`` and ``pytest-qt``.
|
|
||||||
|
|
||||||
|
|
||||||
Simple Test Run
|
Simple Test Run
|
||||||
===============
|
===============
|
||||||
|
|
||||||
@@ -28,19 +17,35 @@ To run the tests, you simply need to execute the following from the root of the
|
|||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
pytest
|
uv run pytest
|
||||||
|
|
||||||
|
This uses uv_. See below for manually installing dependencies using ``pip``.
|
||||||
|
|
||||||
Since several of the tests involve opening up the novelWriter GUI, you may want to disable the GUI
|
Since several of the tests involve opening up the novelWriter GUI, you may want to disable the GUI
|
||||||
for the duration of the test run. Moving your mouse while the tests are running may otherwise
|
for the duration of the test run. Moving your mouse while the tests are running may otherwise
|
||||||
interfere with the execution of some tests.
|
interfere with the execution of some tests.
|
||||||
|
|
||||||
You can disable the renderring of the GUI by setting the flag ``QT_QPA_PLATFORM=offscreen``:
|
You can disable the rendering of the GUI by setting the flag ``QT_QPA_PLATFORM=offscreen``:
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
|
||||||
export QT_QPA_PLATFORM=offscreen pytest
|
export QT_QPA_PLATFORM=offscreen pytest
|
||||||
|
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
|
To generate the requirements file and install dependencies using ``pip``, run:
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
python pkgutils.py gen-req app test
|
||||||
|
pip install -r tests/requirements.txt
|
||||||
|
|
||||||
|
This will install a couple of extra packages for coverage and test management. The minimum
|
||||||
|
requirement is ``pytest`` and ``pytest-qt``.
|
||||||
|
|
||||||
|
|
||||||
Advanced Options
|
Advanced Options
|
||||||
================
|
================
|
||||||
|
|
||||||
|
|||||||
@@ -6,14 +6,6 @@ novelWriter – Start Script
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
try:
|
|
||||||
import PyQt6.QtCore # noqa: F401
|
|
||||||
import PyQt6.QtGui # noqa: F401
|
|
||||||
import PyQt6.QtWidgets # noqa: F401
|
|
||||||
except Exception:
|
|
||||||
print("ERROR: Failed to load dependency PyQt6")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
os.curdir = os.path.abspath(os.path.dirname(__file__))
|
os.curdir = os.path.abspath(os.path.dirname(__file__))
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -49,9 +49,9 @@ __license__ = "GPLv3"
|
|||||||
__author__ = "Veronica Berglyd Olsen"
|
__author__ = "Veronica Berglyd Olsen"
|
||||||
__maintainer__ = "Veronica Berglyd Olsen"
|
__maintainer__ = "Veronica Berglyd Olsen"
|
||||||
__email__ = "code@vkbo.net"
|
__email__ = "code@vkbo.net"
|
||||||
__version__ = "2.8a2"
|
__version__ = "2.8a3"
|
||||||
__hexversion__ = "0x020800a2"
|
__hexversion__ = "0x020800a3"
|
||||||
__date__ = "2025-07-16"
|
__date__ = "2025-10-18"
|
||||||
__status__ = "Stable"
|
__status__ = "Stable"
|
||||||
__domain__ = "novelwriter.io"
|
__domain__ = "novelwriter.io"
|
||||||
|
|
||||||
@@ -206,9 +206,9 @@ def main(sysArgs: list | None = None) -> GuiMain | None:
|
|||||||
# Check Packages and Versions
|
# Check Packages and Versions
|
||||||
errorData = []
|
errorData = []
|
||||||
errorCode = 0
|
errorCode = 0
|
||||||
if sys.hexversion < 0x030a00f0:
|
if sys.hexversion < 0x030b00f0:
|
||||||
errorData.append(
|
errorData.append(
|
||||||
f"At least Python 3.10 is required, found {CONFIG.verPyString}"
|
f"At least Python 3.11 is required, found {CONFIG.verPyString}"
|
||||||
)
|
)
|
||||||
errorCode |= 0x04
|
errorCode |= 0x04
|
||||||
if CONFIG.verQtValue < 0x060400:
|
if CONFIG.verQtValue < 0x060400:
|
||||||
|
|||||||
@@ -615,7 +615,7 @@ class GuiTheme:
|
|||||||
lookup = f"{prefix}{name} {key}"
|
lookup = f"{prefix}{name} {key}"
|
||||||
keys.append(lookup)
|
keys.append(lookup)
|
||||||
data[lookup] = (file.stem, name, mode == "dark", file)
|
data[lookup] = (file.stem, name, mode == "dark", file)
|
||||||
except Exception: # noqa: PERF203
|
except Exception:
|
||||||
logger.error("Could not read file: %s", file)
|
logger.error("Could not read file: %s", file)
|
||||||
logException()
|
logException()
|
||||||
|
|
||||||
|
|||||||
+29
-44
@@ -29,7 +29,6 @@ from __future__ import annotations
|
|||||||
import argparse
|
import argparse
|
||||||
import datetime
|
import datetime
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import utils.assets
|
import utils.assets
|
||||||
@@ -40,7 +39,10 @@ import utils.build_windows
|
|||||||
import utils.docs
|
import utils.docs
|
||||||
import utils.icon_themes
|
import utils.icon_themes
|
||||||
|
|
||||||
from utils.common import ROOT_DIR, SETUP_DIR, extractVersion, readFile, stripVersion, writeFile
|
from utils.common import (
|
||||||
|
ROOT_DIR, SETUP_DIR, extractReqs, extractVersion, readFile, stripVersion,
|
||||||
|
writeFile
|
||||||
|
)
|
||||||
|
|
||||||
OS_LINUX = sys.platform.startswith("linux")
|
OS_LINUX = sys.platform.startswith("linux")
|
||||||
OS_DARWIN = sys.platform.startswith("darwin")
|
OS_DARWIN = sys.platform.startswith("darwin")
|
||||||
@@ -52,33 +54,6 @@ def printVersion(args: argparse.Namespace) -> None:
|
|||||||
print(extractVersion(beQuiet=True)[0], end=None)
|
print(extractVersion(beQuiet=True)[0], end=None)
|
||||||
|
|
||||||
|
|
||||||
def installPackages(args: argparse.Namespace) -> None:
|
|
||||||
"""Install package dependencies both for this script and for running
|
|
||||||
novelWriter itself.
|
|
||||||
"""
|
|
||||||
print("")
|
|
||||||
print("Installing Dependencies")
|
|
||||||
print("=======================")
|
|
||||||
print("")
|
|
||||||
|
|
||||||
installQueue = ["pip", "-r requirements.txt"]
|
|
||||||
if args.mac:
|
|
||||||
installQueue.append("pyobjc")
|
|
||||||
elif args.win:
|
|
||||||
installQueue.append("pywin32")
|
|
||||||
|
|
||||||
pyCmd = [sys.executable, "-m"]
|
|
||||||
pipCmd = ["pip", "install", "--user", "--upgrade"]
|
|
||||||
for stepCmd in installQueue:
|
|
||||||
pkgCmd = stepCmd.split(" ")
|
|
||||||
try:
|
|
||||||
subprocess.call(pyCmd + pipCmd + pkgCmd)
|
|
||||||
except Exception as exc:
|
|
||||||
print("Failed with error:")
|
|
||||||
print(str(exc))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
def cleanBuildDirs(args: argparse.Namespace) -> None:
|
def cleanBuildDirs(args: argparse.Namespace) -> None:
|
||||||
"""Recursively delete the 'build' and 'dist' folders."""
|
"""Recursively delete the 'build' and 'dist' folders."""
|
||||||
print("")
|
print("")
|
||||||
@@ -130,6 +105,15 @@ def genMacOSPlist(args: argparse.Namespace) -> None:
|
|||||||
writeFile(outDir / "Info.plist", plistXML)
|
writeFile(outDir / "Info.plist", plistXML)
|
||||||
|
|
||||||
|
|
||||||
|
def genReqFiles(args: argparse.Namespace) -> None:
|
||||||
|
"""Generate requirements.txt file from pyproject.toml."""
|
||||||
|
select = [s.strip().lower() for s in args.groups] if args.groups else ["app"]
|
||||||
|
(ROOT_DIR / "requirements.txt").write_text(
|
||||||
|
"\n".join(extractReqs(select)),
|
||||||
|
encoding="utf-8"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
"""Parse command line options and run the commands."""
|
"""Parse command line options and run the commands."""
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
@@ -148,18 +132,6 @@ if __name__ == "__main__":
|
|||||||
)
|
)
|
||||||
cmdVersion.set_defaults(func=printVersion)
|
cmdVersion.set_defaults(func=printVersion)
|
||||||
|
|
||||||
# General
|
|
||||||
# =======
|
|
||||||
|
|
||||||
# Pip Install
|
|
||||||
cmdPipInstall = parsers.add_parser(
|
|
||||||
"pip", help="Install all package dependencies for novelWriter using pip."
|
|
||||||
)
|
|
||||||
cmdPipInstall.add_argument("--linux", action="store_true", help="For Linux.", default=OS_LINUX)
|
|
||||||
cmdPipInstall.add_argument("--mac", action="store_true", help="For MacOS.", default=OS_DARWIN)
|
|
||||||
cmdPipInstall.add_argument("--win", action="store_true", help="For Windows.", default=OS_WIN)
|
|
||||||
cmdPipInstall.set_defaults(func=installPackages)
|
|
||||||
|
|
||||||
# Additional Builds
|
# Additional Builds
|
||||||
# =================
|
# =================
|
||||||
|
|
||||||
@@ -222,7 +194,7 @@ if __name__ == "__main__":
|
|||||||
cmdBuildHtmlDocs = parsers.add_parser(
|
cmdBuildHtmlDocs = parsers.add_parser(
|
||||||
"docs-html", help="Build the HTML docs."
|
"docs-html", help="Build the HTML docs."
|
||||||
)
|
)
|
||||||
cmdBuildHtmlDocs.add_argument("lang", nargs="+")
|
cmdBuildHtmlDocs.add_argument("lang", nargs="+", help="Language codes to generate docs for.")
|
||||||
cmdBuildHtmlDocs.set_defaults(func=utils.docs.buildHtmlDocs)
|
cmdBuildHtmlDocs.set_defaults(func=utils.docs.buildHtmlDocs)
|
||||||
|
|
||||||
# Build Sample
|
# Build Sample
|
||||||
@@ -295,10 +267,23 @@ if __name__ == "__main__":
|
|||||||
cmdBuildClean.set_defaults(func=cleanBuildDirs)
|
cmdBuildClean.set_defaults(func=cleanBuildDirs)
|
||||||
|
|
||||||
# Generate MacOS PList File
|
# Generate MacOS PList File
|
||||||
cmdBuildMacOSPlist = parsers.add_parser(
|
cmdGenMacOSPlist = parsers.add_parser(
|
||||||
"gen-plist", help="Generate an Info.plist for use in a MacOS Bundle."
|
"gen-plist", help="Generate an Info.plist for use in a MacOS Bundle."
|
||||||
)
|
)
|
||||||
cmdBuildMacOSPlist.set_defaults(func=genMacOSPlist)
|
cmdGenMacOSPlist.set_defaults(func=genMacOSPlist)
|
||||||
|
|
||||||
|
# Generate Requirement File
|
||||||
|
cmdGenReq = parsers.add_parser(
|
||||||
|
"gen-req", help="Generate a requirements.txt file for pip."
|
||||||
|
)
|
||||||
|
cmdGenReq.add_argument(
|
||||||
|
"groups", nargs="*", help=(
|
||||||
|
"Groups to generate for, or 'all' to generate for all groups. "
|
||||||
|
"Use 'app' to generate for just the core application. "
|
||||||
|
"Defaults to 'app' if none are specified."
|
||||||
|
)
|
||||||
|
)
|
||||||
|
cmdGenReq.set_defaults(func=genReqFiles)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
args.func(args)
|
args.func(args)
|
||||||
|
|||||||
+52
-34
@@ -4,16 +4,15 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "novelWriter"
|
name = "novelWriter"
|
||||||
authors = [
|
authors = [{ name = "Veronica Berglyd Olsen", email = "code@vkbo.net" }]
|
||||||
{name = "Veronica Berglyd Olsen", email = "code@vkbo.net"},
|
|
||||||
]
|
|
||||||
description = "A plain text editor for planning and writing novels"
|
description = "A plain text editor for planning and writing novels"
|
||||||
readme = {file = "setup/description_pypi.md", content-type = "text/markdown"}
|
readme = { file = "setup/description_pypi.md", content-type = "text/markdown" }
|
||||||
license = "GPL-3.0-or-later AND Apache-2.0 AND CC-BY-4.0"
|
license = "GPL-3.0-or-later AND Apache-2.0 AND CC-BY-4.0"
|
||||||
license-files = ["LICENSE.md", "setup/LICENSE-Apache-2.0.txt"]
|
license-files = ["LICENSE.md", "setup/LICENSE-Apache-2.0.txt"]
|
||||||
|
dynamic = ["version"]
|
||||||
|
requires-python = ">=3.11"
|
||||||
classifiers = [
|
classifiers = [
|
||||||
"Programming Language :: Python :: 3 :: Only",
|
"Programming Language :: Python :: 3 :: Only",
|
||||||
"Programming Language :: Python :: 3.10",
|
|
||||||
"Programming Language :: Python :: 3.11",
|
"Programming Language :: Python :: 3.11",
|
||||||
"Programming Language :: Python :: 3.12",
|
"Programming Language :: Python :: 3.12",
|
||||||
"Programming Language :: Python :: 3.13",
|
"Programming Language :: Python :: 3.13",
|
||||||
@@ -25,12 +24,32 @@ classifiers = [
|
|||||||
"Natural Language :: English",
|
"Natural Language :: English",
|
||||||
"Topic :: Text Editors",
|
"Topic :: Text Editors",
|
||||||
]
|
]
|
||||||
requires-python = ">=3.10"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pyqt6>=6.4",
|
"pyqt6>=6.4",
|
||||||
"pyenchant>=3.0.0",
|
"pyenchant>=3.3.0", # 3.3 is needed for MacOS AARCH64 builds
|
||||||
]
|
]
|
||||||
dynamic = ["version"]
|
|
||||||
|
[dependency-groups]
|
||||||
|
dev = [
|
||||||
|
{ include-group = "build" },
|
||||||
|
{ include-group = "docs" },
|
||||||
|
{ include-group = "test" },
|
||||||
|
{ include-group = "lint" },
|
||||||
|
]
|
||||||
|
build = ["build", "setuptools>=77.0.3"]
|
||||||
|
docs = [
|
||||||
|
"docutils>=0.17.1",
|
||||||
|
"pygments>=2.7",
|
||||||
|
"sphinx-book-theme",
|
||||||
|
"sphinx-copybutton",
|
||||||
|
"sphinx-design",
|
||||||
|
"sphinx-favicon",
|
||||||
|
"sphinx-intl",
|
||||||
|
"sphinx>=5.0",
|
||||||
|
]
|
||||||
|
test = ["coverage>=7.2.0", "pytest-qt", "pytest-timeout", "pytest>=6.0.0"]
|
||||||
|
lint = ["isort", "pyright", "ruff"]
|
||||||
|
macos = ["pyobjc"]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Homepage = "https://novelwriter.io"
|
Homepage = "https://novelwriter.io"
|
||||||
@@ -42,13 +61,13 @@ Issues = "https://github.com/vkbo/novelWriter/issues"
|
|||||||
novelwriter = "novelwriter:main"
|
novelwriter = "novelwriter:main"
|
||||||
|
|
||||||
[tool.setuptools.dynamic]
|
[tool.setuptools.dynamic]
|
||||||
version = {attr = "novelwriter.__version__"}
|
version = { attr = "novelwriter.__init__.__version__" }
|
||||||
|
|
||||||
[tool.setuptools.packages.find]
|
[tool.setuptools.packages.find]
|
||||||
include = ["novelwriter*"]
|
include = ["novelwriter*"]
|
||||||
|
|
||||||
[tool.isort]
|
[tool.isort]
|
||||||
py_version="310"
|
py_version = "311"
|
||||||
line_length = 99
|
line_length = 99
|
||||||
wrap_length = 79
|
wrap_length = 79
|
||||||
multi_line_output = 5
|
multi_line_output = 5
|
||||||
@@ -64,26 +83,26 @@ preview = true
|
|||||||
|
|
||||||
# Rules: https://docs.astral.sh/ruff/rules
|
# Rules: https://docs.astral.sh/ruff/rules
|
||||||
select = [
|
select = [
|
||||||
"A", # flake8-builtins (A)
|
"A", # flake8-builtins (A)
|
||||||
"ANN", # flake8-annotations (ANN)
|
"ANN", # flake8-annotations (ANN)
|
||||||
"B", # flake8-bugbear (B)
|
"B", # flake8-bugbear (B)
|
||||||
"D", # pydocstyle (D)
|
"D", # pydocstyle (D)
|
||||||
"E", # pycodestyle (E)
|
"E", # pycodestyle (E)
|
||||||
"F", # Pyflakes (F)
|
"F", # Pyflakes (F)
|
||||||
"FA", # flake8-future-annotations (FA)
|
"FA", # flake8-future-annotations (FA)
|
||||||
"PERF", # Perflint (PERF)
|
"PERF", # Perflint (PERF)
|
||||||
"PLC", # Pylint Convention (PLC)
|
"PLC", # Pylint Convention (PLC)
|
||||||
"PLE", # Pylint Error (PLE)
|
"PLE", # Pylint Error (PLE)
|
||||||
"PLR17", # Refactor (PLR) - Only PLR17xx
|
"PLR17", # Refactor (PLR) - Only PLR17xx
|
||||||
"PLW", # Pylint Warning (PLW)
|
"PLW", # Pylint Warning (PLW)
|
||||||
"Q", # flake8-quotes (Q)
|
"Q", # flake8-quotes (Q)
|
||||||
"RET", # flake8-return (RET)
|
"RET", # flake8-return (RET)
|
||||||
"RUF", # Ruff-specific rules (RUF)
|
"RUF", # Ruff-specific rules (RUF)
|
||||||
"SLF", # flake8-self (SLF)
|
"SLF", # flake8-self (SLF)
|
||||||
"SLOT", # flake8-slots (SLOT)
|
"SLOT", # flake8-slots (SLOT)
|
||||||
"TC", # flake8-type-checking (TC)
|
"TC", # flake8-type-checking (TC)
|
||||||
"UP", # pyupgrade (UP)
|
"UP", # pyupgrade (UP)
|
||||||
"W", # pycodestyle (W)
|
"W", # pycodestyle (W)
|
||||||
]
|
]
|
||||||
ignore = [
|
ignore = [
|
||||||
"ANN401", # any-type
|
"ANN401", # any-type
|
||||||
@@ -133,7 +152,7 @@ include = ["novelwriter"]
|
|||||||
exclude = ["**/__pycache__"]
|
exclude = ["**/__pycache__"]
|
||||||
|
|
||||||
reportIncompatibleMethodOverride = false
|
reportIncompatibleMethodOverride = false
|
||||||
pythonVersion = "3.10"
|
pythonVersion = "3.11"
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
log_level = "DEBUG"
|
log_level = "DEBUG"
|
||||||
@@ -146,9 +165,8 @@ markers = [
|
|||||||
|
|
||||||
[tool.coverage.run]
|
[tool.coverage.run]
|
||||||
branch = false
|
branch = false
|
||||||
|
source = ["novelwriter"]
|
||||||
|
|
||||||
[tool.coverage.report]
|
[tool.coverage.report]
|
||||||
precision = 2
|
precision = 2
|
||||||
exclude_also = [
|
exclude_also = ["if TYPE_CHECKING:"]
|
||||||
"if TYPE_CHECKING:"
|
|
||||||
]
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
-r requirements.txt
|
|
||||||
-r requirements-dev.txt
|
|
||||||
-r docs/requirements.txt
|
|
||||||
-r setup/requirements.txt
|
|
||||||
-r tests/requirements.txt
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
build
|
|
||||||
isort
|
|
||||||
pyright
|
|
||||||
ruff
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
pyqt6>=6.4
|
|
||||||
pyenchant>=3.0.0
|
|
||||||
+19
-10
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import os
|
import os
|
||||||
|
import shlex
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@@ -12,27 +13,35 @@ if __name__ == "__main__":
|
|||||||
parser.add_argument("-o", action="store_true", help="Run off screen")
|
parser.add_argument("-o", action="store_true", help="Run off screen")
|
||||||
parser.add_argument("-r", action="store_true", help="Generate reports")
|
parser.add_argument("-r", action="store_true", help="Generate reports")
|
||||||
parser.add_argument("-t", action="store_true", help="Generate terminal report")
|
parser.add_argument("-t", action="store_true", help="Generate terminal report")
|
||||||
parser.add_argument("-m", help="Test modules")
|
parser.add_argument("-u", action="store_true", help="Generate uncovered terminal report")
|
||||||
parser.add_argument("-k", help="Test filters")
|
parser.add_argument("-m", help="Test modules", metavar="MARKEXPR")
|
||||||
|
parser.add_argument("-k", help="Test filters", metavar="EXPRESSION")
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
env = os.environ.copy()
|
env = os.environ.copy()
|
||||||
env["QT_SCALE_FACTOR"] = "1.0"
|
env["QT_SCALE_FACTOR"] = "1.0"
|
||||||
cmd = [sys.executable, "-m", "pytest", "-vv"]
|
|
||||||
|
|
||||||
|
if args.r or args.t or args.u:
|
||||||
|
cmd = ["coverage", "run", "-m"]
|
||||||
|
else:
|
||||||
|
cmd = [sys.executable, "-m"]
|
||||||
|
|
||||||
|
cmd += ["pytest", "-vv"]
|
||||||
if args.o:
|
if args.o:
|
||||||
env["QT_QPA_PLATFORM"] = "offscreen"
|
env["QT_QPA_PLATFORM"] = "offscreen"
|
||||||
if args.r or args.t:
|
|
||||||
cmd += ["--cov=novelwriter"]
|
|
||||||
if args.r:
|
|
||||||
cmd += ["--cov-report=xml", "--cov-report=html"]
|
|
||||||
if args.t:
|
|
||||||
cmd += ["--cov-report=term"]
|
|
||||||
if args.m:
|
if args.m:
|
||||||
cmd += ["-m", args.m]
|
cmd += ["-m", args.m]
|
||||||
if args.k:
|
if args.k:
|
||||||
cmd += ["-k", args.k]
|
cmd += ["-k", args.k]
|
||||||
|
|
||||||
print("Calling:", " ".join(cmd))
|
print("Calling:", shlex.join(cmd))
|
||||||
subprocess.call(cmd, env=env)
|
subprocess.call(cmd, env=env)
|
||||||
|
|
||||||
|
if args.r:
|
||||||
|
subprocess.call(["coverage", "xml"])
|
||||||
|
subprocess.call(["coverage", "html"])
|
||||||
|
if args.t and not args.u:
|
||||||
|
subprocess.call(["coverage", "report"])
|
||||||
|
if args.u:
|
||||||
|
subprocess.call(["coverage", "report", "--skip-covered "])
|
||||||
|
|||||||
@@ -4,24 +4,26 @@ Section: text
|
|||||||
Priority: optional
|
Priority: optional
|
||||||
Build-Depends:
|
Build-Depends:
|
||||||
dh-python,
|
dh-python,
|
||||||
|
pybuild-plugin-pyproject,
|
||||||
|
python3-build,
|
||||||
python3-setuptools,
|
python3-setuptools,
|
||||||
python3-all,
|
python3-all,
|
||||||
debhelper (>= 9),
|
debhelper (>= 9),
|
||||||
python3 (>=3.10),
|
python3 (>=3.11),
|
||||||
python3-pyqt6 (>= 6.4),
|
python3-pyqt6 (>= 6.4),
|
||||||
python3-pyqt6.qtsvg (>= 6.4),
|
python3-pyqt6.qtsvg (>= 6.4),
|
||||||
python3-enchant (>= 2.0),
|
python3-enchant (>= 2.0),
|
||||||
qt6-image-formats-plugins (>= 6.4)
|
qt6-image-formats-plugins (>= 6.4)
|
||||||
Standards-Version: 4.5.1
|
Standards-Version: 4.5.1
|
||||||
Homepage: https://novelwriter.io
|
Homepage: https://novelwriter.io
|
||||||
X-Python3-Version: >= 3.10
|
X-Python3-Version: >= 3.11
|
||||||
|
|
||||||
Package: novelwriter
|
Package: novelwriter
|
||||||
Architecture: all
|
Architecture: all
|
||||||
Depends:
|
Depends:
|
||||||
${misc:Depends},
|
${misc:Depends},
|
||||||
${python3:Depends},
|
${python3:Depends},
|
||||||
python3 (>=3.10),
|
python3 (>=3.11),
|
||||||
python3-pyqt6 (>= 6.4),
|
python3-pyqt6 (>= 6.4),
|
||||||
python3-pyqt6.qtsvg (>= 6.4),
|
python3-pyqt6.qtsvg (>= 6.4),
|
||||||
python3-enchant (>= 2.0),
|
python3-enchant (>= 2.0),
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
|
|
||||||
if [[ -z "$1" || -z "$2" || -z "$3" ]]; then
|
if [[ -z "$1" || -z "$2" || -z "$3" ]]; then
|
||||||
echo "Not enouch input arguments"
|
echo "Not enough input arguments"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -108,8 +108,8 @@ conda install -c conda-forge enchant hunspell-en --yes
|
|||||||
|
|
||||||
# Install dependencies
|
# Install dependencies
|
||||||
echo "Installing Python dependencies ..."
|
echo "Installing Python dependencies ..."
|
||||||
|
python3 pkgutils.py gen-req
|
||||||
pip install -r "$SRC_DIR/requirements.txt"
|
pip install -r "$SRC_DIR/requirements.txt"
|
||||||
pip install pyenchant==3.3.0rc1
|
|
||||||
|
|
||||||
# Leave conda env
|
# Leave conda env
|
||||||
conda deactivate
|
conda deactivate
|
||||||
|
|||||||
+3
-23
@@ -1,36 +1,23 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
ENVPATH=/tmp/nwBuild
|
|
||||||
|
|
||||||
if [ ! -f pkgutils.py ]; then
|
if [ ! -f pkgutils.py ]; then
|
||||||
echo "Must be called from the root folder of the source"
|
echo "Must be called from the root folder of the source"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo " Create Python Env"
|
|
||||||
echo "================================================================================"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
if [ ! -d $ENVPATH ]; then
|
|
||||||
python3 -m venv $ENVPATH
|
|
||||||
fi
|
|
||||||
source $ENVPATH/bin/activate
|
|
||||||
pip3 install -U build twine -r requirements.txt -r docs/requirements.txt
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " Building Dependencies"
|
echo " Building Dependencies"
|
||||||
echo "================================================================================"
|
echo "================================================================================"
|
||||||
echo ""
|
echo ""
|
||||||
python3 pkgutils.py build-assets
|
uv run pkgutils.py build-assets
|
||||||
python3 pkgutils.py icons optional
|
uv run pkgutils.py icons optional
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " Building Packages"
|
echo " Building Packages"
|
||||||
echo "================================================================================"
|
echo "================================================================================"
|
||||||
echo ""
|
echo ""
|
||||||
python3 -m build
|
uv build
|
||||||
mkdir -pv dist_upload
|
mkdir -pv dist_upload
|
||||||
cp -v dist/novelwriter-*.whl dist_upload/
|
cp -v dist/novelwriter-*.whl dist_upload/
|
||||||
cd dist_upload
|
cd dist_upload
|
||||||
@@ -38,13 +25,6 @@ FILE=$(ls -t | head -1)
|
|||||||
shasum -a 256 $FILE | tee $FILE.sha256
|
shasum -a 256 $FILE | tee $FILE.sha256
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo " Checking Packages"
|
|
||||||
echo "================================================================================"
|
|
||||||
echo ""
|
|
||||||
twine check dist/*
|
|
||||||
deactivate
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " Done!"
|
echo " Done!"
|
||||||
echo "================================================================================"
|
echo "================================================================================"
|
||||||
|
|||||||
+4
-12
@@ -1,8 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
ENVPATH=/tmp/nwBuild
|
|
||||||
|
|
||||||
if [ ! -f pkgutils.py ]; then
|
if [ ! -f pkgutils.py ]; then
|
||||||
echo "Must be called from the root folder of the source"
|
echo "Must be called from the root folder of the source"
|
||||||
exit 1
|
exit 1
|
||||||
@@ -12,18 +10,12 @@ echo ""
|
|||||||
echo " Building Dependencies"
|
echo " Building Dependencies"
|
||||||
echo "================================================================================"
|
echo "================================================================================"
|
||||||
echo ""
|
echo ""
|
||||||
if [ ! -d $ENVPATH ]; then
|
uv run pkgutils.py build-assets
|
||||||
python3 -m venv $ENVPATH
|
uv run pkgutils.py icons optional
|
||||||
fi
|
|
||||||
source $ENVPATH/bin/activate
|
|
||||||
pip3 install -r requirements.txt -r docs/requirements.txt
|
|
||||||
python3 pkgutils.py build-assets
|
|
||||||
python3 pkgutils.py icons optional
|
|
||||||
deactivate
|
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo " Building Linux Packages"
|
echo " Building Linux Packages"
|
||||||
echo "================================================================================"
|
echo "================================================================================"
|
||||||
echo ""
|
echo ""
|
||||||
python3 pkgutils.py build-deb --sign
|
uv run pkgutils.py build-deb --sign
|
||||||
python3 pkgutils.py build-ubuntu --sign
|
uv run pkgutils.py build-ubuntu --sign
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
setuptools>=77.0.3
|
|
||||||
twine
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
coverage>=7.2.0
|
|
||||||
pytest-cov
|
|
||||||
pytest-qt
|
|
||||||
pytest-timeout
|
|
||||||
pytest>=6.0.0
|
|
||||||
@@ -183,6 +183,7 @@ def launchpad(args: argparse.Namespace) -> None:
|
|||||||
("24.04", "noble", True),
|
("24.04", "noble", True),
|
||||||
("25.04", "plucky", True),
|
("25.04", "plucky", True),
|
||||||
("25.10", "questing", False),
|
("25.10", "questing", False),
|
||||||
|
("26.04", "resolute", False),
|
||||||
]
|
]
|
||||||
|
|
||||||
print("Building Ubuntu packages for:")
|
print("Building Ubuntu packages for:")
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import zipfile
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from utils.common import (
|
from utils.common import (
|
||||||
ROOT_DIR, SETUP_DIR, copySourceCode, extractVersion, readFile,
|
ROOT_DIR, SETUP_DIR, copySourceCode, extractReqs, extractVersion, readFile,
|
||||||
removeRedundantQt, systemCall, writeFile
|
removeRedundantQt, systemCall, writeFile
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -45,7 +45,6 @@ def prepareCode(outDir: Path) -> None:
|
|||||||
files = [
|
files = [
|
||||||
ROOT_DIR / "CREDITS.md",
|
ROOT_DIR / "CREDITS.md",
|
||||||
ROOT_DIR / "LICENSE.md",
|
ROOT_DIR / "LICENSE.md",
|
||||||
ROOT_DIR / "requirements.txt",
|
|
||||||
SETUP_DIR / "iss_license.txt",
|
SETUP_DIR / "iss_license.txt",
|
||||||
SETUP_DIR / "windows" / "novelWriter.ico",
|
SETUP_DIR / "windows" / "novelWriter.ico",
|
||||||
SETUP_DIR / "windows" / "novelWriter.exe",
|
SETUP_DIR / "windows" / "novelWriter.exe",
|
||||||
@@ -85,7 +84,7 @@ def installRequirements(libDir: Path) -> None:
|
|||||||
"""Install dependencies."""
|
"""Install dependencies."""
|
||||||
print("Install dependencies ...")
|
print("Install dependencies ...")
|
||||||
systemCall([
|
systemCall([
|
||||||
sys.executable, "-m", "pip", "install", "-r", "requirements.txt", "--target", libDir
|
sys.executable, "-m", "pip", "install", *extractReqs(["app"]), "--target", libDir
|
||||||
])
|
])
|
||||||
print("Done")
|
print("Done")
|
||||||
print("")
|
print("")
|
||||||
|
|||||||
+21
-3
@@ -23,6 +23,7 @@ from __future__ import annotations
|
|||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
import tomllib
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
@@ -30,6 +31,18 @@ ROOT_DIR = Path(__file__).parent.parent
|
|||||||
SETUP_DIR = ROOT_DIR / "setup"
|
SETUP_DIR = ROOT_DIR / "setup"
|
||||||
|
|
||||||
|
|
||||||
|
def extractReqs(groups: list[str]) -> list[str]:
|
||||||
|
"""Extract dependency groups from pyproject.toml."""
|
||||||
|
data = tomllib.loads((ROOT_DIR / "pyproject.toml").read_text(encoding="utf-8"))
|
||||||
|
reqs = []
|
||||||
|
if "app" in groups or "all" in groups:
|
||||||
|
reqs += data["project"]["dependencies"]
|
||||||
|
for group in data["dependency-groups"]:
|
||||||
|
if group in groups or "all" in groups:
|
||||||
|
reqs += [d for d in data["dependency-groups"][group] if isinstance(d, str)]
|
||||||
|
return reqs
|
||||||
|
|
||||||
|
|
||||||
def extractVersion(beQuiet: bool = False) -> tuple[str, str, str]:
|
def extractVersion(beQuiet: bool = False) -> tuple[str, str, str]:
|
||||||
"""Extract the novelWriter version number without having to import
|
"""Extract the novelWriter version number without having to import
|
||||||
anything else from the main package.
|
anything else from the main package.
|
||||||
@@ -92,14 +105,19 @@ def copySourceCode(dst: Path) -> None:
|
|||||||
|
|
||||||
def copyPackageFiles(dst: Path, oldLicense: bool = False) -> None:
|
def copyPackageFiles(dst: Path, oldLicense: bool = False) -> None:
|
||||||
"""Copy files needed for packaging."""
|
"""Copy files needed for packaging."""
|
||||||
copyFiles = ["LICENSE.md", "setup/LICENSE-Apache-2.0.txt", "CREDITS.md", "pyproject.toml"]
|
copyFiles = [
|
||||||
|
ROOT_DIR / "LICENSE.md",
|
||||||
|
SETUP_DIR / "LICENSE-Apache-2.0.txt",
|
||||||
|
ROOT_DIR / "CREDITS.md",
|
||||||
|
ROOT_DIR / "pyproject.toml",
|
||||||
|
]
|
||||||
for copyFile in copyFiles:
|
for copyFile in copyFiles:
|
||||||
shutil.copyfile(copyFile, dst / copyFile)
|
shutil.copyfile(copyFile, dst / copyFile.name)
|
||||||
print("Copied:", copyFile, flush=True)
|
print("Copied:", copyFile, flush=True)
|
||||||
|
|
||||||
writeFile(dst / "MANIFEST.in", (
|
writeFile(dst / "MANIFEST.in", (
|
||||||
"include LICENSE.md\n"
|
"include LICENSE.md\n"
|
||||||
"include setup/LICENSE-Apache-2.0.txt\n"
|
"include LICENSE-Apache-2.0.txt\n"
|
||||||
"include CREDITS.md\n"
|
"include CREDITS.md\n"
|
||||||
"recursive-include novelwriter/assets *\n"
|
"recursive-include novelwriter/assets *\n"
|
||||||
))
|
))
|
||||||
|
|||||||
Reference in New Issue
Block a user