Skip to content

Commit

Permalink
Merge branch 'master' into feature/use-personal-branch
Browse files Browse the repository at this point in the history
  • Loading branch information
DylanBaker authored Apr 18, 2024
2 parents 23f5805 + a813974 commit 238da2a
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 11 deletions.
16 changes: 14 additions & 2 deletions spectacles/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@

import spectacles.printer as printer
import spectacles.tracking as tracking
from spectacles.client import DEFAULT_API_VERSION, LookerClient
from spectacles.client import (
DEFAULT_API_VERSION,
LOOKML_VALIDATION_TIMEOUT,
LookerClient,
)
from spectacles.exceptions import (
GenericValidationError,
LookerApiError,
Expand Down Expand Up @@ -381,6 +385,7 @@ def main() -> None:
severity=args.severity,
pin_imports=pin_imports,
use_personal_branch=args.use_personal_branch,
timeout=args.timeout,
)
)

Expand Down Expand Up @@ -614,6 +619,12 @@ def _build_lookml_subparser(
"validator to fail. The default is 'warning'."
),
)
subparser.add_argument(
"--timeout",
type=int,
default=LOOKML_VALIDATION_TIMEOUT,
help="Specify the timeout for the LookML validation in seconds.",
)
_build_validator_subparser(subparser_action, subparser)


Expand Down Expand Up @@ -802,6 +813,7 @@ async def run_lookml(
severity: str,
pin_imports: Dict[str, str],
use_personal_branch: bool,
timeout: int,
) -> None:
# Don't trust env to ignore .netrc credentials
async_client = httpx.AsyncClient(trust_env=False)
Expand All @@ -811,7 +823,7 @@ async def run_lookml(
)
runner = Runner(client, project, remote_reset, pin_imports, use_personal_branch)

results = await runner.validate_lookml(ref, severity)
results = await runner.validate_lookml(ref, severity, timeout)
finally:
await async_client.aclose()

Expand Down
11 changes: 8 additions & 3 deletions spectacles/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

DEFAULT_API_VERSION = 4.0
TIMEOUT_SEC = 300
LOOKML_VALIDATION_TIMEOUT = 7200
MAX_ASYNC_CONNECTIONS = 200
DEFAULT_MAX_TRIES = 3
BACKOFF_EXCEPTIONS = (
Expand Down Expand Up @@ -862,10 +863,14 @@ async def content_validation(self) -> JsonDict:
return result # type: ignore[no-any-return]

@backoff.on_exception(backoff.expo, BACKOFF_EXCEPTIONS, max_tries=DEFAULT_MAX_TRIES)
async def lookml_validation(self, project: str) -> JsonDict:
logger.debug(f"Validating LookML for project '{project}'")
async def lookml_validation(
self, project: str, timeout: int = LOOKML_VALIDATION_TIMEOUT
) -> JsonDict:
logger.debug(
f"Validating LookML for project '{project}' with timeout {timeout} seconds."
)
url = utils.compose_url(self.api_url, path=["projects", project, "validate"])
response = await self.post(url=url, timeout=7200)
response = await self.post(url=url, timeout=timeout)

try:
response.raise_for_status()
Expand Down
11 changes: 8 additions & 3 deletions spectacles/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from dataclasses import dataclass
from typing import Any, Dict, List, Optional, Set, Tuple

from spectacles.client import LookerClient
from spectacles.client import LOOKML_VALIDATION_TIMEOUT, LookerClient
from spectacles.exceptions import LookerApiError, SpectaclesException, SqlError
from spectacles.logger import GLOBAL_LOGGER as logger
from spectacles.lookml import CompiledSql, Explore, build_project
Expand Down Expand Up @@ -515,11 +515,16 @@ async def validate_data_tests(
results = project.get_results(validator="data_test")
return results

async def validate_lookml(self, ref: Optional[str], severity: str) -> JsonDict:
async def validate_lookml(
self,
ref: Optional[str],
severity: str,
timeout: int = LOOKML_VALIDATION_TIMEOUT,
) -> JsonDict:
async with self.branch_manager(ref=ref):
validator = LookMLValidator(self.client)
print_header(f"Validating LookML in project {self.project} [{severity}]")
results = await validator.validate(self.project, severity)
results = await validator.validate(self.project, severity, timeout)
return results

async def validate_content(
Expand Down
11 changes: 8 additions & 3 deletions spectacles/validators/lookml.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import Any, Dict, Optional

from spectacles.client import LookerClient
from spectacles.client import LOOKML_VALIDATION_TIMEOUT, LookerClient
from spectacles.exceptions import LookMLError

# Define constants for severity levels
Expand Down Expand Up @@ -31,11 +31,16 @@ class LookMLValidator:
def __init__(self, client: LookerClient):
self.client = client

async def validate(self, project: str, severity: str = "warning") -> Dict[str, Any]:
async def validate(
self,
project: str,
severity: str = "warning",
timeout: int = LOOKML_VALIDATION_TIMEOUT,
) -> Dict[str, Any]:
severity_level: int = NAME_TO_LEVEL[severity]
validation_results = await self.client.cached_lookml_validation(project)
if not validation_results or validation_results.get("stale"):
validation_results = await self.client.lookml_validation(project)
validation_results = await self.client.lookml_validation(project, timeout)
errors = []
lookml_url: Optional[str] = None
for error in validation_results["errors"]:
Expand Down

0 comments on commit 238da2a

Please sign in to comment.