Skip to content

Commit

Permalink
✨ Allow the cli to be imported as module
Browse files Browse the repository at this point in the history
  • Loading branch information
nikhilbadyal committed Aug 18, 2024
1 parent 0809dfa commit d93c96c
Show file tree
Hide file tree
Showing 12 changed files with 42 additions and 44 deletions.
4 changes: 4 additions & 0 deletions esxport/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
"""EsXport CLi."""

from esxport.click_opt.cli_options import CliOptions
from esxport.esxport import EsXport

__version__ = "8.10.0"
__all__ = ["CliOptions", "EsXport", "__version__"]
16 changes: 7 additions & 9 deletions esxport/esxport_cli.py → esxport/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@
from typing import TYPE_CHECKING, Any

import click
from __init__ import __version__
from click import Context, Parameter
from click_params import URL

from esxport import esxport
from esxport.__init__ import __version__
from esxport.click_opt.cli_options import CliOptions
from esxport.click_opt.click_custom import JSON, sort
from esxport.constant import META_FIELDS, default_config_fields
from esxport.elastic import ElasticsearchClient
from esxport.strings import cli_version
from esxport import CliOptions, EsXport

from .click_opt.click_custom import JSON, sort
from .constant import META_FIELDS, default_config_fields
from .strings import cli_version

