pyallel 2.0.4__tar.gz → 2.0.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. pyallel-2.0.5/.base_branch +1 -0
  2. pyallel-2.0.5/.github/workflows/build.yml +43 -0
  3. pyallel-2.0.5/.github/workflows/test.yml +49 -0
  4. pyallel-2.0.5/.gitignore +160 -0
  5. pyallel-2.0.5/.vim/project.shada +0 -0
  6. pyallel-2.0.5/Dockerfile +25 -0
  7. pyallel-2.0.5/Dockerfile.alpine +46 -0
  8. {pyallel-2.0.4 → pyallel-2.0.5}/PKG-INFO +11 -20
  9. {pyallel-2.0.4 → pyallel-2.0.5}/README.md +4 -4
  10. pyallel-2.0.5/benchmark_process.py +68 -0
  11. pyallel-2.0.5/bin/ldd +13 -0
  12. pyallel-2.0.5/bin/pyinstaller.sh +9 -0
  13. pyallel-2.0.5/build.sh +36 -0
  14. pyallel-2.0.5/build_all.sh +27 -0
  15. pyallel-2.0.5/pyproject.toml +48 -0
  16. {pyallel-2.0.4 → pyallel-2.0.5}/src/pyallel/process.py +39 -14
  17. pyallel-2.0.5/tests/assets/test_handle_multiple_signals.sh +7 -0
  18. pyallel-2.0.5/tests/assets/test_output.sh +21 -0
  19. pyallel-2.0.5/tests/test_main.py +505 -0
  20. pyallel-2.0.5/tests/test_printer.py +302 -0
  21. pyallel-2.0.5/tests/test_process.py +101 -0
  22. pyallel-2.0.5/tests/test_process_group.py +120 -0
  23. pyallel-2.0.5/tests/test_process_manager.py +197 -0
  24. pyallel-2.0.5/uv.lock +364 -0
  25. pyallel-2.0.4/pyproject.toml +0 -38
  26. {pyallel-2.0.4 → pyallel-2.0.5}/LICENSE +0 -0
  27. {pyallel-2.0.4 → pyallel-2.0.5}/src/pyallel/__init__.py +0 -0
  28. {pyallel-2.0.4 → pyallel-2.0.5}/src/pyallel/colours.py +0 -0
  29. {pyallel-2.0.4 → pyallel-2.0.5}/src/pyallel/constants.py +0 -0
  30. {pyallel-2.0.4 → pyallel-2.0.5}/src/pyallel/errors.py +0 -0
  31. {pyallel-2.0.4 → pyallel-2.0.5}/src/pyallel/main.py +0 -0
  32. {pyallel-2.0.4 → pyallel-2.0.5}/src/pyallel/parser.py +0 -0
  33. {pyallel-2.0.4 → pyallel-2.0.5}/src/pyallel/printer.py +0 -0
  34. {pyallel-2.0.4 → pyallel-2.0.5}/src/pyallel/process_group.py +0 -0
  35. {pyallel-2.0.4 → pyallel-2.0.5}/src/pyallel/process_group_manager.py +0 -0
  36. {pyallel-2.0.4 → pyallel-2.0.5}/src/pyallel/py.typed +0 -0
