Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 2.1.0 #737

Merged
merged 15 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 41 additions & 23 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,22 @@ jobs:
name: Lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: actions/cache@v2
- uses: actions/cache@v4
name: Cache pip directory
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-3.9

- uses: actions/cache@v2
- uses: actions/cache@v4
name: Cache poetry deps
with:
path: .venv
key: ${{ runner.os }}-build-${{ hashFiles('poetry.lock') }}-3.9

- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: 3.9

Expand Down Expand Up @@ -60,15 +60,15 @@ jobs:
lang: [C, en_US.UTF-8]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: actions/cache@v2
- uses: actions/cache@v4
name: Cache pip directory
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-3.9

- uses: actions/cache@v2
- uses: actions/cache@v4
name: Cache poetry deps
env:
cache-name: poetry-deps
Expand All @@ -77,7 +77,7 @@ jobs:
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('poetry.lock') }}-${{ matrix.python-version }}

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

Expand All @@ -92,24 +92,24 @@ jobs:

- name: Run tests
run: |
SH_TESTS_RUNNING=1 SH_TESTS_USE_SELECT=${{ matrix.use-select }} LANG=${{ matrix.lang }} poetry run coverage run -a -m pytest
SH_TESTS_RUNNING=1 SH_TESTS_USE_SELECT=${{ matrix.use-select }} LANG=${{ matrix.lang }} poetry run coverage run --data-file=coverage.data -a -m pytest

- name: Store coverage
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: coverage.${{ matrix.use-select }}.${{ matrix.lang }}.${{ matrix.python-version }}
path: .coverage
path: coverage.data

report:
name: Report Coverage
needs: test
runs-on: ubuntu-latest
steps:
# required because coveralls complains if we're not in a git dir
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: 3.9

Expand All @@ -118,13 +118,13 @@ jobs:
pip install coverage coveralls

- name: Download coverage artifacts
uses: actions/download-artifact@v2
uses: actions/download-artifact@v4
with:
path: coverage-artifacts

- name: Combine coverage
run: |
find coverage-artifacts -name .coverage | xargs coverage combine -a
find coverage-artifacts -name coverage.data | xargs coverage combine -a

- name: Report coverage
env:
Expand All @@ -140,22 +140,18 @@ jobs:
if: github.ref_name == 'master'

permissions:
contents: write
id-token: write

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- name: Get current version
id: get_version
run: echo "::set-output name=version::$(sed -n 's/^version = "\(.*\)"/\1/p' pyproject.toml)"

- name: Tag commit
run: |
git tag "${{steps.get_version.outputs.version}}" "${{github.ref_name}}"
git push -f origin "${{steps.get_version.outputs.version}}"
run: echo "version=$(sed -n 's/^version = "\(.*\)"/\1/p' pyproject.toml)" >> $GITHUB_ENV

- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: 3.9

Expand All @@ -165,5 +161,27 @@ jobs:
- name: Build
run: python -m build

- name: Tag commit
run: |
git tag "${{steps.get_version.outputs.version}}" "${{github.ref_name}}"
git push -f origin "${{steps.get_version.outputs.version}}"

- name: Get changes
id: changelog
run: |
python dev_scripts/changelog_extract.py ${{ steps.get_version.outputs.version }} \
> release_changes.md