if TYPE_CHECKING:
from pathlib import Path
Expand Down Expand Up @@ -163,8 +162,7 @@ def cli( # noqa: PLR0913
"""Elastic Search to CSV Exporter."""
kwargs: dict[str, Any] = {k: v for k, v in locals().items() if k != "self"}
cli_options = CliOptions(kwargs)
client = ElasticsearchClient(cli_options)
es = esxport.EsXport(cli_options, client)
es = EsXport(cli_options)
es.export()


Expand Down
6 changes: 2 additions & 4 deletions esxport/click_opt/cli_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@
from __future__ import annotations

import json
from typing import TYPE_CHECKING, Any
from typing import Any

# noinspection PyPackageRequirements
import urllib3
from elastic_transport import SecurityWarning
from typing_extensions import Self

from esxport.constant import default_config_fields

if TYPE_CHECKING:
from typing_extensions import Self

urllib3.disable_warnings()
urllib3.disable_warnings(SecurityWarning)

Expand Down
6 changes: 2 additions & 4 deletions esxport/click_opt/click_custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
from __future__ import annotations

import json
from typing import TYPE_CHECKING, Any
from typing import Any

from click import Context, Parameter, ParamType
from typing_extensions import Self

from esxport.strings import invalid_query_format, invalid_sort_format

if TYPE_CHECKING:
from typing_extensions import Self


class FormatError(ValueError):
"""Invalid input format."""
Expand Down
9 changes: 4 additions & 5 deletions esxport/elastic.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@

import elasticsearch
from elasticsearch import Elasticsearch
from typing_extensions import Self

from esxport.constant import CONNECTION_TIMEOUT
from esxport.exceptions import ScrollExpiredError
from .constant import CONNECTION_TIMEOUT
from .exceptions import ScrollExpiredError

if TYPE_CHECKING:
from typing_extensions import Self

from esxport.click_opt.cli_options import CliOptions
from .click_opt.cli_options import CliOptions


class ElasticsearchClient:
Expand Down
23 changes: 12 additions & 11 deletions esxport/esxport.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,34 @@
from loguru import logger
from tenacity import retry, retry_if_exception_type, stop_after_attempt, wait_exponential
from tqdm import tqdm

from esxport.constant import FLUSH_BUFFER, TIMES_TO_TRY
from esxport.exceptions import FieldNotFoundError, IndexNotFoundError, MetaFieldNotFoundError, ScrollExpiredError
from esxport.strings import index_not_found, meta_field_not_found, output_fields, sorting_by, using_indexes, using_query
from esxport.writer import Writer
from typing_extensions import Self

from .click_opt.click_custom import Json
from .constant import FLUSH_BUFFER, TIMES_TO_TRY
from .elastic import ElasticsearchClient
from .exceptions import FieldNotFoundError, IndexNotFoundError, MetaFieldNotFoundError, ScrollExpiredError
from .strings import index_not_found, meta_field_not_found, output_fields, sorting_by, using_indexes, using_query
from .writer import Writer

if TYPE_CHECKING:
from typing_extensions import Self

from esxport.click_opt.cli_options import CliOptions
from esxport.elastic import ElasticsearchClient
from .click_opt.cli_options import CliOptions


class EsXport(object):
"""Main class."""

def __init__(self: Self, opts: CliOptions, es_client: ElasticsearchClient) -> None:
def __init__(self: Self, opts: CliOptions, es_client: ElasticsearchClient | None = None) -> None:
self.search_args: dict[str, Any] = {}
self.opts = opts
self.num_results = 0
self.scroll_ids: list[str] = []
self.scroll_time = "30m"
self.rows_written = 0

self.es_client = es_client
self.es_client = es_client or self._create_default_client(opts)

def _create_default_client(self: Self, opts: CliOptions) -> ElasticsearchClient:
return ElasticsearchClient(opts)

@retry(
wait=wait_exponential(2),
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Homepage = "https://github.com/nikhilbadyal/esxport"
"Bug Tracker"="https://github.com/nikhilbadyal/esxport/issues"
Repository = "https://github.com/nikhilbadyal/esxport.git"
[project.scripts]
esxport = "esxport.esxport_cli:cli"
esxport = "esxport.cli:cli"


[tool.hatch.version]
Expand Down
File renamed without changes.
6 changes: 3 additions & 3 deletions test/click/cli_test.py → test/cli/cli_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
from typing_extensions import Self

from esxport.__init__ import __version__
from esxport.cli import cli
from esxport.esxport import EsXport
from esxport.esxport_cli import cli
from esxport.strings import cli_version, invalid_query_format, invalid_sort_format

args = {
Expand All @@ -21,7 +21,7 @@
}
usage_error_code = 2
random_pass = "password\n" # noqa: S105
export_module = "esxport.esxport.EsXport"
export_module = "esxport.cli.EsXport"


# noinspection PyTypeChecker
Expand Down Expand Up @@ -119,7 +119,7 @@ def test_query_accepts_dict(self: Self, cli_runner: CliRunner, esxport_obj_with_
assert result.exit_code == 0
TestExport.rm_csv_export_file(esxport_obj_with_data.opts.output_file)

def test_error_is_rasied_on_invalid_json(self: Self, cli_runner: CliRunner) -> None:
def test_error_is_raised_on_invalid_json(self: Self, cli_runner: CliRunner) -> None:
"""Test sort input is in the form field:sort_order."""
result = cli_runner.invoke(
cli,
Expand Down
File renamed without changes.
10 changes: 6 additions & 4 deletions test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,16 @@ def es_client_with_data() -> Mock:

@pytest.fixture()
def esxport_obj(cli_options: CliOptions, es_client_without_data: Mock) -> EsXport:
"""Mocked EsXport class."""
return EsXport(cli_options, es_client_without_data)
"""Mocked EsXport class with patched Elasticsearch client."""
with patch("esxport.esxport.ElasticsearchClient", return_value=es_client_without_data):
return EsXport(cli_options)


@pytest.fixture()
def esxport_obj_with_data(cli_options: CliOptions, es_client_with_data: Mock) -> EsXport:
"""Mocked EsXport class."""
return EsXport(cli_options, es_client_with_data)
"""Mocked EsXport class with patched Elasticsearch client."""
with patch("esxport.esxport.ElasticsearchClient", return_value=es_client_with_data):
return EsXport(cli_options)


@pytest.fixture(autouse=True)
Expand Down
4 changes: 1 addition & 3 deletions test/es_bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ mkdir -p "$(pwd)"/es/plugins

if [[ ! -z $PLUGINS ]]; then
docker run --rm \
--user=0:0 \
--network=elastic \
-v "$(pwd)"/es/plugins/:/usr/share/elasticsearch/plugins/ \
--entrypoint=/usr/share/elasticsearch/bin/elasticsearch-plugin \
Expand Down Expand Up @@ -85,7 +86,6 @@ do
--env "node.name=es${node}" \
--env "cluster.name=docker-elasticsearch" \
--env "cluster.initial_master_nodes=es1" \
--env "discovery.seed_hosts=es1" \
--env "cluster.routing.allocation.disk.threshold_enabled=false" \
--env "bootstrap.memory_lock=true" \
--env "ES_JAVA_OPTS=-Xms1g -Xmx1g" \
Expand All @@ -111,7 +111,6 @@ do
--env "node.name=es${node}" \
--env "cluster.name=docker-elasticsearch" \
--env "cluster.initial_master_nodes=es1" \
--env "discovery.seed_hosts=es1" \
--env "cluster.routing.allocation.disk.threshold_enabled=false" \
--env "bootstrap.memory_lock=true" \
--env "ES_JAVA_OPTS=-Xms1g -Xmx1g" \
Expand All @@ -132,7 +131,6 @@ do
--env "node.name=es${node}" \
--env "cluster.name=docker-elasticsearch" \
--env "cluster.initial_master_nodes=es1" \
--env "discovery.seed_hosts=es1" \
--env "cluster.routing.allocation.disk.threshold_enabled=false" \
--env "bootstrap.memory_lock=true" \
--env "ES_JAVA_OPTS=-Xms1g -Xmx1g" \
Expand Down

0 comments on commit d93c96c

Please sign in to comment.