Skip to content

Commit

Permalink
chore: go live
Browse files Browse the repository at this point in the history
  • Loading branch information
stainless-bot committed Jul 4, 2024
1 parent 7b057fc commit a7590d1
Show file tree
Hide file tree
Showing 15 changed files with 124 additions and 80 deletions.
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM mcr.microsoft.com/vscode/devcontainers/python:0-${VARIANT}

USER vscode

RUN curl -sSf https://rye.astral.sh/get | RYE_VERSION="0.24.0" RYE_INSTALL_OPTION="--yes" bash
RUN curl -sSf https://rye.astral.sh/get | RYE_VERSION="0.35.0" RYE_INSTALL_OPTION="--yes" bash
ENV PATH=/home/vscode/.rye/shims:$PATH

RUN echo "[[ -d .venv ]] && source .venv/bin/activate" >> /home/vscode/.bashrc
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ jobs:
curl -sSf https://rye.astral.sh/get | bash
echo "$HOME/.rye/shims" >> $GITHUB_PATH
env:
RYE_VERSION: 0.24.0
RYE_VERSION: '0.35.0'
RYE_INSTALL_OPTION: '--yes'

- name: Install dependencies
Expand All @@ -41,7 +41,7 @@ jobs:
curl -sSf https://rye.astral.sh/get | bash
echo "$HOME/.rye/shims" >> $GITHUB_PATH
env:
RYE_VERSION: 0.24.0
RYE_VERSION: '0.35.0'
RYE_INSTALL_OPTION: '--yes'

- name: Bootstrap
Expand Down
38 changes: 0 additions & 38 deletions .github/workflows/create-releases.yml

This file was deleted.

25 changes: 0 additions & 25 deletions .github/workflows/handle-release-pr-title-edit.yml

This file was deleted.

12 changes: 8 additions & 4 deletions .github/workflows/publish-pypi.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# workflow for re-running publishing to PyPI in case it fails for some reason
# you can run this workflow by navigating to https://www.github.com/intercom/python-intercom/actions/workflows/publish-pypi.yml
# This workflow is triggered when a GitHub release is created.
# It can also be run manually to re-publish to PyPI in case it failed for some reason.
# You can run this workflow by navigating to https://www.github.com/intercom/python-intercom/actions/workflows/publish-pypi.yml
name: Publish PyPI
on:
workflow_dispatch:

release:
types: [published]

jobs:
publish:
name: publish
Expand All @@ -17,8 +21,8 @@ jobs:
curl -sSf https://rye.astral.sh/get | bash
echo "$HOME/.rye/shims" >> $GITHUB_PATH
env:
RYE_VERSION: 0.24.0
RYE_INSTALL_OPTION: "--yes"
RYE_VERSION: '0.35.0'
RYE_INSTALL_OPTION: '--yes'

