Skip to content

Commit

Permalink
Merge pull request #304 from manparvesh/v2
Browse files Browse the repository at this point in the history
Simplify plugin & config management, change plugin format
  • Loading branch information
manparvesh authored Oct 13, 2024
2 parents 09809fb + 0760ea0 commit e6313c9
Show file tree
Hide file tree
Showing 27 changed files with 1,725 additions and 714 deletions.
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

0 comments on commit e6313c9

Please sign in to comment.