Skip to content

Commit

Permalink
Propagate return code of subprocess calls (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
AttilaGombosER authored Aug 4, 2024
1 parent fc05fa2 commit 1a61903
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 186 deletions.
40 changes: 34 additions & 6 deletions python/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,37 @@ Packaging scripts to create installable packages from Python projects.

## Overview

The main entry point is `pack_python` script. It is calling the packaging-specific scripts and passing arguments to them.
The main entry point is `pack_python` script.
It is calling the packaging-specific scripts and passing arguments to them.
Also parses the configuration from the target project's `setup.cfg` file if there is any.

## Requirements

### python

```bash
$ sudo apt-get install python3 python3-pip
```

### wheel

```bash
$ pip install wheel
```

### fpm

```bash
$ sudo apt-get install ruby ruby-dev rubygems build-essential
$ sudo gem install -N fpm
```

### dh-virtualenv

```bash
sudo apt-get install debhelper devscripts equivs dh-virtualenv dh-python python3-virtualenv python3-all python3-stdeb
```

## Configuration

The configuration is read from the `setup.cfg` file in the target project's root directory by default.
Expand Down Expand Up @@ -78,19 +106,19 @@ $ ./pack_python tests/test-project --scripts "wheel fpm-deb"
/home/attilagombos/EffectiveRange/packaging-tools/python/tests/test-project/dist/python3-test-project_1.0.0_all.deb
```

## Scripts
## Packaging scripts

- `wheel` - Create binary wheel package
- `fpm-deb` - Create debian .deb package using [FPM](https://fpm.readthedocs.io/en/latest/index.html)
- `dh-virtualenv` - Create debian .deb package using [dh-virtualenv](https://dh-virtualenv.readthedocs.io/en/latest/)
and [stdeb](https://github.com/astraw/stdeb)
and [stdeb](https://github.com/astraw/stdeb)

### wheel

The `wheel` script is using the `bdist_wheel` setuptools command to create a binary wheel package.

```bash
$ scripts/wheel --help
$ wheel --help
usage: wheel [-h] [-p PYTHON_BIN] [-o OUTPUT_DIR] workspace_dir

positional arguments:
Expand All @@ -109,7 +137,7 @@ options:
The `fpm-deb` script is using the `fpm` to create a debian .deb package.

```bash
$ scripts/fpm-deb --help
$ fpm-deb --help
usage: fpm-deb [-h] [-a ARGUMENTS] [-p PYTHON_BIN] [-o OUTPUT_DIR] workspace_dir

positional arguments:
Expand All @@ -131,7 +159,7 @@ The `dh-virtualenv` script is using `stdeb` and `dh-virtualenv` to create a debi
with all Python dependecies pre-installed in a virtual environment.

```bash
$ scripts/dh-virtualenv --help
$ dh-virtualenv --help
usage: dh-virtualenv [-h] [-a ARGUMENTS] [-p PYTHON_BIN] [-s SERVICE_FILE] [-e EXTRA_FILES] [-o OUTPUT_DIR] workspace_dir

positional arguments:
Expand Down
3 changes: 2 additions & 1 deletion python/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def run_command(workspace_dir: str, command: Union[str, list[str]], matcher: str
first_match_only: bool = True) -> Generator[str, None, None]:
command_line = command if isinstance(command, str) else ' '.join(command)

print(f'Running command "{command_line}"', file=sys.stderr)
print(f"Running command '{command_line}' with output matcher {matcher}", file=sys.stderr)

with Popen(command_line, cwd=workspace_dir, shell=True, text=True, stdout=PIPE, stderr=PIPE) as process:
pattern = re.compile(matcher)
Expand All @@ -42,6 +42,7 @@ def run_command(workspace_dir: str, command: Union[str, list[str]], matcher: str
return_code = process.poll()

if return_code:
print(f"Command '{command_line}' failed with return code {return_code}", file=sys.stderr)
exit(return_code)

for line in output:
Expand Down
71 changes: 25 additions & 46 deletions python/dh-virtualenv
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,12 @@
# SPDX-License-Identifier: MIT

import glob
import os
from posixpath import dirname
import re
import shutil
import sys
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter, Namespace
from os.path import abspath
from pathlib import Path
from typing import Generator

sys.path.insert(0, dirname(abspath(__file__)))

from common import check_workspace, run_command, get_absolute_path


Expand All @@ -27,55 +21,48 @@ def main() -> None:

check_workspace(workspace_dir)

output_dir = f"{workspace_dir}/dist"
output_dir = f'{workspace_dir}/dist'

if arguments.output_dir:
output_dir = abspath(arguments.output_dir)

results = _create_sources(arguments, workspace_dir, output_dir)

build_dir = f"{output_dir}/{next(results)}"
build_dir = f'{output_dir}/{next(results)}'

results = _build_package(arguments, workspace_dir, build_dir)

for result in results:
print(f"{output_dir}/{result}")
print(f'{output_dir}/{result}')


def _create_sources(
arguments: Namespace, workspace_dir: str, output_dir: str
) -> Generator[str, None, None]:
def _create_sources(arguments: Namespace, workspace_dir: str, output_dir: str) -> Generator[str, None, None]:
package_name = _extract_package_name(workspace_dir)

command_arguments = [
"--package3",
package_name,
"--dist-dir",
output_dir,
"--with-dh-virtualenv",
"--compat",
"10",
'--package3', package_name,
'--dist-dir', output_dir,
'--with-dh-virtualenv',
'--compat', '10',
]

if arguments.arguments:
command_arguments.extend(arguments.arguments.split())

if arguments.service_file:
command_arguments.append("--with-dh-systemd")
command_arguments.append('--with-dh-systemd')

command = [
arguments.python_bin,
"setup.py",
"--command-packages=stdeb.command",
"sdist_dsc",
*command_arguments,
arguments.python_bin, 'setup.py',
'--command-packages=stdeb.command',
'sdist_dsc', *command_arguments,
]

return run_command(workspace_dir, command, r"copying setup.py -> (.+)")
return run_command(workspace_dir, command, r'copying setup.py -> (.+)')


def _extract_package_name(workspace_dir: str) -> str:
with open(f"{workspace_dir}/setup.py", "r") as file:
with open(f'{workspace_dir}/setup.py', 'r') as file:
setup_code = file.read()

pattern = r'name\s*=\s*[\'"]([^\'"]+)[\'"]'
Expand All @@ -85,13 +72,11 @@ def _extract_package_name(workspace_dir: str) -> str:
if match:
return match.group(1)
else:
return workspace_dir.split("/")[-1]
return workspace_dir.split('/')[-1]


def _build_package(
arguments: Namespace, workspace_dir: str, build_dir: str
) -> Generator[str, None, None]:
debian_dir = f"{build_dir}/debian"
def _build_package(arguments: Namespace, workspace_dir: str, build_dir: str) -> Generator[str, None, None]:
debian_dir = f'{build_dir}/debian'

if arguments.service_file:
service_file = get_absolute_path(arguments.service_file, workspace_dir)
Expand All @@ -103,27 +88,21 @@ def _build_package(
for file in glob.glob(extra_files):
shutil.copy(file, debian_dir)

command = ["dpkg-buildpackage", "-us", "-uc", "-ui", "-b"]
command = ['dpkg-buildpackage', '-us', '-uc', '-ui', '-b']

return run_command(build_dir, command, r".*'\.\./(.+\.deb)'")


def _get_arguments() -> Namespace:
parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
parser.add_argument("-a", "--arguments", help="extra arguments passed to stdeb")
parser.add_argument(
"-p", "--python-bin", help="python executable to use", default="python3"
)
parser.add_argument("-s", "--service-file", help="service unit file path")
parser.add_argument(
"-e", "--extra-files", help="add extra files into debian folder before build"
)
parser.add_argument("-o", "--output-dir", help="package output directory")
parser.add_argument(
"workspace_dir", help="workspace directory where setup.py is located"
)
parser.add_argument('-a', '--arguments', help='extra arguments passed to stdeb')
parser.add_argument('-p', '--python-bin', help='python executable to use', default='python3')
parser.add_argument('-s', '--service-file', help='service unit file path')
parser.add_argument('-e', '--extra-files', help='add extra files into debian folder before build')
parser.add_argument('-o', '--output-dir', help='package output directory')
parser.add_argument('workspace_dir', help='workspace directory where setup.py is located')
return parser.parse_args()


if __name__ == "__main__":
if __name__ == '__main__':
main()
42 changes: 14 additions & 28 deletions python/fpm-deb
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,8 @@
# SPDX-License-Identifier: MIT

import os
from os.path import dirname
import sys
from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter, Namespace
from os.path import abspath
from pathlib import Path

sys.path.insert(0, dirname(abspath(__file__)))

from common import check_workspace, run_command, get_absolute_path

Expand All @@ -24,31 +19,26 @@ def main() -> None:
check_workspace(workspace_dir)

fpm_arguments = [
"-s",
"python",
"-t",
"deb",
"--python-bin",
arguments.python_bin,
"--python-package-name-prefix",
"python3",
"--log",
"error",
"-f",
'-s', 'python',
'-t', 'deb',
'--python-bin', arguments.python_bin,
'--python-package-name-prefix', 'python3',
'--log', 'error',
'-f',
]

if arguments.arguments:
fpm_arguments.extend(arguments.arguments.split())

output_dir = f"{workspace_dir}/dist"
output_dir = f'{workspace_dir}/dist'

if arguments.output_dir:
output_dir = abspath(arguments.output_dir)

os.makedirs(output_dir, exist_ok=True)
fpm_arguments.extend(["--package", output_dir])
fpm_arguments.extend(['--package', output_dir])

command = ["fpm", *fpm_arguments, "setup.py"]
command = ['fpm', *fpm_arguments, 'setup.py']

results = run_command(workspace_dir, command, r'.*"(.+\.deb)"')

Expand All @@ -59,16 +49,12 @@ def main() -> None:

def _get_arguments() -> Namespace:
parser = ArgumentParser(formatter_class=ArgumentDefaultsHelpFormatter)
parser.add_argument("-a", "--arguments", help="extra arguments passed to fpm")
parser.add_argument(
"-p", "--python-bin", help="python executable to use", default="python3"
)
parser.add_argument("-o", "--output-dir", help="package output directory")
parser.add_argument(
"workspace_dir", help="workspace directory where setup.py is located"
)
parser.add_argument('-a', '--arguments', help='extra arguments passed to fpm')
parser.add_argument('-p', '--python-bin', help='python executable to use', default='python3')
parser.add_argument('-o', '--output-dir', help='package output directory')
parser.add_argument('workspace_dir', help='workspace directory where setup.py is located')
return parser.parse_args()


if __name__ == "__main__":
if __name__ == '__main__':
main()
Loading

0 comments on commit 1a61903

Please sign in to comment.