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

Simplify plugin & config management, change plugin format #304

Merged
merged 12 commits into from
Oct 13, 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
126 changes: 60 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ The help command will list all the available plugins.
$ yoda --help
```

![img.png](docs/docs/img.png)

You can find the details for each plugin with the `--help` flag. Some examples:

![img_1.png](docs/docs/img_1.png)

![img_2.png](docs/docs/img_2.png)

![img_3.png](docs/docs/img_3.png)

### Write your own plugin for Yoda

Simply create a class with the `@yoda_plugin(name="plugin-name")` decorator and add methods to it. The non-private
Expand All @@ -41,94 +51,78 @@ decorator.

```python
import typer
from yodapa.plugin_manager.decorator import yoda_plugin


@yoda_plugin(name="hi")
class HiPlugin:
"""
app = typer.Typer(help="""
Hi plugin. Say hello.

Example:

$ yoda hi hello --name MP

$ yoda hi hello
"""
""")

def hello(self, name: str = None):
"""Say hello."""
name = name or "Padawan"
typer.echo(f"Hello {name}!")

def _private_method_should_not_be_added(self):
"""This method should not be added as a command."""
raise NotImplementedError()
@app.command()
def hello(name: str = None):
"""Say hello."""
name = name or "Padawan"
typer.echo(f"Hello {name}!")
```

### Use AI to generate your own plugin

```bash
$ yoda ai generate-command todo "todo list that keeps track of your todos"
$ yoda ai generate-command weather "show weather for the provided location"

🤖 Generated code:

import typer

from yodapa.plugin_manager.decorator import yoda_plugin

import requests
from typing import Optional

@yoda_plugin(name="todo")
class TodoPlugin:
"""
Todo plugin. Keeps track of your todos.
app = typer.Typer(help="""
Show weather for a given location.

Example:
$ yoda todo list --all
$ yoda todo add "Finish assignment"
$ yoda todo done 1
$ yoda todo delete 2
"""

def list(self, all: bool = False):
"""List all todos."""
if all:
typer.echo("All todos:")
for todo in self.todos:
typer.echo(f"- {todo}")
else:
typer.echo("Active todos:")
for todo in self.active_todos:
typer.echo(f"- {todo}")

def add(self, name: str):
"""Add a new todo."""
if name == "":
raise ValueError("Todo name cannot be empty")
self.todos.append(name)
typer.echo(f"Added todo '{name}'")

def done(self, id: int):
"""Mark a todo as done."""
if id < 0 or id >= len(self.todos):
raise ValueError("Todo ID out of range")
self.active_todos.remove(self.todos[id])
typer.echo(f"Marked todo {id} as done")

def delete(self, id: int):
"""Delete a todo."""
if id < 0 or id >= len(self.todos):
raise ValueError("Todo ID out of range")
self.todos.remove(self.todos[id])
typer.echo(f"Deleted todo {id}")

def __init__(self):
self.todos = []
self.active_todos = []

if __name__ == "__main__":
typer.run(TodoPlugin())

$ yoda weather London

$ yoda weather -l London
""")

@app.command()
def weather(location: str, units: Optional[str] = None):
"""Show the current weather for a given location."""
# Set up your API key or database connection here
api_key = "YOUR_API_KEY"
db_conn = None # Initialize your DB connection here

# Use the requests library to make an HTTP request to the API
url = f"https://api.openweathermap.org/data/2.5/weather?q={location}&appid={api_key}"
response = requests.get(url)

# If the response is successful, parse the JSON data and return it in a format that typer can display
if response.status_code == 200:
data = response.json()
temperature = data["main"]["temp"]
humidity = data["main"]["humidity"]
wind = data["wind"]["speed"]
pressure = data["main"]["pressure"]

typer.echo(f"Weather for {location}:")
typer.echo(f"\tTemperature: {temperature}°C")
typer.echo(f"\tHumidity: {humidity}%")
typer.echo(f"\tWind speed: {wind} m/s")
typer.echo(f"\tPressure: {pressure} hPa")

