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 all 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
1 change: 1 addition & 0 deletions .github/workflows/requirements.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ jobs:
--ignore-file=covalent/triggers/**
--ignore-file=covalent/cloud_resource_manager/**
--ignore-file=covalent/quantum/qserver/**
--ignore-file=covalent/_programmatic/**
covalent

- name: Check missing dispatcher requirements
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ 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`

### Changed

- Changed the azurebatch.rst banner from default covalent jpg to azure batch's svg file
Expand Down
5 changes: 5 additions & 0 deletions covalent/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
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 ( # nopycln: import
covalent_start,
covalent_stop,
is_covalent_running,
)
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`.
"""
161 changes: 161 additions & 0 deletions covalent/_programmatic/commands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
# 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 subprocess
from typing import List, Optional

import psutil

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

__all__ = ["is_covalent_running", "covalent_start", "covalent_stop"]


app_log = logger.app_log

_MISSING_SERVER_WARNING = "Covalent has not been installed with the server component."


def _call_cli_command(cmd: List[str], *, quiet: bool = False) -> subprocess.CompletedProcess:
"""
Call a CLI command with the specified kwargs.

Args:
func: The CLI command to call.
quiet: Suppress stdout. Defaults to :code:`False`.
"""

if quiet:
return subprocess.run(
cmd,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=True,
)

return subprocess.run(cmd, check=True)


def is_covalent_running() -> bool:
"""
Check if the Covalent server is running.

Returns:
:code:`True` if the Covalent server is in a ready state, :code:`False` otherwise.
"""
try:
from covalent_dispatcher._cli.service import _read_pid

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") != ""
)

except ModuleNotFoundError:
# If the covalent_dispatcher is not installed, assume Covalent is not running.
app_log.warning(_MISSING_SERVER_WARNING)
return False


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:
"""
santoshkumarradha marked this conversation as resolved.
Show resolved Hide resolved
Start the Covalent server. Wrapper for the :code:`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 :code:`False`.
port: Local server port number. Defaults to :code:`"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 :code:`False`.
no_cluster: Start server without Dask cluster. Defaults to :code:`False`.
no_triggers: Start server without a triggers server. Defaults to :code:`False`.
triggers_only: Start only the triggers server. Defaults to :code:`False`.
quiet: Suppress stdout. Defaults to :code:`False`.
"""

if is_covalent_running():
msg = "Covalent server is already running."
if not quiet:
print(msg)

app_log.debug(msg)
return

flags = {
"--develop": develop,
"--ignore-migrations": ignore_migrations,
"--no-cluster": no_cluster,
"--no-triggers": no_triggers,
"--triggers-only": triggers_only,
}

args = {
"--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"),
}

cmd = ["covalent", "start"]
cmd.extend(flag for flag, value in flags.items() if value)

for arg, value in args.items():
cmd.extend((arg, str(value)))

# Run the `covalent start [OPTIONS]` command.
app_log.debug("Starting Covalent server programmatically...")
_call_cli_command(cmd, quiet=quiet)


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

Args:
quiet: Suppress stdout. Defaults to :code:`False`.
"""

if not is_covalent_running():
msg = "Covalent server is not running."
if not quiet:
print(msg)

app_log.debug(msg)
return

# Run the `covalent stop` command.
app_log.debug("Stopping Covalent server programmatically...")
_call_cli_command(["covalent", "stop"], quiet=quiet)
24 changes: 24 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,29 @@ 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.is_covalent_running


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


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


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

.. _electrons_api:

Electron
Expand Down
15 changes: 15 additions & 0 deletions tests/covalent_tests/programmatic/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# 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.
Loading
Loading