Skip to content

Commit

Permalink
release v0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Chandra Irugalbandara committed Jul 28, 2024
1 parent 0acd659 commit 1f072c7
Show file tree
Hide file tree
Showing 11 changed files with 304 additions and 69 deletions.
20 changes: 1 addition & 19 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/python
{
"name": "Python 3",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/python:1-3.12-bullseye",
"features": {
"ghcr.io/devcontainers/features/conda:1": {
Expand All @@ -13,19 +10,4 @@
"fisher": true
}
}

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "pip3 install --user -r requirements.txt",

// Configure tool-specific properties.
// "customizations": {},

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
}
25 changes: 25 additions & 0 deletions .github/workflows/precommit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Linting and Pre-commit checks

on:
pull_request:
push:
branches:
- main

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2

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

- name: Install pre-commit
run: pip install pre-commit

- name: Run pre-commit hooks
run: pre-commit run --all-files
29 changes: 29 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: PyPI Release

on:
workflow_dispatch:

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.10'
- name: Install Poetry
run: |
pip install poetry
- name: Build package
run: poetry build
- name: Publish package
run: |
poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }}
poetry publish
continue-on-error: true
- run: pip install githubrelease markdown-to-json
- run: python scripts/gh_release.py
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# RELEASES

## `0.1.0` - 2024-07-28
- [INIT] Working Initial Version
17 changes: 17 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Contributing Guidelines

Thank you for your interest in contributing to our project! To ensure a smooth collaboration, please follow the steps below:

1. **Create an Issue**: Before starting any work, please create an issue to discuss the changes you plan to make. This allows for better coordination and avoids duplication of efforts.

2. **Create a Pull Request**: Once you have identified the changes you want to make, fork the repository and create a new branch for your changes. Make your modifications and submit a pull request (PR) to the main repository.

3. **Do Your Thing**: Implement your changes according to the project's guidelines and coding standards. Ensure that your code is well-documented and follows best practices.

4. **Run Pre-commit Hooks**: Before submitting your PR, run the pre-commit hooks to ensure that your code adheres to the project's formatting and style guidelines. This helps maintain consistency across the codebase.

5. **Run Tests**: It is essential to run the project's tests to verify that your changes do not introduce any regressions or break existing functionality. Make sure all tests pass successfully before submitting your PR.

6. **Maintainer Review and Merge**: Once your PR is submitted, a project maintainer will review your changes. They may provide feedback or request further modifications. Once approved, your changes will be merged into the main repository.

We appreciate your contributions and look forward to working with you!
133 changes: 132 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,132 @@
# argonauts
<div align="center">

# ARGONAUTS 🧑🏽‍🚀

