Skip to content

Commit

Permalink
initial code from splitting off the 'bork download' subcommand.
Browse files Browse the repository at this point in the history
  • Loading branch information
duckinator committed Nov 20, 2023
0 parents commit 73469bd
Show file tree
Hide file tree
Showing 17 changed files with 701 additions and 0 deletions.
148 changes: 148 additions & 0 deletions .cirrus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
Lint_task:
container:
image: python:3.11-slim
install_script:
- pip install -U --upgrade-strategy eager pip 'setuptools>61'
- pip install .
- pip install .[lint] .[test]
script:
- pylint --version
- bork run lint

Linux_task:
alias: Linux tests
container:
matrix:
- image: python:3.8-slim
- image: python:3.9-slim
- image: python:3.10-slim
- image: python:3.11-slim
install_script:
- apt-get update
- apt-get install -y git
- pip install -U --upgrade-strategy eager pip 'setuptools>61'
- pip install . .[test]
script:
- python3 --version
- bork run test

macOS_task:
alias: macOS tests
macos_instance:
image: ghcr.io/cirruslabs/macos-ventura-base:latest
env:
LC_ALL: en_US.UTF-8
LANG: en_US.UTF-8
PATH: ${HOME}/.pyenv/shims:${PATH}
matrix:
# https://formulae.brew.sh/formula/[email protected]
- PYTHON: 3.8.16
- PYTHON: 3.9.16
- PYTHON: 3.10.9
- PYTHON: 3.11.1
brew_update_script:
- brew update
brew_install_script:
# Per the pyenv homebrew recommendations.
# https://github.com/pyenv/pyenv/wiki#suggested-build-environment
- brew install openssl readline sqlite3 xz zlib pyenv git
pyenv_install_script:
- pyenv install ${PYTHON}
- pyenv global ${PYTHON}
- pyenv rehash
pip_install_script:
- pip install -U --upgrade-strategy eager pip 'setuptools>61'
- pip install .[test]
script:
- python3 --version
- bork run test
always:
upload_results_artifacts:
path: ./homf-junit.xml
format: junit
type: text/xml

FreeBSD_task:
alias: FreeBSD tests
freebsd_instance:
image_family: freebsd-13-2
env:
matrix:
- PYTHON: 3.8
- PYTHON: 3.9
- PYTHON: 3.10
- PYTHON: 3.11
install_script:
- PY=`echo $PYTHON | tr -d '.'`
- pkg install -y python${PY} git
- python${PYTHON} -m ensurepip
pip_install_script:
- python${PYTHON} -m pip install -U --upgrade-strategy eager pip 'setuptools>61'
- python${PYTHON} -m pip install .[test]
script:
- python${PYTHON} --version
- bork run test
always:
upload_results_artifacts:
path: ./homf-junit.xml
format: junit
type: text/xml

Windows_task:
windows_container:
image: cirrusci/windowsservercore:2019
env:
matrix:
- PYTHON: 3.8.10
- PYTHON: 3.9.13
- PYTHON: 3.10.9
- PYTHON: 3.11.1
python_install_script:
# https://docs.python.org/3.6/using/windows.html#installing-without-ui
- ps: Invoke-WebRequest -Uri https://www.python.org/ftp/python/${env:PYTHON}/python-${env:PYTHON}-amd64.exe -OutFile C:\python-installer.exe
- C:\python-installer.exe /quiet TargetDir=C:\Python SimpleInstall=1
install_script:
- C:\Python\python.exe -m pip install -U --upgrade-strategy eager pip "setuptools>61"
- C:\Python\python.exe -m pip install .[test]
version_info_script:
- C:\Python\python.exe --version
test_script:
- C:\Python\python.exe -m pytest --verbose
always:
upload_results_artifacts:
path: ./homf-junit.xml
format: junit
type: text/xml

success_task:
name: CI success
container: {image: "busybox"}
depends_on:
- Lint
- FreeBSD tests
- Linux tests
- macOS tests
- Windows

