diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 210bd5b..8c8e6f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,15 +16,9 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: ["3.9", "3.10", "3.11"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v4 - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - - name: Install dependencies - run: pip install .[tests] - - name: Run unit tests - run: pytest -vv + - uses: astral-sh/setup-uv@v3 + - run: uv run --all-extras -p ${{ matrix.python-version }} pytest -vv diff --git a/.gitignore b/.gitignore index a4124c6..23724a3 100644 --- a/.gitignore +++ b/.gitignore @@ -100,3 +100,6 @@ ENV/ # mypy .mypy_cache/ + +# uv +uv.lock diff --git a/README.md b/README.md index 3916a9b..1d126d4 100644 --- a/README.md +++ b/README.md @@ -35,12 +35,6 @@ If you want to try it out on your own, run: pip install shell-functools ``` -If you only want to try it out temporarily, you can also use: -``` bash -git clone https://github.com/sharkdp/shell-functools /tmp/shell-functools -export PATH="$PATH:/tmp/shell-functools/ft" -``` - ## Documentation and examples ### Usage of `map` diff --git a/ft/filter b/ft/filter deleted file mode 100755 index 49ac9a1..0000000 --- a/ft/filter +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -from ft.commands.filter import Filter - - -Filter().run() diff --git a/ft/foldl b/ft/foldl deleted file mode 100755 index 2f65a08..0000000 --- a/ft/foldl +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -from ft.commands.foldl import Foldl - - -Foldl().run() diff --git a/ft/foldl1 b/ft/foldl1 deleted file mode 100755 index 8c361b8..0000000 --- a/ft/foldl1 +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -from ft.commands.foldl1 import Foldl1 - - -Foldl1().run() diff --git a/ft/ft-functions b/ft/ft-functions deleted file mode 100755 index c3de893..0000000 --- a/ft/ft-functions +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python3 - -from ft.types import T_VOID -from ft.functions import function_list -from ft.termcolor import colored - -type_color = { - "String": "yellow", - "Path": "cyan", - "Int": "blue", - "Bool": "magenta", - "Array": "red", - "*": "white", - "!": "red" -} - - -def with_color(typename): - if typename in type_color: - return colored(typename, type_color[typename]) - - return typename - - -for name, fn in sorted(function_list.items()): - type_in = fn.type_in - type_out = fn.type_out - - if type_in is None: - type_in = with_color("*") - else: - type_in = with_color(str(type_in)) - - if type_out is None: - type_out = with_color("*") - elif type_out == "returned": - type_out = with_color("*") - elif type_out == T_VOID: - type_out = with_color("!") - else: - type_out = with_color(str(type_out)) - - arg_names = fn.inner_argspec.args[:-1] - - name_and_args = colored(name, "green") - - if len(arg_names) > 0: - name_and_args += " " + " ".join(arg_names) - - print("{name_and_args:<28} :: {type_in:<15} → {type_out}".format( - name_and_args=name_and_args, - type_in=type_in, - type_out=type_out)) diff --git a/ft/ft/command.py b/ft/ft/command.py index 3c7d3d8..23df260 100644 --- a/ft/ft/command.py +++ b/ft/ft/command.py @@ -1,6 +1,6 @@ import sys import argparse -from signal import signal, SIGPIPE, SIG_DFL +import signal from functools import partial @@ -22,7 +22,8 @@ def __init__(self, name): @staticmethod def configure_broken_pipe(): # Use the default behavior (exit quietly) when catching SIGPIPE - signal(SIGPIPE, SIG_DFL) + if hasattr(signal, 'SIGPIPE'): + signal.signal(signal.SIGPIPE, signal.SIG_DFL) def get_argument_parser(self): parser = argparse.ArgumentParser(description=self.name) diff --git a/ft/ft/commands/ft_functions.py b/ft/ft/commands/ft_functions.py new file mode 100644 index 0000000..779ad11 --- /dev/null +++ b/ft/ft/commands/ft_functions.py @@ -0,0 +1,56 @@ +from ft.types import T_VOID +from ft.functions import function_list +from ft.termcolor import colored + +type_color = { + "String": "yellow", + "Path": "cyan", + "Int": "blue", + "Bool": "magenta", + "Array": "red", + "*": "white", + "!": "red" +} + + +def with_color(typename): + if typename in type_color: + return colored(typename, type_color[typename]) + + return typename + + +def main(): + for name, fn in sorted(function_list.items()): + type_in = fn.type_in + type_out = fn.type_out + + if type_in is None: + type_in = with_color("*") + else: + type_in = with_color(str(type_in)) + + if type_out is None: + type_out = with_color("*") + elif type_out == "returned": + type_out = with_color("*") + elif type_out == T_VOID: + type_out = with_color("!") + else: + type_out = with_color(str(type_out)) + + arg_names = fn.inner_argspec.args[:-1] + + name_and_args = colored(name, "green") + + if len(arg_names) > 0: + name_and_args += " " + " ".join(arg_names) + + print("{name_and_args:<28} :: {type_in:<15} → {type_out}".format( + name_and_args=name_and_args, + type_in=type_in, + type_out=type_out)) + + +if __name__ == "__main__": + main() diff --git a/ft/ft/version.py b/ft/ft/version.py deleted file mode 100644 index 493f741..0000000 --- a/ft/ft/version.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = "0.3.0" diff --git a/ft/map b/ft/map deleted file mode 100755 index 9270f12..0000000 --- a/ft/map +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -from ft.commands.map import Map - - -Map().run() diff --git a/ft/sort_by b/ft/sort_by deleted file mode 100755 index 8790dbb..0000000 --- a/ft/sort_by +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python3 - -from ft.commands.sort_by import SortBy - -SortBy().run() diff --git a/ft/take_while b/ft/take_while deleted file mode 100755 index caae320..0000000 --- a/ft/take_while +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env python3 - -from ft.commands.take_while import TakeWhile - - -TakeWhile().run() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..032c312 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,43 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "shell-functools" +version = "0.3.1" +description = "A collection of functional programming tools for the shell." +authors = [{ name = "David Peter", email = "mail@david-peter.de" }] +urls = { Home = "https://github.com/sharkdp/shell-functools" } +keywords = ["shell", "functional-programming", "filesystem", "string-manipulation", "command-line"] +classifiers=[ + "Development Status :: 4 - Beta", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", +] +readme = { file = "README.md", content-type = "text/markdown" } +license = "MIT" +requires-python = ">=3.9" + +[project.optional-dependencies] +tests = [ + "pytest", +] + +[project.scripts] +filter = "ft.commands.filter:Filter.main" +foldl = "ft.commands.foldl:Foldl.main" +foldl1 = "ft.commands.foldl1:Foldl1.main" +ft-functions = "ft.commands.ft_functions:main" +map = "ft.commands.map:Map.main" +sort_by = "ft.commands.sort_by:SortBy.main" +take_while = "ft.commands.take_while:TakeWhile.main" + +[tool.hatch.build.targets.wheel] +packages = ["ft/ft"] diff --git a/setup.py b/setup.py deleted file mode 100644 index 82b6dcb..0000000 --- a/setup.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -from __future__ import absolute_import, print_function -import os - -from setuptools import setup, find_packages - -NAME = "shell-functools" - -exec(open("ft/ft/version.py").read()) - -VERSION = __version__ -PACKAGES = find_packages("ft", exclude=["*.tests", "*.tests.*", "tests.*", "tests"]) -PACKAGE_DIR = {"": "ft"} -PACKAGE_DATA = {"": [""]} -AUTHOR = "David Peter" -AUTHOR_EMAIL = "mail@david-peter.de" -URL = "https://github.com/sharkdp/shell-functools" - - -REQUIRES = [] -if os.path.exists("requirements.txt"): - with open("requirements.txt", "r") as ifile: - for line in ifile: - REQUIRES.append(line.strip()) -DESCRIPTION = "A collection of functional programming tools for the shell." -KEYWORDS = "shell functional-programming filesystem string-manipulation command-line" -with open("README.md") as ifile: - LONG_DESC = ifile.read() - -setup( - name=NAME, - version=VERSION, - author=AUTHOR, - author_email=AUTHOR_EMAIL, - description=DESCRIPTION, - long_description=LONG_DESC, - long_description_content_type="text/markdown", - url=URL, - keywords=KEYWORDS, - license="MIT", - packages=PACKAGES, - package_dir=PACKAGE_DIR, - package_data=PACKAGE_DATA, - include_package_data=True, - install_requires=REQUIRES, - python_requires=">=3.5", - extras_require={ - 'tests': ['pytest'], - }, - scripts=[ - "ft/filter", - "ft/foldl", - "ft/foldl1", - "ft/ft-functions", - "ft/map", - "ft/sort_by", - "ft/take_while", - ], - classifiers=[ - "Programming Language :: Python :: 3.5", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python", - "Development Status :: 4 - Beta", - ], -)