Skip to content

Commit

Permalink
Merge branch 'main' into zack-192-git-repo-settings
Browse files Browse the repository at this point in the history
* main:
  build: Embrace ruff (#319)
  refactor: inject url path parts instead of endpoints (#315)
  • Loading branch information
schloerke committed Oct 31, 2024
2 parents 0dde373 + 22842ea commit cad4808
Show file tree
Hide file tree
Showing 46 changed files with 399 additions and 394 deletions.
5 changes: 5 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"recommendations": [
"charliermarsh.ruff"
]
}
17 changes: 17 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
{
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
"files.encoding": "utf8",
"files.eol": "\n",
"python.testing.pytestArgs": [
"tests"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"[python]": {
"editor.defaultFormatter": "charliermarsh.ruff",
"editor.formatOnSave": true,
"editor.tabSize": 4,
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
},
"files.exclude": {
"**/__pycache__": true,
"build/**": true
},
"editor.rulers": [99],
}
5 changes: 3 additions & 2 deletions examples/connect/databricks/dash/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
html.Div(id="greeting", children="Loading..."),
html.Div(id="table-container"),
html.Div(id="dummy"), # dummy element to trigger callback on page load
]
],
)


Expand All @@ -38,7 +38,8 @@ def update_page(_):
"""
session_token = flask.request.headers.get("Posit-Connect-User-Session-Token")
posit_strategy = PositCredentialsStrategy(
local_strategy=databricks_cli, user_session_token=session_token
local_strategy=databricks_cli,
user_session_token=session_token,
)
cfg = Config(
host=DATABRICKS_HOST_URL,
Expand Down
8 changes: 6 additions & 2 deletions examples/connect/databricks/fastapi/app.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# -*- coding: utf-8 -*-
# mypy: ignore-errors
from __future__ import annotations

import os
from typing import Annotated
from typing import TYPE_CHECKING, Annotated

from databricks import sql
from databricks.sdk.core import Config, databricks_cli
from fastapi import FastAPI, Header
from fastapi.responses import JSONResponse

from posit.connect.external.databricks import PositCredentialsStrategy

if TYPE_CHECKING:
from fastapi.responses import JSONResponse

DATABRICKS_HOST = os.getenv("DATABRICKS_HOST")
DATABRICKS_HOST_URL = f"https://{DATABRICKS_HOST}"
SQL_HTTP_PATH = os.getenv("DATABRICKS_PATH")
Expand Down
3 changes: 2 additions & 1 deletion examples/connect/databricks/flask/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ def get_fares():

session_token = request.headers.get("Posit-Connect-User-Session-Token")
posit_strategy = PositCredentialsStrategy(
local_strategy=databricks_cli, user_session_token=session_token
local_strategy=databricks_cli,
user_session_token=session_token,
)
cfg = Config(
host=DATABRICKS_HOST_URL,
Expand Down
3 changes: 2 additions & 1 deletion examples/connect/databricks/shiny/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ def server(i: Inputs, o: Outputs, session: Session):
"""
session_token = session.http_conn.headers.get("Posit-Connect-User-Session-Token")
posit_strategy = PositCredentialsStrategy(
local_strategy=databricks_cli, user_session_token=session_token
local_strategy=databricks_cli,
user_session_token=session_token,
)
cfg = Config(
host=DATABRICKS_HOST_URL,
Expand Down
3 changes: 2 additions & 1 deletion examples/connect/databricks/streamlit/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@

session_token = st.context.headers.get("Posit-Connect-User-Session-Token")
posit_strategy = PositCredentialsStrategy(
local_strategy=databricks_cli, user_session_token=session_token
local_strategy=databricks_cli,
user_session_token=session_token,
)
cfg = Config(
host=DATABRICKS_HOST_URL,
Expand Down
16 changes: 12 additions & 4 deletions integration/tests/posit/connect/test_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ class TestUser:
def setup_class(cls):
cls.client = client = connect.Client()
cls.aron = client.users.create(
username="aron", email="[email protected]", password="s3cur3p@ssword"
username="aron",
email="[email protected]",
password="s3cur3p@ssword",
)
cls.bill = client.users.create(
username="bill", email="[email protected]", password="s3cur3p@ssword"
username="bill",
email="[email protected]",
password="s3cur3p@ssword",
)
cls.cole = client.users.create(
username="cole", email="[email protected]", password="s3cur3p@ssword"
username="cole",
email="[email protected]",
password="s3cur3p@ssword",
)

def test_lock(self):
Expand Down Expand Up @@ -71,7 +77,9 @@ def test_find_one(self):

def test_multiple_users(self):
user = self.client.users.create(
username="example", email="[email protected]", password="s3cur3p@ssword"
username="example",
email="[email protected]",
password="s3cur3p@ssword",
)
# assert filtering limits to the provided user.
assert self.me.content.find_one() == self.content
Expand Down
55 changes: 43 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,19 @@ docstring-code-format = true
docstring-code-line-length = "dynamic"

[tool.ruff.lint]
select = [
extend-ignore = [
"E501", # Line too long
"PT011", # `pytest.raises(ValueError)` is too broad
"PT022", # No teardown in fixture
"F841", # Local variable is assigned but never used
"COM812", # missing-trailing-comma
"ISC001", # single-line-implicit-string-concatenation
"ISC002", # multi-line-implicit-string-concatenation
]
extend-select = [
# "C90", # Many false positives # C90; mccabe: https://docs.astral.sh/ruff/rules/complex-structure/
# "DTZ", # Dates with timezones are different from dates without timezones # DTZ; flake8-datetimez: https://docs.astral.sh/ruff/rules/#flake8-datetimez-dtz

# flake8-builtins
# https://docs.astral.sh/ruff/rules/#flake8-builtins-a
#
Expand All @@ -58,17 +70,28 @@ select = [
# Check docstring formatting. Many of these rules are intentionally ignored below.
"D",

# pyflakes - unused-import
# https://docs.astral.sh/ruff/rules/unused-import/
#
# Check for unused imports.
"F401",

# isort
# https://docs.astral.sh/ruff/rules/#isort-i
#
# Sort imports.
"I",
"E", # E; pycodestyle: https://docs.astral.sh/ruff/rules/#pycodestyle-e-w
"F", # F; Pyflakes: https://docs.astral.sh/ruff/rules/#pyflakes-f
"I", # I; isort: https://docs.astral.sh/ruff/rules/#isort-i
"B", # B; flake8-bugbear: https://docs.astral.sh/ruff/rules/#flake8-bugbear-b
"Q", # Q; flake8-quotes: https://docs.astral.sh/ruff/rules/#flake8-quotes-q
"COM", # COM; Commas: https://docs.astral.sh/ruff/rules/#flake8-commas-com
"C4", # C4; flake8-comprehensions: https://docs.astral.sh/ruff/rules/#flake8-comprehensions-c4
"FA102", # FA102; flake8-future-annotations: https://docs.astral.sh/ruff/rules/#flake8-future-annotations-fa
"ISC", # ISC; flake8-implicit-str-concat: https://docs.astral.sh/ruff/rules/#flake8-implicit-str-concat-isc
"ICN", # ICN; flake8-import-conventions: https://docs.astral.sh/ruff/rules/#flake8-import-conventions-icn
"PIE", # PIE; flake8-pie: https://docs.astral.sh/ruff/rules/#flake8-pie-pie
"PYI013", # PYI013; flake8-pyi Non-empty class body must not contain `...`: https://docs.astral.sh/ruff/rules/#flake8-pyi-pyi
"PYI030", # PYI030; flake8-pyi Multiple literal members in a union: https://docs.astral.sh/ruff/rules/#flake8-pyi-pyi
"PYI034", # PYI034; flake8-pyi `__new__` methods usually reutrn `Self`: https://docs.astral.sh/ruff/rules/#flake8-pyi-pyi
"PT", # PT; flake8-pytest-style: https://docs.astral.sh/ruff/rules/#flake8-pytest-style-pt
"SIM118", # SIM118; flake8-simplify Use `key {operator} dict`: https://docs.astral.sh/ruff/rules/#flake8-simplify-sim
"TCH", # TCH; flake8-type-checking: https://docs.astral.sh/ruff/rules/#flake8-type-checking-tch
# "FIX", # FIX; flake8-fixme: https://docs.astral.sh/ruff/rules/#flake8-fixme-fix
# "PGH", # PGH; pygrep-hooks: https://docs.astral.sh/ruff/rules/#pygrep-hooks-pgh
"NPY", # NPY; NumPy-specific rules: https://docs.astral.sh/ruff/rules/#numpy-specific-rules-npy
"RUF005", # RUF005; Ruff specific rules Consider {expression} instead of concatenation: https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf
"RUF100", # RUF100; Ruff specific rules Unused `noqa` directive https://docs.astral.sh/ruff/rules/#ruff-specific-rules-ruf
]
ignore = [
# NumPy style docstring convention with noted exceptions.
Expand All @@ -95,6 +118,14 @@ ignore = [
[tool.ruff.lint.pydocstyle]
convention = "numpy"

# # Ruff is enabled in config file to run on save
# Disable isort due to timing conflict with ruff
[tool.isort]
skip_glob = "**"
# Disable local black to avoid conflict with ruff
[tool.black]
exclude = ".*"


[dependency-groups]
build = ["build"]
Expand Down
4 changes: 2 additions & 2 deletions src/posit/connect/bundles.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ def download(self, output: io.BufferedWriter | str) -> None:
"""
if not isinstance(output, (io.BufferedWriter, str)):
raise TypeError(
f"download() expected argument type 'io.BufferedWriter` or 'str', but got '{type(output).__name__}'"
f"download() expected argument type 'io.BufferedWriter` or 'str', but got '{type(output).__name__}'",
)

path = f"v1/content/{self.content_guid}/bundles/{self.id}/download"
Expand Down Expand Up @@ -160,7 +160,7 @@ def create(self, archive: io.BufferedReader | bytes | str) -> Bundle:
data = file.read()
else:
raise TypeError(
f"create() expected argument type 'io.BufferedReader', 'bytes', or 'str', but got '{type(archive).__name__}'"
f"create() expected argument type 'io.BufferedReader', 'bytes', or 'str', but got '{type(archive).__name__}'",
)

path = f"v1/content/{self.content_guid}/bundles"
Expand Down
3 changes: 0 additions & 3 deletions src/posit/connect/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ def __init__(self) -> None:
--------
Client()
"""
...

@overload
def __init__(self, url: str) -> None:
Expand All @@ -88,7 +87,6 @@ def __init__(self, url: str) -> None:
--------
Client("https://connect.example.com)
"""
...

@overload
def __init__(self, url: str, api_key: str) -> None:
Expand All @@ -105,7 +103,6 @@ def __init__(self, url: str, api_key: str) -> None:
--------
>>> Client("https://connect.example.com", abcdefghijklmnopqrstuvwxyz012345")
"""
...

def __init__(self, *args, **kwargs) -> None:
"""Initialize a Client instance.
Expand Down
26 changes: 10 additions & 16 deletions src/posit/connect/content.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import posixpath
import time
from posixpath import dirname
from typing import Any, List, Literal, Optional, overload
from typing import TYPE_CHECKING, Any, List, Literal, Optional, overload

from . import tasks
from .bundles import Bundles
Expand All @@ -15,10 +15,12 @@
from .oauth.associations import ContentItemAssociations
from .permissions import Permissions
from .resources import Resource, ResourceParameters, Resources
from .tasks import Task
from .vanities import VanityMixin
from .variants import Variants

if TYPE_CHECKING:
from .tasks import Task


class ContentItemRepository(Resource):
def __init__(self, params: ResourceParameters, content_guid: str, **kwargs) -> None:
Expand Down Expand Up @@ -88,7 +90,9 @@ class ContentItemOwner(Resource):
class ContentItem(JobsMixin, VanityMixin, Resource):
def __init__(self, /, params: ResourceParameters, **kwargs):
ctx = Context(params.session, params.url)
super().__init__(ctx, **kwargs)
uid = kwargs["guid"]
path = f"v1/content/{uid}"
super().__init__(ctx, path, **kwargs)

def __getitem__(self, key: Any) -> Any:
v = super().__getitem__(key)
Expand Down Expand Up @@ -209,13 +213,13 @@ def render(self) -> Task:
variants = [variant for variant in variants if variant.is_default]
if len(variants) != 1:
raise RuntimeError(
f"Found {len(variants)} default variants. Expected 1. Without a single default variant, the content cannot be refreshed. This is indicative of a corrupted state."
f"Found {len(variants)} default variants. Expected 1. Without a single default variant, the content cannot be refreshed. This is indicative of a corrupted state.",
)
variant = variants[0]
return variant.render()
else:
raise ValueError(
f"Render not supported for this application mode: {self.app_mode}. Did you need to use the 'restart()' method instead? Note that some application modes do not support 'render()' or 'restart()'."
f"Render not supported for this application mode: {self.app_mode}. Did you need to use the 'restart()' method instead? Note that some application modes do not support 'render()' or 'restart()'.",
)


Expand Down Expand Up @@ -245,7 +249,7 @@ def restart(self) -> None:
return None
else:
raise ValueError(
f"Restart not supported for this application mode: {self.app_mode}. Did you need to use the 'render()' method instead? Note that some application modes do not support 'render()' or 'restart()'."
f"Restart not supported for this application mode: {self.app_mode}. Did you need to use the 'render()' method instead? Note that some application modes do not support 'render()' or 'restart()'.",
)

@overload
Expand Down Expand Up @@ -342,12 +346,10 @@ def update(
-------
None
"""
...

@overload
def update(self, **attributes: Any) -> None:
"""Update the content."""
...

def update(self, **attributes: Any) -> None:
"""Update the content."""
Expand Down Expand Up @@ -532,7 +534,6 @@ def create(
-------
ContentItem
"""
...

@overload
def create(self, **attributes) -> ContentItem:
Expand All @@ -542,7 +543,6 @@ def create(self, **attributes) -> ContentItem:
-------
ContentItem
"""
...

def create(self, **attributes) -> ContentItem:
"""Create a content item.
Expand Down Expand Up @@ -588,7 +588,6 @@ def find(
----
Specifying both `name` and `owner_guid` returns at most one content item due to uniqueness.
"""
...

@overload
def find(
Expand Down Expand Up @@ -620,7 +619,6 @@ def find(
----
Specifying both `name` and `owner_guid` returns at most one content item due to uniqueness.
"""
...

@overload
def find(self, include: Optional[str | list[Any]], **conditions) -> List[ContentItem]: ...
Expand Down Expand Up @@ -746,7 +744,6 @@ def find_by(
-------
Optional[ContentItem]
"""
...

@overload
def find_by(self, **attributes) -> Optional[ContentItem]:
Expand All @@ -756,7 +753,6 @@ def find_by(self, **attributes) -> Optional[ContentItem]:
-------
Optional[ContentItem]
"""
...

def find_by(self, **attributes) -> Optional[ContentItem]:
"""Find the first content record matching the specified attributes. There is no implied ordering so if order matters, you should find it yourself.
Expand Down Expand Up @@ -807,7 +803,6 @@ def find_one(
----
Specifying both `name` and `owner_guid` returns at most one content item due to uniqueness.
"""
...

@overload
def find_one(
Expand Down Expand Up @@ -839,7 +834,6 @@ def find_one(
----
Specifying both `name` and `owner_guid` returns at most one content item due to uniqueness.
"""
...

@overload
def find_one(self, **conditions) -> Optional[ContentItem]: ...
Expand Down
Loading

0 comments on commit cad4808

Please sign in to comment.