add initial generation

Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2021-12-06 12:43:34 -08:00
parent f8e040433e
commit a9cdec3d2b
27 changed files with 1237 additions and 3 deletions

View File

@ -11,7 +11,9 @@ generate: docker-image
--name python-generator \ --name python-generator \
-v $(CURDIR):/usr/src \ -v $(CURDIR):/usr/src \
--workdir /usr/src \ --workdir /usr/src \
$(DOCKER_IMAGE_NAME) openapi-python-client generate --path ./spec.yml $(DOCKER_IMAGE_NAME) openapi-python-client update \
--path ./spec.yml \
--config /usr/src/config.yml
.PHONY: docker-image .PHONY: docker-image
docker-image: docker-image:

View File

@ -1,9 +1,24 @@
# kittycad.py # kittycad.py
The Python API client for KittyCAD.
This is generated from This is generated from
[openapi-generators/openapi-python-client](https://github.com/openapi-generators/openapi-python-client). [openapi-generators/openapi-python-client](https://github.com/openapi-generators/openapi-python-client).
## Generating
You can trigger a build with the GitHub action to generate the client. This will You can trigger a build with the GitHub action to generate the client. This will
automatically update the client to the latest version of the hosted API at automatically update the client to the latest version of the hosted API at
[api.kittycad.io](https://api.kittycad.io). [api.kittycad.io](https://api.kittycad.io).
Alternatively, if you wish to generate the client locally, make sure you have
[Docker installed](https://docs.docker.com/get-docker/) and run:
```bash
$ make generate
```
## Contributing
Please do not change the code directly since it is generated. PRs that change
the code directly will be automatically closed by a bot.

View File

@ -1,2 +1,2 @@
project_name_override: kittycad.py project_name_override: kittycad
package_name_override: kittycad.py package_name_override: kittycad

23
kittycad/.gitignore vendored Normal file
View File

@ -0,0 +1,23 @@
__pycache__/
build/
dist/
*.egg-info/
.pytest_cache/
# pyenv
.python-version
# Environments
.env
.venv
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# JetBrains
.idea/
/coverage.xml
/.coverage

87
kittycad/README.md Normal file
View File

@ -0,0 +1,87 @@
# kittycad
A client library for accessing KittyCAD
## Usage
First, create a client:
```python
from kittycad import Client
client = Client(base_url="https://api.example.com")
```
If the endpoints you're going to hit require authentication, use `AuthenticatedClient` instead:
```python
from kittycad import AuthenticatedClient
client = AuthenticatedClient(base_url="https://api.example.com", token="SuperSecretToken")
```
Now call your endpoint and use your models:
```python
from kittycad.models import MyDataModel
from kittycad.api.my_tag import get_my_data_model
from kittycad.types import Response
my_data: MyDataModel = get_my_data_model.sync(client=client)
# or if you need more info (e.g. status_code)
response: Response[MyDataModel] = get_my_data_model.sync_detailed(client=client)
```
Or do the same thing with an async version:
```python
from kittycad.models import MyDataModel
from kittycad.api.my_tag import get_my_data_model
from kittycad.types import Response
my_data: MyDataModel = await get_my_data_model.asyncio(client=client)
response: Response[MyDataModel] = await get_my_data_model.asyncio_detailed(client=client)
```
By default, when you're calling an HTTPS API it will attempt to verify that SSL is working correctly. Using certificate verification is highly recommended most of the time, but sometimes you may need to authenticate to a server (especially an internal server) using a custom certificate bundle.
```python
client = AuthenticatedClient(
base_url="https://internal_api.example.com",
token="SuperSecretToken",
verify_ssl="/path/to/certificate_bundle.pem",
)
```
You can also disable certificate validation altogether, but beware that **this is a security risk**.
```python
client = AuthenticatedClient(
base_url="https://internal_api.example.com",
token="SuperSecretToken",
verify_ssl=False
)
```
Things to know:
1. Every path/method combo becomes a Python module with four functions:
1. `sync`: Blocking request that returns parsed data (if successful) or `None`
1. `sync_detailed`: Blocking request that always returns a `Request`, optionally with `parsed` set if the request was successful.
1. `asyncio`: Like `sync` but the async instead of blocking
1. `asyncio_detailed`: Like `sync_detailed` by async instead of blocking
1. All path/query params, and bodies become method arguments.
1. If your endpoint had any tags on it, the first tag will be used as a module name for the function (my_tag above)
1. Any endpoint which did not have a tag will be in `kittycad.api.default`
## Building / publishing this Client
This project uses [Poetry](https://python-poetry.org/) to manage dependencies and packaging. Here are the basics:
1. Update the metadata in pyproject.toml (e.g. authors, version)
1. If you're using a private repository, configure it with Poetry
1. `poetry config repositories.<your-repository-name> <url-to-your-repository>`
1. `poetry config http-basic.<your-repository-name> <username> <password>`
1. Publish the client with `poetry publish --build -r <your-repository-name>` or, if for public PyPI, just `poetry publish --build`
If you want to install this client into another project without publishing it (e.g. for development) then:
1. If that project **is using Poetry**, you can simply do `poetry add <path-to-this-client>` from that project
1. If that project is not using Poetry:
1. Build a wheel with `poetry build -f wheel`
1. Install that wheel from the other project `pip install <path-to-wheel>`

View File

@ -0,0 +1,2 @@
""" A client library for accessing KittyCAD """
from .client import AuthenticatedClient, Client

View File

@ -0,0 +1 @@
""" Contains methods for accessing the API """

View File

View File

@ -0,0 +1,124 @@
from typing import Any, Dict, Optional, Union
import httpx
from ...client import AuthenticatedClient
from ...models.file_conversion import FileConversion
from ...types import Response
def _get_kwargs(
id: str,
*,
client: AuthenticatedClient,
) -> Dict[str, Any]:
url = "{}/file/conversion/{id}".format(client.base_url, id=id)
headers: Dict[str, Any] = client.get_headers()
cookies: Dict[str, Any] = client.get_cookies()
return {
"url": url,
"headers": headers,
"cookies": cookies,
"timeout": client.get_timeout(),
}
def _parse_response(*, response: httpx.Response) -> Optional[Union[Any, FileConversion]]:
if response.status_code == 200:
response_200 = FileConversion.from_dict(response.json())
return response_200
if response.status_code == 400:
response_400 = None
return response_400
if response.status_code == 401:
response_401 = None
return response_401
if response.status_code == 403:
response_403 = None
return response_403
if response.status_code == 404:
response_404 = None
return response_404
if response.status_code == 406:
response_406 = None
return response_406
return None
def _build_response(*, response: httpx.Response) -> Response[Union[Any, FileConversion]]:
return Response(
status_code=response.status_code,
content=response.content,
headers=response.headers,
parsed=_parse_response(response=response),
)
def sync_detailed(
id: str,
*,
client: AuthenticatedClient,
) -> Response[Union[Any, FileConversion]]:
kwargs = _get_kwargs(
id=id,
client=client,
)
response = httpx.get(
verify=client.verify_ssl,
**kwargs,
)
return _build_response(response=response)
def sync(
id: str,
*,
client: AuthenticatedClient,
) -> Optional[Union[Any, FileConversion]]:
"""Get the status of a file conversion."""
return sync_detailed(
id=id,
client=client,
).parsed
async def asyncio_detailed(
id: str,
*,
client: AuthenticatedClient,
) -> Response[Union[Any, FileConversion]]:
kwargs = _get_kwargs(
id=id,
client=client,
)
async with httpx.AsyncClient(verify=client.verify_ssl) as _client:
response = await _client.get(**kwargs)
return _build_response(response=response)
async def asyncio(
id: str,
*,
client: AuthenticatedClient,
) -> Optional[Union[Any, FileConversion]]:
"""Get the status of a file conversion."""
return (
await asyncio_detailed(
id=id,
client=client,
)
).parsed

View File

View File

@ -0,0 +1,107 @@
from typing import Any, Dict, Optional, Union
import httpx
from ...client import AuthenticatedClient
from ...models.instance_metadata import InstanceMetadata
from ...types import Response
def _get_kwargs(
*,
client: AuthenticatedClient,
) -> Dict[str, Any]:
url = "{}/_meta/debug/instance".format(client.base_url)
headers: Dict[str, Any] = client.get_headers()
cookies: Dict[str, Any] = client.get_cookies()
return {
"url": url,
"headers": headers,
"cookies": cookies,
"timeout": client.get_timeout(),
}
def _parse_response(*, response: httpx.Response) -> Optional[Union[Any, InstanceMetadata]]:
if response.status_code == 200:
response_200 = InstanceMetadata.from_dict(response.json())
return response_200
if response.status_code == 400:
response_400 = None
return response_400
if response.status_code == 401:
response_401 = None
return response_401
if response.status_code == 403:
response_403 = None
return response_403
return None
def _build_response(*, response: httpx.Response) -> Response[Union[Any, InstanceMetadata]]:
return Response(
status_code=response.status_code,
content=response.content,
headers=response.headers,
parsed=_parse_response(response=response),
)
def sync_detailed(
*,
client: AuthenticatedClient,
) -> Response[Union[Any, InstanceMetadata]]:
kwargs = _get_kwargs(
client=client,
)
response = httpx.get(
verify=client.verify_ssl,
**kwargs,
)
return _build_response(response=response)
def sync(
*,
client: AuthenticatedClient,
) -> Optional[Union[Any, InstanceMetadata]]:
"""Get information about this specific API server instance. This is primarily used for debugging."""
return sync_detailed(
client=client,
).parsed
async def asyncio_detailed(
*,
client: AuthenticatedClient,
) -> Response[Union[Any, InstanceMetadata]]:
kwargs = _get_kwargs(
client=client,
)
async with httpx.AsyncClient(verify=client.verify_ssl) as _client:
response = await _client.get(**kwargs)
return _build_response(response=response)
async def asyncio(
*,
client: AuthenticatedClient,
) -> Optional[Union[Any, InstanceMetadata]]:
"""Get information about this specific API server instance. This is primarily used for debugging."""
return (
await asyncio_detailed(
client=client,
)
).parsed

View File

@ -0,0 +1,107 @@
from typing import Any, Dict, Optional, Union
import httpx
from ...client import AuthenticatedClient
from ...models.auth_session import AuthSession
from ...types import Response
def _get_kwargs(
*,
client: AuthenticatedClient,
) -> Dict[str, Any]:
url = "{}/_meta/debug/session".format(client.base_url)
headers: Dict[str, Any] = client.get_headers()
cookies: Dict[str, Any] = client.get_cookies()
return {
"url": url,
"headers": headers,
"cookies": cookies,
"timeout": client.get_timeout(),
}
def _parse_response(*, response: httpx.Response) -> Optional[Union[Any, AuthSession]]:
if response.status_code == 200:
response_200 = AuthSession.from_dict(response.json())
return response_200
if response.status_code == 400:
response_400 = None
return response_400
if response.status_code == 401:
response_401 = None
return response_401
if response.status_code == 403:
response_403 = None
return response_403
return None
def _build_response(*, response: httpx.Response) -> Response[Union[Any, AuthSession]]:
return Response(
status_code=response.status_code,
content=response.content,
headers=response.headers,
parsed=_parse_response(response=response),
)
def sync_detailed(
*,
client: AuthenticatedClient,
) -> Response[Union[Any, AuthSession]]:
kwargs = _get_kwargs(
client=client,
)
response = httpx.get(
verify=client.verify_ssl,
**kwargs,
)
return _build_response(response=response)
def sync(
*,
client: AuthenticatedClient,
) -> Optional[Union[Any, AuthSession]]:
"""Get information about your API request session. This is primarily used for debugging."""
return sync_detailed(
client=client,
).parsed
async def asyncio_detailed(
*,
client: AuthenticatedClient,
) -> Response[Union[Any, AuthSession]]:
kwargs = _get_kwargs(
client=client,
)
async with httpx.AsyncClient(verify=client.verify_ssl) as _client:
response = await _client.get(**kwargs)
return _build_response(response=response)
async def asyncio(
*,
client: AuthenticatedClient,
) -> Optional[Union[Any, AuthSession]]:
"""Get information about your API request session. This is primarily used for debugging."""
return (
await asyncio_detailed(
client=client,
)
).parsed

View File

@ -0,0 +1,95 @@
from typing import Any, Dict, Optional
import httpx
from ...client import Client
from ...models.ping_response_200 import PingResponse200
from ...types import Response
def _get_kwargs(
*,
client: Client,
) -> Dict[str, Any]:
url = "{}/ping".format(client.base_url)
headers: Dict[str, Any] = client.get_headers()
cookies: Dict[str, Any] = client.get_cookies()
return {
"url": url,
"headers": headers,
"cookies": cookies,
"timeout": client.get_timeout(),
}
def _parse_response(*, response: httpx.Response) -> Optional[PingResponse200]:
if response.status_code == 200:
response_200 = PingResponse200.from_dict(response.json())
return response_200
return None
def _build_response(*, response: httpx.Response) -> Response[PingResponse200]:
return Response(
status_code=response.status_code,
content=response.content,
headers=response.headers,
parsed=_parse_response(response=response),
)
def sync_detailed(
*,
client: Client,
) -> Response[PingResponse200]:
kwargs = _get_kwargs(
client=client,
)
response = httpx.get(
verify=client.verify_ssl,
**kwargs,
)
return _build_response(response=response)
def sync(
*,
client: Client,
) -> Optional[PingResponse200]:
"""Simple ping to the server."""
return sync_detailed(
client=client,
).parsed
async def asyncio_detailed(
*,
client: Client,
) -> Response[PingResponse200]:
kwargs = _get_kwargs(
client=client,
)
async with httpx.AsyncClient(verify=client.verify_ssl) as _client:
response = await _client.get(**kwargs)
return _build_response(response=response)
async def asyncio(
*,
client: Client,
) -> Optional[PingResponse200]:
"""Simple ping to the server."""
return (
await asyncio_detailed(
client=client,
)
).parsed

View File

@ -0,0 +1,48 @@
import ssl
from typing import Dict, Union
import attr
@attr.s(auto_attribs=True)
class Client:
"""A class for keeping track of data related to the API"""
base_url: str
cookies: Dict[str, str] = attr.ib(factory=dict, kw_only=True)
headers: Dict[str, str] = attr.ib(factory=dict, kw_only=True)
timeout: float = attr.ib(5.0, kw_only=True)
verify_ssl: Union[str, bool, ssl.SSLContext] = attr.ib(True, kw_only=True)
def get_headers(self) -> Dict[str, str]:
"""Get headers to be used in all endpoints"""
return {**self.headers}
def with_headers(self, headers: Dict[str, str]) -> "Client":
"""Get a new client matching this one with additional headers"""
return attr.evolve(self, headers={**self.headers, **headers})
def get_cookies(self) -> Dict[str, str]:
return {**self.cookies}
def with_cookies(self, cookies: Dict[str, str]) -> "Client":
"""Get a new client matching this one with additional cookies"""
return attr.evolve(self, cookies={**self.cookies, **cookies})
def get_timeout(self) -> float:
return self.timeout
def with_timeout(self, timeout: float) -> "Client":
"""Get a new client matching this one with a new timeout (in seconds)"""
return attr.evolve(self, timeout=timeout)
@attr.s(auto_attribs=True)
class AuthenticatedClient(Client):
"""A Client which has been authenticated for use on secured endpoints"""
token: str
def get_headers(self) -> Dict[str, str]:
"""Get headers to be used in authenticated endpoints"""
return {"Authorization": f"Bearer {self.token}", **self.headers}

View File

@ -0,0 +1,11 @@
""" Contains all the data models used in inputs/outputs """
from .auth_session import AuthSession
from .error_message import ErrorMessage
from .file_conversion import FileConversion
from .file_conversion_status import FileConversionStatus
from .instance_metadata import InstanceMetadata
from .instance_metadata_environment import InstanceMetadataEnvironment
from .ping_response_200 import PingResponse200
from .ping_response_200_message import PingResponse200Message
from .valid_file_types import ValidFileTypes

View File

@ -0,0 +1,98 @@
import datetime
from typing import Any, Dict, List, Type, TypeVar, Union
import attr
from dateutil.parser import isoparse
from ..types import UNSET, Unset
T = TypeVar("T", bound="AuthSession")
@attr.s(auto_attribs=True)
class AuthSession:
""" """
id: Union[Unset, str] = UNSET
token: Union[Unset, str] = UNSET
user_id: Union[Unset, str] = UNSET
ip_address: Union[Unset, str] = UNSET
is_valid: Union[Unset, bool] = False
created_at: Union[Unset, datetime.datetime] = UNSET
additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)
def to_dict(self) -> Dict[str, Any]:
id = self.id
token = self.token
user_id = self.user_id
ip_address = self.ip_address
is_valid = self.is_valid
created_at: Union[Unset, str] = UNSET
if not isinstance(self.created_at, Unset):
created_at = self.created_at.isoformat()
field_dict: Dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update({})
if id is not UNSET:
field_dict["id"] = id
if token is not UNSET:
field_dict["token"] = token
if user_id is not UNSET:
field_dict["user_id"] = user_id
if ip_address is not UNSET:
field_dict["ip_address"] = ip_address
if is_valid is not UNSET:
field_dict["is_valid"] = is_valid
if created_at is not UNSET:
field_dict["created_at"] = created_at
return field_dict
@classmethod
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
d = src_dict.copy()
id = d.pop("id", UNSET)
token = d.pop("token", UNSET)
user_id = d.pop("user_id", UNSET)
ip_address = d.pop("ip_address", UNSET)
is_valid = d.pop("is_valid", UNSET)
_created_at = d.pop("created_at", UNSET)
created_at: Union[Unset, datetime.datetime]
if isinstance(_created_at, Unset):
created_at = UNSET
else:
created_at = isoparse(_created_at)
auth_session = cls(
id=id,
token=token,
user_id=user_id,
ip_address=ip_address,
is_valid=is_valid,
created_at=created_at,
)
auth_session.additional_properties = d
return auth_session
@property
def additional_keys(self) -> List[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View File

@ -0,0 +1,54 @@
from typing import Any, Dict, List, Type, TypeVar, Union
import attr
from ..types import UNSET, Unset
T = TypeVar("T", bound="ErrorMessage")
@attr.s(auto_attribs=True)
class ErrorMessage:
""" """
message: Union[Unset, str] = UNSET
additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)
def to_dict(self) -> Dict[str, Any]:
message = self.message
field_dict: Dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update({})
if message is not UNSET:
field_dict["message"] = message
return field_dict
@classmethod
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
d = src_dict.copy()
message = d.pop("message", UNSET)
error_message = cls(
message=message,
)
error_message.additional_properties = d
return error_message
@property
def additional_keys(self) -> List[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View File

@ -0,0 +1,140 @@
import datetime
from typing import Any, Dict, List, Type, TypeVar, Union
import attr
from dateutil.parser import isoparse
from ..models.file_conversion_status import FileConversionStatus
from ..models.valid_file_types import ValidFileTypes
from ..types import UNSET, Unset
T = TypeVar("T", bound="FileConversion")
@attr.s(auto_attribs=True)
class FileConversion:
""" """
id: Union[Unset, str] = UNSET
created_at: Union[Unset, datetime.datetime] = UNSET
completed_at: Union[Unset, datetime.datetime] = UNSET
status: Union[Unset, FileConversionStatus] = UNSET
src_format: Union[Unset, ValidFileTypes] = UNSET
output_format: Union[Unset, ValidFileTypes] = UNSET
output: Union[Unset, str] = UNSET
additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)
def to_dict(self) -> Dict[str, Any]:
id = self.id
created_at: Union[Unset, str] = UNSET
if not isinstance(self.created_at, Unset):
created_at = self.created_at.isoformat()
completed_at: Union[Unset, str] = UNSET
if not isinstance(self.completed_at, Unset):
completed_at = self.completed_at.isoformat()
status: Union[Unset, str] = UNSET
if not isinstance(self.status, Unset):
status = self.status.value
src_format: Union[Unset, str] = UNSET
if not isinstance(self.src_format, Unset):
src_format = self.src_format.value
output_format: Union[Unset, str] = UNSET
if not isinstance(self.output_format, Unset):
output_format = self.output_format.value
output = self.output
field_dict: Dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update({})
if id is not UNSET:
field_dict["id"] = id
if created_at is not UNSET:
field_dict["created_at"] = created_at
if completed_at is not UNSET:
field_dict["completed_at"] = completed_at
if status is not UNSET:
field_dict["status"] = status
if src_format is not UNSET:
field_dict["src_format"] = src_format
if output_format is not UNSET:
field_dict["output_format"] = output_format
if output is not UNSET:
field_dict["output"] = output
return field_dict
@classmethod
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
d = src_dict.copy()
id = d.pop("id", UNSET)
_created_at = d.pop("created_at", UNSET)
created_at: Union[Unset, datetime.datetime]
if isinstance(_created_at, Unset):
created_at = UNSET
else:
created_at = isoparse(_created_at)
_completed_at = d.pop("completed_at", UNSET)
completed_at: Union[Unset, datetime.datetime]
if isinstance(_completed_at, Unset):
completed_at = UNSET
else:
completed_at = isoparse(_completed_at)
_status = d.pop("status", UNSET)
status: Union[Unset, FileConversionStatus]
if isinstance(_status, Unset):
status = UNSET
else:
status = FileConversionStatus(_status)
_src_format = d.pop("src_format", UNSET)
src_format: Union[Unset, ValidFileTypes]
if isinstance(_src_format, Unset):
src_format = UNSET
else:
src_format = ValidFileTypes(_src_format)
_output_format = d.pop("output_format", UNSET)
output_format: Union[Unset, ValidFileTypes]
if isinstance(_output_format, Unset):
output_format = UNSET
else:
output_format = ValidFileTypes(_output_format)
output = d.pop("output", UNSET)
file_conversion = cls(
id=id,
created_at=created_at,
completed_at=completed_at,
status=status,
src_format=src_format,
output_format=output_format,
output=output,
)
file_conversion.additional_properties = d
return file_conversion
@property
def additional_keys(self) -> List[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View File

@ -0,0 +1,12 @@
from enum import Enum
class FileConversionStatus(str, Enum):
QUEUED = "Queued"
UPLOADED = "Uploaded"
IN_PROGRESS = "In Progress"
COMPLETED = "Completed"
FAILED = "Failed"
def __str__(self) -> str:
return str(self.value)

View File

@ -0,0 +1,133 @@
from typing import Any, Dict, List, Type, TypeVar, Union
import attr
from ..models.instance_metadata_environment import InstanceMetadataEnvironment
from ..types import UNSET, Unset
T = TypeVar("T", bound="InstanceMetadata")
@attr.s(auto_attribs=True)
class InstanceMetadata:
""" """
id: Union[Unset, str] = UNSET
git_hash: Union[Unset, str] = UNSET
environment: Union[Unset, InstanceMetadataEnvironment] = UNSET
name: Union[Unset, str] = UNSET
description: Union[Unset, str] = UNSET
ip_address: Union[Unset, str] = UNSET
zone: Union[Unset, str] = UNSET
image: Union[Unset, str] = UNSET
hostname: Union[Unset, str] = UNSET
cpu_platform: Union[Unset, str] = UNSET
machine_type: Union[Unset, str] = UNSET
additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)
def to_dict(self) -> Dict[str, Any]:
id = self.id
git_hash = self.git_hash
environment: Union[Unset, str] = UNSET
if not isinstance(self.environment, Unset):
environment = self.environment.value
name = self.name
description = self.description
ip_address = self.ip_address
zone = self.zone
image = self.image
hostname = self.hostname
cpu_platform = self.cpu_platform
machine_type = self.machine_type
field_dict: Dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update({})
if id is not UNSET:
field_dict["id"] = id
if git_hash is not UNSET:
field_dict["git_hash"] = git_hash
if environment is not UNSET:
field_dict["environment"] = environment
if name is not UNSET:
field_dict["name"] = name
if description is not UNSET:
field_dict["description"] = description
if ip_address is not UNSET:
field_dict["ip_address"] = ip_address
if zone is not UNSET:
field_dict["zone"] = zone
if image is not UNSET:
field_dict["image"] = image
if hostname is not UNSET:
field_dict["hostname"] = hostname
if cpu_platform is not UNSET:
field_dict["cpu_platform"] = cpu_platform
if machine_type is not UNSET:
field_dict["machine_type"] = machine_type
return field_dict
@classmethod
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
d = src_dict.copy()
id = d.pop("id", UNSET)
git_hash = d.pop("git_hash", UNSET)
_environment = d.pop("environment", UNSET)
environment: Union[Unset, InstanceMetadataEnvironment]
if isinstance(_environment, Unset):
environment = UNSET
else:
environment = InstanceMetadataEnvironment(_environment)
name = d.pop("name", UNSET)
description = d.pop("description", UNSET)
ip_address = d.pop("ip_address", UNSET)
zone = d.pop("zone", UNSET)
image = d.pop("image", UNSET)
hostname = d.pop("hostname", UNSET)
cpu_platform = d.pop("cpu_platform", UNSET)
machine_type = d.pop("machine_type", UNSET)
instance_metadata = cls(
id=id,
git_hash=git_hash,
environment=environment,
name=name,
description=description,
ip_address=ip_address,
zone=zone,
image=image,
hostname=hostname,
cpu_platform=cpu_platform,
machine_type=machine_type,
)
instance_metadata.additional_properties = d
return instance_metadata
@property
def additional_keys(self) -> List[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View File

@ -0,0 +1,10 @@
from enum import Enum
class InstanceMetadataEnvironment(str, Enum):
DEVELOPMENT = "DEVELOPMENT"
PREVIEW = "PREVIEW"
PRODUCTION = "PRODUCTION"
def __str__(self) -> str:
return str(self.value)

View File

@ -0,0 +1,62 @@
from typing import Any, Dict, List, Type, TypeVar, Union
import attr
from ..models.ping_response_200_message import PingResponse200Message
from ..types import UNSET, Unset
T = TypeVar("T", bound="PingResponse200")
@attr.s(auto_attribs=True)
class PingResponse200:
""" """
message: Union[Unset, PingResponse200Message] = UNSET
additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)
def to_dict(self) -> Dict[str, Any]:
message: Union[Unset, str] = UNSET
if not isinstance(self.message, Unset):
message = self.message.value
field_dict: Dict[str, Any] = {}
field_dict.update(self.additional_properties)
field_dict.update({})
if message is not UNSET:
field_dict["message"] = message
return field_dict
@classmethod
def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
d = src_dict.copy()
_message = d.pop("message", UNSET)
message: Union[Unset, PingResponse200Message]
if isinstance(_message, Unset):
message = UNSET
else:
message = PingResponse200Message(_message)
ping_response_200 = cls(
message=message,
)
ping_response_200.additional_properties = d
return ping_response_200
@property
def additional_keys(self) -> List[str]:
return list(self.additional_properties.keys())
def __getitem__(self, key: str) -> Any:
return self.additional_properties[key]
def __setitem__(self, key: str, value: Any) -> None:
self.additional_properties[key] = value
def __delitem__(self, key: str) -> None:
del self.additional_properties[key]
def __contains__(self, key: str) -> bool:
return key in self.additional_properties

View File

@ -0,0 +1,8 @@
from enum import Enum
class PingResponse200Message(str, Enum):
PONG = "pong"
def __str__(self) -> str:
return str(self.value)

View File

@ -0,0 +1,12 @@
from enum import Enum
class ValidFileTypes(str, Enum):
STEP = "step"
OBJ = "obj"
STL = "stl"
DXF = "dxf"
DWG = "dwg"
def __str__(self) -> str:
return str(self.value)

View File

@ -0,0 +1 @@
# Marker file for PEP 561

View File

@ -0,0 +1,43 @@
""" Contains some shared types for properties """
from typing import BinaryIO, Generic, MutableMapping, Optional, TextIO, Tuple, TypeVar, Union
import attr
class Unset:
def __bool__(self) -> bool:
return False
UNSET: Unset = Unset()
FileJsonType = Tuple[Optional[str], Union[BinaryIO, TextIO], Optional[str]]
@attr.s(auto_attribs=True)
class File:
"""Contains information for file uploads"""
payload: Union[BinaryIO, TextIO]
file_name: Optional[str] = None
mime_type: Optional[str] = None
def to_tuple(self) -> FileJsonType:
"""Return a tuple representation that httpx will accept for multipart/form-data"""
return self.file_name, self.payload, self.mime_type
T = TypeVar("T")
@attr.s(auto_attribs=True)
class Response(Generic[T]):
"""A response from an endpoint"""
status_code: int
content: bytes
headers: MutableMapping[str, str]
parsed: Optional[T]
__all__ = ["File", "Response", "FileJsonType"]

39
kittycad/pyproject.toml Normal file
View File

@ -0,0 +1,39 @@
[tool.poetry]
name = "kittycad"
version = "0.1.0"
description = "A client library for accessing KittyCAD"
authors = []
readme = "README.md"
packages = [
{include = "kittycad"},
]
include = ["CHANGELOG.md", "kittycad/py.typed"]
[tool.poetry.dependencies]
python = "^3.6"
httpx = ">=0.15.4,<0.21.0"
attrs = ">=20.1.0,<22.0.0"
python-dateutil = "^2.8.0"
[build-system]
requires = ["poetry>=1.0"]
build-backend = "poetry.masonry.api"
[tool.black]
line-length = 120
target_version = ['py36', 'py37', 'py38']
exclude = '''
(
/(
| \.git
| \.venv
| \.mypy_cache
)/
)
'''
[tool.isort]
line_length = 120
profile = "black"