- name: Create Release
id: create-release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.get_version.outputs.version }}
name: Release ${{ steps.get_version.outputs.version }}
body_path: release_changes.md
draft: false
prerelease: false
files: dist/*

- name: Publish
uses: pypa/gh-action-pypi-publish@release/v1
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## 2.1.0 - 10/8/24

- Add contrib command `sh.contrib.bash` [#736](https://github.com/amoffat/sh/pull/736)

## 2.0.7 - 5/31/24

- Fix `sh.glob` arguments [#708](https://github.com/amoffat/sh/issues/708)
Expand Down
37 changes: 37 additions & 0 deletions dev_scripts/changelog_extract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import re
import sys
from pathlib import Path
from typing import Iterable

THIS_DIR = Path(__file__).parent
CHANGELOG = THIS_DIR.parent / "CHANGELOG.md"


def fetch_changes(changelog: Path, version: str) -> Iterable[str]:
with open(changelog, "r") as f:
lines = f.readlines()

found_a_change = False
aggregate = False
for line in lines:
if line.startswith(f"## {version}"):
aggregate = True

if aggregate:
if line.startswith("-"):
line = re.sub(r"-\s*", "", line).strip()
found_a_change = True
yield line
elif found_a_change:
aggregate = False

return changes


version = sys.argv[1].strip()
changes = fetch_changes(CHANGELOG, version)
if not changes:
exit(1)

for change in changes:
print("- " + change)
2 changes: 1 addition & 1 deletion docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ sh
:target: https://github.com/amoffat/sh
:alt: Github

sh is a full-fledged subprocess replacement for Python 3.8 - 3.11, PyPy that
sh is a full-fledged subprocess replacement for Python 3.8+, and PyPy that
allows you to call any program as if it were a function:


Expand Down
26 changes: 26 additions & 0 deletions docs/source/sections/contrib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,32 @@ this.

The currently written character.


.. _contrib_bash:

Bash
---

Often users may find themselves having to run bash commands directly, whether due
to commands having special characters (e.g. dash, or dot) or other reasons.
This can lead into recurrently having to bake the ``bash`` command to call it directly. To
account for this, the contrib version provides a ``bash`` command baked in:

.. py:function:: bash(*args, **kwargs)

Call bash with the prefix of "bash -c [...]".

.. code-block:: python

from sh.contrib import bash

# Calling commands directly
bash.ls() # equivallent to "bash -c ls"

# Or adding the full commands
bash("command-with-dashes args")


Extending
=========

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "sh"
version = "2.0.7"
version = "2.1.0"
description = "Python subprocess replacement"
authors = ["Andrew Moffat <arwmoffat@gmail.com>"]
readme = "README.rst"
Expand Down
21 changes: 11 additions & 10 deletions sh.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""
http://amoffat.github.io/sh/
https://sh.readthedocs.io/en/latest/
https://github.com/amoffat/sh
"""
# ===============================================================================
# Copyright (C) 2011-2023 by Andrew Moffat
Expand All @@ -24,11 +25,7 @@
# ===============================================================================
import asyncio
from collections import deque

try:
from collections.abc import Mapping
except ImportError: # pragma: no cover
from collections.abc import Mapping
from collections.abc import Mapping

import errno
import fcntl
Expand Down Expand Up @@ -75,9 +72,7 @@

if "windows" in platform.system().lower(): # pragma: no cover
raise ImportError(
f"sh {__version__} is currently only supported on linux and osx. \
please install pbs 0.110 (http://pypi.python.org/pypi/pbs) for windows \
support."
f"sh {__version__} is currently only supported on Linux and macOS."
)

TEE_STDOUT = {True, "out", 1}
Expand Down Expand Up @@ -1098,7 +1093,7 @@ def fg_validator(passed_kwargs, merged_kwargs):
msg = """\
_fg is invalid with nearly every other option, see warning and workaround here:

https://amoffat.github.io/sh/sections/special_arguments.html#fg"""
https://sh.readthedocs.io/en/latest/sections/special_arguments.html#fg"""
allowlist = {"env", "fg", "cwd", "ok_code"}
offending = set(passed_kwargs.keys()) - allowlist

Expand Down Expand Up @@ -3476,6 +3471,12 @@ def git(orig): # pragma: no cover
return cmd


@contrib("bash")
def bash(orig):
cmd = orig.bake("-c")
return cmd


@contrib("sudo")
def sudo(orig): # pragma: no cover
"""a nicer version of sudo that uses getpass to ask for a password, or
Expand Down