# If homf/version.py is modified on the main branch, make a release.
Release_task:
only_if: "changesInclude('homf/version.py') && $BRANCH == 'main' && $CIRRUS_CRON == ''"
depends_on: [CI success]
env:
TWINE_USERNAME: "__token__"
TWINE_PASSWORD: ENCRYPTED[...]
BORK_GITHUB_TOKEN: ENCRYPTED[...]
container:
image: python:3.11-slim
install_script:
- apt-get update
- apt-get install -y git
- pip install -U --upgrade-strategy eager pip 'setuptools>61'
- pip3 install . .[test]
build_script:
- bork clean
- bork build
test_script:
- bork run test
release_script:
- bork release
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/.eggs/
/.mypy_cache/
/.pytest_cache/
/.tox/
/build/
/dist/
/*.egg-info/
/venv
/homf-junit.xml
/homf-junit.xml.html
/docs/build/
__pycache__
23 changes: 23 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[MASTER]
# Use multiple processes to speed up Pylint.
jobs=4

[MESSAGES CONTROL]

# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once).
enable=all

# Disable the message, report, category or checker with the given id(s).
disable=missing-docstring,
compare-to-zero


[REPORTS]

# Set the output format. Available formats are text, parseable, colorized, json
# and msvs (visual studio).You can also give a reporter class, eg
# mypackage.mymodule.MyReporterClass.
output-format=colorized
22 changes: 22 additions & 0 deletions LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
The MIT License (MIT)

Copyright (c) 2023 Ellen Marie Dash <[email protected]>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# homf [![Build Status][build-status-img]][build-status-link] [![PyPI][pypi-version-img]][pypi-version-link] [![Documentation Status][docs-img]][docs-link]

Homf is a tool for downloading artifacts from online services, like a ZipApp from GitHub Releases or a Wheel from PyPi.

homf requires Python 3.8 or newer.

[build-status-img]: https://api.cirrus-ci.com/github/duckinator/homf.svg
[build-status-link]: https://cirrus-ci.com/github/duckinator/homf

[pypi-version-img]: https://img.shields.io/pypi/v/homf
[pypi-version-link]: https://pypi.org/project/homf

[docs-img]: https://readthedocs.org/projects/homf/badge/?version=latest
[docs-link]: https://homf.readthedocs.io/en/latest/?badge=latest
2 changes: 2 additions & 0 deletions homf/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Expose `homf.version.__version__` as `homf.__version__`.
from .version import __version__ # noqa: F401
3 changes: 3 additions & 0 deletions homf/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import cli

cli.main()
2 changes: 2 additions & 0 deletions homf/api/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from . import github
from . import pypi
25 changes: 25 additions & 0 deletions homf/api/asset_manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import logging
from pathlib import Path
from urllib.request import urlopen


def download(asset_list, directory, name_key=None, url_key=None):
if name_key is None:
name_key = 'name'

if url_key is None:
url_key = 'url'

directory = Path(directory)
directory.mkdir(parents=True, exist_ok=True)

for asset in asset_list:
name = asset[name_key]
url = asset[url_key]
path = directory / name

with urlopen(url) as f:
contents = f.read()

path.write_bytes(contents)
logging.info("Downloaded '%s'", path)
57 changes: 57 additions & 0 deletions homf/api/github.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import fnmatch
import json
import logging
from urllib.request import urlopen

import packaging.version

from . import asset_manager


def relevant_asset(asset, file_pattern):
file_patterns = file_pattern.split(',')
for pattern in file_patterns:
if fnmatch.fnmatch(asset['name'], pattern):
return True
return False


def get_release_info(repo, name, draft=False, prerelease=False):
if '/' not in repo:
raise ValueError(
f"repo must be of format <user>/<repo>, got '{repo}'",
)

url = f"https://api.github.com/repos/{repo}/releases"
with urlopen(url) as f:
req = f.read().decode()
releases = json.loads(req)

try:
if name == 'latest':
# Filter out prereleases and drafts (unless specified in the arguments)
releases = (
r for r in releases
if (draft or not r['draft'])
and (prerelease or not r['prerelease']) # noqa: W503
)
# Find the latest
release = max(
releases,
key=lambda x: packaging.version.parse(x['tag_name']).public,
)
logging.info("Selected release '%s' as latest", release['name'])
else:
release = list(filter(lambda x: x['tag_name'] == name, releases))[0]

except (IndexError, ValueError) as e:
raise RuntimeError(f"No such Github release: '{name}'") from e

return release


def download(repo, release, file_pattern, directory):
release_info = get_release_info(repo, release, file_pattern)
assets = filter(lambda x: relevant_asset(x, file_pattern),
release_info['assets'])
asset_manager.download(assets, directory, url_key='browser_download_url')
Loading

0 comments on commit 73469bd

Please sign in to comment.