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

Expose programmatic equivalent of CLI commands #1854

Merged
merged 48 commits into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
d030306
export `covalent_start` and `covalent_stop`
araghukas Nov 20, 2023
290481f
check server stopped
araghukas Nov 20, 2023
fab67cd
update changelog
araghukas Nov 20, 2023
46b395c
move commands to main namespace
araghukas Nov 20, 2023
f706575
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 20, 2023
afb9aad
improve docstrings
araghukas Nov 21, 2023
9eba72a
fix `covalent_is_running` to return bool
araghukas Nov 21, 2023
a1004e3
reorder `covalent_is_running` conditions
araghukas Nov 21, 2023
8622ac3
`quiet` mode to suppress stdout; more docstrings
araghukas Nov 21, 2023
7e4117b
use poll function instead of while loop
araghukas Nov 21, 2023
58a48b2
explain package
araghukas Nov 21, 2023
bd367cb
add api docs entry
araghukas Nov 21, 2023
c784193
update api docs
araghukas Nov 21, 2023
e430db5
restore import from `._programmatic`
araghukas Nov 21, 2023
10cd66e
update api docs
araghukas Nov 21, 2023
4cbe7d3
Merge branch 'develop' into 1853-programmatic-cli-commands
araghukas Nov 21, 2023
e18852d
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 21, 2023
8ea150a
add test for new functions
araghukas Nov 21, 2023
e023bde
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 21, 2023
60f9ca2
add test for `covalent_is_running`
araghukas Nov 21, 2023
112c5f4
removing covalent's dependency on dispatcher
kessler-frost Nov 21, 2023
d7c6c05
ignore pip reqs in new package
araghukas Nov 21, 2023
2b4d947
refactor docstrings
araghukas Nov 21, 2023
bca8bc0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 21, 2023
7d18fa4
update docs
araghukas Nov 21, 2023
f6e0e3a
revert api docs
araghukas Nov 21, 2023
d54ee56
include 'Returns' in docstrings so maybe docs will render 🤷 pls
araghukas Nov 21, 2023
ea1c6a6
remove useless 'Returns' from docstrings 🤦‍♂️
araghukas Nov 21, 2023
d7ef463
try autofunction refs to main namespace instead
araghukas Nov 21, 2023
8b107eb
revert using main namespace refs
araghukas Nov 21, 2023
de284c1
add more logging and edit messages
araghukas Nov 22, 2023
13bfdb6
refactor hanging tests
araghukas Nov 22, 2023
f308f8e
refactor tests into functional tests
araghukas Nov 22, 2023
e7709ea
Revert "refactor tests into functional tests"
araghukas Nov 23, 2023
cf6f286
create global var for timeout
araghukas Nov 23, 2023
07fa34e
use mock start and stop commands
araghukas Nov 23, 2023
11247fc
Merge branch 'develop' into 1853-programmatic-cli-commands
kessler-frost Nov 23, 2023
73ac729
Merge branch 'develop' into 1853-programmatic-cli-commands
kessler-frost Nov 23, 2023
3294979
Merge branch 'develop' into 1853-programmatic-cli-commands
kessler-frost Nov 23, 2023
f7220c6
Merge branch 'develop' into 1853-programmatic-cli-commands
kessler-frost Nov 23, 2023
61c27b8
renamed server check function and added import error check tests
kessler-frost Nov 24, 2023
243982b
None wasn't an acceptable value to redirect_stdout
kessler-frost Nov 24, 2023
0e1e07c
refactor to use subprocess
araghukas Nov 24, 2023
ea53935
refactor as multiple tests w/ patched start/stop
araghukas Nov 24, 2023
cf6e48a
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 24, 2023
0491ab1
add nopycln inside new tests
araghukas Nov 24, 2023
2b7f126
renaming things a bit
kessler-frost Nov 24, 2023
1daecca
Merge branch 'develop' into 1853-programmatic-cli-commands
kessler-frost Nov 24, 2023
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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [UNRELEASED]

### Added

- Programmatic equivalents of CLI commands `covalent start` and `covalent stop`

### Fixed