- name: Publish to PyPI
run: |
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/release-doctor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,4 @@ jobs:
run: |
bash ./bin/check-release-environment
env:
STAINLESS_API_KEY: ${{ secrets.STAINLESS_API_KEY }}
PYPI_TOKEN: ${{ secrets.INTERCOM_PYPI_TOKEN || secrets.PYPI_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.prism.log
.vscode
_dev

Expand Down
4 changes: 0 additions & 4 deletions bin/check-release-environment
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@

errors=()

if [ -z "${STAINLESS_API_KEY}" ]; then
errors+=("The STAINLESS_API_KEY secret has not been set. Please contact Stainless for an API key & set it in your organization secrets on GitHub.")
fi

if [ -z "${PYPI_TOKEN}" ]; then
errors+=("The INTERCOM_PYPI_TOKEN secret has not been set. Please set it in either this repository's secrets or your organization secrets.")
fi
Expand Down
16 changes: 16 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ dev-dependencies = [
"nox",
"dirty-equals>=0.6.0",
"importlib-metadata>=6.7.0",
"rich>=13.7.1",

]

Expand Down Expand Up @@ -99,6 +100,21 @@ include = [
[tool.hatch.build.targets.wheel]
packages = ["src/python_minus_intercom"]

[tool.hatch.build.targets.sdist]
# Basically everything except hidden files/directories (such as .github, .devcontainers, .python-version, etc)
include = [
"/*.toml",
"/*.json",
"/*.lock",
"/*.md",
"/mypy.ini",
"/noxfile.py",
"bin/*",
"examples/*",
"src/*",
"tests/*",
]

[tool.hatch.metadata.hooks.fancy-pypi-readme]
content-type = "text/markdown"

Expand Down
11 changes: 10 additions & 1 deletion requirements-dev.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
# features: []
# all-features: true
# with-sources: false
# generate-hashes: false

-e file:.
annotated-types==0.6.0
# via pydantic
anyio==4.1.0
anyio==4.4.0
# via httpx
# via python-intercom
argcomplete==3.1.2
Expand Down Expand Up @@ -44,6 +45,10 @@ idna==3.4
importlib-metadata==7.0.0
iniconfig==2.0.0
# via pytest
markdown-it-py==3.0.0
# via rich
mdurl==0.1.2
# via markdown-it-py
mypy==1.7.1
mypy-extensions==1.0.0
# via mypy
Expand All @@ -63,6 +68,8 @@ pydantic==2.7.1
# via python-intercom
pydantic-core==2.18.2
# via pydantic
pygments==2.18.0
# via rich
pyright==1.1.364
pytest==7.1.1
# via pytest-asyncio
Expand All @@ -72,6 +79,7 @@ python-dateutil==2.8.2
pytz==2023.3.post1
# via dirty-equals
respx==0.20.2
rich==13.7.1
ruff==0.1.9
setuptools==68.2.2
# via nodeenv
Expand All @@ -86,6 +94,7 @@ tomli==2.0.1
# via mypy
# via pytest
typing-extensions==4.8.0
# via anyio
# via mypy
# via pydantic
# via pydantic-core
Expand Down
4 changes: 3 additions & 1 deletion requirements.lock
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
# features: []
# all-features: true
# with-sources: false
# generate-hashes: false

-e file:.
annotated-types==0.6.0
# via pydantic
anyio==4.1.0
anyio==4.4.0
# via httpx
# via python-intercom
certifi==2023.7.22
Expand Down Expand Up @@ -38,6 +39,7 @@ sniffio==1.3.0
# via httpx
# via python-intercom
typing-extensions==4.8.0
# via anyio
# via pydantic
# via pydantic-core
# via python-intercom
20 changes: 18 additions & 2 deletions src/python_minus_intercom/_base_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
HttpxSendArgs,
AsyncTransport,
RequestOptions,
HttpxRequestFiles,
ModelBuilderProtocol,
)
from ._utils import is_dict, is_list, asyncify, is_given, lru_cache, is_mapping
Expand Down Expand Up @@ -459,6 +460,7 @@ def _build_request(
headers = self._build_headers(options)
params = _merge_mappings(self.default_query, options.params)
content_type = headers.get("Content-Type")
files = options.files

# If the given Content-Type header is multipart/form-data then it
# has to be removed so that httpx can generate the header with
Expand All @@ -472,14 +474,23 @@ def _build_request(
headers.pop("Content-Type")

# As we are now sending multipart/form-data instead of application/json
# we need to tell httpx to use it, https://www.python-httpx.org/advanced/#multipart-file-encoding
# we need to tell httpx to use it, https://www.python-httpx.org/advanced/clients/#multipart-file-encoding
if json_data:
if not is_dict(json_data):
raise TypeError(
f"Expected query input to be a dictionary for multipart requests but got {type(json_data)} instead."
)
kwargs["data"] = self._serialize_multipartform(json_data)

# httpx determines whether or not to send a "multipart/form-data"
# request based on the truthiness of the "files" argument.
# This gets around that issue by generating a dict value that
# evaluates to true.
#
# https://github.com/encode/httpx/discussions/2399#discussioncomment-3814186
if not files:
files = cast(HttpxRequestFiles, ForceMultipartDict())

# TODO: report this error to httpx
return self._client.build_request( # pyright: ignore[reportUnknownMemberType]
headers=headers,
Expand All @@ -492,7 +503,7 @@ def _build_request(
# https://github.com/microsoft/pyright/issues/3526#event-6715453066
params=self.qs.stringify(cast(Mapping[str, Any], params)) if params else None,
json=json_data,
files=options.files,
files=files,
**kwargs,
)

Expand Down Expand Up @@ -1863,6 +1874,11 @@ def make_request_options(
return options


class ForceMultipartDict(Dict[str, None]):
def __bool__(self) -> bool:
return True


class OtherPlatform:
def __init__(self, name: str) -> None:
self.name = name
Expand Down
27 changes: 27 additions & 0 deletions src/python_minus_intercom/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
ClassVar,
Protocol,
Required,
ParamSpec,
TypedDict,
TypeGuard,
final,
Expand Down Expand Up @@ -67,6 +68,9 @@
__all__ = ["BaseModel", "GenericModel"]

_T = TypeVar("_T")
_BaseModelT = TypeVar("_BaseModelT", bound="BaseModel")

P = ParamSpec("P")


@runtime_checkable
Expand Down Expand Up @@ -379,6 +383,29 @@ def is_basemodel_type(type_: type) -> TypeGuard[type[BaseModel] | type[GenericMo
return issubclass(origin, BaseModel) or issubclass(origin, GenericModel)


def build(
base_model_cls: Callable[P, _BaseModelT],
*args: P.args,
**kwargs: P.kwargs,
) -> _BaseModelT:
"""Construct a BaseModel class without validation.
This is useful for cases where you need to instantiate a `BaseModel`
from an API response as this provides type-safe params which isn't supported
by helpers like `construct_type()`.
```py
build(MyModel, my_field_a="foo", my_field_b=123)
```
"""
if args:
raise TypeError(
"Received positional arguments which are not supported; Keyword arguments must be used instead",
)

return cast(_BaseModelT, construct_type(type_=base_model_cls, value=kwargs))


def construct_type(*, value: object, type_: object) -> object:
"""Loose coercion to the expected type with construction of nested values.
Expand Down
5 changes: 4 additions & 1 deletion src/python_minus_intercom/_utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,7 @@
maybe_transform as maybe_transform,
async_maybe_transform as async_maybe_transform,
)
from ._reflection import function_has_argument as function_has_argument
from ._reflection import (
function_has_argument as function_has_argument,
assert_signatures_in_sync as assert_signatures_in_sync,
)
Loading

0 comments on commit a7590d1

Please sign in to comment.