dotslash 0.5.8__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.
- dotslash-0.5.8/.gemini/config.yaml +6 -0
- dotslash-0.5.8/.gitattributes +2 -0
- dotslash-0.5.8/.github/workflows/build.yml +112 -0
- dotslash-0.5.8/.github/workflows/test.yml +34 -0
- dotslash-0.5.8/.gitignore +2 -0
- dotslash-0.5.8/PKG-INFO +61 -0
- dotslash-0.5.8/README.md +59 -0
- dotslash-0.5.8/hatch_build.py +152 -0
- dotslash-0.5.8/pyproject.toml +61 -0
- dotslash-0.5.8/ruff.toml +11 -0
- dotslash-0.5.8/src/dotslash/__init__.py +36 -0
- dotslash-0.5.8/src/dotslash/__main__.py +16 -0
- dotslash-0.5.8/src/dotslash/_locate.py +39 -0
- dotslash-0.5.8/src/dotslash/py.typed +0 -0
@@ -0,0 +1,112 @@
|
|
1
|
+
name: build
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
tags:
|
6
|
+
- v*
|
7
|
+
branches:
|
8
|
+
- main
|
9
|
+
pull_request:
|
10
|
+
branches:
|
11
|
+
- main
|
12
|
+
|
13
|
+
concurrency:
|
14
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
|
15
|
+
cancel-in-progress: true
|
16
|
+
|
17
|
+
defaults:
|
18
|
+
run:
|
19
|
+
shell: bash
|
20
|
+
|
21
|
+
jobs:
|
22
|
+
sdist:
|
23
|
+
name: Build source distribution
|
24
|
+
runs-on: ubuntu-latest
|
25
|
+
|
26
|
+
outputs:
|
27
|
+
dotslash-version: ${{ steps.dotslash-version.outputs.dotslash-version }}
|
28
|
+
|
29
|
+
steps:
|
30
|
+
- uses: actions/checkout@v5
|
31
|
+
|
32
|
+
- name: Set DotSlash version
|
33
|
+
id: dotslash-version
|
34
|
+
run: |-
|
35
|
+
dotslash_version=$(gh api repos/facebook/dotslash/releases/latest --jq '.tag_name')
|
36
|
+
echo "dotslash-version=${dotslash_version}" >> $GITHUB_OUTPUT
|
37
|
+
env:
|
38
|
+
GH_TOKEN: ${{ github.token }}
|
39
|
+
|
40
|
+
- name: Install uv
|
41
|
+
uses: astral-sh/setup-uv@v6
|
42
|
+
|
43
|
+
- name: Build source distribution
|
44
|
+
run: uv build --sdist
|
45
|
+
env:
|
46
|
+
DOTSLASH_VERSION: ${{ steps.dotslash-version.outputs.dotslash-version }}
|
47
|
+
|
48
|
+
- uses: actions/upload-artifact@v4
|
49
|
+
with:
|
50
|
+
name: artifact-sdist
|
51
|
+
path: dist/*
|
52
|
+
if-no-files-found: error
|
53
|
+
|
54
|
+
wheels:
|
55
|
+
name: Build wheels on ${{ matrix.os }}
|
56
|
+
needs:
|
57
|
+
- sdist
|
58
|
+
runs-on: ${{ matrix.os }}
|
59
|
+
strategy:
|
60
|
+
fail-fast: false
|
61
|
+
matrix:
|
62
|
+
include:
|
63
|
+
- os: ubuntu-24.04-arm
|
64
|
+
archs: aarch64
|
65
|
+
- os: ubuntu-latest
|
66
|
+
archs: x86_64
|
67
|
+
- os: macos-latest
|
68
|
+
archs: arm64
|
69
|
+
- os: macos-15-intel
|
70
|
+
archs: x86_64
|
71
|
+
- os: windows-11-arm
|
72
|
+
archs: ARM64
|
73
|
+
- os: windows-latest
|
74
|
+
archs: AMD64
|
75
|
+
|
76
|
+
steps:
|
77
|
+
- uses: actions/checkout@v5
|
78
|
+
|
79
|
+
- name: Build wheels
|
80
|
+
uses: pypa/cibuildwheel@v3.2.1
|
81
|
+
env:
|
82
|
+
DOTSLASH_VERSION: ${{ needs.sdist.outputs.dotslash-version }}
|
83
|
+
CIBW_ARCHS: ${{ matrix.archs }}
|
84
|
+
|
85
|
+
- uses: actions/upload-artifact@v4
|
86
|
+
with:
|
87
|
+
name: artifact-wheels-${{ matrix.os }}-${{ matrix.archs }}
|
88
|
+
path: wheelhouse/*.whl
|
89
|
+
if-no-files-found: error
|
90
|
+
|
91
|
+
publish:
|
92
|
+
name: Publish release
|
93
|
+
needs:
|
94
|
+
- sdist
|
95
|
+
- wheels
|
96
|
+
runs-on: ubuntu-latest
|
97
|
+
if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags')
|
98
|
+
|
99
|
+
permissions:
|
100
|
+
id-token: write
|
101
|
+
|
102
|
+
steps:
|
103
|
+
- uses: actions/download-artifact@v4
|
104
|
+
with:
|
105
|
+
pattern: artifact-*
|
106
|
+
merge-multiple: true
|
107
|
+
path: dist
|
108
|
+
|
109
|
+
- name: Push build artifacts to PyPI
|
110
|
+
uses: pypa/gh-action-pypi-publish@v1.13.0
|
111
|
+
with:
|
112
|
+
skip-existing: true
|
@@ -0,0 +1,34 @@
|
|
1
|
+
name: test
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- main
|
7
|
+
pull_request:
|
8
|
+
branches:
|
9
|
+
- main
|
10
|
+
|
11
|
+
concurrency:
|
12
|
+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
|
13
|
+
cancel-in-progress: true
|
14
|
+
|
15
|
+
defaults:
|
16
|
+
run:
|
17
|
+
shell: bash
|
18
|
+
|
19
|
+
jobs:
|
20
|
+
test:
|
21
|
+
name: Test
|
22
|
+
runs-on: ubuntu-latest
|
23
|
+
|
24
|
+
steps:
|
25
|
+
- uses: actions/checkout@v5
|
26
|
+
|
27
|
+
- name: Install uv
|
28
|
+
uses: astral-sh/setup-uv@v6
|
29
|
+
|
30
|
+
- name: Static analysis
|
31
|
+
run: uvx ruff check ./src
|
32
|
+
|
33
|
+
- name: Formatting
|
34
|
+
run: uvx ruff format --check --diff ./src
|
dotslash-0.5.8/PKG-INFO
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: dotslash
|
3
|
+
Version: 0.5.8
|
4
|
+
Summary: Command-line tool to facilitate fetching an executable, caching it, and then running it.
|
5
|
+
Project-URL: Homepage, https://dotslash-cli.com
|
6
|
+
Project-URL: Tracker, https://github.com/facebook/dotslash/issues
|
7
|
+
Project-URL: Source, https://github.com/facebook/dotslash
|
8
|
+
Author-email: Ofek Lev <oss@ofek.dev>
|
9
|
+
License-Expression: MIT OR Apache-2.0
|
10
|
+
Keywords: dotslash
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
12
|
+
Classifier: Intended Audience :: Developers
|
13
|
+
Classifier: Natural Language :: English
|
14
|
+
Classifier: Operating System :: OS Independent
|
15
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
16
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
17
|
+
Requires-Python: >=3.10
|
18
|
+
Description-Content-Type: text/markdown
|
19
|
+
|
20
|
+
# DotSlash: simplified executable deployment
|
21
|
+
|
22
|
+
[](https://github.com/ofek/dotslash/actions/workflows/build.yml)
|
23
|
+
[](https://github.com/ofek/dotslash/actions/workflows/test.yml)
|
24
|
+
[](https://pypi.org/project/dotslash/)
|
25
|
+
[](https://pypi.org/project/dotslash/)
|
26
|
+
[](https://github.com/pypa/hatch)
|
27
|
+
[](https://github.com/astral-sh/ruff)
|
28
|
+
|
29
|
+
-----
|
30
|
+
|
31
|
+
[DotSlash](https://dotslash-cli.com/docs/) (`dotslash`) is a command-line tool that lets you represent a set of platform-specific, heavyweight executables with an equivalent small, easy-to-read text file. In turn, this makes it efficient to store executables in source control without hurting repository size. This paves the way for checking build toolchains and other tools directly into the repo, reducing dependencies on the host environment and thereby facilitating reproducible builds.
|
32
|
+
|
33
|
+
The `dotslash` package allows you to use DotSlash in your Python projects without having to install DotSlash globally.
|
34
|
+
|
35
|
+
***Table of Contents***
|
36
|
+
|
37
|
+
- [Using as a library](#using-as-a-library)
|
38
|
+
- [Using as a command-line tool](#using-as-a-command-line-tool)
|
39
|
+
- [License](#license)
|
40
|
+
|
41
|
+
## Using as a library
|
42
|
+
|
43
|
+
The `dotslash.locate` function returns the path to the DotSlash binary that was installed by this package.
|
44
|
+
|
45
|
+
```pycon
|
46
|
+
>>> import dotslash
|
47
|
+
>>> dotslash.locate()
|
48
|
+
'/root/.local/bin/dotslash'
|
49
|
+
```
|
50
|
+
|
51
|
+
## Using as a command-line tool
|
52
|
+
|
53
|
+
The installed DotSlash binary can be invoked directly by running the `dotslash` module as a script.
|
54
|
+
|
55
|
+
```
|
56
|
+
python -m dotslash path/to/dotslash-file.json
|
57
|
+
```
|
58
|
+
|
59
|
+
## License
|
60
|
+
|
61
|
+
DotSlash is licensed under both the MIT license and Apache-2.0 license; the exact terms can be found in the [LICENSE-MIT]() and LICENSE-APACHE files, respectively.
|
dotslash-0.5.8/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# DotSlash: simplified executable deployment
|
2
|
+
|
3
|
+
[](https://github.com/ofek/dotslash/actions/workflows/build.yml)
|
4
|
+
[](https://github.com/ofek/dotslash/actions/workflows/test.yml)
|
5
|
+
[](https://pypi.org/project/dotslash/)
|
6
|
+
[](https://pypi.org/project/dotslash/)
|
7
|
+
[](https://github.com/pypa/hatch)
|
8
|
+
[](https://github.com/astral-sh/ruff)
|
9
|
+
|
10
|
+
-----
|
11
|
+
|
12
|
+
[DotSlash](https://dotslash-cli.com/docs/) (`dotslash`) is a command-line tool that lets you represent a set of platform-specific, heavyweight executables with an equivalent small, easy-to-read text file. In turn, this makes it efficient to store executables in source control without hurting repository size. This paves the way for checking build toolchains and other tools directly into the repo, reducing dependencies on the host environment and thereby facilitating reproducible builds.
|
13
|
+
|
14
|
+
The `dotslash` package allows you to use DotSlash in your Python projects without having to install DotSlash globally.
|
15
|
+
|
16
|
+
***Table of Contents***
|
17
|
+
|
18
|
+
- [Using as a library](#using-as-a-library)
|
19
|
+
- [Using as a command-line tool](#using-as-a-command-line-tool)
|
20
|
+
- [Building from source](#building-from-source)
|
21
|
+
- [License](#license)
|
22
|
+
|
23
|
+
## Using as a library
|
24
|
+
|
25
|
+
The `dotslash.locate` function returns the path to the DotSlash binary that was installed by this package.
|
26
|
+
|
27
|
+
```pycon
|
28
|
+
>>> import dotslash
|
29
|
+
>>> dotslash.locate()
|
30
|
+
'/root/.local/bin/dotslash'
|
31
|
+
```
|
32
|
+
|
33
|
+
## Using as a command-line tool
|
34
|
+
|
35
|
+
The installed DotSlash binary can be invoked directly by running the `dotslash` module as a script.
|
36
|
+
|
37
|
+
```
|
38
|
+
python -m dotslash path/to/dotslash-file.json
|
39
|
+
```
|
40
|
+
|
41
|
+
## Building from source
|
42
|
+
|
43
|
+
When building or installing from this directory, the `DOTSLASH_VERSION` environment variable must be set to the version of DotSlash to use. A preceding `v` is accepted but not required.
|
44
|
+
|
45
|
+
```
|
46
|
+
DOTSLASH_VERSION=0.5.8 python -m build
|
47
|
+
```
|
48
|
+
|
49
|
+
This will use the binaries from DotSlash's [GitHub releases](https://github.com/facebook/dotslash/releases). If there is a directory of GitHub release assets, you can use that directly with the `DOTSLASH_SOURCE` environment variable.
|
50
|
+
|
51
|
+
```
|
52
|
+
DOTSLASH_VERSION=0.5.8 DOTSLASH_SOURCE=path/to/dotslash-assets python -m build
|
53
|
+
```
|
54
|
+
|
55
|
+
The DotSlash source is set to `release` by default.
|
56
|
+
|
57
|
+
## License
|
58
|
+
|
59
|
+
DotSlash is licensed under both the MIT license and Apache-2.0 license; the exact terms can be found in the [LICENSE-MIT]() and LICENSE-APACHE files, respectively.
|
@@ -0,0 +1,152 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import os
|
4
|
+
import sys
|
5
|
+
from contextlib import contextmanager
|
6
|
+
from functools import cached_property
|
7
|
+
from platform import machine
|
8
|
+
from typing import TYPE_CHECKING, Any, BinaryIO
|
9
|
+
|
10
|
+
from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
11
|
+
|
12
|
+
if TYPE_CHECKING:
|
13
|
+
from collections.abc import Generator
|
14
|
+
|
15
|
+
|
16
|
+
class CustomBuildHook(BuildHookInterface):
|
17
|
+
def initialize(self, version: str, build_data: dict[str, Any]) -> None: # noqa: ARG002
|
18
|
+
if self.__source == "release":
|
19
|
+
asset = self.__release_asset
|
20
|
+
elif os.path.isdir(self.__source):
|
21
|
+
asset = self.__local_asset
|
22
|
+
elif not os.path.isabs(self.__source) and os.path.isfile(os.path.join(self.root, "PKG-INFO")):
|
23
|
+
msg = (
|
24
|
+
"The current directory has a `PKG-INFO` file, which likely means that the wheel is being "
|
25
|
+
"built from an unpacked source distribution. You must do one of the following:\n"
|
26
|
+
"- Set the source to an absolute rather than relative path.\n"
|
27
|
+
"- Build the wheel separately e.g. run `python -m build --wheel` rather than just `python -m build`.\n"
|
28
|
+
"- Set the source to `release`."
|
29
|
+
)
|
30
|
+
raise ValueError(msg)
|
31
|
+
else:
|
32
|
+
msg = "Source must be `release` or an absolute path to a directory containing release assets"
|
33
|
+
raise ValueError(msg)
|
34
|
+
|
35
|
+
import tarfile
|
36
|
+
|
37
|
+
with asset() as reader, tarfile.open(fileobj=reader, mode="r:gz") as tf:
|
38
|
+
tf.extractall(self.__temp_dir)
|
39
|
+
|
40
|
+
if not os.path.isfile(self.__binary_path):
|
41
|
+
msg = f"Binary not found: {self.__binary_path}"
|
42
|
+
raise RuntimeError(msg)
|
43
|
+
|
44
|
+
build_data["shared_scripts"][self.__binary_path] = self.__binary_name
|
45
|
+
build_data["tag"] = f"py3-none-{self.__wheel_arch}"
|
46
|
+
|
47
|
+
def finalize(self, version: str, build_data: dict[str, Any], artifact: str) -> None: # noqa: ARG002
|
48
|
+
import shutil
|
49
|
+
|
50
|
+
shutil.rmtree(self.__temp_dir)
|
51
|
+
|
52
|
+
@contextmanager
|
53
|
+
def __release_asset(self) -> Generator[BinaryIO, None, None]:
|
54
|
+
from urllib.request import HTTPError, urlopen
|
55
|
+
|
56
|
+
tag = f"v{self.metadata.version.removeprefix('v')}"
|
57
|
+
url = f"https://github.com/facebook/dotslash/releases/download/{tag}/{self.__asset_name}"
|
58
|
+
|
59
|
+
try:
|
60
|
+
with urlopen(url) as response:
|
61
|
+
yield response
|
62
|
+
except HTTPError as e:
|
63
|
+
e.msg += f"\nURL: {url}"
|
64
|
+
raise
|
65
|
+
|
66
|
+
@contextmanager
|
67
|
+
def __local_asset(self) -> Generator[BinaryIO, None, None]:
|
68
|
+
asset_path = os.path.join(self.__source, self.__asset_name)
|
69
|
+
if not os.path.isfile(asset_path):
|
70
|
+
msg = f"Asset not found: {asset_path}"
|
71
|
+
raise RuntimeError(msg)
|
72
|
+
|
73
|
+
with open(asset_path, "rb") as f:
|
74
|
+
yield f
|
75
|
+
|
76
|
+
@cached_property
|
77
|
+
def __platform(self) -> str:
|
78
|
+
match sys.platform:
|
79
|
+
case "win32":
|
80
|
+
return "windows"
|
81
|
+
case "darwin":
|
82
|
+
return "macos"
|
83
|
+
case "linux":
|
84
|
+
return "linux"
|
85
|
+
case _:
|
86
|
+
msg = f"Unsupported platform: {sys.platform}"
|
87
|
+
raise ValueError(msg)
|
88
|
+
|
89
|
+
@cached_property
|
90
|
+
def __arch(self) -> str:
|
91
|
+
return machine().lower()
|
92
|
+
|
93
|
+
@cached_property
|
94
|
+
def __target_data(self) -> tuple[str, str]:
|
95
|
+
match self.__platform, self.__arch:
|
96
|
+
case "linux", "aarch64":
|
97
|
+
return "dotslash-linux-musl.aarch64.tar.gz", self.__get_linux_wheel_arch()
|
98
|
+
case "linux", "x86_64":
|
99
|
+
return "dotslash-linux-musl.x86_64.tar.gz", self.__get_linux_wheel_arch()
|
100
|
+
case "windows", "arm64":
|
101
|
+
return "dotslash-windows-arm64.tar.gz", "win_arm64"
|
102
|
+
case "windows", "amd64":
|
103
|
+
return "dotslash-windows.tar.gz", "win_amd64"
|
104
|
+
case "macos", "arm64":
|
105
|
+
return "dotslash-macos-arm64.tar.gz", "macosx_11_0_arm64"
|
106
|
+
case "macos", "x86_64":
|
107
|
+
return "dotslash-macos-x86_64.tar.gz", "macosx_10_12_x86_64"
|
108
|
+
case _:
|
109
|
+
msg = f"Unsupported platform/arch pair: {self.__platform} {self.__arch}"
|
110
|
+
raise ValueError(msg)
|
111
|
+
|
112
|
+
@cached_property
|
113
|
+
def __asset_name(self) -> str:
|
114
|
+
return self.__target_data[0]
|
115
|
+
|
116
|
+
@cached_property
|
117
|
+
def __wheel_arch(self) -> str:
|
118
|
+
return self.__target_data[1]
|
119
|
+
|
120
|
+
@cached_property
|
121
|
+
def __source(self) -> str:
|
122
|
+
return os.environ.get("DOTSLASH_SOURCE") or self.config.get("source") or "release"
|
123
|
+
|
124
|
+
@cached_property
|
125
|
+
def __temp_dir(self) -> str:
|
126
|
+
import tempfile
|
127
|
+
|
128
|
+
return tempfile.mkdtemp()
|
129
|
+
|
130
|
+
@cached_property
|
131
|
+
def __binary_name(self) -> str:
|
132
|
+
return "dotslash.exe" if self.__platform == "windows" else "dotslash"
|
133
|
+
|
134
|
+
@cached_property
|
135
|
+
def __binary_path(self) -> str:
|
136
|
+
return os.path.join(self.__temp_dir, self.__binary_name)
|
137
|
+
|
138
|
+
def __get_linux_wheel_arch(self) -> str:
|
139
|
+
default_arch = f"musllinux_1_1_{self.__arch}"
|
140
|
+
|
141
|
+
if not (hasattr(os, "confstr") and "CS_GNU_LIBC_VERSION" in os.confstr_names):
|
142
|
+
return default_arch
|
143
|
+
|
144
|
+
try:
|
145
|
+
value = os.confstr("CS_GNU_LIBC_VERSION")
|
146
|
+
except (OSError, ValueError):
|
147
|
+
pass
|
148
|
+
else:
|
149
|
+
if value and value.startswith("glibc"):
|
150
|
+
return f"manylinux_2_28_{self.__arch}"
|
151
|
+
|
152
|
+
return default_arch
|
@@ -0,0 +1,61 @@
|
|
1
|
+
[build-system]
|
2
|
+
build-backend = "hatchling.build"
|
3
|
+
requires = ["hatchling>=1.27.0", "hatch-fancy-pypi-readme"]
|
4
|
+
|
5
|
+
[project]
|
6
|
+
name = "dotslash"
|
7
|
+
dynamic = ["readme", "version"]
|
8
|
+
authors = [
|
9
|
+
{ name = "Ofek Lev", email = "oss@ofek.dev" },
|
10
|
+
]
|
11
|
+
description = "Command-line tool to facilitate fetching an executable, caching it, and then running it."
|
12
|
+
keywords = [
|
13
|
+
"dotslash",
|
14
|
+
]
|
15
|
+
license = "MIT OR Apache-2.0"
|
16
|
+
requires-python = ">=3.10"
|
17
|
+
classifiers = [
|
18
|
+
"Development Status :: 5 - Production/Stable",
|
19
|
+
"Intended Audience :: Developers",
|
20
|
+
"Natural Language :: English",
|
21
|
+
"Operating System :: OS Independent",
|
22
|
+
"Programming Language :: Python :: Implementation :: CPython",
|
23
|
+
"Programming Language :: Python :: Implementation :: PyPy",
|
24
|
+
]
|
25
|
+
|
26
|
+
[project.urls]
|
27
|
+
Homepage = "https://dotslash-cli.com"
|
28
|
+
Tracker = "https://github.com/facebook/dotslash/issues"
|
29
|
+
Source = "https://github.com/facebook/dotslash"
|
30
|
+
|
31
|
+
[tool.hatch.version]
|
32
|
+
source = "env"
|
33
|
+
variable = "DOTSLASH_VERSION"
|
34
|
+
|
35
|
+
[tool.hatch.metadata.hooks.fancy-pypi-readme]
|
36
|
+
content-type = "text/markdown"
|
37
|
+
|
38
|
+
[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
|
39
|
+
path = "README.md"
|
40
|
+
end-before = "## Building from source"
|
41
|
+
|
42
|
+
[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
|
43
|
+
path = "README.md"
|
44
|
+
start-at = "## License"
|
45
|
+
|
46
|
+
[[tool.hatch.metadata.hooks.fancy-pypi-readme.substitutions]]
|
47
|
+
pattern = "(?m)^- \\[Building from source.+$\\s+-"
|
48
|
+
replacement = "-"
|
49
|
+
|
50
|
+
[tool.hatch.build.targets.wheel.hooks.custom]
|
51
|
+
|
52
|
+
[tool.cibuildwheel]
|
53
|
+
enable = ["pypy"]
|
54
|
+
test-command = "python -m dotslash -- cache-dir"
|
55
|
+
# Only build on one version of Python since all distributions of a given platform/arch pair are the same
|
56
|
+
build = "cp314-*"
|
57
|
+
# Disable wheel repair since it's not necessary
|
58
|
+
repair-wheel-command = ""
|
59
|
+
|
60
|
+
[tool.cibuildwheel.linux]
|
61
|
+
environment-pass = ["DOTSLASH_SOURCE", "DOTSLASH_VERSION"]
|
dotslash-0.5.8/ruff.toml
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
|
4
|
+
def locate() -> str:
|
5
|
+
"""
|
6
|
+
Returns:
|
7
|
+
The path to the DotSlash binary that was installed by this package.
|
8
|
+
"""
|
9
|
+
import os
|
10
|
+
import sys
|
11
|
+
import sysconfig
|
12
|
+
|
13
|
+
from dotslash._locate import _search_paths
|
14
|
+
|
15
|
+
if extension := sysconfig.get_config_var("EXE"):
|
16
|
+
binary_name = f"dotslash{extension}"
|
17
|
+
elif sys.platform == "win32":
|
18
|
+
binary_name = "dotslash.exe"
|
19
|
+
else:
|
20
|
+
binary_name = "dotslash"
|
21
|
+
|
22
|
+
# Map of normalized paths to the actual path
|
23
|
+
seen_paths: dict[str, str] = {}
|
24
|
+
for search_path in _search_paths():
|
25
|
+
normalized_path = os.path.normcase(search_path)
|
26
|
+
if normalized_path in seen_paths:
|
27
|
+
continue
|
28
|
+
|
29
|
+
seen_paths[normalized_path] = search_path
|
30
|
+
binary_path = os.path.join(search_path, binary_name)
|
31
|
+
if os.path.isfile(binary_path):
|
32
|
+
return binary_path
|
33
|
+
|
34
|
+
search_paths = "\n".join(f"- {search_path}" for search_path in seen_paths.values())
|
35
|
+
msg = f"The `{binary_name}` binary was not found in any of the following paths:\n{search_paths}"
|
36
|
+
raise FileNotFoundError(msg)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
if __name__ == "__main__":
|
2
|
+
import sys
|
3
|
+
|
4
|
+
from dotslash import locate
|
5
|
+
|
6
|
+
dotslash = locate()
|
7
|
+
|
8
|
+
if sys.platform == "win32":
|
9
|
+
import subprocess
|
10
|
+
|
11
|
+
process = subprocess.run([dotslash, *sys.argv[1:]])
|
12
|
+
sys.exit(process.returncode)
|
13
|
+
else:
|
14
|
+
import os
|
15
|
+
|
16
|
+
os.execvp(dotslash, [dotslash, *sys.argv[1:]])
|
@@ -0,0 +1,39 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import os
|
4
|
+
import sys
|
5
|
+
import sysconfig
|
6
|
+
|
7
|
+
|
8
|
+
def _search_paths():
|
9
|
+
# The scripts directory for the current Python installation
|
10
|
+
yield sysconfig.get_path("scripts")
|
11
|
+
|
12
|
+
# The scripts directory for the base prefix if in a virtual environment
|
13
|
+
yield sysconfig.get_path("scripts", vars={"base": sys.base_prefix, "platbase": sys.base_exec_prefix})
|
14
|
+
|
15
|
+
module_dir = os.path.dirname(os.path.abspath(__file__))
|
16
|
+
package_parent, package_name = os.path.split(module_dir)
|
17
|
+
if package_name == "dotslash":
|
18
|
+
# Above the package root e.g. when running `pip install --prefix` or `uv run --with`
|
19
|
+
# Windows: <prefix>\Lib\site-packages\dotslash
|
20
|
+
# macOS: <prefix>/lib/pythonX.Y/site-packages/dotslash
|
21
|
+
# Linux:
|
22
|
+
# <prefix>/lib/pythonX.Y/site-packages/dotslash
|
23
|
+
# <prefix>/lib/pythonX.Y/dist-packages/dotslash (Debian-based distributions)
|
24
|
+
head, tail = os.path.split(package_parent)
|
25
|
+
if tail.endswith("-packages"):
|
26
|
+
head, tail = os.path.split(head)
|
27
|
+
if sys.platform == "win32":
|
28
|
+
if tail == "Lib":
|
29
|
+
yield os.path.join(head, "Scripts")
|
30
|
+
elif tail.startswith("python"):
|
31
|
+
head, tail = os.path.split(head)
|
32
|
+
if tail == sys.platlibdir:
|
33
|
+
yield os.path.join(head, "bin")
|
34
|
+
else:
|
35
|
+
# Adjacent to the package root e.g. when using the `--target` option of pip-like installers
|
36
|
+
yield os.path.join(package_parent, "bin")
|
37
|
+
|
38
|
+
# The scripts directory for user installations
|
39
|
+
yield sysconfig.get_path("scripts", scheme=sysconfig.get_preferred_scheme("user"))
|
File without changes
|