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

Move to flat layout #3

Merged
merged 3 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:

- name: Install project
run: |
uv sync
make install-dev

- name: Install LocalStack
run: |
Expand Down
27 changes: 9 additions & 18 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,28 @@ TEST_EXEC ?= python -m
PYTEST_LOGLEVEL ?= warning
PIP_CMD ?= pip

venv: $(VENV_ACTIVATE) ## Create a new (empty) virtual environment
install: ## omit dev dependencies
uv sync --no-dev

$(VENV_ACTIVATE): src
test -d $(VENV_DIR) || $(VENV_BIN) $(VENV_DIR)
$(VENV_RUN); $(PIP_CMD) install --upgrade pip
touch $(VENV_ACTIVATE)

install: venv #
$(VENV_RUN); $(PIP_CMD) install -r ./localstack-sdk-generated/requirements.txt
$(VENV_RUN); pip install -e ./localstack-sdk-generated
$(VENV_RUN); pip install -e ./localstack-sdk-python

install-dev: install
$(VENV_RUN); pip install -e ./localstack-sdk-python[test]
install-dev: ## create the venv and install
uv sync

build-spec: ## build the entire localstack api spec (openapi.yaml in the root folder)
$(VENV_RUN); python scripts/create_spec.py

clean: ## Clean up
clean: ## Clean up the virtual environment
rm -rf $(VENV_DIR)

clean-generated: ## Cleanup generated code
rm -rf packages/localstack-sdk-generated/localstack/

format: ## Run ruff to format the whole codebase
($(VENV_RUN); python -m ruff format .; python -m ruff check --output-format=full --exclude packages --fix .)
format:
($(VENV_RUN); python -m ruff format --exclude packages .; python -m ruff check --output-format=full --exclude packages --fix .)

lint:
($(VENV_RUN); python -m ruff check --exclude localstack-sdk/localstack/generated --output-format=full . && python -m ruff format --exclude packages --check .)
($(VENV_RUN); python -m ruff check --exclude packages --output-format=full . && python -m ruff format --exclude packages --check .)

test: ## Run automated tests
($(VENV_RUN); $(TEST_EXEC) pytest --durations=10 --log-cli-level=$(PYTEST_LOGLEVEL) $(PYTEST_ARGS) $(TEST_PATH))

.PHONY: venv clean
.PHONY: clean install install-dev
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

class BaseClient:
"""A BaseClient creates a configuration and instantiate a ApiClient"""