@@ -0,0 +1 @@
1
+ main
@@ -0,0 +1,43 @@
1
+ name: Build
2
+
3
+ on:
4
+ - workflow_dispatch
5
+
6
+ jobs:
7
+ build:
8
+ runs-on: ${{ matrix.os }}
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ os:
13
+ - ubuntu-latest
14
+ - macos-latest
15
+
16
+ steps:
17
+ - name: Checkout
18
+ uses: actions/checkout@v3
19
+
20
+ - name: 📦 Install uv
21
+ run: |
22
+ pipx install uv
23
+
24
+ - name: Setup Python
25
+ uses: actions/setup-python@v4
26
+ with:
27
+ python-version: 3.12
28
+ cache: 'pip'
29
+
30
+ - name: Install dependencies
31
+ run: uv sync
32
+
33
+ - name: Run pyinstaller
34
+ run: |
35
+ source .venv/bin/activate && \
36
+ ./build.sh
37
+
38
+ - name: Upload artifacts
39
+ uses: actions/upload-artifact@v4
40
+ if: ${{ always() }}
41
+ with:
42
+ name: ${{ runner.os }} Build
43
+ path: dist/*
@@ -0,0 +1,49 @@
1
+ name: Test
2
+
3
+ on:
4
+ - pull_request
5
+ - workflow_dispatch
6
+
7
+ jobs:
8
+ tests:
9
+ name: ${{ matrix.os.name }} ${{ matrix.python }}
10
+ runs-on: ${{ matrix.os.runs-on }}
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ python:
15
+ - "3.8"
16
+ - "3.9"
17
+ - "3.10"
18
+ - "3.11"
19
+ - "3.12"
20
+ - "3.13"
21
+ os:
22
+ - name: Linux
23
+ matrix: linux
24
+ runs-on: [ubuntu-latest]
25
+ - name: macOS
26
+ matrix: macos
27
+ runs-on: [macos-latest]
28
+
29
+ steps:
30
+ - name: Checkout
31
+ uses: actions/checkout@v4
32
+
33
+ - name: 📦 Install uv
34
+ run: |
35
+ pipx install uv
36
+
37
+ - name: Set up Python ${{ matrix.python }}
38
+ uses: actions/setup-python@v5
39
+ with:
40
+ python-version: ${{ matrix.python }}
41
+ cache: 'pip'
42
+
43
+ - name: Install dependencies
44
+ run: uv sync
45
+
46
+ - name: Run pyallel
47
+ run: |
48
+ source .venv/bin/activate && \
49
+ pyallel --colour yes -- MYPY_FORCE_COLOR=1 mypy . :: pytest --color=yes -s .
@@ -0,0 +1,160 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.py,cover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Translations
55
+ *.mo
56
+ *.pot
57
+
58
+ # Django stuff:
59
+ *.log
60
+ local_settings.py
61
+ db.sqlite3
62
+ db.sqlite3-journal
63
+
64
+ # Flask stuff:
65
+ instance/
66
+ .webassets-cache
67
+
68
+ # Scrapy stuff:
69
+ .scrapy
70
+
71
+ # Sphinx documentation
72
+ docs/_build/
73
+
74
+ # PyBuilder
75
+ .pybuilder/
76
+ target/
77
+
78
+ # Jupyter Notebook
79
+ .ipynb_checkpoints
80
+
81
+ # IPython
82
+ profile_default/
83
+ ipython_config.py
84
+
85
+ # pyenv
86
+ # For a library or package, you might want to ignore these files since the code is
87
+ # intended to run in multiple environments; otherwise, check them in:
88
+ # .python-version
89
+
90
+ # pipenv
91
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
92
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
93
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
94
+ # install all needed dependencies.
95
+ #Pipfile.lock
96
+
97
+ # poetry
98
+ # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
99
+ # This is especially recommended for binary packages to ensure reproducibility, and is more
100
+ # commonly ignored for libraries.
101
+ # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
102
+ #poetry.lock
103
+
104
+ # pdm
105
+ # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
106
+ #pdm.lock
107
+ # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
108
+ # in version control.
109
+ # https://pdm.fming.dev/#use-with-ide
110
+ .pdm.toml
111
+
112
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
113
+ __pypackages__/
114
+
115
+ # Celery stuff
116
+ celerybeat-schedule
117
+ celerybeat.pid
118
+
119
+ # SageMath parsed files
120
+ *.sage.py
121
+
122
+ # Environments
123
+ .env
124
+ .venv
125
+ env/
126
+ venv/
127
+ ENV/
128
+ env.bak/
129
+ venv.bak/
130
+
131
+ # Spyder project settings
132
+ .spyderproject
133
+ .spyproject
134
+
135
+ # Rope project settings
136
+ .ropeproject
137
+
138
+ # mkdocs documentation
139
+ /site
140
+
141
+ # mypy
142
+ .mypy_cache/
143
+ .dmypy.json
144
+ dmypy.json
145
+
146
+ # Pyre type checker
147
+ .pyre/
148
+
149
+ # pytype static type analyzer
150
+ .pytype/
151
+
152
+ # Cython debug symbols
153
+ cython_debug/
154
+
155
+ # PyCharm
156
+ # JetBrains specific template is maintained in a separate JetBrains.gitignore that can
157
+ # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
158
+ # and can be added to the global gitignore or merged into this file. For a more nuclear
159
+ # option (not recommended) you can uncomment the following to ignore the entire idea folder.
160
+ #.idea/
Binary file
@@ -0,0 +1,25 @@
1
+ ARG arch
2
+ FROM --platform=linux/${arch} python:3.13-bullseye
3
+
4
+ ARG uid=
5
+ ARG gid=
6
+
7
+ VOLUME /src
8
+ WORKDIR /src
9
+
10
+ # Setup a build user
11
+ RUN addgroup --system build --gid 1000 && adduser --system build --uid ${uid} --gid 1000
12
+
13
+ COPY src src
14
+ COPY pyproject.toml pyproject.toml
15
+ COPY README.md README.md
16
+
17
+ # Also install pyallel so we can copy it's metadata when running pyinstaller
18
+ RUN pip install . --group dev
19
+
20
+ # Switch to the build user before running the build scripts
21
+ USER build
22
+
23
+ ENV arch ${arch}
24
+ CMD [ "./build.sh", "linux" ]
25
+
@@ -0,0 +1,46 @@
1
+ ARG arch
2
+ FROM --platform=linux/${arch} python:3.13-alpine
3
+
4
+ ARG uid=
5
+ ARG gid=
6
+
7
+ # Official Python base image is needed or some applications will segfault.
8
+ # PyInstaller needs zlib-dev, gcc, libc-dev, and musl-dev
9
+ RUN apk --update --no-cache add \
10
+ zlib-dev \
11
+ musl-dev \
12
+ libc-dev \
13
+ libffi-dev \
14
+ gcc \
15
+ g++ \
16
+ git \
17
+ && pip install --upgrade pip
18
+
19
+ # Build bootloader for alpine
20
+ RUN git clone --depth 1 --single-branch --branch v6.11.0 https://github.com/pyinstaller/pyinstaller.git /tmp/pyinstaller \
21
+ && cd /tmp/pyinstaller/bootloader \
22
+ && CFLAGS="-Wno-stringop-overflow -Wno-stringop-truncation" python ./waf configure all \
23
+ && pip install .. \
24
+ && rm -Rf /tmp/pyinstaller
25
+
26
+ VOLUME /src
27
+ WORKDIR /src
28
+
29
+ # Setup a build user
30
+ RUN addgroup -g 1000 build && adduser -S -u ${uid} build -G build
31
+
32
+ COPY src .
33
+ COPY pyproject.toml .
34
+ COPY README.md .
35
+
36
+ RUN pip install . --group dev
37
+
38
+ ADD ./bin /pyinstaller
39
+ RUN chmod a+x /pyinstaller/*
40
+
41
+ # Switch to the build user before running the build scripts
42
+ USER build
43
+
44
+ # ENV arch ${arch}
45
+ CMD [ "/pyinstaller/pyinstaller.sh" ]
46
+
@@ -1,27 +1,19 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyallel
3
- Version: 2.0.4
3
+ Version: 2.0.5
4
4
  Summary: Run and handle the output of multiple executables in pyallel (as in parallel)
5
- License: MIT
5
+ Project-URL: Homepage, https://github.com/Danthewaann/pyallel
6
+ Project-URL: Repository, https://github.com/Danthewaann/pyallel
7
+ Author-email: Daniel Black <danielcrblack@gmail.com>
8
+ License-Expression: MIT
6
9
  License-File: LICENSE
7
- Keywords: parallel,command,runner,executable,shell,terminal
8
- Author: Daniel Black
9
- Author-email: danielcrblack@gmail.com
10
- Requires-Python: >=3.8
10
+ Keywords: command,executable,parallel,runner,shell,terminal
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: License :: OSI Approved :: MIT License
13
13
  Classifier: Operating System :: MacOS :: MacOS X
14
14
  Classifier: Operating System :: POSIX :: Linux
15
15
  Classifier: Programming Language :: Python :: 3
16
- Classifier: Programming Language :: Python :: 3.8
17
- Classifier: Programming Language :: Python :: 3.9
18
- Classifier: Programming Language :: Python :: 3.10
19
- Classifier: Programming Language :: Python :: 3.11
20
- Classifier: Programming Language :: Python :: 3.12
21
- Classifier: Programming Language :: Python :: 3.13
22
- Classifier: Programming Language :: Python :: 3.14
23
- Project-URL: Homepage, https://github.com/Danthewaann/pyallel
24
- Project-URL: Repository, https://github.com/Danthewaann/pyallel
16
+ Requires-Python: >=3.8
25
17
  Description-Content-Type: text/markdown
26
18
 
27
19
  # Pyallel
@@ -36,10 +28,10 @@ Tested on Linux and MacOS only
36
28
 
37
29
  Pre-built executables are available on the [Releases](https://github.com/Danthewaann/pyallel/releases) page.
38
30
 
39
- `pyallel` can also be installed using pip (requires Python >=3.8):
31
+ `pyallel` can also be installed using pipx (requires Python >=3.8):
40
32
 
41
33
  ```bash
42
- pip install pyallel
34
+ pipx install pyallel
43
35
  ```
44
36
 
45
37
  # Quick start
@@ -148,9 +140,9 @@ docker build --tag pyallel-alpine --build-arg 'arch=x86_64' --build-arg "uid=$(i
148
140
  #### Build locally
149
141
 
150
142
  ```bash
151
- python -m venv .venv && \
143
+ pipx install uv && \
144
+ uv sync && \
152
145
  source .venv/bin/activate && \
153
- pip install . -r requirements_build.txt && \
154
146
  ./build.sh
155
147
  ```
156
148
 
@@ -174,4 +166,3 @@ python -m venv .venv && \
174
166
  - [ ] Allow list of files to be provided to supply as input arguments to each command
175
167
  - [ ] Allow input to be piped into `pyallel` via stdin to supply as standard input to each
176
168
  command
177
-
@@ -10,10 +10,10 @@ Tested on Linux and MacOS only
10
10
 
11
11
  Pre-built executables are available on the [Releases](https://github.com/Danthewaann/pyallel/releases) page.
12
12
 
13
- `pyallel` can also be installed using pip (requires Python >=3.8):
13
+ `pyallel` can also be installed using pipx (requires Python >=3.8):
14
14
 
15
15
  ```bash
16
- pip install pyallel
16
+ pipx install pyallel
17
17
  ```
18
18
 
19
19
  # Quick start
@@ -122,9 +122,9 @@ docker build --tag pyallel-alpine --build-arg 'arch=x86_64' --build-arg "uid=$(i
122
122
  #### Build locally
123
123
 
124
124
  ```bash
125
- python -m venv .venv && \
125
+ pipx install uv && \
126
+ uv sync && \
126
127
  source .venv/bin/activate && \
127
- pip install . -r requirements_build.txt && \
128
128
  ./build.sh
129
129
  ```
130
130
 
@@ -0,0 +1,68 @@
1
+ """
2
+ Ad-hoc benchmark comparing Process's stdout reading approach against two
3
+ scenarios:
4
+
5
+ 1. A chatty command that produces a lot of output while it's running.
6
+ 2. A quick command that exits almost immediately, followed by a period of
7
+ idle polling (simulating other still-running commands in the same group).
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import resource
13
+ import sys
14
+ import time
15
+
16
+ sys.path.insert(0, "src")
17
+
18
+ from pyallel.process import Process
19
+
20
+ CHATTY_CMD = "python3 -c \"[print('line', i) for i in range(200000)]\""
21
+ QUICK_CMD = "echo hi"
22
+
23
+
24
+ def cpu_time() -> float:
25
+ usage = resource.getrusage(resource.RUSAGE_SELF)
26
+ return usage.ru_utime + usage.ru_stime
27
+
28
+
29
+ def run_scenario(
30
+ name: str, command: str, poll_seconds: float, extra_idle_seconds: float
31
+ ) -> None:
32
+ process = Process(1, command)
33
+
34
+ start_wall = time.perf_counter()
35
+ start_cpu = cpu_time()
36
+
37
+ process.run()
38
+
39
+ total_bytes = 0
40
+ while process.poll() is None:
41
+ time.sleep(poll_seconds)
42
+ total_bytes += len(process.read())
43
+
44
+ idle_deadline = time.perf_counter() + extra_idle_seconds
45
+ while time.perf_counter() < idle_deadline:
46
+ time.sleep(poll_seconds)
47
+ total_bytes += len(process.read())
48
+
49
+ end_wall = time.perf_counter()
50
+ end_cpu = cpu_time()
51
+
52
+ print(
53
+ f"{name:12} wall={end_wall - start_wall:6.3f}s "
54
+ f"cpu={end_cpu - start_cpu:6.3f}s bytes={total_bytes}"
55
+ )
56
+
57
+
58
+ def main() -> None:
59
+ print("--- scenario: chatty command, output while it's still running ---")
60
+ run_scenario("chatty", CHATTY_CMD, poll_seconds=0.1, extra_idle_seconds=0.0)
61
+
62
+ print()
63
+ print("--- scenario: quick command, then 2s of idle polling ---")
64
+ run_scenario("quick+idle", QUICK_CMD, poll_seconds=0.1, extra_idle_seconds=2.0)
65
+
66
+
67
+ if __name__ == "__main__":
68
+ main()
pyallel-2.0.5/bin/ldd ADDED
@@ -0,0 +1,13 @@
1
+ #!/bin/sh
2
+
3
+ # From http://wiki.musl-libc.org/wiki/FAQ#Q:_where_is_ldd_.3F
4
+ #
5
+ # Musl's dynlinker comes with ldd functionality built in. just create a
6
+ # symlink from ld-musl-$ARCH.so to /bin/ldd. If the dynlinker was started
7
+ # as "ldd", it will detect that and print the appropriate DSO information.
8
+ #
9
+ # Instead, this string replaced "ldd" with the package so that pyinstaller
10
+ # can find the actual lib.
11
+ exec /usr/bin/ldd "$@" | \
12
+ sed -r 's/([^[:space:]]+) => ldd/\1 => \/lib\/\1/g' | \
13
+ sed -r 's/ldd \(.*\)//g'
@@ -0,0 +1,9 @@
1
+ #!/bin/sh
2
+ # Simple wrapper around pyinstaller
3
+
4
+ set -e
5
+
6
+ # Use the hacked ldd to fix libc.musl-x86_64.so.1 location
7
+ PATH="/pyinstaller:$PATH"
8
+
9
+ ./build.sh alpine
pyallel-2.0.5/build.sh ADDED
@@ -0,0 +1,36 @@
1
+ #!/bin/sh
2
+
3
+ set -e
4
+
5
+ distro="${1:-$distro}"
6
+ arch="${2:-$arch}"
7
+
8
+ if [ -z "$distro" ]; then
9
+ distro=linux
10
+ fi
11
+
12
+ if [ -z "$arch" ]; then
13
+ arch=unknown
14
+ fi
15
+
16
+ name=pyallel-"$(pyallel -V)"-"$distro"-"$arch"
17
+
18
+ # --bootloader-ignore-signals is needed as two interrupt signals where getting sent
19
+ # to pyallel as it is apart of the same process group as the bootloader
20
+ # From: https://pyinstaller.org/en/stable/usage.html#cmdoption-bootloader-ignore-signals
21
+ pyinstaller \
22
+ --onefile \
23
+ --noconfirm \
24
+ --clean \
25
+ --log-level DEBUG \
26
+ --exclude-module PyInstaller \
27
+ --copy-metadata pyallel \
28
+ --bootloader-ignore-signals \
29
+ --specpath ./specs \
30
+ --name "$name" \
31
+ ./src/pyallel/main.py
32
+
33
+ printf "\nExecutable written to './dist/%s'\n" "$name"
34
+
35
+ cd dist
36
+ md5sum "$name" > "$name".md5
@@ -0,0 +1,27 @@
1
+ #!/bin/sh
2
+
3
+ rm -rf build dist specs
4
+
5
+ user_id=$(id -u)
6
+ group_id=$(id -g)
7
+ cur_dir=$(pwd)
8
+
9
+ # Local OS setup
10
+ distro=$(uname | tr '[:upper:]' '[:lower:]')
11
+ arch=$(uname -m)
12
+
13
+ if [ "$arch" = "arm64" ]; then
14
+ arch="aarch64"
15
+ elif [ "$arch" = "x86_64" ]; then
16
+ arch="x86_64"
17
+ else
18
+ arch=unknown
19
+ fi
20
+
21
+ uv sync
22
+
23
+ uv run pyallel "docker build --tag pyallel-x86_64 --build-arg 'arch=x86_64' --build-arg 'uid=$user_id' --build-arg 'gid=$group_id' . && docker run -e 'arch=x86_64' --rm --volume '$cur_dir:/src' pyallel-x86_64" :: \
24
+ "docker build --tag pyallel-aarch64 --build-arg 'arch=aarch64' --build-arg 'uid=$user_id' --build-arg 'gid=$group_id' . && docker run -e 'arch=aarch64' --rm --volume '$cur_dir:/src' pyallel-aarch64" :: \
25
+ "docker build --tag pyallel-x86_64-alpine --build-arg 'arch=x86_64' --build-arg 'uid=$user_id' --build-arg 'gid=$group_id' --file Dockerfile.alpine . && docker run -e 'arch=x86_64' --rm --volume '$cur_dir:/src' pyallel-x86_64-alpine" :: \
26
+ "docker build --tag pyallel-aarch64-alpine --build-arg 'arch=aarch64' --build-arg 'uid=$user_id' --build-arg 'gid=$group_id' --file Dockerfile.alpine . && docker run -e 'arch=aarch64' --rm --volume '$cur_dir:/src' pyallel-aarch64-alpine" :: \
27
+ "source .venv/bin/activate && ./build.sh $distro $arch"
@@ -0,0 +1,48 @@
1
+ [project]
2
+ name = "pyallel"
3
+ version = "2.0.5"
4
+ description = "Run and handle the output of multiple executables in pyallel (as in parallel)"
5
+ authors = [{ name = "Daniel Black", email = "danielcrblack@gmail.com" }]
6
+ requires-python = ">=3.8"
7
+ readme = "README.md"
8
+ license = "MIT"
9
+ keywords = [
10
+ "parallel",
11
+ "command",
12
+ "runner",
13
+ "executable",
14
+ "shell",
15
+ "terminal",
16
+ ]
17
+ classifiers = [
18
+ "Development Status :: 5 - Production/Stable",
19
+ "Programming Language :: Python :: 3",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Operating System :: MacOS :: MacOS X",
22
+ "Operating System :: POSIX :: Linux",
23
+ ]
24
+
25
+ [project.urls]
26
+ Homepage = "https://github.com/Danthewaann/pyallel"
27
+ Repository = "https://github.com/Danthewaann/pyallel"
28
+
29
+ [project.scripts]
30
+ pyallel = "pyallel.main:entry_point"
31
+
32
+ [dependency-groups]
33
+ dev = [
34
+ "pytest>=7.4.3,<8",
35
+ "mypy>=1.7.0,<2",
36
+ "pyinstaller==6.11.0",
37
+ ]
38
+
39
+ [build-system]
40
+ requires = ["hatchling"]
41
+ build-backend = "hatchling.build"
42
+
43
+ [tool.mypy]
44
+ strict = true
45
+ show_error_codes = true
46
+
47
+ [tool.pytest.ini_options]
48
+ addopts = "-vvv"