Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Hörist <philipp@hoerist.com>2022-12-30 16:01:15 +0300
committerPhilipp Hörist <philipp@hoerist.com>2023-01-28 14:53:14 +0300
commit76c32a5d44d7bd197ccbc9e5a6955ff2e4022066 (patch)
tree4744438e15f409cf54f97c2a91c162342427fb2d
parent4c57bd71c6665803be2c61445c90fa2295dd993a (diff)
new: Add custom PEP517 build backend
-rw-r--r--MANIFEST.in3
-rw-r--r--README.md80
-rw-r--r--pep517build/__init__.py0
-rw-r--r--pep517build/backend.py89
-rwxr-xr-xpep517build/build_metadata.py85
-rwxr-xr-xpep517build/install_metadata.py43
-rw-r--r--pyproject.toml17
-rwxr-xr-xsetup.py194
8 files changed, 289 insertions, 222 deletions
diff --git a/MANIFEST.in b/MANIFEST.in
index 91460f387..b5c91eebc 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,4 +1,7 @@
include COPYING
+include ChangeLog
+recursive-include pep517build *
recursive-include po *
recursive-include data *.1 *.in
recursive-include test *
+prune */__pycache__
diff --git a/README.md b/README.md
index f3fe21bd6..75d5137de 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,6 @@
-# Welcome to Gajim
+[[_TOC_]]
+
+## Requirements
### Runtime Requirements
@@ -39,19 +41,67 @@
- [gst-plugins-ugly](https://gitlab.freedesktop.org/gstreamer/gst-plugins-ugly)
- [gst-libav](https://gitlab.freedesktop.org/gstreamer/gst-libav)
-### Install Requirements
+### Build Requirements
- [setuptools](https://pypi.org/project/setuptools/) (>=65.0.0)
- [gettext](https://savannah.gnu.org/projects/gettext/)
-### Running Tests
+To build Gajim a PEP517 build frontend like pip (https://pip.pypa.io/en/stable/) or build (https://pypa-build.readthedocs.io/en/stable/) must be used.
+
+The build frontend takes care of installing all python build requirements. Beware `gettext` is not a python library and cannot be installed by the build frontend.
+
+## Building
+
+### Building the metadata files (Unix only)
+
+```bash
+./pep517build/build_metadata.py -o dist/metadata
+```
+
+### Building the wheel
+
+This is only necessary if you need the wheel, otherwise you can skip to the Installing section.
+
+#### Using `build`
+
+```bash
+python -m build -w
+```
+
+#### Using `pip`
+
+```bash
+pip wheel --no-deps --use-pep517 -w dist .
+```
+
+## Installing
+
+### Installing with `pip`
+
+```bash
+pip install .
+```
+
+### Installing the wheel
+
+```bash
+pip install dist/name_of_wheel.whl
+```
+
+### Installing the metadata files (Unix only)
+
+```bash
+./pep517build/install_metadata.py dist/metadata --prefix=/usr
+```
+
+## Tests
- `python -m unittest discover -s test`
- `python -m unittest ./test/dialogs/gui_file.py` (for testing GUI files)
-### Installation Procedure
+## Packages and install instructions
-#### Packages
+### Packages
- [Arch Linux](https://www.archlinux.org/packages/community/any/gajim/)
- [Debian](https://packages.debian.org/stable/gajim)
@@ -59,24 +109,20 @@
- [Ubuntu](https://packages.ubuntu.com/gajim)
- [FreeBSD](https://www.freshports.org/net-im/gajim/)
-#### Flatpak
+### Flatpak
see [README](./flatpak/README.md)
-#### Snapshots
+### Snapshots
- [Daily Linux](https://www.gajim.org/downloads/snap/)
- [Daily Windows](https://gajim.org/downloads/snap/win)
-#### Linux
-
- pip install .
-
-#### Mac
+### Mac
see [Wiki](https://dev.gajim.org/gajim/gajim/-/wikis/help/Gajim-on-macOS)
-#### Developing
+## Developing
To create a virtualenv you can execute
@@ -89,17 +135,17 @@ Afterwards activate the virtual environment with
source .venv/bin/activate
./launch.py
-#### Windows
+### Windows
see [README](./win/README.md)
-### Miscellaneous
+## Miscellaneous
-#### Debugging
+### Debugging
Execute gajim with `--verbose`
-#### Links
+### Links
- [FAQ](https://dev.gajim.org/gajim/gajim/wikis/help/gajimfaq)
- [Wiki](https://dev.gajim.org/gajim/gajim/wikis/home)
diff --git a/pep517build/__init__.py b/pep517build/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/pep517build/__init__.py
diff --git a/pep517build/backend.py b/pep517build/backend.py
new file mode 100644
index 000000000..1592ccb57
--- /dev/null
+++ b/pep517build/backend.py
@@ -0,0 +1,89 @@
+from __future__ import annotations
+
+from typing import Any
+
+import logging
+import subprocess
+from pathlib import Path
+
+import setuptools.build_meta as _orig
+
+logging.basicConfig(level='INFO', format='%(message)s')
+
+ALLOWED_CONFIG_SETTINGS = {'target'}
+MAN_FILES = [
+ Path('data/gajim.1'),
+ Path('data/gajim-remote.1')
+]
+META_FILES = [
+ (Path('data/org.gajim.Gajim.desktop.in'), '--desktop'),
+ (Path('data/org.gajim.Gajim.appdata.xml.in'), '--xml')
+]
+ICONS = [
+ Path('gajim/data/icons/hicolor/scalable/apps/org.gajim.Gajim.svg'),
+ Path('gajim/data/icons/hicolor/scalable/apps/org.gajim.Gajim-symbolic.svg'),
+]
+
+
+def build_translations() -> None:
+ # Compile translation files and place them into "gajim/data/locale"
+
+ source_dir = Path.cwd()
+ translation_dir = source_dir / 'po'
+ locale_dir = source_dir / 'gajim' / 'data' / 'locale'
+
+ langs = sorted([lang.stem for lang in translation_dir.glob('*.po')])
+
+ for lang in langs:
+ po_file = source_dir / 'po' / f'{lang}.po'
+ mo_file = locale_dir / lang / 'LC_MESSAGES' / 'gajim.mo'
+ mo_file.parent.mkdir(parents=True, exist_ok=True)
+
+ logging.info('Compile %s >> %s', po_file, mo_file)
+
+ subprocess.run(['msgfmt',
+ str(po_file),
+ '-o',
+ str(mo_file)],
+ check=True)
+
+
+def _check_config_settings(config_settings: dict[str, str]) -> None:
+ settings = set(config_settings.keys()) - ALLOWED_CONFIG_SETTINGS
+ if settings:
+ raise ValueError('Unknown config setting %s' % settings)
+
+
+def get_requires_for_build_sdist(*args: Any, **kwargs: Any) -> str:
+ return _orig.get_requires_for_build_sdist(*args, **kwargs)
+
+
+def build_sdist(*args: Any, **kwargs: Any) -> str:
+ return _orig.build_sdist(*args, **kwargs)
+
+
+def get_requires_for_build_wheel(*args: Any, **kwargs: Any) -> str:
+ return _orig.get_requires_for_build_wheel(*args, **kwargs)
+
+
+def prepare_metadata_for_build_wheel(*args: Any, **kwargs: Any) -> str:
+ return _orig.prepare_metadata_for_build_wheel(*args, **kwargs)
+
+
+def build_wheel(wheel_directory: str,
+ config_settings: dict[str, str] | None = None,
+ metadata_directory: str | None = None
+ ) -> str:
+
+ if config_settings is not None:
+ _check_config_settings(config_settings)
+
+ build_translations()
+
+ basename = _orig.build_wheel(
+ wheel_directory,
+ config_settings=config_settings,
+ metadata_directory=metadata_directory,
+ )
+
+ return basename
diff --git a/pep517build/build_metadata.py b/pep517build/build_metadata.py
new file mode 100755
index 000000000..7e7d53f4b
--- /dev/null
+++ b/pep517build/build_metadata.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python3
+
+from __future__ import annotations
+
+import argparse
+import gzip
+import logging
+import shutil
+import subprocess
+from pathlib import Path
+
+logging.basicConfig(level='INFO', format='%(message)s')
+
+DEFAULT_METADATA_PATH = Path('dist/metadata')
+
+MAN_FILES = [
+ Path('data/gajim.1'),
+ Path('data/gajim-remote.1')
+]
+META_FILES = [
+ (Path('data/org.gajim.Gajim.desktop.in'), '--desktop'),
+ (Path('data/org.gajim.Gajim.appdata.xml.in'), '--xml')
+]
+ICONS = [
+ Path('gajim/data/icons/hicolor/scalable/apps/org.gajim.Gajim.svg'),
+ Path('gajim/data/icons/hicolor/scalable/apps/org.gajim.Gajim-symbolic.svg'),
+]
+
+
+def build_man(target_path: Path) -> None:
+ # Build man files in target path
+
+ for man_path in MAN_FILES:
+ data = man_path.read_bytes()
+ man_file_name = man_path.name
+
+ man_out_path = target_path / f'{man_file_name}.gz'
+ logging.info('Compress %s >> %s', man_file_name, man_out_path)
+
+ with gzip.open(man_out_path, 'wb') as f_out:
+ f_out.write(data)
+
+
+
+def build_intl(target_path: Path) -> None:
+ # Merge translation files into desktop and metadata files
+
+ for file_path, option in META_FILES:
+ out_path = target_path / file_path.name
+ out_path = out_path.with_suffix('')
+
+ logging.info('Compile %s >> %s', file_path, out_path)
+
+ subprocess.run(['msgfmt',
+ option,
+ '-d',
+ 'po',
+ '--template',
+ str(file_path),
+ '-o',
+ str(out_path)],
+ check=True)
+
+
+def build_app_icons(target_path: Path) -> None:
+ for file_path in ICONS:
+ out_path = target_path / file_path.name
+
+ logging.info('Copy %s >> %s', file_path, out_path)
+ shutil.copy2(file_path, out_path)
+
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description='Build metadata files')
+ parser.add_argument('-o',
+ '--output-dir',
+ type=Path,
+ default=DEFAULT_METADATA_PATH)
+ args = parser.parse_args()
+
+ args.output_dir.mkdir(parents=True, exist_ok=True)
+
+ build_man(args.output_dir)
+ build_intl(args.output_dir)
+ build_app_icons(args.output_dir)
diff --git a/pep517build/install_metadata.py b/pep517build/install_metadata.py
new file mode 100755
index 000000000..17a5a2104
--- /dev/null
+++ b/pep517build/install_metadata.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+
+from __future__ import annotations
+
+import argparse
+import logging
+import shutil
+from pathlib import Path
+
+logging.basicConfig(level='INFO', format='%(message)s')
+
+DEFAULT_METADATA_PATH = Path('dist/metadata')
+
+FILES = {
+ 'gajim-remote.1.gz': 'share/man/man1',
+ 'gajim.1.gz': 'share/man/man1',
+ 'org.gajim.Gajim.desktop': 'share/applications',
+ 'org.gajim.Gajim-symbolic.svg': 'share/icons/hicolor/scalable/apps',
+ 'org.gajim.Gajim.svg': 'share/icons/hicolor/scalable/apps',
+ 'org.gajim.Gajim.appdata.xml': 'share/metainfo',
+}
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description='Install metadata files')
+ parser.add_argument('input',
+ type=Path,
+ default=DEFAULT_METADATA_PATH,
+ help='Path to the metadata folder, '
+ 'default: dist/metadata')
+ parser.add_argument('--prefix',
+ type=Path,
+ required=True,
+ help='The path prefix, for example "/usr"')
+
+ args = parser.parse_args()
+
+ for file, path in FILES.items():
+ src = args.input / file
+ dest_dir = args.prefix / path
+ logging.info('Copy %s to %s', src, dest_dir)
+ if not dest_dir.exists():
+ dest_dir.mkdir(parents=True)
+ shutil.copy(src, dest_dir / file)
diff --git a/pyproject.toml b/pyproject.toml
index 09daf3287..1b1dfebb1 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -2,7 +2,8 @@
requires = [
"setuptools >= 65.0.0",
]
-build-backend = "setuptools.build_meta"
+build-backend = "backend"
+backend-path = ["pep517build"]
[project]
name = "gajim"
@@ -56,25 +57,18 @@ gajim-remote = "gajim.gajim_remote:main"
[project.gui-scripts]
gajim = "gajim.gajim:main"
-[tool.setuptools]
-include-package-data = true
-
[tool.setuptools.packages.find]
include = ["gajim*"]
-# Necessary so gajim.data is recogniced as namespace package and all files
-# under it are included as package-data
-namespaces = true
[tool.setuptools.package-data]
-"gajim.data" = [
- "icons/**/index.theme",
-]
+gajim = ["py.typed"]
+"gajim.data" = ["**/*"]
[tool.setuptools.dynamic]
version = {attr = "gajim.__version__"}
[tool.codespell]
-skip = "*__pycache__*,build,test,*.egg-info,.git,*.po,*.nsi,*.spec"
+skip = "*__pycache__*,build,dist,test,*.egg-info,.git,*.po,*.nsi,*.spec"
ignore-words-list = "claus,pres,ser,trough"
[tool.pyright]
@@ -113,6 +107,7 @@ include = [
"mac/*",
"scripts/*",
"win/*",
+ "pep517build/*",
"gajim/common/application.py",
"gajim/common/call_manager.py",
"gajim/common/cert_store.py",
diff --git a/setup.py b/setup.py
deleted file mode 100755
index 0cb78c633..000000000
--- a/setup.py
+++ /dev/null
@@ -1,194 +0,0 @@
-#!/usr/bin/env python3
-
-from __future__ import annotations
-
-from typing import cast
-
-import logging
-import os
-import sys
-
-if sys.version_info < (3, 10):
- sys.exit('Gajim needs Python 3.10+')
-
-import subprocess
-from pathlib import Path
-
-from setuptools import setup
-from setuptools.command.build_py import build_py as _build
-from setuptools.command.install import install as _install
-
-DataFilesT = list[tuple[str, list[str]]]
-
-
-MAN_FILES = [
- 'gajim.1',
- 'gajim-remote.1'
-]
-META_FILES = [
- ('data/org.gajim.Gajim.desktop', 'share/applications', '--desktop'),
- ('data/org.gajim.Gajim.appdata.xml', 'share/metainfo', '--xml')]
-
-
-TRANS_DIR = Path('po')
-TRANS_TEMPLATE = TRANS_DIR / 'gajim.pot'
-REPO_DIR = Path(__file__).resolve().parent
-BUILD_DIR = REPO_DIR / 'build'
-
-ALL_LINGUAS = sorted([lang.stem for lang in TRANS_DIR.glob('*.po')])
-
-
-logging.basicConfig(level='INFO', format='%(levelname)s: %(message)s')
-log = logging.getLogger()
-
-
-def newer(source: Path, target: Path) -> bool:
- if not source.exists():
- raise ValueError('file "%s" does not exist' % source.resolve())
- if not target.exists():
- return True
-
- from stat import ST_MTIME
- mtime1 = source.stat()[ST_MTIME]
- mtime2 = target.stat()[ST_MTIME]
-
- return mtime1 > mtime2
-
-
-def build_translation() -> None:
- for lang in ALL_LINGUAS:
- po_file = TRANS_DIR / f'{lang}.po'
- mo_file = BUILD_DIR / 'mo' / lang / 'LC_MESSAGES' / 'gajim.mo'
- mo_dir = mo_file.parent
- if not (mo_dir.is_dir() or mo_dir.is_symlink()):
- mo_dir.mkdir(parents=True)
-
- if newer(po_file, mo_file):
- subprocess.run(['msgfmt',
- str(po_file),
- '-o',
- str(mo_file)],
- cwd=REPO_DIR,
- check=True)
-
- log.info('Compiling %s >> %s', po_file, mo_file)
-
-
-def install_trans(data_files: DataFilesT) -> None:
- for lang in ALL_LINGUAS:
- mo_file = str(BUILD_DIR / 'mo' / lang / 'LC_MESSAGES' / 'gajim.mo')
- target = f'share/locale/{lang}/LC_MESSAGES'
- data_files.append((target, [mo_file]))
-
-
-def build_man() -> None:
- '''
- Compress Gajim manual files
- '''
- newdir = BUILD_DIR / 'man'
- if not (newdir.is_dir() or newdir.is_symlink()):
- newdir.mkdir()
-
- for man in MAN_FILES:
- filename = Path('data') / man
- man_file_gz = newdir / (man + '.gz')
- if man_file_gz.exists():
- if newer(filename, man_file_gz):
- man_file_gz.unlink()
- else:
- continue
-
- import gzip
-
- # Binary io, so open is OK
- with open(filename, 'rb') as f_in,\
- gzip.open(man_file_gz, 'wb') as f_out:
- f_out.writelines(f_in)
- log.info('Compiling %s >> %s', filename, man_file_gz)
-
-
-def install_man(data_files: DataFilesT) -> None:
- man_dir = BUILD_DIR / 'man'
- target = 'share/man/man1'
-
- for man in MAN_FILES:
- man_file_gz = str(man_dir / (man + '.gz'))
- data_files.append((target, [man_file_gz]))
-
-
-def build_intl() -> None:
- '''
- Merge translation files into desktop and mime files
- '''
- base = BUILD_DIR
-
- for filename, _, option in META_FILES:
- newfile = base / filename
- newdir = newfile.parent
- if not (newdir.is_dir() or newdir.is_symlink()):
- newdir.mkdir()
- merge(Path(filename + '.in'), newfile, option)
-
-
-def install_intl(data_files: DataFilesT) -> None:
- for filename, target, _ in META_FILES:
- data_files.append((target, [str(BUILD_DIR / filename)]))
-
-
-def merge(in_file: Path,
- out_file: Path,
- option: str,
- po_dir: str = 'po') -> None:
- '''
- Run the msgfmt command.
- '''
- if in_file.exists():
- cmd = (('msgfmt %(opt)s -d %(po_dir)s --template %(in_file)s '
- '-o %(out_file)s') %
- {'opt': option,
- 'po_dir': po_dir,
- 'in_file': in_file,
- 'out_file': out_file})
- if os.system(cmd) != 0:
- msg = ('ERROR: %s was not merged into the translation files!\n' %
- out_file)
- raise SystemExit(msg)
- log.info('Compiling %s >> %s', in_file, out_file)
-
-
-class Build(_build):
- def run(self):
- build_translation()
- if sys.platform != 'win32':
- build_man()
- build_intl()
- _build.run(self)
-
-
-class Install(_install):
- def run(self):
- data_files = cast(DataFilesT, self.distribution.data_files) # pyright: ignore # noqa: E501
- install_trans(data_files)
- if sys.platform != 'win32':
- install_man(data_files)
- install_intl(data_files)
- _install.run(self) # pyright: ignore
-
-
-# only install subdirectories of data
-data_files_app_icon = [
- ('share/icons/hicolor/scalable/apps',
- ['gajim/data/icons/hicolor/scalable/apps/org.gajim.Gajim.svg']),
- ('share/icons/hicolor/scalable/apps',
- ['gajim/data/icons/hicolor/scalable/apps/org.gajim.Gajim-symbolic.svg'])
-]
-
-data_files: DataFilesT = data_files_app_icon
-
-setup(
- cmdclass={
- 'build_py': Build,
- 'install': Install,
- },
- data_files=data_files
-)