Skip to content

Commit

Permalink
Merge pull request #260 from bogdant36/CTX-6257
Browse files Browse the repository at this point in the history
CTX-6257: coretex task run entrypoint.py command improvements regarding task acceptance criteria.
  • Loading branch information
dule1322 authored Aug 27, 2024
2 parents 92ecc3f + fa9959d commit 8f5d310
Show file tree
Hide file tree
Showing 10 changed files with 84 additions and 19 deletions.
6 changes: 5 additions & 1 deletion coretex/cli/commands/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import click

from ..modules import user, ui
from ...configuration import UserConfiguration, InvalidConfiguration, ConfigurationNotFound
from ...configuration import UserConfiguration, InvalidConfiguration, ConfigurationNotFound, utils


@click.command()
Expand All @@ -38,5 +38,9 @@ def login() -> None:

ui.stdEcho("Please enter your credentials:")
userConfig = user.configUser()

initialData = utils.fetchInitialData()
userConfig.frontendUrl = initialData.get("frontend_url", "app.coretex.ai/")

userConfig.save()
ui.successEcho(f"User {userConfig.username} successfully logged in.")
2 changes: 1 addition & 1 deletion coretex/cli/commands/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def create(name: str, path: str, project: Optional[str], accuracy: float) -> Non
model.upload(path)

ui.successEcho(f"Model \"{model.name}\" created successfully")
ui.stdEcho(f"A new model has been created. You can open it by clicking on this URL {ui.outputUrl(model.entityUrl())}.")
ui.stdEcho(f"A new model has been created. You can open it by clicking on this URL {ui.outputUrl(userConfig.frontendUrl, model.entityUrl())}.")


@click.group()
Expand Down
8 changes: 6 additions & 2 deletions coretex/cli/commands/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
@click.option("--type", "-t", "projectType", type = int, help = "Project type")
@click.option("--description", "-d", type = str, help = "Project description")
def create(name: Optional[str], projectType: Optional[int], description: Optional[str]) -> None:
project = project_utils.createProject(name, projectType, description)
userConfig = UserConfiguration.load()
project = project_utils.createProject(userConfig.frontendUrl, name, projectType, description)

selectNewProject = ui.clickPrompt("Do you want to select the new project as default? (Y/n)", type = bool, default = True)
if selectNewProject:
Expand Down Expand Up @@ -86,7 +86,11 @@ def select(name: str) -> None:
userConfig.selectProject(project.id)
except ValueError:
ui.errorEcho(f"Project \"{name}\" not found.")
project = project_utils.promptProjectCreate("Do you want to create a project with that name?", name)
project = project_utils.promptProjectCreate(
"Do you want to create a project with that name?",
name,
userConfig.frontendUrl
)
if project is None:
return

Expand Down
28 changes: 26 additions & 2 deletions coretex/cli/commands/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@
from typing import Optional

import click
import webbrowser

from ..modules import ui
from ..modules.project_utils import getProject
from ..modules.user import initializeUserSession
from ..modules.utils import onBeforeCommandExecute
from ..modules.project_utils import getProject
from ..._folder_manager import folder_manager
from ..._task import TaskRunWorker, executeRunLocally, readTaskConfig, runLogger
from ...configuration import UserConfiguration, NodeConfiguration
from ...configuration import UserConfiguration
from ...entities import TaskRun, TaskRunStatus
from ...resources import PYTHON_ENTRY_POINT_PATH
from ..._task import TaskRunWorker, executeRunLocally, readTaskConfig, runLogger
Expand All @@ -36,7 +38,6 @@ class RunException(Exception):


