diff --git a/esxport/__init__.py b/esxport/__init__.py index e94beba..daca1ee 100644 --- a/esxport/__init__.py +++ b/esxport/__init__.py @@ -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__"] diff --git a/esxport/esxport_cli.py b/esxport/cli.py similarity index 89% rename from esxport/esxport_cli.py rename to esxport/cli.py index fbf025f..79de787 100644 --- a/esxport/esxport_cli.py +++ b/esxport/cli.py @@ -7,13 +7,12 @@ 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 .__init__ import __version__ +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 @@ -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() diff --git a/esxport/click_opt/cli_options.py b/esxport/click_opt/cli_options.py index a0e7607..a5bde42 100644 --- a/esxport/click_opt/cli_options.py +++ b/esxport/click_opt/cli_options.py @@ -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) diff --git a/esxport/click_opt/click_custom.py b/esxport/click_opt/click_custom.py index c1e0e05..886a45a 100644 --- a/esxport/click_opt/click_custom.py +++ b/esxport/click_opt/click_custom.py @@ -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.""" diff --git a/esxport/elastic.py b/esxport/elastic.py index cd46b44..176871b 100644 --- a/esxport/elastic.py +++ b/esxport/elastic.py @@ -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: diff --git a/esxport/esxport.py b/esxport/esxport.py index 9acc77c..c2f45f0 100644 --- a/esxport/esxport.py +++ b/esxport/esxport.py @@ -10,25 +10,23 @@ 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 @@ -36,7 +34,10 @@ def __init__(self: Self, opts: CliOptions, es_client: ElasticsearchClient) -> No 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), diff --git a/pyproject.toml b/pyproject.toml index 1f3a736..b050c2e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -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] diff --git a/test/click/__init__.py b/test/cli/__init__.py similarity index 100% rename from test/click/__init__.py rename to test/cli/__init__.py diff --git a/test/click/cli_test.py b/test/cli/cli_test.py similarity index 97% rename from test/click/cli_test.py rename to test/cli/cli_test.py index eafbf79..a3dc3e1 100644 --- a/test/click/cli_test.py +++ b/test/cli/cli_test.py @@ -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 = { @@ -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 @@ -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, diff --git a/test/click/click_test.py b/test/cli/click_test.py similarity index 100% rename from test/click/click_test.py rename to test/cli/click_test.py diff --git a/test/conftest.py b/test/conftest.py index 598a704..dd67600 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -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) diff --git a/test/es_bootstrap.sh b/test/es_bootstrap.sh index 9156e39..9cdaf4f 100755 --- a/test/es_bootstrap.sh +++ b/test/es_bootstrap.sh @@ -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 \ @@ -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" \ @@ -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" \ @@ -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" \