configuration: Configuration
_api_client: ApiClient
auth_token: str | None
Expand All @@ -14,4 +15,4 @@ def __init__(self, host: str | None = None, auth_token: str | None = None, **kwa
_host = host or "http://localhost.localstack.cloud:4566"
self.auth_token = auth_token or os.getenv("LOCALSTACK_AUTH_TOKEN", "").strip("'\" ")
self.configuration = Configuration(host=_host)
self._api_client = ApiClient(configuration=self.configuration)
self._api_client = ApiClient(configuration=self.configuration)
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from localstack.sdk.chaos.client import ChaosClient

__all__ = [
"ChaosClient"
]
__all__ = ["ChaosClient"]
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@ def get_network_effects(self) -> NetworkEffectsConfig:
def set_network_effects(
self, network_effects_config: NetworkEffectsConfig
) -> NetworkEffectsConfig:
return self._client.set_network_effects_0(
network_effects_config=network_effects_config
)
return self._client.set_network_effects_0(network_effects_config=network_effects_config)


def get_default(**args) -> ChaosClient:
"""Return a default chaos client with a default configuration"""
return ChaosClient(**args)
return ChaosClient(**args)
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from localstack.sdk.pods.client import PodsClient

__all__ = [
"PodsClient"
]
__all__ = ["PodsClient"]
Original file line number Diff line number Diff line change
@@ -1,31 +1,26 @@
import base64
import json

from localstack.sdk.api import PodsApi
from localstack.clients import BaseClient
from localstack.sdk.models import RemoteConfig, PodSaveRequest
from localstack.sdk.api import PodsApi
from localstack.sdk.models import PodSaveRequest, RemoteConfig


def _empty_remote_config() -> RemoteConfig:
return RemoteConfig(
oneof_schema_1_validator={},
actual_instance={}
)
return RemoteConfig(oneof_schema_1_validator={}, actual_instance={})


def _read_ndjson(raw_content: bytes) -> list[dict]:
ndjson_str = raw_content.decode('utf-8')
ndjson_str = raw_content.decode("utf-8")
return [json.loads(line) for line in ndjson_str.splitlines()]


def _get_completion_event(streamed_response: list[dict]) -> dict | None:
completion_events = [
line for line in streamed_response if line.get("event") == "completion"
]
completion_events = [line for line in streamed_response if line.get("event") == "completion"]
return completion_events[0] if completion_events else None

class PodsClient(BaseClient):

class PodsClient(BaseClient):
def __init__(self, **args) -> None:
super().__init__(**args)
self._client = PodsApi(self._api_client)
Expand All @@ -39,9 +34,11 @@ def save_pod(self, pod_name: str) -> None:
:raise exception if the save does not succeed
"""
try:
response = self._client.save_pod_0_with_http_info(name=pod_name, pod_save_request=PodSaveRequest())
response = self._client.save_pod_0_with_http_info(
name=pod_name, pod_save_request=PodSaveRequest()
)
except Exception as e:
raise(e)
raise (e)
if response.status_code != 200:
pass
streamed_response = _read_ndjson(response.raw_data)
Expand All @@ -54,7 +51,9 @@ def load_pod(self, pod_name: str) -> None:
"""
:raise exception if the load does not succeed
"""
response = self._client.load_pod_0_with_http_info(name=pod_name, remote_config=_empty_remote_config())
response = self._client.load_pod_0_with_http_info(
name=pod_name, remote_config=_empty_remote_config()
)
if response.status_code != 200:
pass
streamed_response = _read_ndjson(response.raw_data)
Expand All @@ -74,6 +73,5 @@ def list_pods(self):

def get_platform_auth_header(token: str) -> dict[str, str]:
_token = f":{token}"
auth_encoded = base64.b64encode(_token.encode('utf-8')).decode('utf-8')
auth_encoded = base64.b64encode(_token.encode("utf-8")).decode("utf-8")
return {"Authorization": f"Basic {auth_encoded}"}

34 changes: 28 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,46 @@ members = ["packages/*"]
[tool.setuptools]
include-package-data = false

package-dir = { "" = "localstack-sdk-python"}

[tool.setuptools.packages.find]
where = ["src"]
include = ["*"]
where = ["localstack-sdk-python/"]
include = ["localstack*"]
exclude = ["tests*"]

[tool.ruff]
# Extend the ruff config in the root dir
extend = "../ruff.toml"
# Always generate Python 3.8-compatible code.
target-version = "py38"
line-length = 100
src = ["tests", "localstack"]
src = ["localstack-sdk-python", "tests"]
exclude = [
".venv*",
"venv*",
"dist",
"build",
"target",
"*.egg-info",
"localstack-sdk-python/*.egg-info",
".git",
]
]

[tool.ruff.lint]
ignore = [
"B007", # TODO Loop control variable x not used within loop body
"B017", # TODO `pytest.raises(Exception)` should be considered evil
"B019", # TODO Use of `functools.lru_cache` or `functools.cache` on methods can lead to memory leaks
"B022", # TODO No arguments passed to `contextlib.suppress`. No exceptions will be suppressed and therefore this context manager is redundant
"B023", # TODO Function definition does not bind loop variable `server`
"B024", # TODO x is an abstract base class, but it has no abstract methods
"B027", # TODO `Server.do_shutdown` is an empty method in an abstract base class, but has no abstract decorator
"B904", # TODO Within an `except` clause, raise exceptions with `raise ... from err` or `raise ... from None` to distinguish them from errors in exception handling
"C408", # TODO Unnecessary `list` call (rewrite as a literal)
"C416", # TODO Unnecessary `set` comprehension
"C901", # TODO function is too complex
"E402", # TODO Module level import not at top of file
"E501", # E501 Line too long - handled by black, see https://docs.astral.sh/ruff/faq/#is-ruff-compatible-with-black
"E721", # TODO Do not compare types, use `isinstance()`
"T201", # TODO `print` found
"T203", # TODO `pprint` found
]
select = ["B", "C", "E", "F", "I", "W", "T", "B9", "G"]
1 change: 1 addition & 0 deletions scripts/create_spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from pathlib import Path

import yaml

from localstack.utils.openapi import get_localstack_openapi_spec

openapi_path = Path(os.path.dirname(__file__)) / ".." / "openapi.yaml"
Expand Down
Empty file removed src/README.md
Empty file.
2 changes: 1 addition & 1 deletion tests/integration/test_chaos.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ def test_context_manager(self):
rules = [FaultRule(region="us-east-1", service="s3")]
with fault_configuration(fault_rules=rules):
assert self.client.get_fault_rules() == rules
assert not self.client.get_fault_rules()
assert not self.client.get_fault_rules()
6 changes: 3 additions & 3 deletions tests/integration/test_pods.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from localstack.sdk.pods import PodsClient

POD_NAME = f"ls-sdk-integration"
POD_NAME = "ls-sdk-integration"


class TestPodsClient():
class TestPodsClient:
client = PodsClient()

def test_pod_list(self):
Expand All @@ -13,4 +13,4 @@ def test_pod_list(self):
def test_pod_crud(self):
self.client.save_pod(pod_name=POD_NAME)
self.client.load_pod(pod_name=POD_NAME)
self.client.delete_pod(pod_name=POD_NAME)
self.client.delete_pod(pod_name=POD_NAME)