@click.command()
@onBeforeCommandExecute(initializeUserSession)
@click.argument("path", type = click.Path(exists = True, dir_okay = False))
@click.option("--name", type = str, default = None)
@click.option("--description", type = str, default = None)
Expand All @@ -58,6 +59,14 @@ def run(path: str, name: Optional[str], description: Optional[str], snapshot: bo
if selectedProject is None:
return

ui.stdEcho(
"Project info: "
f"\n\tName: {selectedProject.name}"
f"\n\tProject type: {selectedProject.projectType.name}"
f"\n\tDescription: {selectedProject.description}"
f"\n\tCreated on: {selectedProject.createdOn}"
)

taskRun: TaskRun = TaskRun.runLocal(
selectedProject.id,
snapshot,
Expand All @@ -67,6 +76,12 @@ def run(path: str, name: Optional[str], description: Optional[str], snapshot: bo
entryPoint = path
)

ui.stdEcho(
"Task Run successfully started. "
f"You can open it by clicking on this URL {ui.outputUrl(userConfig.frontendUrl, taskRun.entityUrl())}."
)
webbrowser.open(f"{userConfig.frontendUrl}/{taskRun.entityUrl()}")

taskRun.updateStatus(TaskRunStatus.preparingToStart)

with TaskRunWorker(userConfig.refreshToken, taskRun.id):
Expand Down Expand Up @@ -95,3 +110,12 @@ def run(path: str, name: Optional[str], description: Optional[str], snapshot: bo
taskRun.updateStatus(TaskRunStatus.completedWithSuccess)

folder_manager.clearTempFiles()


@click.group()
@onBeforeCommandExecute(initializeUserSession)
def task() -> None:
pass


task.add_command(run, "run")
4 changes: 2 additions & 2 deletions coretex/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from .commands.login import login
from .commands.model import model
from .commands.node import node
from .commands.task import run
from .commands.task import task
from .commands.project import project

from .modules import ui, utils
Expand Down Expand Up @@ -67,6 +67,6 @@ def cli() -> None:
cli.add_command(model)
cli.add_command(project)
cli.add_command(node)
cli.add_command(run)
cli.add_command(task)
cli.add_command(version)
cli.add_command(update)
28 changes: 21 additions & 7 deletions coretex/cli/modules/project_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def selectProjectVisibility() -> ProjectVisibility:
return selectedProjectVisibility


def promptProjectCreate(message: str, name: str) -> Optional[Project]:
def promptProjectCreate(message: str, name: str, frontendUrl: str) -> Optional[Project]:
if not click.confirm(message, default = True):
return None

Expand All @@ -49,7 +49,10 @@ def promptProjectCreate(message: str, name: str) -> Optional[Project]:
try:
project = Project.createProject(name, selectedProjectType)
ui.successEcho(f"Project \"{name}\" created successfully.")
ui.stdEcho(f"A new Project has been created. You can open it by clicking on this URL {ui.outputUrl(project.entityUrl())}.")
ui.stdEcho(
"A new Project has been created. "
f"You can open it by clicking on this URL {ui.outputUrl(frontendUrl, project.entityUrl())}."
)
return project
except NetworkRequestError as ex:
logging.getLogger("cli").debug(ex, exc_info = ex)
Expand All @@ -66,7 +69,11 @@ def promptProjectSelect(userConfig: UserConfiguration) -> Optional[Project]:
userConfig.selectProject(project.id)
except ValueError:
ui.errorEcho(f"Project \"{name}\" not found.")
newProject = promptProjectCreate("Do you want to create a project with that name?", name)
newProject = promptProjectCreate(
"Do you want to create a project with that name?",
name,
userConfig.frontendUrl
)
if newProject is None:
return None

Expand All @@ -75,7 +82,7 @@ def promptProjectSelect(userConfig: UserConfiguration) -> Optional[Project]:
return project


def createProject(name: Optional[str] = None, projectType: Optional[int] = None, description: Optional[str] = None) -> Project:
def createProject(frontendUrl: str, name: Optional[str] = None, projectType: Optional[int] = None, description: Optional[str] = None) -> Project:
if name is None:
name = ui.clickPrompt("Please enter name of the project you want to create", type = str)

Expand All @@ -90,7 +97,10 @@ def createProject(name: Optional[str] = None, projectType: Optional[int] = None,
try:
project = Project.createProject(name, projectType, description = description)
ui.successEcho(f"Project \"{name}\" created successfully.")
ui.stdEcho(f"A new Project has been created. You can open it by clicking on this URL {ui.outputUrl(project.entityUrl())}.")
ui.stdEcho(
"A new Project has been created. "
f"You can open it by clicking on this URL {ui.outputUrl(frontendUrl, project.entityUrl())}."
)
return project
except NetworkRequestError as ex:
logging.getLogger("cli").debug(ex, exc_info = ex)
Expand All @@ -104,7 +114,11 @@ def getProject(name: Optional[str], userConfig: UserConfiguration) -> Optional[P
return Project.fetchOne(name = name)
except:
if projectId is None:
return promptProjectCreate("Project not found. Do you want to create a new Project with that name?", name)
return promptProjectCreate(
"Project not found. Do you want to create a new Project with that name?",
name,
userConfig.frontendUrl
)

return Project.fetchById(projectId)

Expand All @@ -116,6 +130,6 @@ def getProject(name: Optional[str], userConfig: UserConfiguration) -> Optional[P
if not click.confirm("Would you like to create a new Project?", default = True):
return None

return createProject(name)
return createProject(userConfig.frontendUrl, name)

return Project.fetchById(projectId)
4 changes: 2 additions & 2 deletions coretex/cli/modules/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,8 @@ def previewNodeConfig(nodeConfig: NodeConfiguration) -> None:
stdEcho(tabulate(table))


def outputUrl(entityUrl: str) -> str:
return ("\033[4m" + f"https://app.coretex.ai/{entityUrl}" + "\033[0m")
def outputUrl(baseUrl: str, entityUrl: str) -> str:
return ("\033[4m" + f"{baseUrl}/{entityUrl}" + "\033[0m")


def stdEcho(text: str) -> None:
Expand Down
8 changes: 8 additions & 0 deletions coretex/configuration/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ def projectId(self) -> Optional[int]:
def projectId(self, value: Optional[int]) -> None:
self._raw["projectId"] = value

@property
def frontendUrl(self) -> str:
return self.getValue("frontendUrl", str, default = "app.coretex.ai")

@frontendUrl.setter
def frontendUrl(self, value: Optional[str]) -> None:
self._raw["frontendUrl"] = value

def _isConfigValid(self) -> Tuple[bool, List[str]]:
isValid = True
errorMessages = []
Expand Down
11 changes: 10 additions & 1 deletion coretex/configuration/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

from typing import Optional, Tuple, Any
from typing import Optional, Tuple, Any, Dict

from . import config_defaults
from ..networking import networkManager, NetworkRequestError
Expand Down Expand Up @@ -132,3 +132,12 @@ def fetchNodeId(name: str) -> int:
raise TypeError(f"Invalid \"id\" type {type(id)}. Expected: \"int\"")

return id


def fetchInitialData() -> Dict[str, Any]:
response = networkManager.get("user/initial-data")

if response.hasFailed():
raise NetworkRequestError(response, "Failed to fetch user's initial data.")

return response.getJson(dict)
4 changes: 3 additions & 1 deletion coretex/entities/task_run/task_run.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ class TaskRun(NetworkObject, Generic[DatasetType]):
useCachedEnv: bool
executionType: ExecutionType
metrics: List[Metric]
workflowRunId: int

def __init__(self) -> None:
super(TaskRun, self).__init__()
Expand Down Expand Up @@ -164,6 +165,7 @@ def _keyDescriptors(cls) -> Dict[str, KeyDescriptor]:
descriptors["taskId"] = KeyDescriptor("sub_project_id")
descriptors["taskName"] = KeyDescriptor("sub_project_name")
descriptors["executionType"] = KeyDescriptor("execution_type", ExecutionType)
descriptors["workflowRunId"] = KeyDescriptor("pipeline_run_id")

# private properties of the object should not be encoded
descriptors["__parameters"] = KeyDescriptor(isEncodable = False)
Expand All @@ -177,7 +179,7 @@ def _endpoint(cls) -> str:

@override
def entityUrl(self) -> str:
return f"run?id={self.id}"
return f"workflow-run?id={self.workflowRunId}"

def onDecode(self) -> None:
super().onDecode()
Expand Down

0 comments on commit 8f5d310

Please sign in to comment.