- Lattice-default metadata attributes are now applied correctly
Expand Down
1 change: 1 addition & 0 deletions covalent/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from ._dispatcher_plugins import local_redispatch as redispatch # nopycln: import
from ._dispatcher_plugins import stop_triggers # nopycln: import
from ._file_transfer import strategies as fs_strategies # nopycln: import
from ._programmatic.commands import covalent_is_running, covalent_start, covalent_stop
cjao marked this conversation as resolved.
Show resolved Hide resolved
from ._results_manager.results_manager import ( # nopycln: import
cancel,
get_result,
Expand Down
20 changes: 20 additions & 0 deletions covalent/_programmatic/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Copyright 2021 Agnostiq Inc.
#
# This file is part of Covalent.
#
# Licensed under the Apache License 2.0 (the "License"). A copy of the
# License may be obtained with this software package or at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Use of this file is prohibited except in compliance with the License.
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
NOTE: This package exists to avoid circular imports that would be encountered if
`covalent` imports from `covalent_dispatcher._cli`.
"""
166 changes: 166 additions & 0 deletions covalent/_programmatic/commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
# Copyright 2021 Agnostiq Inc.
#
# This file is part of Covalent.
#
# Licensed under the Apache License 2.0 (the "License"). A copy of the
# License may be obtained with this software package or at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Use of this file is prohibited except in compliance with the License.
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Functions providing programmatic access to Covalent CLI commands."""
import contextlib
import sys
import time
from typing import Any, Callable, Dict, Optional

import click
import psutil

from covalent_dispatcher._cli.service import _read_pid, start, stop

from .._shared_files import logger
from .._shared_files.config import get_config

app_log = logger.app_log


def covalent_is_running() -> bool:
"""Return True if the Covalent server is in a ready state."""
pid = _read_pid(get_config("dispatcher.cache_dir") + "/ui.pid")
return (
pid != -1
and psutil.pid_exists(pid)
and get_config("dispatcher.address") != ''
and get_config("dispatcher.port") != ''
)


def _call_cli_command(
cmd: click.Command,
*,
quiet: bool = False,
**kwargs: Dict[str, Any]
) -> None:
"""Call a CLI command with the specified kwargs.

Args:
func: The CLI command to call.
quiet: Suppress stdout. Defaults to False.
"""
with contextlib.redirect_stdout(None if quiet else sys.stdout):
ctx = click.Context(cmd)
ctx.invoke(cmd, **kwargs)


def _poll_with_timeout(
callable_: Callable[[], bool],
*,
waiting_msg: str,
timeout_msg: str,
timeout: int,
) -> None:
"""Poll a callable once per second, until it returns True or a timeout is reached.

Args:
callable_: The callable to poll.
waiting_msg: Log message to display while waiting.
timeout_msg: Error message to display if timeout is reached.
timeout: Timeout in seconds.

Raises:
TimeoutError: _description_
"""
_num_wait = 0
_max_wait = timeout

while not callable_():
app_log.debug(waiting_msg)

time.sleep(1)
_num_wait += 1
if _num_wait >= _max_wait:
raise TimeoutError(timeout_msg)


def covalent_start(
develop: bool = False,
port: Optional[str] = None,
mem_per_worker: Optional[str] = None,
workers: Optional[int] = None,
threads_per_worker: Optional[int] = None,
ignore_migrations: bool = False,
no_cluster: bool = False,
no_triggers: bool = False,
triggers_only: bool = False,
*,
quiet: bool = False,
) -> None:
"""Start the Covalent server. Wrapper for the `covalent start` CLI command.
This function returns immediately if the local Covalent server is already running.

Args:
develop: Start local server in develop mode. Defaults to False.
port: Local server port number. Defaults to 48008.
mem_per_worker: Memory limit per worker in GB. Defaults to auto.
workers: Number of Dask workers. Defaults to 8.
threads_per_worker: Number of threads per Dask worker. Defaults to 1.
ignore_migrations: Start server without database migrations. Defaults to False.
no_cluster: Start server without Dask cluster. Defaults to False.
no_triggers: Start server without a triggers server. Defaults to False.
triggers_only: Start only the triggers server. Defaults to False.
quiet: Suppress stdout. Defaults to False.
"""
if covalent_is_running():
return

kwargs = {
"develop": develop,
"port": port or get_config("dispatcher.port"),
"mem_per_worker": mem_per_worker or get_config("dask.mem_per_worker"),
"workers": workers or get_config("dask.num_workers"),
"threads_per_worker": threads_per_worker or get_config("dask.threads_per_worker"),
"ignore_migrations": ignore_migrations,
"no_cluster": no_cluster,
"no_triggers": no_triggers,
"triggers_only": triggers_only,
}

# Run the `covalent start [OPTIONS]` command.
_call_cli_command(start, quiet=quiet, **kwargs)

# Wait to confirm Covalent server is running.
_poll_with_timeout(
covalent_is_running,
waiting_msg="Waiting for Covalent Server to start...",
timeout_msg="Covalent Server failed to start!",
timeout=10,
)


def covalent_stop(*, quiet: bool = False) -> None:
"""Stop the Covalent server. Wrapper for the `covalent stop` CLI command.
This function returns immediately if the local Covalent server is not running.

Args:
quiet: Suppress stdout. Defaults to False.
"""
if not covalent_is_running():
santoshkumarradha marked this conversation as resolved.
Show resolved Hide resolved
return

# Run the `covalent stop` command.
_call_cli_command(stop, quiet=quiet)

# Wait to confirm Covalent server is stopped.
_poll_with_timeout(
lambda: not covalent_is_running(),
waiting_msg="Waiting for Covalent server to stop...",
timeout_msg="Failed to stop Covalent server!",
timeout=10,
)
22 changes: 22 additions & 0 deletions doc/source/api/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Covalent API

The following API documentation describes how to use Covalent.

- The :ref:`covalent_server` manages workflow dispatch, orchestration, and metadata
- :ref:`electrons_api` and :ref:`lattices_api` are used for constructing workflows
- :ref:`qelectrons_api` are used to customize and track quantum circuit execution
- :ref:`qclusters_api` are used to distribute Quantum Electrons across multiple quantum backends.
Expand All @@ -22,6 +23,27 @@ The following API documentation describes how to use Covalent.
- :ref:`dispatcher_interface` is used for dispatching workflows and stopping triggered dispatches
- The :ref:`dispatcher_server_api` is used for interfacing with the Covalent server

.. _covalent_server:

Covalent Server
"""""""""""""""""""""""""""
A Covalent server must be running in order to dispatch workflows. The Covalent CLI provides various utilities for starting, stopping, and managing a Covalent server. For more information, see:

.. code-block:: bash

covalent --help

The Covalent SDK also includes a Python interface for starting and stopping the covalent server.

.. autofunction:: covalent._programmatic.commands.covalent_is_running

.. autofunction:: covalent._programmatic.commands.covalent_start

.. autofunction:: covalent._programmatic.commands.covalent_stop


----------------------------------------------------------------

.. _electrons_api:

Electron
Expand Down
Loading