# If the response is not successful, print an error message
else:
typer.echo(f"Error: {response.status_code}")
```

.. or chat with Yoda:
![img_5.png](docs/docs/img_5.png)

## Development setup

```bash
Expand Down
Binary file added docs/docs/img.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/docs/img_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/docs/img_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/docs/img_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/docs/img_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
126 changes: 60 additions & 66 deletions docs/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ The help command will list all the available plugins.
$ yoda --help
```

![img.png](img.png)

You can find the details for each plugin with the `--help` flag. Some examples:

![img_1.png](img_1.png)

![img_2.png](img_2.png)

![img_3.png](img_3.png)

### Write your own plugin for Yoda

Simply create a class with the `@yoda_plugin(name="plugin-name")` decorator and add methods to it. The non-private
Expand All @@ -41,94 +51,78 @@ decorator.

```python
import typer
from yodapa.plugin_manager.decorator import yoda_plugin


@yoda_plugin(name="hi")
class HiPlugin:
"""
app = typer.Typer(help="""
Hi plugin. Say hello.

Example:

$ yoda hi hello --name MP

$ yoda hi hello
"""
""")

def hello(self, name: str = None):
"""Say hello."""
name = name or "Padawan"
typer.echo(f"Hello {name}!")

def _private_method_should_not_be_added(self):
"""This method should not be added as a command."""
raise NotImplementedError()
@app.command()
def hello(name: str = None):
"""Say hello."""
name = name or "Padawan"
typer.echo(f"Hello {name}!")
```

### Use AI to generate your own plugin

```bash
$ yoda ai generate-command todo "todo list that keeps track of your todos"
$ yoda ai generate-command weather "show weather for the provided location"

🤖 Generated code:

import typer

from yodapa.plugin_manager.decorator import yoda_plugin

import requests
from typing import Optional

@yoda_plugin(name="todo")
class TodoPlugin:
"""
Todo plugin. Keeps track of your todos.
app = typer.Typer(help="""
Show weather for a given location.

Example:
$ yoda todo list --all
$ yoda todo add "Finish assignment"
$ yoda todo done 1
$ yoda todo delete 2
"""

def list(self, all: bool = False):
"""List all todos."""
if all:
typer.echo("All todos:")
for todo in self.todos:
typer.echo(f"- {todo}")
else:
typer.echo("Active todos:")
for todo in self.active_todos:
typer.echo(f"- {todo}")

def add(self, name: str):
"""Add a new todo."""
if name == "":
raise ValueError("Todo name cannot be empty")
self.todos.append(name)
typer.echo(f"Added todo '{name}'")

def done(self, id: int):
"""Mark a todo as done."""
if id < 0 or id >= len(self.todos):
raise ValueError("Todo ID out of range")
self.active_todos.remove(self.todos[id])
typer.echo(f"Marked todo {id} as done")

def delete(self, id: int):
"""Delete a todo."""
if id < 0 or id >= len(self.todos):
raise ValueError("Todo ID out of range")
self.todos.remove(self.todos[id])
typer.echo(f"Deleted todo {id}")

def __init__(self):
self.todos = []
self.active_todos = []

if __name__ == "__main__":
typer.run(TodoPlugin())

$ yoda weather London

$ yoda weather -l London
""")

@app.command()
def weather(location: str, units: Optional[str] = None):
"""Show the current weather for a given location."""
# Set up your API key or database connection here
api_key = "YOUR_API_KEY"
db_conn = None # Initialize your DB connection here

# Use the requests library to make an HTTP request to the API
url = f"https://api.openweathermap.org/data/2.5/weather?q={location}&appid={api_key}"
response = requests.get(url)

# If the response is successful, parse the JSON data and return it in a format that typer can display
if response.status_code == 200:
data = response.json()
temperature = data["main"]["temp"]
humidity = data["main"]["humidity"]
wind = data["wind"]["speed"]
pressure = data["main"]["pressure"]

typer.echo(f"Weather for {location}:")
typer.echo(f"\tTemperature: {temperature}°C")
typer.echo(f"\tHumidity: {humidity}%")
typer.echo(f"\tWind speed: {wind} m/s")
typer.echo(f"\tPressure: {pressure} hPa")

# If the response is not successful, print an error message
else:
typer.echo(f"Error: {response.status_code}")
```

.. or chat with Yoda:
![img_5.png](img_5.png)

## Development setup

```bash
Expand Down
Loading
Loading