[![PyPI version](https://badge.fury.io/py/argonauts.svg)](https://badge.fury.io/py/argonauts)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python Versions](https://img.shields.io/pypi/pyversions/argonauts.svg)](https://pypi.org/project/argonauts/)
</div>

---

Argonauts is a Python library that transforms your functions into interactive command-line interfaces with ease. Using simple decorators, you can create engaging CLI experiences without the hassle of manual argument parsing.

## 🚀 Features

- Transform functions into interactive CLIs with a single decorator
- Automatic type inference and validation
- Chainable interactive functions

## 📦 Installation

Install Argonauts using pip:

```bash
pip install argonauts
```

Install from source:

```bash
git clone <repo-url>
cd argonauts
pip install .
```

## 🛠 Usage

### Basic Usage

Here's a simple example of how to use Argonaut:

```python
from argonauts import argonaut
from enum import Enum

class PizzaSize(Enum):
SMALL = "Small"
MEDIUM = "Medium"
LARGE = "Large"

class Topping(Enum):
PEPPERONI = "Pepperoni"
MUSHROOMS = "Mushrooms"
ONIONS = "Onions"
SAUSAGE = "Sausage"
BELL_PEPPERS = "Bell Peppers"


@argonaut(process_name="We are making your pizza! Keep calm!")
def order_pizza(
size: PizzaSize,
toppings: list[Topping],
extra_cheese: bool = False,
delivery: bool = True,
):
"""Order a delicious pizza with your favorite toppings."""
pizza = f"{size.value} pizza with {', '.join(t.value for t in toppings)}"
if extra_cheese:
pizza += " and extra cheese"
print(f"You've ordered: {pizza}")

time.sleep(20) # Simulate making the pizza

if delivery:
print("Your pizza will be delivered soon!")
else:
print("Your pizza is ready for pickup!")

order_pizza()
```

[GIF placeholder: Show the code snippet side-by-side with a GIF of the resulting interactive CLI]

### Chaining Interactive Functions

Astrolink allows you to chain multiple interactive functions with the ability to share the previous arguments:

```python
from argonauts import argonaut, LogBook

args = LogBook()

@argonaut(logbook=args)
def select_movie(title: str, genre: str):
rating = some_fn_to_get_rating(title)
return {"title": title, "rating": rating}

@argonaut(logbook=args, include_params=["popcorn", "drinks"]) # Include only the specified parameters
def select_snacks(movie: dict, genre: str, popcorn: bool, drinks: list[Drinks]):
print(f"Watching {args.title} ({movie['rating']} stars)") # Reuse the title argument
print("Genre:", genre)
if popcorn:
print("- Popcorn")
print(f"- Drinks: {', '.join(drinks)}")

def movie_night():
movie = select_movie()
select_snacks(movie=movie, genre=args.genre) # Reuse the genre argument

movie_night()
```

[GIF placeholder: Show the code snippet side-by-side with a GIF of the resulting chained interactive CLI]

## 🤝 Contributing

We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for more details.

## 📄 License

Astrolink is released under the MIT License. See the [LICENSE](LICENSE) file for details.

## 🙏 Acknowledgements

- [Questionary](https://github.com/tmbo/questionary) for providing an excellent prompt library
- [Rich](https://github.com/Textualize/rich) for beautiful and interactive terminal output

---

<div align="right">
Made with ❤️ for the Developers by the Developers
</div>
4 changes: 2 additions & 2 deletions argonauts/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Argonauts: Easy Interactive or Non-Interactive CLI Arguments."""

from argonauts.decorators import interactive, LogBook
from argonauts.decorators import LogBook, argonaut

__all__ = ["interactive", "LogBook"]
__all__ = ["argonaut", "LogBook"]
35 changes: 17 additions & 18 deletions argonauts/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import argparse
import inspect
from enum import Enum
from typing import get_origin, get_args, Any, Callable
from functools import wraps
from typing import Any, Callable, get_args, get_origin

import questionary

from rich.console import Console

console = Console()
Expand All @@ -15,26 +17,33 @@ class LogBook:
"""LogBook for storing previous arguments values."""

def __init__(self) -> None:
"""Initialize LogBook."""
self.log = argparse.Namespace()

def __setitem__(self, key, value):
def __setitem__(self, key: str, value: Any) -> None: # noqa
"""Set item in LogBook."""
setattr(self.log, key, value)

def __getitem__(self, key):
def __getitem__(self, key: str) -> Any: # noqa
"""Get item from LogBook."""
return getattr(self.log, key)

def __getattribute__(self, name: str) -> Any:
def __getattribute__(self, name: str) -> Any: # noqa
"""Get attribute from LogBook."""
if name == "log":
return super().__getattribute__(name)
return getattr(self.log, name)

def __repr__(self) -> str:
"""Representation of LogBook."""
attr_str = ", ".join([f"{k}={v}" for k, v in self.log.__dict__.items()])
return f"LogBook({attr_str})"


def interactive(
logbook: LogBook | None = None, include_params: list = [], process_name: str = ""
def argonaut(
logbook: LogBook | None = None,
include_params: list | None = None,
process_name: str | None = None,
) -> Callable:
"""Decorator of Interactive Arguments using questionary."""

Expand All @@ -45,7 +54,7 @@ def decorator(func: Callable) -> Callable:
def wrapper(*args: list, **kwargs: dict) -> Any: # noqa
"""Wrapper of Interactive Arguments."""
sig = inspect.signature(func)
params = sig.parameters
params = dict(sig.parameters)
doc_string = func.__doc__
if doc_string:
console.print(f"\n{doc_string}\n", style="bold")
Expand All @@ -62,7 +71,7 @@ def wrapper(*args: list, **kwargs: dict) -> Any: # noqa
logbook[name] = kwargs[name] if name in kwargs else None
print()
with console.status(
f"Running {func.__name__}..." if not process_name else process_name
process_name if process_name else f"Running {func.__name__}..."
):
output = func(*args, **kwargs)
return output
Expand Down Expand Up @@ -139,13 +148,3 @@ def convert_value(value: Any, annotation: Any) -> Any: # noqa
return float(value)
else:
return value


def non_interactive(func: Callable) -> Callable:
"""Decorator for non-interactive functions."""

@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)

return wrapper
Loading

0 comments on commit 1f072c7

Please sign in to comment.