Skip to content

Commit

Permalink
Merge pull request #15 from openweathermap/dev
Browse files Browse the repository at this point in the history
Release v1.1.0
  • Loading branch information
SerGeRybakov authored Jan 4, 2024
2 parents a475fe8 + 97adf0a commit 6d4a2a6
Show file tree
Hide file tree
Showing 5 changed files with 632 additions and 460 deletions.
111 changes: 96 additions & 15 deletions deker_shell/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,13 @@
import datetime # noqa F401
import runpy
import sys
from pathlib import Path

from typing import TYPE_CHECKING, Optional # noqa: I101
from typing import TYPE_CHECKING, Optional, Union, Any # noqa: I101

import click as click
import numpy as np # noqa F401
from click import Context, ClickException

from deker import * # noqa F403
from ptpython.repl import embed
Expand All @@ -31,22 +34,22 @@
from deker_shell.help import help # noqa F401
from deker_shell.utils import validate_uri


if TYPE_CHECKING:
from deker import Client, Collection

collection: Optional[Collection] = None # default collection variable, set by use("coll_name") method
client: Optional[Client] = None # default variable for Client instance


async def interactive_shell(uri: str) -> None:
async def interactive_shell(uri: str, **kwargs: Any) -> None:
"""Coroutine that starts a Python REPL from which we can access the Deker interface.
:param uri: client uri
:param uri: uri to Deker storage
:param kwargs: Client parameters
"""
global client
try:
client = Client(uri)
client = Client(uri, **kwargs)
collections: list[str] = [coll.name for coll in client]

def use(name: str) -> None:
Expand All @@ -68,7 +71,7 @@ def get_global_coll_variable() -> Collection:
if client.is_closed:
sys.exit("Client is closed")

print(help_start)
click.echo(help_start)
await embed( # type: ignore
globals=globals(), locals=locals(), return_asyncio_coroutine=True, patch_stdout=True, configure=configure
)
Expand All @@ -79,21 +82,99 @@ def get_global_coll_variable() -> Collection:
if client is not None:
try:
client.close()
print("Exiting Deker")
click.echo("Exiting Deker")
except Exception:
pass


def start() -> None:
"""Application entrypoint."""
if len(sys.argv) < 2:
print("No params passed")
elif sys.argv[1].endswith(".py"):
runpy.run_path(path_name=sys.argv[1])
@click.command(context_settings=dict(ignore_unknown_options=True, allow_extra_args=True))
@click.argument("uri", required=True, type=str)
@click.option("-w", "--workers", type=int, help="Number of threads for Deker.")
@click.option(
"-t",
"--write-lock-timeout",
type=int,
help="An amount of seconds " "during which a parallel writing process " "waits for release of the locked file.",
)
@click.option(
"-c",
"--write-lock-check-interval",
type=int,
help="An amount of time (in seconds) "
"during which a parallel writing process "
"sleeps between checks for locks.",
)
@click.option("-l", "--loglevel", type=str, help="Level of Deker loggers.")
@click.option(
"-m",
"--memory-limit",
type=str,
help="Limit of memory allocation per one array/subset in bytes "
"or in human representation of kilobytes, megabytes or gigabytes,"
" e.g. '100K', '512M', '4G'."
" Human representations will be converted into bytes. "
"If result is <= 0, total RAM + total swap is used.",
)
@click.pass_context
def start(
ctx: Context,
uri: str,
workers: Optional[int] = None,
write_lock_timeout: Optional[int] = None,
write_lock_check_interval: Optional[int] = None,
loglevel: Optional[str] = None,
memory_limit: Optional[Union[int, str]] = None,
) -> None:
"""Application entrypoint.
:param ctx: click Context with extra parameters (kwargs)
:param uri: uri to Deker storage
:param workers: number of threads for Deker
:param write_lock_timeout: An amount of seconds during which a parallel writing process waits for release
of the locked file
:param write_lock_check_interval: An amount of time (in seconds) during which a parallel writing process sleeps
between checks for locks
:param loglevel: Level of Deker loggers
:param memory_limit: Limit of memory allocation per one array/subset in bytes or in human representation of
kilobytes, megabytes or gigabytes, e.g. ``"100K"``, ``"512M"``, ``"4G"``. Human representations will be
converted into bytes. If result is ``<= 0`` - total RAM + total swap is used
.. note:: This parameter is used for early runtime break in case of potential memory overflow
"""
if uri.endswith(".py"):
path = Path(uri)
if not path.exists():
raise ClickException("File does not exist")
runpy.run_path(path_name=uri)
else:
uri: str = sys.argv[1]
validate_uri(uri)
asyncio.run(interactive_shell(uri))

# deker client default parameters
kwargs = {
"workers": workers,
"write_lock_timeout": write_lock_timeout,
"write_lock_check_interval": write_lock_check_interval,
"loglevel": loglevel,
"memory_limit": memory_limit,
}
default_keys = tuple(kwargs.keys())
for key in default_keys:
if not kwargs.get(key):
kwargs.pop(key, None)

# extra parameters
if ctx.args:
for i in range(0, len(ctx.args), 2):
key = ctx.args[i].replace("-", "")
value = ctx.args[i + 1]
if "." in ctx.args[i]:
kwargs_key, inner_key = key.split(".", 1)
kwargs[kwargs_key] = {}
kwargs[kwargs_key][inner_key] = value
else:
kwargs[key] = value

asyncio.run(interactive_shell(uri, **kwargs))


if __name__ == "__main__":
Expand Down
4 changes: 3 additions & 1 deletion deker_shell/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

from urllib.parse import urlparse

from click import ClickException


def validate_uri(uri: str) -> None:
"""Validate uri.
Expand All @@ -24,4 +26,4 @@ def validate_uri(uri: str) -> None:
"""
uri_scheme = urlparse(uri).scheme
if uri_scheme not in ("http", "file"):
raise ValueError("Invalid uri")
raise ClickException("Invalid uri")
Loading

0 comments on commit 6d4a2a6

Please sign in to comment.