weni-cli 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.1
2
+ Name: weni-cli
3
+ Version: 0.1.0
4
+ Requires-Dist: Click
5
+ Requires-Dist: requests
6
+ Requires-Dist: flask
7
+ Requires-Dist: waitress
8
+ Requires-Dist: pyyaml
9
+ Requires-Dist: python-slugify
@@ -0,0 +1 @@
1
+ # Weni-CLI
@@ -0,0 +1,24 @@
1
+ [tool.poetry]
2
+ name = "weni-cli"
3
+ version = "0.1.0"
4
+ description = ""
5
+ authors = ["Paulo Bernardo <paulo.bernardo@weni.ai>"]
6
+ readme = "README.md"
7
+
8
+ [tool.poetry.dependencies]
9
+ python = "^3.12"
10
+ click = "^8.1.8"
11
+ requests = "^2.32.3"
12
+ flask = "^3.1.0"
13
+ waitress = "^3.0.2"
14
+ pyyaml = "^6.0.2"
15
+ python-slugify = "^8.0.4"
16
+ setuptools = "^75.7.0"
17
+ twine = "^6.0.1"
18
+
19
+ [tool.poetry.scripts]
20
+ weni = "weni_cli.cli:cli"
21
+
22
+ [build-system]
23
+ requires = ["poetry-core"]
24
+ build-backend = "poetry.core.masonry.api"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,21 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name="weni-cli",
5
+ version="0.1.0",
6
+ packages=find_packages(),
7
+ include_package_data=True,
8
+ install_requires=[
9
+ "Click",
10
+ "requests",
11
+ "flask",
12
+ "waitress",
13
+ "pyyaml",
14
+ "python-slugify",
15
+ ],
16
+ entry_points={
17
+ "console_scripts": [
18
+ "weni = weni_cli.cli:cli",
19
+ ],
20
+ },
21
+ )
File without changes
File without changes
@@ -0,0 +1,52 @@
1
+ import requests
2
+
3
+ from weni_cli.store import (
4
+ STORE_KEYCLOAK_CLIENT_ID,
5
+ STORE_KEYCLOAK_REALM,
6
+ STORE_KEYCLOAK_URL,
7
+ Store,
8
+ )
9
+
10
+ DEFAULT_KEYCLOAK_URL = "https://accounts.weni.ai/auth"
11
+ DEFAULT_KEYCLOAK_REALM = "weni"
12
+ DEFAULT_KEYCLOAK_CLIENT_ID = "weni-cli"
13
+
14
+
15
+ class Auth:
16
+ keycloak_url = None
17
+ realm = None
18
+ client_id = None
19
+ response_type = "code"
20
+ redirect_uri = "http://localhost:8081/sso-callback"
21
+
22
+ def __init__(self):
23
+ store = Store()
24
+ self.keycloak_url = store.get(STORE_KEYCLOAK_URL, DEFAULT_KEYCLOAK_URL)
25
+ self.realm = store.get(STORE_KEYCLOAK_REALM, DEFAULT_KEYCLOAK_REALM)
26
+ self.client_id = store.get(STORE_KEYCLOAK_CLIENT_ID, DEFAULT_KEYCLOAK_CLIENT_ID)
27
+
28
+ def get_login_url(self) -> str:
29
+ return f"{self.keycloak_url}/realms/{self.realm}/protocol/openid-connect/auth?client_id={self.client_id}&redirect_uri={self.redirect_uri}&response_type={self.response_type}"
30
+
31
+ def exchange_code(self, code) -> str:
32
+ token_url = (
33
+ f"{self.keycloak_url}/realms/{self.realm}/protocol/openid-connect/token"
34
+ )
35
+
36
+ data = {
37
+ "client_id": self.client_id,
38
+ "grant_type": "authorization_code",
39
+ "code": code,
40
+ "redirect_uri": self.redirect_uri,
41
+ }
42
+
43
+ response = requests.post(
44
+ token_url,
45
+ data=data,
46
+ headers={"Content-Type": "application/x-www-form-urlencoded"},
47
+ )
48
+
49
+ if response.status_code != 200:
50
+ return None
51
+
52
+ return response.json().get("access_token", None)
@@ -0,0 +1,74 @@
1
+ import click
2
+
3
+
4
+ # Main CLI Group
5
+ @click.group()
6
+ def cli():
7
+ """Weni CLI"""
8
+
9
+
10
+ # Login Command
11
+ @cli.command("login")
12
+ def login():
13
+ """Login with your Weni account"""
14
+ from weni_cli.commands.login import LoginHandler
15
+
16
+ LoginHandler().execute()
17
+
18
+
19
+ # Nested CLI Project Group
20
+ @cli.group()
21
+ def project():
22
+ """Project commands"""
23
+
24
+
25
+ # Project Group Commands
26
+ @project.command("list")
27
+ @click.option("--org", "-o", help="Filter by organization", type=click.UUID)
28
+ def list_projects(org):
29
+ """List projects"""
30
+ from weni_cli.commands.project_list import ProjectListHandler
31
+
32
+ ProjectListHandler().execute(org_uuid=org)
33
+
34
+
35
+ @project.command("use")
36
+ @click.argument("project_uuid", required=True)
37
+ def use_project(project_uuid):
38
+ """Set the project to be used in the CLI
39
+
40
+ PROJECT_UUID: The UUID of the project to be used
41
+ """
42
+ from weni_cli.commands.project_use import ProjectUseHandler
43
+
44
+ ProjectUseHandler().execute(project_uuid=project_uuid)
45
+
46
+
47
+ @project.command("current")
48
+ def current_project():
49
+ """Show current selected project"""
50
+ from weni_cli.commands.project_current import ProjectCurrentHandler
51
+
52
+ ProjectCurrentHandler().execute()
53
+
54
+
55
+ @project.command("push")
56
+ @click.argument(
57
+ "definition", required=True, type=click.Path(exists=True, dir_okay=False)
58
+ )
59
+ @click.option("--force-update", is_flag=True, help="Force update to the project")
60
+ def push_project(definition, force_update):
61
+ """Push an Agent definition to the current project
62
+
63
+ DEFINITION: The path to the YAML agent definition file
64
+ """
65
+ from weni_cli.commands.project_push import ProjectPushHandler
66
+
67
+ try:
68
+ ProjectPushHandler().execute(definition=definition, force_update=force_update)
69
+ except Exception as e:
70
+ click.echo(f"Error: {e}")
71
+
72
+
73
+ if __name__ == "__main__":
74
+ cli()
@@ -0,0 +1,10 @@
1
+ import click
2
+
3
+
4
+ class Handler:
5
+ def execute(self, **kwargs):
6
+ raise NotImplementedError()
7
+
8
+ def exit(self, error=None):
9
+ if error:
10
+ click.echo(f"An error occurred: {error}")
@@ -0,0 +1,46 @@
1
+ import click
2
+ import os
3
+ import json
4
+
5
+ from pathlib import Path
6
+
7
+ STORE_TOKEN_KEY = "token"
8
+ STORE_PROJECT_UUID_KEY = "project_uuid"
9
+ STORE_WENI_BASE_URL = "weni_base_url"
10
+ STORE_NEXUS_BASE_URL = "nexus_base_url"
11
+ STORE_KEYCLOAK_URL = "keycloak_url"
12
+ STORE_KEYCLOAK_REALM = "keycloak_realm"
13
+ STORE_KEYCLOAK_CLIENT_ID = "keycloak_client_id"
14
+
15
+
16
+ class Store:
17
+ file_path = f"{Path.home()}{os.sep}.weni_cli"
18
+
19
+ # Validates that the file exists, if it does not exist, it creates it with an empty dictionary
20
+ def __init__(self):
21
+ with click.open_file(self.file_path, "a+") as file:
22
+ file.seek(0)
23
+ content = file.read()
24
+ if not content:
25
+ file.write("{}")
26
+
27
+ file.close()
28
+
29
+ def get(self, key, default=None):
30
+ with click.open_file(self.file_path, "r") as file:
31
+ content = json.loads(file.read())
32
+ file.close()
33
+ return content.get(key, default)
34
+
35
+ def set(self, key, value):
36
+ content = {}
37
+ with click.open_file(self.file_path, "r") as file:
38
+ content = json.loads(file.read())
39
+ file.close()
40
+
41
+ with click.open_file(self.file_path, "w") as file:
42
+ content[key] = value
43
+ file.write(json.dumps(content))
44
+ file.close()
45
+
46
+ return True
@@ -0,0 +1,33 @@
1
+ import click
2
+
3
+ from flask import Flask, request
4
+ from multiprocessing import Process, Pipe
5
+
6
+ app = Flask(__name__)
7
+ server_process = None
8
+ auth_parent_conn, auth_child_conn = Pipe()
9
+
10
+
11
+ @app.route("/sso-callback", methods=["GET"])
12
+ def sso_callback():
13
+ auth_child_conn.send(request.args.get("code"))
14
+ return "Successfully logged in, you can close this window now"
15
+
16
+
17
+ def serve():
18
+ from waitress import serve
19
+
20
+ global server_process
21
+
22
+ server_process = Process(
23
+ target=serve,
24
+ kwargs={"app": app, "host": "0.0.0.0", "port": 8081, "_quiet": True},
25
+ )
26
+ server_process.start()
27
+
28
+
29
+ def shutdown():
30
+ global server_process
31
+ if server_process is not None:
32
+ server_process.terminate()
33
+ server_process = None
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.1
2
+ Name: weni-cli
3
+ Version: 0.1.0
4
+ Requires-Dist: Click
5
+ Requires-Dist: requests
6
+ Requires-Dist: flask
7
+ Requires-Dist: waitress
8
+ Requires-Dist: pyyaml
9
+ Requires-Dist: python-slugify
@@ -0,0 +1,16 @@
1
+ README.md
2
+ pyproject.toml
3
+ setup.py
4
+ tests/__init__.py
5
+ weni_cli/__init__.py
6
+ weni_cli/auth.py
7
+ weni_cli/cli.py
8
+ weni_cli/handler.py
9
+ weni_cli/store.py
10
+ weni_cli/wsgi.py
11
+ weni_cli.egg-info/PKG-INFO
12
+ weni_cli.egg-info/SOURCES.txt
13
+ weni_cli.egg-info/dependency_links.txt
14
+ weni_cli.egg-info/entry_points.txt
15
+ weni_cli.egg-info/requires.txt
16
+ weni_cli.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ weni = weni_cli.cli:cli
@@ -0,0 +1,6 @@
1
+ Click
2
+ requests
3
+ flask
4
+ waitress
5
+ pyyaml
6
+ python-slugify
@@ -0,0 +1,2 @@
1
+ tests
2
+ weni_cli