python-update-checker 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.
@@ -0,0 +1,25 @@
1
+ # generated python files
2
+ __pycache__
3
+ /.pytest_cache
4
+ /.ruff_cache
5
+ /uv.lock
6
+ /.venv
7
+
8
+ # build and dist dirs
9
+ /build
10
+ /dist
11
+ /.achievements
12
+ /MANIFEST
13
+
14
+ # configuration for direnv(1)
15
+ /.envrc
16
+
17
+ # local development files
18
+ /bin
19
+ /.python-version
20
+
21
+ # todo.txt files
22
+ /todo.txt
23
+ /todo.txt.bak
24
+ /done.txt
25
+ /report.txt
@@ -0,0 +1,47 @@
1
+ target-version = "py311"
2
+
3
+ [lint]
4
+ select = [
5
+ "E", # pycodestyle
6
+ "F", # pyflakes
7
+ "B", # flake8-bugbear
8
+ "I", # isort
9
+ "D", # pydocstyle
10
+ "FIX", # fixme
11
+ "FA", # future-annotation
12
+ "LOG", # logging
13
+ "INP", # PEP420
14
+ "PIE", # flake8-pie
15
+ "RSE", # flake8-raise
16
+ "RET", # flake8-return
17
+ "PLC", # pylint convention
18
+ "PLE", # pylint error
19
+ "PLW", # pylint warning
20
+ "RUF", # ruff
21
+ "UP", # pyupgrade
22
+ "YTT", # flake8-2020
23
+ ]
24
+
25
+ # Ignored rules
26
+ ignore = [
27
+ "E501", # line-too-long
28
+ "I001", # unsorted-imports
29
+ "D205", # blank-line-after-summary
30
+ "D402", # no-signature
31
+ "D415", # ends-in-punctuation
32
+ "D417", # undocumented-param
33
+ ]
34
+
35
+
36
+ [lint.per-file-ignores]
37
+
38
+ [lint.isort]
39
+ known-first-party = []
40
+ section-order = ["future", "standard-library", "third-party", "first-party", "local-folder"]
41
+ force-sort-within-sections = false
42
+
43
+ [lint.pydocstyle]
44
+ convention = "google"
45
+
46
+ [format]
47
+ quote-style = "preserve"
@@ -0,0 +1,188 @@
1
+ # This Makefile is only used by developers.
2
+
3
+ ############# Settings ############
4
+ # use Bash as shell, not sh
5
+ SHELL := bash
6
+ # execute makefile in a single bash process instead of one per target
7
+ .ONESHELL:
8
+ # set Bash flags
9
+ .SHELLFLAGS := -eu -o pipefail -c
10
+ # remove target files if a rule fails, forces reruns of aborted rules
11
+ .DELETE_ON_ERROR:
12
+ # warn for undefined variables
13
+ MAKEFLAGS += --warn-undefined-variables
14
+ # disable builtin default rules
15
+ MAKEFLAGS += --no-builtin-rules
16
+
17
+
18
+ ############ Configuration ############
19
+ PROJECT:=$(shell egrep "name[[:space:]]*=" pyproject.toml | cut -d'"' -f2)
20
+ VERSION:=$(shell egrep "version[[:space:]]*=" pyproject.toml | cut -d'"' -f2)
21
+
22
+ # exclude packages that are newer than this
23
+ EXCLUDE_NEWER:="7 days"
24
+ # Pytest options:
25
+ # --full-trace: print full stacktrace on errors
26
+ PYTESTOPTS?=--full-trace
27
+ # which test modules to run
28
+ TESTS ?= tests/
29
+ # set test options
30
+ TESTOPTS=
31
+ # python files and directories
32
+ PY_FILES_DIRS:=\
33
+ src \
34
+ tests
35
+
36
+ # Release configuration
37
+ RELEASE_NAME:=$(subst -,_,$(PROJECT))-$(VERSION)
38
+ RELEASE_SOURCE:=$(RELEASE_NAME).tar.gz
39
+ RELEASE_WHEEL:=$(RELEASE_NAME)-py3-none-any.whl
40
+ RELEASE_BRANCH:=main
41
+ RELEASE_TAG:=$(VERSION)
42
+
43
+
44
+ ############ Default target ############
45
+
46
+ # `make help` displays all targets documented with `##`in the target line
47
+ .PHONY: help
48
+ help: ## display this help section
49
+ @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9_-]+:.*?## / {printf "\033[36m%-38s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
50
+ .DEFAULT_GOAL := help
51
+
52
+
53
+ ############ Installation and provisioning ############
54
+
55
+ .PHONY: init
56
+ init: ## install python virtual env and required development packages
57
+ uv sync
58
+
59
+
60
+ ############ Linting and syntax checks ############
61
+
62
+ .PHONY: lint
63
+ lint: lint-py lint-shell
64
+
65
+ .PHONY: lint-py
66
+ lint-py: ## lint python code
67
+ ruff check $(PY_FILES_DIRS)
68
+
69
+ .PHONY: lint-shell
70
+ lint-shell:
71
+ shellcheck -x scripts/*.sh
72
+
73
+ .PHONY: audit
74
+ audit: ## run audit checks
75
+ uv audit
76
+
77
+ .PHONY: reformat
78
+ reformat: ## format the python code
79
+ ruff check --fix $(PY_FILES_DIRS)
80
+ ruff format $(PY_FILES_DIRS)
81
+
82
+ .PHONY: checkoutdated checkoutdated-py checkoutdated-gh
83
+ checkoutdated: checkoutdated-py checkoutdated-gh
84
+
85
+ checkoutdated-py: ## Check for outdated package requirements
86
+ uv run puc --exclude-newer=$(EXCLUDE_NEWER) check pyproject.toml
87
+
88
+ checkoutdated-gh: ## check for outdated github projects
89
+ # github-check-outdated is a local tool which compares a given version with the latest available github release version
90
+ # see https://gist.github.com/wummel/ef14989766009effa4e262b01096fc8c for an example implementation
91
+ @echo "Check for outdated Github tools"
92
+ github-check-outdated astral-sh uv "$(shell uv --version | cut -f2 -d" ")"
93
+ github-check-outdated python cpython v$(shell python --version | cut -f2 -d" ") '^v3\.14\.[0-9]+$$'
94
+
95
+
96
+ .PHONY: upgradeoutdated
97
+ upgradeoutdated: upgradeoutdated-gh upgradeoutdated-py
98
+
99
+ .PHONY: upgradeoutdated-gh
100
+ upgradeoutdated-gh:
101
+ sed -i -e 's/uv_version_dev = ".*"/uv_version_dev = "$(shell github-check-outdated astral-sh uv 0 | cut -f4 -d" ")"/' pyproject.toml
102
+ sed -i -e 's/python_version_dev = ".*"/python_version_dev = "$(shell github-check-outdated python cpython 0 '^v3\.14\.[0-9]+$$' | cut -f4 -d" " | cut -b2-)"/' pyproject.toml
103
+ scripts/install_dev.sh
104
+
105
+ .PHONY: upgradeoutdated-py
106
+ upgradeoutdated-py: ## upgrade dependencies in pyproject.toml and uv.lock
107
+ # upgrade pyproject.toml dependencies
108
+ uv run puc --exclude-newer=$(EXCLUDE_NEWER) update pyproject.toml
109
+ # upgrade depencencies in uv lock file
110
+ uv lock --exclude-newer=$(EXCLUDE_NEWER) --upgrade
111
+ # install upgraded package versions in virtual environment
112
+ $(MAKE) init
113
+
114
+
115
+ ############ Testing ############
116
+
117
+ .PHONY: test
118
+ test: ## run tests
119
+ uv run --isolated -- pytest $(PYTESTOPTS) $(TESTOPTS) $(TESTS)
120
+
121
+ .PHONY: typecheck
122
+ typecheck: ## run the ty type checker
123
+ ty check $(PY_FILES_DIRS)
124
+
125
+
126
+ ############ Release ############
127
+
128
+ .PHONY: distclean
129
+ distclean:
130
+ rm -rf dist $(shell find src tests -type d -name __pycache__)
131
+
132
+ .PHONY: dist
133
+ dist:
134
+ uv build
135
+
136
+ # Releases are tagged with the version, ie. "0.5"
137
+ .PHONY: release
138
+ release: distclean checkrelease ## create release
139
+ $(MAKE) dist release-gh release-pypi
140
+
141
+ # export GITHUB_TOKEN for the gh command
142
+ # Generate a fine grained access token with:
143
+ # - Restricted to this repository
144
+ # - Repository permission: Metadata -> Read (displayed as "Read access to metadata" in token view)
145
+ # - Repository permission: Contents -> Read and write (displayed as "Read and Write access to code" in token view)
146
+ # - Expiration in 90 days
147
+ # After that run "export GITHUB_TOKEN=<token-content>"
148
+ .PHONY: release-gh
149
+ release-gh: ## upload a new release to github
150
+ gh release create \
151
+ --title "Release $(RELEASE_TAG)" \
152
+ --notes-from-tag \
153
+ --latest \
154
+ --draft=false \
155
+ --prerelease=false \
156
+ --verify-tag \
157
+ "$(RELEASE_TAG)" \
158
+ dist/$(RELEASE_SOURCE)
159
+
160
+ .PHONY: release-pypi
161
+ release-pypi: ## upload a new release to pypi
162
+ uv publish dist/$(RELEASE_SOURCE) dist/$(RELEASE_WHEEL)
163
+
164
+ .PHONY: checkrelease
165
+ checkrelease: lint test typecheck checkgit ## check release conditions
166
+
167
+ .PHONY: checkgit
168
+ checkgit: ## various git release checks
169
+ # check that the current branch is the release branch
170
+ @if [ "$(shell git rev-parse --abbrev-ref HEAD)" != "$(RELEASE_BRANCH)" ]; then \
171
+ echo "ERROR: current branch is not '$(RELEASE_BRANCH)', but '$(shell git rev-parse --abbrev-ref HEAD;)'"; \
172
+ false; \
173
+ fi
174
+ # check for uncommitted versions
175
+ @if [ -n "$(shell git status --porcelain --untracked-files=all)" ]; then \
176
+ echo "ERROR: uncommitted changes"; \
177
+ git status --porcelain --untracked-files=all; \
178
+ false; \
179
+ fi
180
+ # check that release tag exists
181
+ @if [ -z "$(shell git tag -l -- $(RELEASE_TAG))" ]; then \
182
+ echo "ERROR: git tag \"$(RELEASE_TAG)\" does not exist, execute 'git tag -a $(RELEASE_TAG) -m \"$(RELEASE_TAG)\"'"; \
183
+ false; \
184
+ fi
185
+ # check that release tags is pushed to remote
186
+ @if ! git ls-remote --exit-code --tags origin $(RELEASE_TAG); then \
187
+ echo "ERROR: git tag \"$(RELEASE_TAG)\" does not exist on remote repo, execute 'git push --tags'"; \
188
+ fi
@@ -0,0 +1,122 @@
1
+ Metadata-Version: 2.4
2
+ Name: python-update-checker
3
+ Version: 0.5
4
+ License-Expression: GPL-3.0-only
5
+ Classifier: Environment :: Console
6
+ Classifier: Intended Audience :: Developers
7
+ Classifier: Development Status :: 4 - Beta
8
+ Classifier: Operating System :: OS Independent
9
+ Classifier: Programming Language :: Python :: 3 :: Only
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Classifier: Topic :: Software Development :: Build Tools
15
+ Requires-Dist: packaging>=26.1
16
+ Requires-Python: >=3.11
17
+ Description-Content-Type: text/markdown
18
+
19
+ python-update-checker
20
+ ======================
21
+ Python-update-checker (puc) checks or updates pinned dependencies
22
+ in `pyproject.toml`, `requirements.txt` or `uv.lock` files.
23
+
24
+ See https://github.com/astral-sh/uv/issues/6794 for a discussion
25
+ about different pinning strategies.
26
+
27
+
28
+ Features
29
+ ---------
30
+
31
+ * updates pinned dependencies, ignores unpinned dependencies
32
+ * supports pyproject.toml, uv.lock and requirements.txt formats
33
+ * supports `[project.dependencies]`, `[project.optional-dependencies]` and `[dependency-groups]` in pyproject.toml
34
+ * supports recursive references (-r) in requirements.txt formats
35
+ * can run in check only mode, ie. it checks if updates are available
36
+ * limit updates to specific packages
37
+ * limit updates with package version constraints (ie. "django<6")
38
+ * limit updates to versions that were uploaded prior to a given date
39
+ * (limited) support for environment markers, ie. `"pywin32==311; os_name=='nt'"`
40
+ * runs on Linux, MacOS and Windows platforms
41
+
42
+
43
+ Examples
44
+ ---------
45
+
46
+ ```bash
47
+ $ # check all pinned packages for updates in pyproject.toml
48
+ $ puc check pyproject.toml
49
+ puc INFO: check pyproject file pyproject.toml
50
+ puc WARNING: found update 'ty==0.0.29' --> 0.0.32
51
+
52
+ $ # update all pinned packages in pyproject.toml
53
+ $ # limit updates to versions that are at least 7 days old
54
+ $ puc --exclude-newer="7 days" update pyproject.toml
55
+ puc INFO: update pyproject file pyproject.toml
56
+ puc INFO: updating 'ty==0.0.29' --> 0.0.31
57
+ puc INFO: Wrote 1 updated package version(s) to pyproject.toml
58
+
59
+ $ # check all pinned packages for updates in requirements.txt
60
+ $ puc check requirements.txt
61
+ puc INFO: check requirements file requirements.txt
62
+ puc WARNING: found update 'argcomplete==3.6.1' --> 3.6.3
63
+ puc WARNING: found update 'Django==5.2.0' --> 6.0.4
64
+
65
+ $ # update only the django package version in requirements.txt
66
+ $ # limit updates to django versions less than 6
67
+ $ puc --package="Django" --constraints="Django<6" update requirements.txt
68
+ INFO: update requirements file requirements.txt
69
+ INFO: updating 'Django==5.2.0' --> 5.2.13
70
+ INFO: Wrote 1 updated package version(s) to requirements.txt
71
+ ```
72
+
73
+ Script behaviour
74
+ -----------------
75
+
76
+ The exit code of `puc check` is non-zero when updates are available.
77
+
78
+ Checking a `pyproject.toml` or `uv.lock`file with `puc` should be done
79
+ from the project of the `pyproject.toml` file,
80
+ especially if your project relies on a [project directory](https://docs.astral.sh/uv/concepts/projects/layout/) (for example to define additional packages index in pyproject.toml).
81
+
82
+ After updating versions in pyproject.toml, run `uv lock --upgrade` to update
83
+ the transitive dependencies in `uv.lock`.
84
+
85
+ Pinned dependencies are packages with `==` or `===` constraints and no wildcards in the version.
86
+
87
+
88
+ Installation
89
+ -------------
90
+
91
+ 1) Install [python uv](https://docs.astral.sh/uv/getting-started/installation/)
92
+ 2) Install puc with `uv pip install python-update-checker`.
93
+
94
+
95
+
96
+ Architecture
97
+ -------------
98
+
99
+ Dependencies are
100
+
101
+ * [uv](https://docs.astral.sh/uv/):
102
+ The uv binary must be available for the script to call.
103
+ puc uses `echo "package" | uv pip compile -` to get latest package versions.
104
+ puc uses `uv add "package==<version>"` to update pyproject.toml dependencies.
105
+
106
+ * [packaging](https://packaging.pypa.io/):
107
+ Parses dependencies with the packaging.requirements.Requirement class.
108
+
109
+ puc needs Python >= 3.11 since it uses the tomllib Python module.
110
+
111
+ puc consists of a single python script. The script uses [inline script metadata](https://peps.python.org/pep-0723/) to be executed directly with `uv run --script`.
112
+ This enables simple packaging and installation.
113
+
114
+
115
+ Limitations
116
+ ------------
117
+
118
+ * No support for custom dependency formats in pyproject.toml
119
+ (eg. `[tool.poetry.dependencies]`).
120
+ * puc has limited support for environment markers.
121
+ * Constraint references (`-c`) inside requirements.txt are not supported.
122
+ Use the `--constraints` option instead.
@@ -0,0 +1,104 @@
1
+ python-update-checker
2
+ ======================
3
+ Python-update-checker (puc) checks or updates pinned dependencies
4
+ in `pyproject.toml`, `requirements.txt` or `uv.lock` files.
5
+
6
+ See https://github.com/astral-sh/uv/issues/6794 for a discussion
7
+ about different pinning strategies.
8
+
9
+
10
+ Features
11
+ ---------
12
+
13
+ * updates pinned dependencies, ignores unpinned dependencies
14
+ * supports pyproject.toml, uv.lock and requirements.txt formats
15
+ * supports `[project.dependencies]`, `[project.optional-dependencies]` and `[dependency-groups]` in pyproject.toml
16
+ * supports recursive references (-r) in requirements.txt formats
17
+ * can run in check only mode, ie. it checks if updates are available
18
+ * limit updates to specific packages
19
+ * limit updates with package version constraints (ie. "django<6")
20
+ * limit updates to versions that were uploaded prior to a given date
21
+ * (limited) support for environment markers, ie. `"pywin32==311; os_name=='nt'"`
22
+ * runs on Linux, MacOS and Windows platforms
23
+
24
+
25
+ Examples
26
+ ---------
27
+
28
+ ```bash
29
+ $ # check all pinned packages for updates in pyproject.toml
30
+ $ puc check pyproject.toml
31
+ puc INFO: check pyproject file pyproject.toml
32
+ puc WARNING: found update 'ty==0.0.29' --> 0.0.32
33
+
34
+ $ # update all pinned packages in pyproject.toml
35
+ $ # limit updates to versions that are at least 7 days old
36
+ $ puc --exclude-newer="7 days" update pyproject.toml
37
+ puc INFO: update pyproject file pyproject.toml
38
+ puc INFO: updating 'ty==0.0.29' --> 0.0.31
39
+ puc INFO: Wrote 1 updated package version(s) to pyproject.toml
40
+
41
+ $ # check all pinned packages for updates in requirements.txt
42
+ $ puc check requirements.txt
43
+ puc INFO: check requirements file requirements.txt
44
+ puc WARNING: found update 'argcomplete==3.6.1' --> 3.6.3
45
+ puc WARNING: found update 'Django==5.2.0' --> 6.0.4
46
+
47
+ $ # update only the django package version in requirements.txt
48
+ $ # limit updates to django versions less than 6
49
+ $ puc --package="Django" --constraints="Django<6" update requirements.txt
50
+ INFO: update requirements file requirements.txt
51
+ INFO: updating 'Django==5.2.0' --> 5.2.13
52
+ INFO: Wrote 1 updated package version(s) to requirements.txt
53
+ ```
54
+
55
+ Script behaviour
56
+ -----------------
57
+
58
+ The exit code of `puc check` is non-zero when updates are available.
59
+
60
+ Checking a `pyproject.toml` or `uv.lock`file with `puc` should be done
61
+ from the project of the `pyproject.toml` file,
62
+ especially if your project relies on a [project directory](https://docs.astral.sh/uv/concepts/projects/layout/) (for example to define additional packages index in pyproject.toml).
63
+
64
+ After updating versions in pyproject.toml, run `uv lock --upgrade` to update
65
+ the transitive dependencies in `uv.lock`.
66
+
67
+ Pinned dependencies are packages with `==` or `===` constraints and no wildcards in the version.
68
+
69
+
70
+ Installation
71
+ -------------
72
+
73
+ 1) Install [python uv](https://docs.astral.sh/uv/getting-started/installation/)
74
+ 2) Install puc with `uv pip install python-update-checker`.
75
+
76
+
77
+
78
+ Architecture
79
+ -------------
80
+
81
+ Dependencies are
82
+
83
+ * [uv](https://docs.astral.sh/uv/):
84
+ The uv binary must be available for the script to call.
85
+ puc uses `echo "package" | uv pip compile -` to get latest package versions.
86
+ puc uses `uv add "package==<version>"` to update pyproject.toml dependencies.
87
+
88
+ * [packaging](https://packaging.pypa.io/):
89
+ Parses dependencies with the packaging.requirements.Requirement class.
90
+
91
+ puc needs Python >= 3.11 since it uses the tomllib Python module.
92
+
93
+ puc consists of a single python script. The script uses [inline script metadata](https://peps.python.org/pep-0723/) to be executed directly with `uv run --script`.
94
+ This enables simple packaging and installation.
95
+
96
+
97
+ Limitations
98
+ ------------
99
+
100
+ * No support for custom dependency formats in pyproject.toml
101
+ (eg. `[tool.poetry.dependencies]`).
102
+ * puc has limited support for environment markers.
103
+ * Constraint references (`-c`) inside requirements.txt are not supported.
104
+ Use the `--constraints` option instead.
@@ -0,0 +1,59 @@
1
+ [project]
2
+ name = "python-update-checker"
3
+ version = "0.5"
4
+ requires-python = ">=3.11"
5
+ license = "GPL-3.0-only"
6
+ license_files = [
7
+ "COPYING",
8
+ ]
9
+ readme = "README.md"
10
+ # https://pypi.org/classifiers/
11
+ classifiers = [
12
+ "Environment :: Console",
13
+ "Intended Audience :: Developers",
14
+ "Development Status :: 4 - Beta",
15
+ "Operating System :: OS Independent",
16
+ "Programming Language :: Python :: 3 :: Only",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ "Programming Language :: Python :: 3.14",
21
+ "Topic :: Software Development :: Build Tools",
22
+ ]
23
+ dependencies = [
24
+ # track compatibility for dependencies, do not pin
25
+ "packaging>=26.1",
26
+ ]
27
+
28
+ [project.scripts]
29
+ puc = "puc:cli.main"
30
+
31
+ [dependency-groups]
32
+ # these packages are only needed for development
33
+ dev = [
34
+ # for python code linting
35
+ "ruff==0.15.12",
36
+ # for python type checking
37
+ "ty==0.0.34",
38
+ # for testing
39
+ "pytest==9.0.3",
40
+ ]
41
+
42
+ [build-system]
43
+ requires = ["uv_build>=0.11,<0.12"]
44
+ build-backend = "uv_build"
45
+
46
+ [tool.uv.build-backend]
47
+ module-name = "puc"
48
+ source-include = [
49
+ ".gitignore",
50
+ ".ruff.toml",
51
+ "Makefile",
52
+ "scripts/**",
53
+ "tests/**",
54
+ ]
55
+
56
+ [tool.project]
57
+ # pin versions of Python and uv for development
58
+ python_version_dev = "3.14.4"
59
+ uv_version_dev = "0.11.11"
@@ -0,0 +1,113 @@
1
+ #!/bin/bash
2
+ #
3
+ # Description: set up a development environment ready for developing this software
4
+ # Package installation uses apt-get which requires sudo permissions
5
+ # Requirements: a Debian-based Linux system and sudo permissions for the current user
6
+ # Synopsis: scripts/install_dev.sh
7
+
8
+ #### shell settings
9
+ # abort when using unknown variables
10
+ set -o nounset
11
+ # abort on subprogram errors
12
+ set -o errexit
13
+ # abort on piping errors (ie. a|b, a fails)
14
+ set -o pipefail
15
+ # subshells should inherit error handlers/traps (set -E)
16
+ set -o errtrace
17
+ # for debugging: print every command with TRACE=1
18
+ if [[ "${TRACE-0}" == "1" ]]; then
19
+ set -o xtrace
20
+ fi
21
+
22
+ # command substitution inherits the errexit setting
23
+ shopt -s inherit_errexit
24
+ # do not print file globbing patters when no file exists
25
+ shopt -s nullglob
26
+
27
+ #### configuration variables
28
+ # the directory this script is stored
29
+ BASEDIR=$(realpath "$(dirname "${0}")")
30
+ # the project directory
31
+ PROJECTDIR=$(dirname "${BASEDIR}")
32
+
33
+ PY_VER=$(grep "python_version_dev =" "${PROJECTDIR}/pyproject.toml" | cut -f2 -d'"')
34
+ UV_VER=$(grep "uv_version_dev =" "${PROJECTDIR}/pyproject.toml" | cut -f2 -d'"')
35
+ DOWNLOAD_URL_UV=https://github.com/astral-sh/uv/releases/download/${UV_VER}/uv-x86_64-unknown-linux-gnu.tar.gz
36
+ CURL_OPTS=("--location" "--silent" "--show-error" "--retry" "2" "--fail" "--tlsv1.2" "--proto" "=https")
37
+ REINSTALL_PYTHON=0
38
+
39
+
40
+ #### helper functions
41
+
42
+ # Install a debian package
43
+ install_package() {
44
+ local pkg=$1
45
+ if ! dpkg --status "${pkg}" >/dev/null 2>&1; then
46
+ echo "Installing ${pkg}"
47
+ sudo apt-get install "${pkg}"
48
+ fi
49
+ }
50
+
51
+ #### main function
52
+
53
+ # execute make targets
54
+ install_package make
55
+ # download tool
56
+ install_package curl
57
+ # augment the local environment
58
+ install_package direnv
59
+ # lint shell
60
+ install_package shellcheck
61
+
62
+ # the rest of this scripts relies on being in the project directory
63
+ cd "${PROJECTDIR}"
64
+
65
+ # install uv
66
+ if [ ! -d bin ]; then
67
+ mkdir bin
68
+ fi
69
+ if [ ! -f bin/uv ]; then
70
+ echo "Install uv ${UV_VER} from ${DOWNLOAD_URL_UV}"
71
+ (cd bin; curl "${CURL_OPTS[@]}" "${DOWNLOAD_URL_UV}" | tar xzv --strip-components 1)
72
+ elif [ "$(bin/uv --version | cut -d" " -f2)" != "${UV_VER}" ]; then
73
+ echo "Updating $(bin/uv --version) to ${UV_VER} from ${DOWNLOAD_URL_UV}"
74
+ (cd bin; curl "${CURL_OPTS[@]}" "${DOWNLOAD_URL_UV}" | tar xzv --strip-components 1)
75
+ # new uv versions might use new versions from python-build-standalone
76
+ REINSTALL_PYTHON=1
77
+ fi
78
+
79
+ # add local development environment for direnv
80
+ if ! declare -F _direnv_hook >/dev/null; then
81
+ eval "$(direnv hook bash)"
82
+ fi
83
+ if [ ! -f .envrc ]; then
84
+ (
85
+ echo "# to find local tools"
86
+ echo "export PATH=${PROJECTDIR}/bin\${PATH:+:\$PATH}"
87
+ echo "export PATH=${PROJECTDIR}/.venv/bin\${PATH:+:\$PATH}"
88
+ ) > .envrc
89
+ direnv allow .
90
+ source .envrc
91
+ fi
92
+
93
+ # create .python-version
94
+ if [ ! -f .python-version ]; then
95
+ echo "Generating $PROJECTDIR/.python-version"
96
+ echo "${PY_VER}" > .python-version
97
+ else
98
+ PROJ_PY_VER=$(<.python-version)
99
+ if [ ".$PROJ_PY_VER" != ".$PY_VER" ]; then
100
+ echo "Updating $PROJECTDIR/.python-version (${PROJ_PY_VER} -> ${PY_VER})"
101
+ echo "${PY_VER}" >| .python-version
102
+ rm -rf .venv
103
+ fi
104
+ fi
105
+
106
+ # create virtual environment
107
+ if [ ! -d .venv ]; then
108
+ uv venv
109
+ fi
110
+
111
+ if [ "${REINSTALL_PYTHON}" = "1" ]; then
112
+ uv python install --reinstall
113
+ fi
@@ -0,0 +1,3 @@
1
+ # Author: Bastian Kleineidam
2
+ # Copyright: GPL-v3
3
+ """module file"""