style(whole-project): fixing linting and typing errors
This commit is contained in:
@@ -1,4 +1,9 @@
|
||||
repos:
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
hooks:
|
||||
- id: ruff
|
||||
rev: v0.0.186
|
||||
|
||||
- repo: https://github.com/commitizen-tools/commitizen
|
||||
hooks:
|
||||
- id: commitizen
|
||||
@@ -8,9 +13,10 @@ repos:
|
||||
rev: v2.38.0
|
||||
|
||||
- repo: https://github.com/pycqa/isort
|
||||
rev: 5.10.1
|
||||
rev: v5.11.3
|
||||
hooks:
|
||||
- id: isort
|
||||
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.12.0
|
||||
hooks:
|
||||
@@ -21,7 +27,7 @@ repos:
|
||||
# https://pre-commit.com/#top_level-default_language_version
|
||||
# language_version: python3.11
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.3.0
|
||||
rev: v4.4.0
|
||||
hooks:
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
|
||||
@@ -27,7 +27,6 @@ def clean_db():
|
||||
|
||||
|
||||
def one_pass(clean: bool, randomize: bool, child_count: int):
|
||||
|
||||
foo = Base()
|
||||
for i in range(child_count):
|
||||
stuff = random_string() if randomize else "stuff"
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
from devtools import debug
|
||||
|
||||
from specklepy.api import operations
|
||||
from specklepy.api.wrapper import StreamWrapper
|
||||
|
||||
if __name__ == "__main__":
|
||||
stream_url = "https://latest.speckle.dev/streams/7d051a6449"
|
||||
wrapper = StreamWrapper(stream_url)
|
||||
|
||||
transport = wrapper.get_transport()
|
||||
|
||||
rec = operations.receive("98396753f8bf7fe1cb60c5193e9f9d86", transport)
|
||||
|
||||
# hash = operations.send(base=foo, transports=[transport], use_default_cache=False)
|
||||
debug(rec)
|
||||
@@ -25,7 +25,6 @@ def create_object(child_count: int) -> Base:
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
stream_url = "http://hyperion:3000/streams/2372b54c35"
|
||||
|
||||
child_count = 10
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ def patch(tag):
|
||||
lines = f.readlines()
|
||||
|
||||
if "version" not in lines[2]:
|
||||
raise Exception(f"Invalid pyproject.toml. Could not patch version.")
|
||||
raise Exception("Invalid pyproject.toml. Could not patch version.")
|
||||
|
||||
lines[2] = f'version = "{tag}"\n'
|
||||
with open("pyproject.toml", "w") as file:
|
||||
|
||||
Generated
+51
-1
@@ -1172,6 +1172,32 @@ files = [
|
||||
[package.dependencies]
|
||||
requests = ">=2.0.1,<3.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.0.187"
|
||||
description = "An extremely fast Python linter, written in Rust."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "ruff-0.0.187-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:d90cbd30c585a9551695af09c91c07542a4bfebe9870f8ca4de5d9ac34478665"},
|
||||
{file = "ruff-0.0.187-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:bca4d85f182c7452f5b607e99c03a0957126bfb260815b824f7fabde519708d8"},
|
||||
{file = "ruff-0.0.187-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c498a7e183c2cd58e8cc0bed93d88e44305365a93132463911680d20d158ae8a"},
|
||||
{file = "ruff-0.0.187-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb525861aae5b005e92c7f32dff8382bbd13a2da5a06b950a11ba879bb9fef15"},
|
||||
{file = "ruff-0.0.187-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:41cfed788d5f8bd618710432583b0f61195769919e8bc1a77f080d5db2ebbb93"},
|
||||
{file = "ruff-0.0.187-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:25a9f74ee9b9472b750c7f0e25551b6f3b298a62126d0386bc9bdda1fed00c35"},
|
||||
{file = "ruff-0.0.187-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:24d0e61041abd2811cf841b43572fed1d0343e96704aedfac388f03dc2f1f53e"},
|
||||
{file = "ruff-0.0.187-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:88722ddbeec8614c9a5fd90eac3aa13372ede98559c36ef95581a26954a85fb5"},
|
||||
{file = "ruff-0.0.187-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9032f221d28897852c5de173cd6890185f4c86a93eca4ed0c215076e8f0f626"},
|
||||
{file = "ruff-0.0.187-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:11833a0e80ff9d244d11c16cc4d1283e84cf0ac47f2440d88093ee3076687fcb"},
|
||||
{file = "ruff-0.0.187-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:debcd3740da13b786656fcf23caa1a328c678b19ab822243bd00a25efb00ab7b"},
|
||||
{file = "ruff-0.0.187-py3-none-musllinux_1_2_i686.whl", hash = "sha256:51f4bf4940a57b4e04254f2823a0e4de52595987c65e0c9ed7b4546c5362f60e"},
|
||||
{file = "ruff-0.0.187-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:ab7e50ba517f3bfaaadaba3f9e68e0a95ff04abab5c480f05015a156f58f16d3"},
|
||||
{file = "ruff-0.0.187-py3-none-win32.whl", hash = "sha256:25e55cc000ca6fe83df6d25080adec86acb3a39cd623ed9ff122ccede02ab6ba"},
|
||||
{file = "ruff-0.0.187-py3-none-win_amd64.whl", hash = "sha256:a81acd2b111b267cda09c507ad72a7ca47fa6f47e1ec240e594eef37db1bdf8d"},
|
||||
{file = "ruff-0.0.187.tar.gz", hash = "sha256:d209efb6cb4f03b31c76d7be770cb387cbdf0592c604f0d0639c1a6f742db04c"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "65.6.3"
|
||||
@@ -1286,6 +1312,30 @@ files = [
|
||||
{file = "typed_ast-1.5.4.tar.gz", hash = "sha256:39e21ceb7388e4bb37f4c679d72707ed46c2fbf2a5609b8b8ebc4b067d977df2"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "types-deprecated"
|
||||
version = "1.2.9"
|
||||
description = "Typing stubs for Deprecated"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "types-Deprecated-1.2.9.tar.gz", hash = "sha256:e04ce58929509865359e91dcc38720123262b4cd68fa2a8a90312d50390bb6fa"},
|
||||
{file = "types_Deprecated-1.2.9-py3-none-any.whl", hash = "sha256:53d05621e1d75de537f5a57d93508c8df17e37c07ee60b9fb09d39e1b7586c1e"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "types-ujson"
|
||||
version = "5.6.0.0"
|
||||
description = "Typing stubs for ujson"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "types-ujson-5.6.0.0.tar.gz", hash = "sha256:1a20cf7946772756736582612e0da5656d2dbeccd24be4c1e97d1e66b072b97e"},
|
||||
{file = "types_ujson-5.6.0.0-py3-none-any.whl", hash = "sha256:010b221260c24a915c6e713a83f366b91390766850ec110304de5b20c86b4b11"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.4.0"
|
||||
@@ -1670,4 +1720,4 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools"
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.7.2, <4.0"
|
||||
content-hash = "fba4eaa4891e1f626c0d6a04a919985d90a8d0a8bbf334d2846e2a16da28304c"
|
||||
content-hash = "18bc7c2f98f551538bf1dfca42a0c3c352e98f2c0a7a59619b8fd16bd2c13e39"
|
||||
|
||||
+4
-1
@@ -32,6 +32,9 @@ pylint = "^2.14.4"
|
||||
mypy = "^0.982"
|
||||
pre-commit = "^2.20.0"
|
||||
commitizen = "^2.38.0"
|
||||
ruff = "^0.0.187"
|
||||
types-deprecated = "^1.2.9"
|
||||
types-ujson = "^5.6.0.0"
|
||||
|
||||
[tool.black]
|
||||
exclude = '''
|
||||
@@ -50,7 +53,7 @@ exclude = '''
|
||||
'''
|
||||
include = '\.pyi?$'
|
||||
line-length = 88
|
||||
target-version = ["py37", "py38", "py39", "py310"]
|
||||
target-version = ["py37", "py38", "py39", "py310", "py311"]
|
||||
|
||||
|
||||
[tool.commitizen]
|
||||
|
||||
+28
-13
@@ -26,10 +26,13 @@ from specklepy.logging.exceptions import SpeckleException, SpeckleWarning
|
||||
|
||||
class SpeckleClient:
|
||||
"""
|
||||
The `SpeckleClient` is your entry point for interacting with your Speckle Server's GraphQL API.
|
||||
You'll need to have access to a server to use it, or you can use our public server `speckle.xyz`.
|
||||
The `SpeckleClient` is your entry point for interacting with
|
||||
your Speckle Server's GraphQL API.
|
||||
You'll need to have access to a server to use it,
|
||||
or you can use our public server `speckle.xyz`.
|
||||
|
||||
To authenticate the client, you'll need to have downloaded the [Speckle Manager](https://speckle.guide/#speckle-manager)
|
||||
To authenticate the client, you'll need to have downloaded
|
||||
the [Speckle Manager](https://speckle.guide/#speckle-manager)
|
||||
and added your account.
|
||||
|
||||
```py
|
||||
@@ -92,15 +95,22 @@ class SpeckleClient:
|
||||
# ) from ex
|
||||
|
||||
def __repr__(self):
|
||||
return f"SpeckleClient( server: {self.url}, authenticated: {self.account.token is not None} )"
|
||||
return (
|
||||
f"SpeckleClient( server: {self.url}, authenticated:"
|
||||
f" {self.account.token is not None} )"
|
||||
)
|
||||
|
||||
@deprecated(
|
||||
version="2.6.0",
|
||||
reason="Renamed: please use `authenticate_with_account` or `authenticate_with_token` instead.",
|
||||
reason=(
|
||||
"Renamed: please use `authenticate_with_account` or"
|
||||
" `authenticate_with_token` instead."
|
||||
),
|
||||
)
|
||||
def authenticate(self, token: str) -> None:
|
||||
"""Authenticate the client using a personal access token
|
||||
The token is saved in the client object and a synchronous GraphQL entrypoint is created
|
||||
The token is saved in the client object and a synchronous GraphQL
|
||||
entrypoint is created
|
||||
|
||||
Arguments:
|
||||
token {str} -- an api token
|
||||
@@ -109,8 +119,10 @@ class SpeckleClient:
|
||||
self._set_up_client()
|
||||
|
||||
def authenticate_with_token(self, token: str) -> None:
|
||||
"""Authenticate the client using a personal access token
|
||||
The token is saved in the client object and a synchronous GraphQL entrypoint is created
|
||||
"""
|
||||
Authenticate the client using a personal access token.
|
||||
The token is saved in the client object and a synchronous GraphQL
|
||||
entrypoint is created
|
||||
|
||||
Arguments:
|
||||
token {str} -- an api token
|
||||
@@ -121,10 +133,12 @@ class SpeckleClient:
|
||||
|
||||
def authenticate_with_account(self, account: Account) -> None:
|
||||
"""Authenticate the client using an Account object
|
||||
The account is saved in the client object and a synchronous GraphQL entrypoint is created
|
||||
The account is saved in the client object and a synchronous GraphQL
|
||||
entrypoint is created
|
||||
|
||||
Arguments:
|
||||
account {Account} -- the account object which can be found with `get_default_account` or `get_local_accounts`
|
||||
account {Account} -- the account object which can be found with
|
||||
`get_default_account` or `get_local_accounts`
|
||||
"""
|
||||
metrics.track(metrics.CLIENT, account, {"name": "authenticate with account"})
|
||||
self.account = account
|
||||
@@ -153,7 +167,8 @@ class SpeckleClient:
|
||||
if self.user.get() is None:
|
||||
warn(
|
||||
SpeckleWarning(
|
||||
f"Possibly invalid token - could not authenticate Speckle Client for server {self.url}"
|
||||
"Possibly invalid token - could not authenticate Speckle Client"
|
||||
f" for server {self.url}"
|
||||
)
|
||||
)
|
||||
|
||||
@@ -167,7 +182,7 @@ class SpeckleClient:
|
||||
server_version = None
|
||||
try:
|
||||
server_version = self.server.version()
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
self.user = user.Resource(
|
||||
account=self.account,
|
||||
@@ -214,7 +229,7 @@ class SpeckleClient:
|
||||
return attr.Resource(
|
||||
account=self.account, basepath=self.url, client=self.httpclient
|
||||
)
|
||||
except:
|
||||
except AttributeError:
|
||||
raise SpeckleException(
|
||||
f"Method {name} is not supported by the SpeckleClient class"
|
||||
)
|
||||
|
||||
@@ -26,7 +26,10 @@ class Account(BaseModel):
|
||||
id: Optional[str] = None
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Account(email: {self.userInfo.email}, server: {self.serverInfo.url}, isDefault: {self.isDefault})"
|
||||
return (
|
||||
f"Account(email: {self.userInfo.email}, server: {self.serverInfo.url},"
|
||||
f" isDefault: {self.isDefault})"
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.__repr__()
|
||||
@@ -45,7 +48,8 @@ def get_local_accounts(base_path: Optional[str] = None) -> List[Account]:
|
||||
base_path {str} -- custom base path if you are not using the system default
|
||||
|
||||
Returns:
|
||||
List[Account] -- list of all local accounts or an empty list if no accounts were found
|
||||
List[Account] -- list of all local accounts or an empty list if
|
||||
no accounts were found
|
||||
"""
|
||||
accounts: List[Account] = []
|
||||
try:
|
||||
@@ -95,7 +99,9 @@ def get_local_accounts(base_path: Optional[str] = None) -> List[Account]:
|
||||
|
||||
|
||||
def get_default_account(base_path: Optional[str] = None) -> Optional[Account]:
|
||||
"""Gets this environment's default account if any. If there is no default, the first found will be returned and set as default.
|
||||
"""
|
||||
Gets this environment's default account if any. If there is no default,
|
||||
the first found will be returned and set as default.
|
||||
Arguments:
|
||||
base_path {str} -- custom base path if you are not using the system default
|
||||
|
||||
@@ -121,7 +127,8 @@ def get_account_from_token(token: str, server_url: str = None) -> Account:
|
||||
token {str} -- the api token
|
||||
|
||||
Returns:
|
||||
Account -- the local account with this token or a shell account containing just the token and url if no local account is found
|
||||
Account -- the local account with this token or a shell account containing
|
||||
just the token and url if no local account is found
|
||||
"""
|
||||
accounts = get_local_accounts()
|
||||
if not accounts:
|
||||
@@ -145,6 +152,9 @@ def get_account_from_token(token: str, server_url: str = None) -> Account:
|
||||
class StreamWrapper:
|
||||
def __init__(self, url: str = None) -> None:
|
||||
raise SpeckleException(
|
||||
message="The StreamWrapper has moved as of v2.6.0! Please import from specklepy.api.wrapper",
|
||||
exception=DeprecationWarning,
|
||||
message=(
|
||||
"The StreamWrapper has moved as of v2.6.0! Please import from"
|
||||
" specklepy.api.wrapper"
|
||||
),
|
||||
exception=DeprecationWarning(),
|
||||
)
|
||||
|
||||
@@ -25,7 +25,11 @@ class Commit(BaseModel):
|
||||
parents: Optional[List[str]]
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Commit( id: {self.id}, message: {self.message}, referencedObject: {self.referencedObject}, authorName: {self.authorName}, branchName: {self.branchName}, createdAt: {self.createdAt} )"
|
||||
return (
|
||||
f"Commit( id: {self.id}, message: {self.message}, referencedObject:"
|
||||
f" {self.referencedObject}, authorName: {self.authorName}, branchName:"
|
||||
f" {self.branchName}, createdAt: {self.createdAt} )"
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.__repr__()
|
||||
@@ -75,7 +79,10 @@ class Stream(BaseModel):
|
||||
favoritesCount: Optional[int] = None
|
||||
|
||||
def __repr__(self):
|
||||
return f"Stream( id: {self.id}, name: {self.name}, description: {self.description}, isPublic: {self.isPublic})"
|
||||
return (
|
||||
f"Stream( id: {self.id}, name: {self.name}, description:"
|
||||
f" {self.description}, isPublic: {self.isPublic})"
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.__repr__()
|
||||
@@ -99,7 +106,10 @@ class User(BaseModel):
|
||||
streams: Optional[Streams]
|
||||
|
||||
def __repr__(self):
|
||||
return f"User( id: {self.id}, name: {self.name}, email: {self.email}, company: {self.company} )"
|
||||
return (
|
||||
f"User( id: {self.id}, name: {self.name}, email: {self.email}, company:"
|
||||
f" {self.company} )"
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.__repr__()
|
||||
@@ -129,7 +139,11 @@ class PendingStreamCollaborator(BaseModel):
|
||||
token: Optional[str]
|
||||
|
||||
def __repr__(self):
|
||||
return f"PendingStreamCollaborator( inviteId: {self.inviteId}, streamId: {self.streamId}, role: {self.role}, title: {self.title}, invitedBy: {self.user.name if self.user else None})"
|
||||
return (
|
||||
f"PendingStreamCollaborator( inviteId: {self.inviteId}, streamId:"
|
||||
f" {self.streamId}, role: {self.role}, title: {self.title}, invitedBy:"
|
||||
f" {self.user.name if self.user else None})"
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.__repr__()
|
||||
@@ -146,7 +160,10 @@ class Activity(BaseModel):
|
||||
time: Optional[datetime]
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"Activity( streamId: {self.streamId}, actionType: {self.actionType}, message: {self.message}, userId: {self.userId} )"
|
||||
return (
|
||||
f"Activity( streamId: {self.streamId}, actionType: {self.actionType},"
|
||||
f" message: {self.message}, userId: {self.userId} )"
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.__repr__()
|
||||
@@ -158,7 +175,11 @@ class ActivityCollection(BaseModel):
|
||||
cursor: Optional[datetime]
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"ActivityCollection( totalCount: {self.totalCount}, items: {len(self.items) if self.items else 0}, cursor: {self.cursor.isoformat() if self.cursor else None} )"
|
||||
return (
|
||||
f"ActivityCollection( totalCount: {self.totalCount}, items:"
|
||||
f" {len(self.items) if self.items else 0}, cursor:"
|
||||
f" {self.cursor.isoformat() if self.cursor else None} )"
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.__repr__()
|
||||
|
||||
@@ -18,7 +18,8 @@ def send(
|
||||
Arguments:
|
||||
obj {Base} -- the object you want to send
|
||||
transports {list} -- where you want to send them
|
||||
use_default_cache {bool} -- toggle for the default cache. If set to false, it will only send to the provided transports
|
||||
use_default_cache {bool} -- toggle for the default cache.
|
||||
If set to false, it will only send to the provided transports
|
||||
|
||||
Returns:
|
||||
str -- the object id of the sent object
|
||||
@@ -26,7 +27,10 @@ def send(
|
||||
|
||||
if not transports and not use_default_cache:
|
||||
raise SpeckleException(
|
||||
message="You need to provide at least one transport: cannot send with an empty transport list and no default cache"
|
||||
message=(
|
||||
"You need to provide at least one transport: cannot send with an empty"
|
||||
" transport list and no default cache"
|
||||
)
|
||||
)
|
||||
|
||||
if isinstance(transports, AbstractTransport):
|
||||
@@ -62,7 +66,6 @@ def _untracked_receive(
|
||||
remote_transport: Optional[AbstractTransport] = None,
|
||||
local_transport: Optional[AbstractTransport] = None,
|
||||
) -> Base:
|
||||
|
||||
"""Receives an object from a transport.
|
||||
|
||||
Arguments:
|
||||
@@ -86,7 +89,10 @@ def _untracked_receive(
|
||||
|
||||
if not remote_transport:
|
||||
raise SpeckleException(
|
||||
message="Could not find the specified object using the local transport, and you didn't provide a fallback remote from which to pull it."
|
||||
message=(
|
||||
"Could not find the specified object using the local transport, and you"
|
||||
" didn't provide a fallback remote from which to pull it."
|
||||
)
|
||||
)
|
||||
|
||||
obj_string = remote_transport.copy_object_and_children(
|
||||
@@ -98,12 +104,14 @@ def _untracked_receive(
|
||||
|
||||
def serialize(base: Base, write_transports: List[AbstractTransport] = []) -> str:
|
||||
"""
|
||||
Serialize a base object. If no write transports are provided, the object will be serialized
|
||||
Serialize a base object. If no write transports are provided,
|
||||
the object will be serialized
|
||||
without detaching or chunking any of the attributes.
|
||||
|
||||
Arguments:
|
||||
base {Base} -- the object to serialize
|
||||
write_transports {List[AbstractTransport]} -- optional: the transports to write to
|
||||
write_transports {List[AbstractTransport]}
|
||||
-- optional: the transports to write to
|
||||
|
||||
Returns:
|
||||
str -- the serialized object
|
||||
@@ -118,12 +126,17 @@ def deserialize(
|
||||
obj_string: str, read_transport: Optional[AbstractTransport] = None
|
||||
) -> Base:
|
||||
"""
|
||||
Deserialize a string object into a Base object. If the object contains referenced child objects that are not stored in the local db, a read transport needs to be provided in order to recompose the base with the children objects.
|
||||
Deserialize a string object into a Base object.
|
||||
|
||||
If the object contains referenced child objects that are not stored in the local db,
|
||||
a read transport needs to be provided in order to recompose
|
||||
the base with the children objects.
|
||||
|
||||
Arguments:
|
||||
obj_string {str} -- the string object to deserialize
|
||||
read_transport {AbstractTransport} -- the transport to fetch children objects from
|
||||
(defaults to SQLiteTransport)
|
||||
read_transport {AbstractTransport}
|
||||
-- the transport to fetch children objects from
|
||||
(defaults to SQLiteTransport)
|
||||
|
||||
Returns:
|
||||
Base -- the deserialized object
|
||||
|
||||
@@ -52,7 +52,7 @@ class ResourceBase(object):
|
||||
elif self.schema:
|
||||
try:
|
||||
return self.schema.parse_obj(response)
|
||||
except:
|
||||
except Exception:
|
||||
s = BaseObjectSerializer(read_transport=SQLiteTransport())
|
||||
return s.recompose_base(response)
|
||||
else:
|
||||
@@ -61,7 +61,7 @@ class ResourceBase(object):
|
||||
def make_request(
|
||||
self,
|
||||
query: DocumentNode,
|
||||
params: Dict = None,
|
||||
params: Optional[Dict] = None,
|
||||
return_type: Union[str, List, None] = None,
|
||||
schema=None,
|
||||
parse_response: bool = True,
|
||||
@@ -72,13 +72,19 @@ class ResourceBase(object):
|
||||
except Exception as ex:
|
||||
if isinstance(ex, TransportQueryError):
|
||||
return GraphQLException(
|
||||
message=f"Failed to execute the GraphQL {self.name} request. Errors: {ex.errors}",
|
||||
message=(
|
||||
f"Failed to execute the GraphQL {self.name} request. Errors:"
|
||||
f" {ex.errors}"
|
||||
),
|
||||
errors=ex.errors,
|
||||
data=ex.data,
|
||||
)
|
||||
else:
|
||||
return SpeckleException(
|
||||
message=f"Failed to execute the GraphQL {self.name} request. Inner exception: {ex}",
|
||||
message=(
|
||||
f"Failed to execute the GraphQL {self.name} request. Inner"
|
||||
f" exception: {ex}"
|
||||
),
|
||||
exception=ex,
|
||||
)
|
||||
|
||||
@@ -90,16 +96,20 @@ class ResourceBase(object):
|
||||
return response
|
||||
|
||||
def _check_server_version_at_least(
|
||||
self, target_version: Tuple[Any, ...], unsupported_message: str = None
|
||||
self, target_version: Tuple[Any, ...], unsupported_message: Optional[str] = None
|
||||
):
|
||||
"""Use this check to guard against making unsupported requests on older servers.
|
||||
|
||||
Arguments:
|
||||
target_version {tuple} -- the minimum server version in the format (major, minor, patch, (tag, build))
|
||||
eg (2, 6, 3) for a stable build and (2, 6, 4, 'alpha', 4711) for alpha
|
||||
target_version {tuple}
|
||||
the minimum server version in the format (major, minor, patch, (tag, build))
|
||||
eg (2, 6, 3) for a stable build and (2, 6, 4, 'alpha', 4711) for alpha
|
||||
"""
|
||||
if not unsupported_message:
|
||||
unsupported_message = f"The client method used is not supported on Speckle Server versions prior to v{'.'.join(target_version)}"
|
||||
unsupported_message = (
|
||||
"The client method used is not supported on Speckle Server versions"
|
||||
f" prior to v{'.'.join(target_version)}"
|
||||
)
|
||||
# if version is dev, it should be supported... (or not)
|
||||
if self.server_version == ("dev",):
|
||||
return
|
||||
@@ -112,8 +122,7 @@ class ResourceBase(object):
|
||||
"""
|
||||
self._check_server_version_at_least(
|
||||
(2, 6, 4),
|
||||
(
|
||||
"Stream invites are only supported as of Speckle Server v2.6.4. "
|
||||
"Please update your Speckle Server to use this method or use the `grant_permission` flow instead."
|
||||
),
|
||||
"Stream invites are only supported as of Speckle Server v2.6.4. Please"
|
||||
" update your Speckle Server to use this method or use the"
|
||||
" `grant_permission` flow instead.",
|
||||
)
|
||||
|
||||
@@ -2,8 +2,7 @@ import pkgutil
|
||||
import sys
|
||||
from importlib import import_module
|
||||
|
||||
for (_, name, _) in pkgutil.iter_modules(__path__):
|
||||
|
||||
for _, name, _ in pkgutil.iter_modules(__path__):
|
||||
imported_module = import_module("." + name, package=__name__)
|
||||
|
||||
if hasattr(imported_module, "Resource"):
|
||||
|
||||
@@ -25,7 +25,9 @@ class Resource(ResourceBase):
|
||||
self.schema = User
|
||||
|
||||
def get(self) -> User:
|
||||
"""Gets the profile of a user. If no id argument is provided, will return the current authenticated user's profile (as extracted from the authorization header).
|
||||
"""Gets the profile of a user. If no id argument is provided,
|
||||
will return the current authenticated user's profile
|
||||
(as extracted from the authorization header).
|
||||
|
||||
Arguments:
|
||||
id {str} -- the user id
|
||||
@@ -88,7 +90,9 @@ class Resource(ResourceBase):
|
||||
|
||||
if not params["user"]:
|
||||
return SpeckleException(
|
||||
message="You must provide at least one field to update your user profile"
|
||||
message=(
|
||||
"You must provide at least one field to update your user profile"
|
||||
)
|
||||
)
|
||||
|
||||
return self.make_request(
|
||||
@@ -104,24 +108,42 @@ class Resource(ResourceBase):
|
||||
cursor: Optional[datetime] = None,
|
||||
):
|
||||
"""
|
||||
Get the activity from a given stream in an Activity collection. Step into the activity `items` for the list of activity.
|
||||
If no id argument is provided, will return the current authenticated user's activity (as extracted from the authorization header).
|
||||
Get the activity from a given stream in an Activity collection.
|
||||
Step into the activity `items` for the list of activity.
|
||||
If no id argument is provided, will return the current authenticated user's
|
||||
activity (as extracted from the authorization header).
|
||||
|
||||
Note: all timestamps arguments should be `datetime` of any tz as they will be converted to UTC ISO format strings
|
||||
Note: all timestamps arguments should be `datetime` of any tz as they will be
|
||||
converted to UTC ISO format strings
|
||||
|
||||
user_id {str} -- the id of the user to get the activity from
|
||||
action_type {str} -- filter results to a single action type (eg: `commit_create` or `commit_receive`)
|
||||
action_type {str} -- filter results to a single action type
|
||||
(eg: `commit_create` or `commit_receive`)
|
||||
limit {int} -- max number of Activity items to return
|
||||
before {datetime} -- latest cutoff for activity (ie: return all activity _before_ this time)
|
||||
after {datetime} -- oldest cutoff for activity (ie: return all activity _after_ this time)
|
||||
before {datetime} -- latest cutoff for activity
|
||||
(ie: return all activity _before_ this time)
|
||||
after {datetime} -- oldest cutoff for activity
|
||||
(ie: return all activity _after_ this time)
|
||||
cursor {datetime} -- timestamp cursor for pagination
|
||||
"""
|
||||
|
||||
query = gql(
|
||||
"""
|
||||
query UserActivity($action_type: String, $before:DateTime, $after: DateTime, $cursor: DateTime, $limit: Int){
|
||||
query UserActivity(
|
||||
$action_type: String,
|
||||
$before:DateTime,
|
||||
$after: DateTime,
|
||||
$cursor: DateTime,
|
||||
$limit: Int
|
||||
){
|
||||
activeUser {
|
||||
activity(actionType: $action_type, before: $before, after: $after, cursor: $cursor, limit: $limit) {
|
||||
activity(
|
||||
actionType: $action_type,
|
||||
before: $before,
|
||||
after: $after,
|
||||
cursor: $cursor,
|
||||
limit: $limit
|
||||
) {
|
||||
totalCount
|
||||
cursor
|
||||
items {
|
||||
@@ -161,7 +183,8 @@ class Resource(ResourceBase):
|
||||
Requires Speckle Server version >= 2.6.4
|
||||
|
||||
Returns:
|
||||
List[PendingStreamCollaborator] -- a list of pending invites for the current user
|
||||
List[PendingStreamCollaborator]
|
||||
-- a list of pending invites for the current user
|
||||
"""
|
||||
metrics.track(metrics.INVITE, self.account, {"name": "get"})
|
||||
self._check_invites_supported()
|
||||
@@ -207,7 +230,8 @@ class Resource(ResourceBase):
|
||||
token {str} -- the token of the invite to look for (optional)
|
||||
|
||||
Returns:
|
||||
PendingStreamCollaborator -- the invite for the given stream (or None if it isn't found)
|
||||
PendingStreamCollaborator
|
||||
-- the invite for the given stream (or None if it isn't found)
|
||||
"""
|
||||
metrics.track(metrics.INVITE, self.account, {"name": "get"})
|
||||
self._check_invites_supported()
|
||||
|
||||
@@ -61,21 +61,28 @@ class Resource(ResourceBase):
|
||||
"""
|
||||
Not advised - generally, you want to use `operations.send()`.
|
||||
|
||||
Create a new object on a stream. To send a base object, you can prepare it by running it through the
|
||||
`BaseObjectSerializer.traverse_base()` function to get a valid (serialisable) object to send.
|
||||
Create a new object on a stream.
|
||||
To send a base object, you can prepare it by running it through the
|
||||
`BaseObjectSerializer.traverse_base()` function to get a valid (serialisable)
|
||||
object to send.
|
||||
|
||||
NOTE: this does not create a commit - you can create one with `SpeckleClient.commit.create`. Dynamic fields will be located in the 'data' dict of the received `Base` object
|
||||
NOTE: this does not create a commit - you can create one with
|
||||
`SpeckleClient.commit.create`.
|
||||
Dynamic fields will be located in the 'data' dict of the received `Base` object
|
||||
|
||||
Arguments:
|
||||
stream_id {str} -- the id of the stream you want to send the object to
|
||||
objects {List[Dict]} -- a list of base dictionary objects (NOTE: must be json serialisable)
|
||||
objects {List[Dict]}
|
||||
-- a list of base dictionary objects (NOTE: must be json serialisable)
|
||||
|
||||
Returns:
|
||||
str -- the id of the object
|
||||
"""
|
||||
query = gql(
|
||||
"""
|
||||
mutation ObjectCreate($object_input: ObjectCreateInput!) { objectCreate(objectInput: $object_input) }
|
||||
mutation ObjectCreate($object_input: ObjectCreateInput!) {
|
||||
objectCreate(objectInput: $object_input)
|
||||
}
|
||||
"""
|
||||
)
|
||||
params = {"object_input": {"streamId": stream_id, "objects": objects}}
|
||||
|
||||
@@ -58,7 +58,8 @@ class Resource(ResourceBase):
|
||||
def search(
|
||||
self, search_query: str, limit: int = 25
|
||||
) -> Union[List[LimitedUser], SpeckleException]:
|
||||
"""Searches for user by name or email. The search query must be at least 3 characters long
|
||||
"""Searches for user by name or email. The search query must be at least
|
||||
3 characters long
|
||||
|
||||
Arguments:
|
||||
search_query {str} -- a string to search for
|
||||
@@ -104,23 +105,41 @@ class Resource(ResourceBase):
|
||||
cursor: Optional[datetime] = None,
|
||||
) -> ActivityCollection:
|
||||
"""
|
||||
Get the activity from a given stream in an Activity collection. Step into the activity `items` for the list of activity.
|
||||
Get the activity from a given stream in an Activity collection.
|
||||
Step into the activity `items` for the list of activity.
|
||||
|
||||
Note: all timestamps arguments should be `datetime` of any tz as they will be converted to UTC ISO format strings
|
||||
Note: all timestamps arguments should be `datetime` of
|
||||
any tz as they will be converted to UTC ISO format strings
|
||||
|
||||
user_id {str} -- the id of the user to get the activity from
|
||||
action_type {str} -- filter results to a single action type (eg: `commit_create` or `commit_receive`)
|
||||
action_type {str} -- filter results to a single action type
|
||||
(eg: `commit_create` or `commit_receive`)
|
||||
limit {int} -- max number of Activity items to return
|
||||
before {datetime} -- latest cutoff for activity (ie: return all activity _before_ this time)
|
||||
after {datetime} -- oldest cutoff for activity (ie: return all activity _after_ this time)
|
||||
before {datetime} -- latest cutoff for activity
|
||||
(ie: return all activity _before_ this time)
|
||||
after {datetime} -- oldest cutoff for activity
|
||||
(ie: return all activity _after_ this time)
|
||||
cursor {datetime} -- timestamp cursor for pagination
|
||||
"""
|
||||
|
||||
query = gql(
|
||||
"""
|
||||
query UserActivity($user_id: String!, $action_type: String, $before:DateTime, $after: DateTime, $cursor: DateTime, $limit: Int){
|
||||
query UserActivity(
|
||||
$user_id: String!,
|
||||
$action_type: String,
|
||||
$before:DateTime,
|
||||
$after: DateTime,
|
||||
$cursor: DateTime,
|
||||
$limit: Int
|
||||
){
|
||||
otherUser(id: $user_id) {
|
||||
activity(actionType: $action_type, before: $before, after: $after, cursor: $cursor, limit: $limit) {
|
||||
activity(
|
||||
actionType: $action_type,
|
||||
before: $before,
|
||||
after: $after,
|
||||
cursor: $cursor,
|
||||
limit: $limit
|
||||
) {
|
||||
totalCount
|
||||
cursor
|
||||
items {
|
||||
|
||||
@@ -66,8 +66,8 @@ class Resource(ResourceBase):
|
||||
"""Get the server version
|
||||
|
||||
Returns:
|
||||
tuple -- the server version in the format (major, minor, patch, (tag, build))
|
||||
eg (2, 6, 3) for a stable build and (2, 6, 4, 'alpha', 4711) for alpha
|
||||
the server version in the format (major, minor, patch, (tag, build))
|
||||
eg (2, 6, 3) for a stable build and (2, 6, 4, 'alpha', 4711) for alpha
|
||||
"""
|
||||
# not tracking as it will be called along with other mutations / queries as a check
|
||||
query = gql(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from datetime import datetime, timezone
|
||||
from typing import List, Optional
|
||||
from typing import List
|
||||
|
||||
from deprecated import deprecated
|
||||
from gql import gql
|
||||
@@ -346,8 +346,8 @@ class Resource(ResourceBase):
|
||||
@deprecated(
|
||||
version="2.6.4",
|
||||
reason=(
|
||||
"As of Speckle Server v2.6.4, this method is deprecated. "
|
||||
"Users need to be invited and accept the invite before being added to a stream"
|
||||
"As of Speckle Server v2.6.4, this method is deprecated. Users need to be"
|
||||
" invited and accept the invite before being added to a stream"
|
||||
),
|
||||
)
|
||||
def grant_permission(self, stream_id: str, user_id: str, role: str):
|
||||
@@ -370,11 +370,10 @@ class Resource(ResourceBase):
|
||||
self.server_version == ("dev",) or self.server_version >= (2, 6, 4)
|
||||
):
|
||||
raise UnsupportedException(
|
||||
(
|
||||
"Server mutation `grant_permission` is no longer supported as of Speckle Server v2.6.4. "
|
||||
"Please use the new `update_permission` method to change an existing user's permission "
|
||||
"or use the `invite` method to invite a user to a stream."
|
||||
)
|
||||
"Server mutation `grant_permission` is no longer supported as of"
|
||||
" Speckle Server v2.6.4. Please use the new `update_permission` method"
|
||||
" to change an existing user's permission or use the `invite` method to"
|
||||
" invite a user to a stream."
|
||||
)
|
||||
|
||||
query = gql(
|
||||
@@ -482,7 +481,8 @@ class Resource(ResourceBase):
|
||||
|
||||
if email is None and user_id is None:
|
||||
raise SpeckleException(
|
||||
"You must provide either an email or a user id to use the `stream.invite` method"
|
||||
"You must provide either an email or a user id to use the"
|
||||
" `stream.invite` method"
|
||||
)
|
||||
|
||||
query = gql(
|
||||
@@ -533,7 +533,8 @@ class Resource(ResourceBase):
|
||||
self._check_invites_supported()
|
||||
if emails is None and user_ids is None:
|
||||
raise SpeckleException(
|
||||
"You must provide either an email or a user id to use the `stream.invite` method"
|
||||
"You must provide either an email or a user id to use the"
|
||||
" `stream.invite` method"
|
||||
)
|
||||
|
||||
query = gql(
|
||||
@@ -650,10 +651,9 @@ class Resource(ResourceBase):
|
||||
self.server_version != ("dev",) and self.server_version < (2, 6, 4)
|
||||
):
|
||||
raise UnsupportedException(
|
||||
(
|
||||
"Server mutation `update_permission` is only supported as of Speckle Server v2.6.4. "
|
||||
"Please update your Speckle Server to use this method or use the `grant_permission` method instead."
|
||||
)
|
||||
"Server mutation `update_permission` is only supported as of Speckle"
|
||||
" Server v2.6.4. Please update your Speckle Server to use this method"
|
||||
" or use the `grant_permission` method instead."
|
||||
)
|
||||
query = gql(
|
||||
"""
|
||||
@@ -764,7 +764,8 @@ class Resource(ResourceBase):
|
||||
}
|
||||
except AttributeError as e:
|
||||
raise SpeckleException(
|
||||
"Could not get stream activity - `before`, `after`, and `cursor` must be in `datetime` format if provided",
|
||||
"Could not get stream activity - `before`, `after`, and `cursor` must"
|
||||
" be in `datetime` format if provided",
|
||||
ValueError,
|
||||
) from e
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from functools import wraps
|
||||
from typing import Callable, Dict, List, Union
|
||||
from typing import Callable, Dict, List, Optional, Union
|
||||
|
||||
from gql import gql
|
||||
from graphql import DocumentNode
|
||||
@@ -36,11 +36,13 @@ class Resource(ResourceBase):
|
||||
)
|
||||
|
||||
@check_wsclient
|
||||
async def stream_added(self, callback: Callable = None):
|
||||
"""Subscribes to new stream added event for your profile. Use this to display an up-to-date list of streams.
|
||||
async def stream_added(self, callback: Optional[Callable] = None):
|
||||
"""Subscribes to new stream added event for your profile.
|
||||
Use this to display an up-to-date list of streams.
|
||||
|
||||
Arguments:
|
||||
callback {Callable[Stream]} -- a function that takes the updated stream as an argument and executes each time a stream is added
|
||||
callback {Callable[Stream]} -- a function that takes the updated stream
|
||||
as an argument and executes each time a stream is added
|
||||
|
||||
Returns:
|
||||
Stream -- the update stream
|
||||
@@ -55,12 +57,16 @@ class Resource(ResourceBase):
|
||||
)
|
||||
|
||||
@check_wsclient
|
||||
async def stream_updated(self, id: str, callback: Callable = None):
|
||||
"""Subscribes to stream updated event. Use this in clients/components that pertain only to this stream.
|
||||
async def stream_updated(self, id: str, callback: Optional[Callable] = None):
|
||||
"""
|
||||
Subscribes to stream updated event.
|
||||
Use this in clients/components that pertain only to this stream.
|
||||
|
||||
Arguments:
|
||||
id {str} -- the stream id of the stream to subscribe to
|
||||
callback {Callable[Stream]} -- a function that takes the updated stream as an argument and executes each time the stream is updated
|
||||
callback {Callable[Stream]}
|
||||
-- a function that takes the updated stream
|
||||
as an argument and executes each time the stream is updated
|
||||
|
||||
Returns:
|
||||
Stream -- the update stream
|
||||
@@ -81,11 +87,17 @@ class Resource(ResourceBase):
|
||||
)
|
||||
|
||||
@check_wsclient
|
||||
async def stream_removed(self, callback: Callable = None):
|
||||
"""Subscribes to stream removed event for your profile. Use this to display an up-to-date list of streams for your profile. NOTE: If someone revokes your permissions on a stream, this subscription will be triggered with an extra value of revokedBy in the payload.
|
||||
async def stream_removed(self, callback: Optional[Callable] = None):
|
||||
"""Subscribes to stream removed event for your profile.
|
||||
Use this to display an up-to-date list of streams for your profile.
|
||||
NOTE: If someone revokes your permissions on a stream,
|
||||
this subscription will be triggered with an extra value of revokedBy
|
||||
in the payload.
|
||||
|
||||
Arguments:
|
||||
callback {Callable[Dict]} -- a function that takes the returned dict as an argument and executes each time a stream is removed
|
||||
callback {Callable[Dict]}
|
||||
-- a function that takes the returned dict as an argument
|
||||
and executes each time a stream is removed
|
||||
|
||||
Returns:
|
||||
dict -- dict containing 'id' of stream removed and optionally 'revokedBy'
|
||||
@@ -107,9 +119,9 @@ class Resource(ResourceBase):
|
||||
async def subscribe(
|
||||
self,
|
||||
query: DocumentNode,
|
||||
params: Dict = None,
|
||||
callback: Callable = None,
|
||||
return_type: Union[str, List] = None,
|
||||
params: Optional[Dict] = None,
|
||||
callback: Optional[Callable] = None,
|
||||
return_type: Optional[Union[str, List]] = None,
|
||||
schema=None,
|
||||
parse_response: bool = True,
|
||||
):
|
||||
|
||||
@@ -12,7 +12,10 @@ from specklepy.logging.exceptions import SpeckleException
|
||||
NAME = "user"
|
||||
|
||||
DEPRECATION_VERSION = "2.9.0"
|
||||
DEPRECATION_TEXT = "The user resource is deprecated, please use the active_user or other_user resources"
|
||||
DEPRECATION_TEXT = (
|
||||
"The user resource is deprecated, please use the active_user or other_user"
|
||||
" resources"
|
||||
)
|
||||
|
||||
|
||||
class Resource(ResourceBase):
|
||||
@@ -137,7 +140,9 @@ class Resource(ResourceBase):
|
||||
|
||||
if not params["user"]:
|
||||
return SpeckleException(
|
||||
message="You must provide at least one field to update your user profile"
|
||||
message=(
|
||||
"You must provide at least one field to update your user profile"
|
||||
)
|
||||
)
|
||||
|
||||
return self.make_request(
|
||||
|
||||
@@ -14,11 +14,15 @@ from specklepy.transports.server.server import ServerTransport
|
||||
|
||||
class StreamWrapper:
|
||||
"""
|
||||
The `StreamWrapper` gives you some handy helpers to deal with urls and get authenticated clients and transports.
|
||||
The `StreamWrapper` gives you some handy helpers to deal with urls and
|
||||
get authenticated clients and transports.
|
||||
|
||||
Construct a `StreamWrapper` with a stream, branch, commit, or object URL. The corresponding ids will be stored
|
||||
in the wrapper. If you have local accounts on the machine, you can use the `get_account` and `get_client` methods
|
||||
to get a local account for the server. You can also pass a token into `get_client` if you don't have a corresponding
|
||||
Construct a `StreamWrapper` with a stream, branch, commit, or object URL.
|
||||
The corresponding ids will be stored
|
||||
in the wrapper. If you have local accounts on the machine,
|
||||
you can use the `get_account` and `get_client` methods
|
||||
to get a local account for the server. You can also pass a token into `get_client`
|
||||
if you don't have a corresponding
|
||||
local account for the server.
|
||||
|
||||
```py
|
||||
@@ -46,7 +50,10 @@ class StreamWrapper:
|
||||
_account: Account = None
|
||||
|
||||
def __repr__(self):
|
||||
return f"StreamWrapper( server: {self.host}, stream_id: {self.stream_id}, type: {self.type} )"
|
||||
return (
|
||||
f"StreamWrapper( server: {self.host}, stream_id: {self.stream_id}, type:"
|
||||
f" {self.type} )"
|
||||
)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return self.__repr__()
|
||||
@@ -72,7 +79,8 @@ class StreamWrapper:
|
||||
|
||||
if not segments or len(segments) < 2:
|
||||
raise SpeckleException(
|
||||
f"Cannot parse {url} into a stream wrapper class - invalid URL provided."
|
||||
f"Cannot parse {url} into a stream wrapper class - invalid URL"
|
||||
" provided."
|
||||
)
|
||||
|
||||
while segments:
|
||||
@@ -91,7 +99,8 @@ class StreamWrapper:
|
||||
self.commit_id = segments.pop(0)
|
||||
else:
|
||||
raise SpeckleException(
|
||||
f"Cannot parse {url} into a stream wrapper class - invalid URL provided."
|
||||
f"Cannot parse {url} into a stream wrapper class - invalid URL"
|
||||
" provided."
|
||||
)
|
||||
|
||||
if not self.stream_id:
|
||||
@@ -105,7 +114,8 @@ class StreamWrapper:
|
||||
|
||||
def get_account(self, token: str = None) -> Account:
|
||||
"""
|
||||
Gets an account object for this server from the local accounts db (added via Speckle Manager or a json file)
|
||||
Gets an account object for this server from the local accounts db
|
||||
(added via Speckle Manager or a json file)
|
||||
"""
|
||||
if self._account and self._account.token:
|
||||
return self._account
|
||||
@@ -129,14 +139,18 @@ class StreamWrapper:
|
||||
|
||||
def get_client(self, token: str = None) -> SpeckleClient:
|
||||
"""
|
||||
Gets an authenticated client for this server. You may provide a token if there aren't any local accounts on this
|
||||
machine. If no account is found and no token is provided, an unauthenticated client is returned.
|
||||
Gets an authenticated client for this server.
|
||||
You may provide a token if there aren't any local accounts on this
|
||||
machine. If no account is found and no token is provided,
|
||||
an unauthenticated client is returned.
|
||||
|
||||
Arguments:
|
||||
token {str} -- optional token if no local account is available (defaults to None)
|
||||
token {str}
|
||||
-- optional token if no local account is available (defaults to None)
|
||||
|
||||
Returns:
|
||||
SpeckleClient -- authenticated with a corresponding local account or the provided token
|
||||
SpeckleClient
|
||||
-- authenticated with a corresponding local account or the provided token
|
||||
"""
|
||||
if self._client and token is None:
|
||||
return self._client
|
||||
@@ -160,11 +174,14 @@ class StreamWrapper:
|
||||
|
||||
def get_transport(self, token: str = None) -> ServerTransport:
|
||||
"""
|
||||
Gets a server transport for this stream using an authenticated client. If there is no local account for this
|
||||
server and the client was not authenticated with a token, this will throw an exception.
|
||||
Gets a server transport for this stream using an authenticated client.
|
||||
If there is no local account for this
|
||||
server and the client was not authenticated with a token,
|
||||
this will throw an exception.
|
||||
|
||||
Returns:
|
||||
ServerTransport -- constructed for this stream with a pre-authenticated client
|
||||
ServerTransport -- constructed for this stream
|
||||
with a pre-authenticated client
|
||||
"""
|
||||
if not self._account or not self._account.token:
|
||||
self.get_account(token)
|
||||
|
||||
@@ -13,9 +13,11 @@ class SpeckleException(Exception):
|
||||
|
||||
class SpeckleInvalidUnitException(SpeckleException):
|
||||
def __init__(self, invalid_unit: Any) -> None:
|
||||
|
||||
super().__init__(
|
||||
message=f"Invalid units: expected type str but received {type(invalid_unit)} ({invalid_unit}).",
|
||||
message=(
|
||||
"Invalid units: expected type str but received"
|
||||
f" {type(invalid_unit)} ({invalid_unit})."
|
||||
),
|
||||
exception=None,
|
||||
)
|
||||
|
||||
@@ -27,7 +29,10 @@ class SerializationException(SpeckleException):
|
||||
self.unhandled_type = type(obj)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"SpeckleException: Could not serialize object of type {self.unhandled_type}"
|
||||
return (
|
||||
"SpeckleException: Could not serialize object of type"
|
||||
f" {self.unhandled_type}"
|
||||
)
|
||||
|
||||
|
||||
class GraphQLException(SpeckleException):
|
||||
|
||||
@@ -58,7 +58,11 @@ def set_host_app(host_app: str, host_app_version: Optional[str] = None):
|
||||
HOST_APP_VERSION = host_app_version or HOST_APP_VERSION
|
||||
|
||||
|
||||
def track(action: str, account: "Account" = None, custom_props: Optional[dict] = None):
|
||||
def track(
|
||||
action: str,
|
||||
account: Optional["Account"] = None,
|
||||
custom_props: Optional[dict] = None,
|
||||
):
|
||||
if not TRACK:
|
||||
return
|
||||
try:
|
||||
@@ -84,7 +88,7 @@ def track(action: str, account: "Account" = None, custom_props: Optional[dict] =
|
||||
LOG.debug(f"Error queueing metrics request: {str(ex)}")
|
||||
|
||||
|
||||
def initialise_tracker(account: "Account" = None):
|
||||
def initialise_tracker(account: Optional["Account"] = None):
|
||||
global METRICS_TRACKER
|
||||
if not METRICS_TRACKER:
|
||||
METRICS_TRACKER = MetricsTracker()
|
||||
|
||||
@@ -149,7 +149,7 @@ class _RegisteringBase:
|
||||
raise ValueError(
|
||||
f"The speckle_type: {speckle_type} is already registered for type: "
|
||||
f"{cls._type_registry[cls.speckle_type].__name__}. "
|
||||
f"Please choose a different type name."
|
||||
"Please choose a different type name."
|
||||
)
|
||||
cls._type_registry[cls.speckle_type] = cls # type: ignore
|
||||
try:
|
||||
@@ -334,11 +334,14 @@ class Base(_RegisteringBase):
|
||||
@classmethod
|
||||
def update_forward_refs(cls) -> None:
|
||||
"""
|
||||
Attempts to populate the internal defined types dict for type checking sometime after defining the class.
|
||||
This is already done when defining the class, but can be called again if references to undefined types were
|
||||
Attempts to populate the internal defined types dict for type checking
|
||||
sometime after defining the class.
|
||||
This is already done when defining the class, but can be called
|
||||
again if references to undefined types were
|
||||
included.
|
||||
|
||||
See `objects.geometry` for an example of how this is used with the Brep class definitions
|
||||
See `objects.geometry` for an example of how this is used with
|
||||
the Brep class definitions.
|
||||
"""
|
||||
try:
|
||||
cls._attr_types = get_type_hints(cls)
|
||||
@@ -387,7 +390,8 @@ class Base(_RegisteringBase):
|
||||
Mark defined attributes as chunkable for serialisation
|
||||
|
||||
Arguments:
|
||||
kwargs {int} -- the name of the attribute as the keyword and the chunk size as the arg
|
||||
kwargs {int} -- the name of the attribute as the keyword
|
||||
and the chunk size as the arg
|
||||
"""
|
||||
chunkable = {k: v for k, v in kwargs.items() if isinstance(v, int)}
|
||||
self._chunkable = dict(self._chunkable, **chunkable)
|
||||
@@ -397,7 +401,7 @@ class Base(_RegisteringBase):
|
||||
Mark defined attributes as detachable for serialisation
|
||||
|
||||
Arguments:
|
||||
names {Set[str]} -- the names of the attributes to detach as a set of strings
|
||||
names {Set[str]} -- the names of the attributes to detach as a set of string
|
||||
"""
|
||||
self._detachable = self._detachable.union(names)
|
||||
|
||||
@@ -409,7 +413,7 @@ class Base(_RegisteringBase):
|
||||
|
||||
@units.setter
|
||||
def units(self, value: Union[str, Units, None]):
|
||||
if value == None:
|
||||
if value is None:
|
||||
units = value
|
||||
elif isinstance(value, Units):
|
||||
units: Units = value
|
||||
@@ -448,13 +452,17 @@ class Base(_RegisteringBase):
|
||||
|
||||
def get_id(self, decompose: bool = False) -> str:
|
||||
"""
|
||||
Gets the id (a unique hash) of this object. ⚠️ This method fully serializes the object which,
|
||||
in the case of large objects (with many sub-objects), has a tangible cost. Avoid using it!
|
||||
Gets the id (a unique hash) of this object.
|
||||
⚠️ This method fully serializes the object which,
|
||||
in the case of large objects (with many sub-objects), has a tangible cost.
|
||||
Avoid using it!
|
||||
|
||||
Note: the hash of a decomposed object differs from that of a non-decomposed object
|
||||
Note: the hash of a decomposed object differs from that of a
|
||||
non-decomposed object
|
||||
|
||||
Arguments:
|
||||
decompose {bool} -- if True, will decompose the object in the process of hashing it
|
||||
decompose {bool} -- if True, will decompose the object in
|
||||
the process of hashing it
|
||||
|
||||
Returns:
|
||||
str -- the hash (id) of the fully serialized object
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from enum import Enum, IntEnum, auto
|
||||
from enum import Enum
|
||||
from typing import Any, List, Optional
|
||||
|
||||
from specklepy.objects.base import Base
|
||||
@@ -15,11 +15,17 @@ class Point(Base, speckle_type=GEOMETRY + "Point"):
|
||||
z: float = 0.0
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"{self.__class__.__name__}(x: {self.x}, y: {self.y}, z: {self.z}, id: {self.id}, speckle_type: {self.speckle_type})"
|
||||
return (
|
||||
f"{self.__class__.__name__}(x: {self.x}, y: {self.y}, z: {self.z}, id:"
|
||||
f" {self.id}, speckle_type: {self.speckle_type})"
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def from_list(cls, args: List[float]) -> "Point":
|
||||
"""Create a new Point from a list of three floats representing the x, y, and z coordinates"""
|
||||
"""
|
||||
Create a new Point from a list of three floats
|
||||
representing the x, y, and z coordinates
|
||||
"""
|
||||
return cls(x=args[0], y=args[1], z=args[2])
|
||||
|
||||
def to_list(self) -> List[Any]:
|
||||
|
||||
@@ -77,7 +77,8 @@ class Transform(
|
||||
"""The 4x4 transformation matrix
|
||||
|
||||
The 3x3 sub-matrix determines scaling.
|
||||
The 4th column defines translation, where the last value is a divisor (usually equal to 1).
|
||||
The 4th column defines translation,
|
||||
where the last value is a divisor (usually equal to 1).
|
||||
"""
|
||||
|
||||
_value: Optional[List[float]] = None
|
||||
@@ -93,12 +94,14 @@ class Transform(
|
||||
value = [float(x) for x in value]
|
||||
except (ValueError, TypeError) as error:
|
||||
raise ValueError(
|
||||
f"Could not create a Transform object with the requested value. Input must be a 16 element list of numbers. Value provided: {value}"
|
||||
"Could not create a Transform object with the requested value. Input"
|
||||
f" must be a 16 element list of numbers. Value provided: {value}"
|
||||
) from error
|
||||
|
||||
if len(value) != 16:
|
||||
raise ValueError(
|
||||
f"Could not create a Transform object: input list should be 16 floats long, but was {len(value)} long"
|
||||
"Could not create a Transform object: input list should be 16 floats"
|
||||
f" long, but was {len(value)} long"
|
||||
)
|
||||
|
||||
self._value = value
|
||||
@@ -163,14 +166,16 @@ class Transform(
|
||||
"""Transform a list of speckle Points
|
||||
|
||||
Arguments:
|
||||
points {List[float]} -- a flat list of floats representing points to transform
|
||||
points {List[float]}
|
||||
-- a flat list of floats representing points to transform
|
||||
|
||||
Returns:
|
||||
List[float] -- a new transformed list
|
||||
"""
|
||||
if len(points_value) % 3 != 0:
|
||||
raise ValueError(
|
||||
"Cannot apply transform as the points list is malformed: expected length to be multiple of 3"
|
||||
"Cannot apply transform as the points list is malformed: expected"
|
||||
" length to be multiple of 3"
|
||||
)
|
||||
transformed = []
|
||||
for i in range(0, len(points_value), 3):
|
||||
@@ -207,11 +212,13 @@ class Transform(
|
||||
][:3]
|
||||
|
||||
@classmethod
|
||||
def from_list(cls, value: List[float] = None) -> "Transform":
|
||||
"""Returns a Transform object from a list of 16 numbers. If no value is provided, an identity transform will be returned.
|
||||
def from_list(cls, value: Optional[List[float]] = None) -> "Transform":
|
||||
"""Returns a Transform object from a list of 16 numbers.
|
||||
If no value is provided, an identity transform will be returned.
|
||||
|
||||
Arguments:
|
||||
value {List[float]} -- the matrix as a flat list of 16 numbers (defaults to the identity transform)
|
||||
value {List[float]} -- the matrix as a flat list of 16 numbers
|
||||
(defaults to the identity transform)
|
||||
|
||||
Returns:
|
||||
Transform -- a complete transform object
|
||||
|
||||
@@ -9,7 +9,6 @@ STRUCTURAL_LOADING = "Objects.Structural.Loading."
|
||||
|
||||
|
||||
class LoadType(int, Enum):
|
||||
|
||||
none = 0
|
||||
Dead = 1
|
||||
SuperDead = 2
|
||||
@@ -32,7 +31,6 @@ class LoadType(int, Enum):
|
||||
|
||||
|
||||
class ActionType(int, Enum):
|
||||
|
||||
none = 0
|
||||
Permanent = 1
|
||||
Variable = 2
|
||||
@@ -40,7 +38,6 @@ class ActionType(int, Enum):
|
||||
|
||||
|
||||
class BeamLoadType(int, Enum):
|
||||
|
||||
Point = 0
|
||||
Uniform = 1
|
||||
Linear = 2
|
||||
@@ -49,21 +46,18 @@ class BeamLoadType(int, Enum):
|
||||
|
||||
|
||||
class FaceLoadType(int, Enum):
|
||||
|
||||
Constant = 0
|
||||
Variable = 1
|
||||
Point = 2
|
||||
|
||||
|
||||
class LoadDirection2D(int, Enum):
|
||||
|
||||
X = 0
|
||||
Y = 1
|
||||
Z = 2
|
||||
|
||||
|
||||
class LoadDirection(int, Enum):
|
||||
|
||||
X = 0
|
||||
Y = 1
|
||||
Z = 2
|
||||
@@ -81,7 +75,6 @@ class LoadAxisType(int, Enum):
|
||||
|
||||
|
||||
class CombinationType(int, Enum):
|
||||
|
||||
LinearAdd = 0
|
||||
Envelope = 1
|
||||
AbsoluteAdd = 2
|
||||
|
||||
@@ -38,7 +38,6 @@ class ReferenceSurface(int, Enum):
|
||||
|
||||
|
||||
class PropertyType2D(int, Enum):
|
||||
|
||||
Stress = 0
|
||||
Fabric = 1
|
||||
Plate = 2
|
||||
|
||||
@@ -2,15 +2,13 @@ import hashlib
|
||||
import re
|
||||
import warnings
|
||||
from enum import Enum
|
||||
from typing import Any, Dict, List, Tuple
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
from uuid import uuid4
|
||||
from warnings import warn
|
||||
|
||||
import ujson
|
||||
|
||||
# import for serialization
|
||||
import specklepy.objects.geometry
|
||||
import specklepy.objects.other
|
||||
from specklepy.logging.exceptions import SpeckleException, SpeckleWarning
|
||||
from specklepy.objects.base import Base, DataChunk
|
||||
from specklepy.transports.abstract_transport import AbstractTransport
|
||||
@@ -29,7 +27,8 @@ def safe_json_loads(obj: str, obj_id=None) -> Any:
|
||||
import json
|
||||
|
||||
warn(
|
||||
f"Failed to deserialise object (id: {obj_id}). This is likely a ujson big int error - falling back to json. \nError: {err}",
|
||||
f"Failed to deserialise object (id: {obj_id}). This is likely a ujson big"
|
||||
f" int error - falling back to json. \nError: {err}",
|
||||
SpeckleWarning,
|
||||
)
|
||||
return json.loads(obj)
|
||||
@@ -47,7 +46,9 @@ class BaseObjectSerializer:
|
||||
] # holds deserialized objects so objects with same id return the same instance
|
||||
|
||||
def __init__(
|
||||
self, write_transports: List[AbstractTransport] = None, read_transport=None
|
||||
self,
|
||||
write_transports: Optional[List[AbstractTransport]] = None,
|
||||
read_transport: Optional[AbstractTransport] = None,
|
||||
) -> None:
|
||||
self.write_transports = write_transports or []
|
||||
self.read_transport = read_transport
|
||||
@@ -63,7 +64,8 @@ class BaseObjectSerializer:
|
||||
base {Base} -- the base object to be decomposed and serialized
|
||||
|
||||
Returns:
|
||||
(str, str) -- a tuple containing the object id of the base object and the serialized object string
|
||||
(str, str) -- a tuple containing the object id of the base object and
|
||||
the serialized object string
|
||||
"""
|
||||
|
||||
obj_id, obj = self.traverse_base(base)
|
||||
@@ -77,7 +79,8 @@ class BaseObjectSerializer:
|
||||
base {Base} -- the base object to be decomposed and serialized
|
||||
|
||||
Returns:
|
||||
(str, dict) -- a tuple containing the object id of the base object and the constructed serializable dictionary
|
||||
(str, dict) -- a tuple containing the object id of the base object and
|
||||
the constructed serializable dictionary
|
||||
"""
|
||||
self.__reset_writer()
|
||||
|
||||
@@ -247,16 +250,19 @@ class BaseObjectSerializer:
|
||||
else:
|
||||
try:
|
||||
return obj.dict()
|
||||
except:
|
||||
except Exception:
|
||||
warn(
|
||||
f"Failed to handle {type(obj)} in `BaseObjectSerializer.traverse_value`",
|
||||
f"Failed to handle {type(obj)} in"
|
||||
" `BaseObjectSerializer.traverse_value`",
|
||||
SpeckleWarning,
|
||||
)
|
||||
|
||||
return str(obj)
|
||||
|
||||
def detach_helper(self, ref_id: str) -> Dict[str, str]:
|
||||
"""Helper to keep track of detached objects and their depth in the family tree and create reference objects to place in the parent object
|
||||
"""
|
||||
Helper to keep track of detached objects and their depth in the family tree
|
||||
and create reference objects to place in the parent object
|
||||
|
||||
Arguments:
|
||||
ref_id {str} -- the id of the fully traversed object
|
||||
@@ -279,7 +285,10 @@ class BaseObjectSerializer:
|
||||
}
|
||||
|
||||
def __reset_writer(self) -> None:
|
||||
"""Reinitializes the lineage, and other variables that get used during the json writing process"""
|
||||
"""
|
||||
Reinitializes the lineage, and other variables that get used during the json
|
||||
writing process
|
||||
"""
|
||||
self.detach_lineage = [True]
|
||||
self.lineage = []
|
||||
self.family_tree = {}
|
||||
@@ -356,7 +365,8 @@ class BaseObjectSerializer:
|
||||
base.__setattr__(prop, self.recompose_base(obj=ref_obj))
|
||||
else:
|
||||
warnings.warn(
|
||||
f"Could not find the referenced child object of id `{ref_id}` in the given read transport: {self.read_transport.name}",
|
||||
f"Could not find the referenced child object of id `{ref_id}`"
|
||||
f" in the given read transport: {self.read_transport.name}",
|
||||
SpeckleWarning,
|
||||
)
|
||||
base.__setattr__(prop, self.handle_value(value))
|
||||
@@ -371,7 +381,8 @@ class BaseObjectSerializer:
|
||||
return base
|
||||
|
||||
def handle_value(self, obj: Any):
|
||||
"""Helper for recomposing a base object by handling the dictionary representation's values
|
||||
"""Helper for recomposing a base object by handling the dictionary
|
||||
representation's values
|
||||
|
||||
Arguments:
|
||||
obj {Any} -- a value from the base object dictionary
|
||||
@@ -417,7 +428,8 @@ class BaseObjectSerializer:
|
||||
ref_obj_str = self.read_transport.get_object(id=ref_id)
|
||||
if not ref_obj_str:
|
||||
warnings.warn(
|
||||
f"Could not find the referenced child object of id `{ref_id}` in the given read transport: {self.read_transport.name}",
|
||||
f"Could not find the referenced child object of id `{ref_id}` in the"
|
||||
f" given read transport: {self.read_transport.name}",
|
||||
SpeckleWarning,
|
||||
)
|
||||
return obj
|
||||
|
||||
@@ -1 +1 @@
|
||||
from .server import ServerTransport
|
||||
from specklepy.transports.server.server import ServerTransport
|
||||
|
||||
@@ -108,7 +108,8 @@ class BatchSender(object):
|
||||
|
||||
if not new_objects:
|
||||
LOG.info(
|
||||
f"Uploading batch of {len(batch)} objects: all objects are already in the server"
|
||||
f"Uploading batch of {len(batch)} objects: all objects are already in"
|
||||
" the server"
|
||||
)
|
||||
return
|
||||
|
||||
@@ -127,11 +128,16 @@ class BatchSender(object):
|
||||
if r.status_code != 201:
|
||||
LOG.warning("Upload server response: %s", r.text)
|
||||
raise SpeckleException(
|
||||
message=f"Could not save the object to the server - status code {r.status_code}"
|
||||
message=(
|
||||
"Could not save the object to the server - status code"
|
||||
f" {r.status_code}"
|
||||
)
|
||||
)
|
||||
except json.JSONDecodeError as error:
|
||||
return SpeckleException(
|
||||
f"Failed to send objects to {self.server_url}. Please ensure this stream ({self.stream_id}) exists on this server and that you have permission to send to it.",
|
||||
f"Failed to send objects to {self.server_url}. Please ensure this"
|
||||
f" stream ({self.stream_id}) exists on this server and that you have"
|
||||
" permission to send to it.",
|
||||
error,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import json
|
||||
from typing import Any, Dict, List
|
||||
from typing import Any, Dict, List, Optional
|
||||
from warnings import warn
|
||||
|
||||
import requests
|
||||
@@ -14,10 +14,10 @@ from .batch_sender import BatchSender
|
||||
|
||||
class ServerTransport(AbstractTransport):
|
||||
"""
|
||||
The `ServerTransport` is the vehicle through which you transport objects to and from a Speckle Server. Provide it to
|
||||
`operations.send()` or `operations.receive()`.
|
||||
The `ServerTransport` is the vehicle through which you transport objects to and
|
||||
from a Speckle Server. Provide it to `operations.send()` or `operations.receive()`.
|
||||
|
||||
The `ServerTransport` can be authenticted two different ways:
|
||||
The `ServerTransport` can be authenticated two different ways:
|
||||
1. by providing a `SpeckleClient`
|
||||
2. by providing an `Account`
|
||||
3. by providing a `token` and `url`
|
||||
@@ -29,14 +29,15 @@ class ServerTransport(AbstractTransport):
|
||||
# here's the data you want to send
|
||||
block = Block(length=2, height=4)
|
||||
|
||||
# next create the server transport - this is the vehicle through which you will send and receive
|
||||
# next create the server transport - this is the vehicle through which
|
||||
# you will send and receive
|
||||
transport = ServerTransport(stream_id=new_stream_id, client=client)
|
||||
|
||||
# this serialises the block and sends it to the transport
|
||||
hash = operations.send(base=block, transports=[transport])
|
||||
|
||||
# you can now create a commit on your stream with this object
|
||||
commid_id = client.commit.create(
|
||||
commit_id = client.commit.create(
|
||||
stream_id=new_stream_id,
|
||||
obj_id=hash,
|
||||
message="this is a block I made in speckle-py",
|
||||
@@ -45,25 +46,26 @@ class ServerTransport(AbstractTransport):
|
||||
"""
|
||||
|
||||
_name = "RemoteTransport"
|
||||
url: str = None
|
||||
stream_id: str = None
|
||||
account: Account = None
|
||||
url: Optional[str] = None
|
||||
stream_id: Optional[str] = None
|
||||
account: Optional[Account] = None
|
||||
saved_obj_count: int = 0
|
||||
session: requests.Session = None
|
||||
session: Optional[requests.Session] = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
stream_id: str,
|
||||
client: SpeckleClient = None,
|
||||
account: Account = None,
|
||||
token: str = None,
|
||||
url: str = None,
|
||||
client: Optional[SpeckleClient] = None,
|
||||
account: Optional[Account] = None,
|
||||
token: Optional[str] = None,
|
||||
url: Optional[str] = None,
|
||||
**data: Any,
|
||||
) -> None:
|
||||
super().__init__(**data)
|
||||
if client is None and account is None and token is None and url is None:
|
||||
raise SpeckleException(
|
||||
"You must provide either a client or a token and url to construct a ServerTransport."
|
||||
"You must provide either a client or a token and url to construct a"
|
||||
" ServerTransport."
|
||||
)
|
||||
|
||||
if account:
|
||||
@@ -74,7 +76,8 @@ class ServerTransport(AbstractTransport):
|
||||
if not client.account.token:
|
||||
warn(
|
||||
SpeckleWarning(
|
||||
f"Unauthenticated Speckle Client provided to Server Transport for {self.url}. Receiving from private streams will fail."
|
||||
"Unauthenticated Speckle Client provided to Server Transport"
|
||||
f" for {self.url}. Receiving from private streams will fail."
|
||||
)
|
||||
)
|
||||
else:
|
||||
@@ -118,8 +121,10 @@ class ServerTransport(AbstractTransport):
|
||||
# return obj
|
||||
|
||||
raise SpeckleException(
|
||||
"Getting a single object using `ServerTransport.get_object()` is not implemented. To get an object from the server, please use the `SpeckleClient.object.get()` route",
|
||||
NotImplementedError,
|
||||
"Getting a single object using `ServerTransport.get_object()` is not"
|
||||
" implemented. To get an object from the server, please use the"
|
||||
" `SpeckleClient.object.get()` route",
|
||||
NotImplementedError(),
|
||||
)
|
||||
|
||||
def has_objects(self, id_list: List[str]) -> Dict[str, bool]:
|
||||
@@ -134,7 +139,8 @@ class ServerTransport(AbstractTransport):
|
||||
|
||||
if r.status_code != 200:
|
||||
raise SpeckleException(
|
||||
f"Can't get object {self.stream_id}/{id}: HTTP error {r.status_code} ({r.text[:1000]})"
|
||||
f"Can't get object {self.stream_id}/{id}: HTTP error"
|
||||
f" {r.status_code} ({r.text[:1000]})"
|
||||
)
|
||||
root_obj_serialized = r.text
|
||||
root_obj = json.loads(root_obj_serialized)
|
||||
|
||||
@@ -10,21 +10,21 @@ from specklepy.transports.abstract_transport import AbstractTransport
|
||||
|
||||
class SQLiteTransport(AbstractTransport):
|
||||
_name = "SQLite"
|
||||
_base_path: str = None
|
||||
_root_path: str = None
|
||||
__connection: sqlite3.Connection = None
|
||||
_base_path: Optional[str] = None
|
||||
_root_path: Optional[str] = None
|
||||
__connection: Optional[sqlite3.Connection] = None
|
||||
app_name: str = ""
|
||||
scope: str = ""
|
||||
saved_obj_count: int = 0
|
||||
max_size: int = None
|
||||
_current_batch: List[Tuple[str, str]] = None
|
||||
_current_batch_size: int = None
|
||||
max_size: Optional[int] = None
|
||||
_current_batch: Optional[List[Tuple[str, str]]] = None
|
||||
_current_batch_size: Optional[int] = None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
base_path: Optional[str] = None,
|
||||
app_name: Optional[str] = None,
|
||||
scope: str = None,
|
||||
scope: Optional[str] = None,
|
||||
max_batch_size_mb: float = 10.0,
|
||||
**data: Any,
|
||||
) -> None:
|
||||
@@ -45,7 +45,9 @@ class SQLiteTransport(AbstractTransport):
|
||||
self.__initialise()
|
||||
except Exception as ex:
|
||||
raise SpeckleException(
|
||||
f"SQLiteTransport could not initialise {self.scope}.db at {self._base_path}. Either provide a different `base_path` or use an alternative transport.",
|
||||
f"SQLiteTransport could not initialise {self.scope}.db at"
|
||||
f" {self._base_path}. Either provide a different `base_path` or use an"
|
||||
" alternative transport.",
|
||||
ex,
|
||||
)
|
||||
|
||||
@@ -79,14 +81,16 @@ class SQLiteTransport(AbstractTransport):
|
||||
|
||||
Arguments:
|
||||
id {str} -- the object id
|
||||
source_transport {AbstractTransport) -- the transport through which the object can be found
|
||||
source_transport {AbstractTransport)
|
||||
-- the transport through which the object can be found
|
||||
"""
|
||||
serialized_object = source_transport.get_object(id)
|
||||
self.save_object(id, serialized_object)
|
||||
|
||||
def save_object(self, id: str, serialized_object: str) -> None:
|
||||
"""
|
||||
Adds an object to the current batch to be written to the db. If the current batch is full,
|
||||
Adds an object to the current batch to be written to the db.
|
||||
If the current batch is full,
|
||||
the batch is written to the db and the current batch is reset.
|
||||
|
||||
Arguments:
|
||||
@@ -118,7 +122,8 @@ class SQLiteTransport(AbstractTransport):
|
||||
self.__connection.commit()
|
||||
except Exception as ex:
|
||||
raise SpeckleException(
|
||||
f"Could not save the batch of objects to the local db. Inner exception: {ex}",
|
||||
"Could not save the batch of objects to the local db. Inner exception:"
|
||||
f" {ex}",
|
||||
ex,
|
||||
)
|
||||
|
||||
@@ -157,7 +162,10 @@ class SQLiteTransport(AbstractTransport):
|
||||
raise NotImplementedError
|
||||
|
||||
def get_all_objects(self):
|
||||
"""Returns all the objects in the store. NOTE: do not use for large collections!"""
|
||||
"""
|
||||
Returns all the objects in the store.
|
||||
NOTE: do not use for large collections!
|
||||
"""
|
||||
self.__check_connection()
|
||||
with closing(self.__connection.cursor()) as c:
|
||||
rows = c.execute("SELECT * FROM objects").fetchall()
|
||||
|
||||
+6
-6
@@ -13,11 +13,11 @@ from specklepy.objects.units import Units
|
||||
@pytest.mark.parametrize(
|
||||
"invalid_prop_name",
|
||||
[
|
||||
(""),
|
||||
("@"),
|
||||
("@@wow"),
|
||||
("this.is.bad"),
|
||||
("super/bad"),
|
||||
"",
|
||||
"@",
|
||||
"@@wow",
|
||||
"this.is.bad",
|
||||
"super/bad",
|
||||
],
|
||||
)
|
||||
def test_empty_prop_names(invalid_prop_name: str) -> None:
|
||||
@@ -95,7 +95,7 @@ def test_setting_units():
|
||||
assert b.units == "ft"
|
||||
|
||||
b.units = None # None should be a valid arg
|
||||
assert b.units == None
|
||||
assert b.units is None
|
||||
|
||||
b.units = Units.none
|
||||
assert b.units == "none"
|
||||
|
||||
@@ -85,4 +85,4 @@ class TestCommit:
|
||||
message="testing received",
|
||||
)
|
||||
|
||||
assert commit_marked_received == True
|
||||
assert commit_marked_received is True
|
||||
|
||||
@@ -517,8 +517,7 @@ def test_mesh_create():
|
||||
mesh = Mesh.create(vertices, faces)
|
||||
|
||||
with pytest.raises(SpeckleException):
|
||||
# pylint: disable=unused-variable
|
||||
bad_mesh = Mesh.create(vertices=7, faces=faces)
|
||||
bad_mesh = Mesh.create(vertices=7, faces=faces) # noqa: F841
|
||||
|
||||
assert mesh.vertices == vertices
|
||||
assert mesh.textureCoordinates == []
|
||||
|
||||
@@ -2,7 +2,6 @@ import pytest
|
||||
|
||||
from specklepy.api.client import SpeckleClient
|
||||
from specklepy.api.models import Activity, ActivityCollection, LimitedUser
|
||||
from specklepy.logging.exceptions import SpeckleException
|
||||
|
||||
|
||||
@pytest.mark.run(order=4)
|
||||
|
||||
@@ -6,7 +6,6 @@ from specklepy.api import operations
|
||||
from specklepy.objects import Base
|
||||
from specklepy.objects.fakemesh import FakeMesh
|
||||
from specklepy.objects.geometry import Point
|
||||
from specklepy.serialization.base_object_serializer import BaseObjectSerializer
|
||||
from specklepy.transports.memory import MemoryTransport
|
||||
from specklepy.transports.server import ServerTransport
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
|
||||
from specklepy.api.client import SpeckleClient
|
||||
|
||||
@@ -4,12 +4,7 @@ import pytest
|
||||
|
||||
from specklepy.api import operations
|
||||
from specklepy.objects.geometry import Point, Vector
|
||||
from specklepy.objects.other import (
|
||||
IDENTITY_TRANSFORM,
|
||||
BlockDefinition,
|
||||
BlockInstance,
|
||||
Transform,
|
||||
)
|
||||
from specklepy.objects.other import Transform
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
@@ -81,7 +76,7 @@ def test_point_transform(point: Point, transform: Transform):
|
||||
def test_points_transform(points: List[Point], transform: Transform):
|
||||
new_points = transform.apply_to_points(points)
|
||||
|
||||
for (i, new_point) in enumerate(new_points):
|
||||
for i, new_point in enumerate(new_points):
|
||||
assert new_point.x == points[i].x + 1
|
||||
assert new_point.y == points[i].y + 2
|
||||
assert new_point.z == points[i].z * 0.5
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
from typing import Generator, Iterable
|
||||
|
||||
import pytest
|
||||
|
||||
from specklepy.api.wrapper import StreamWrapper
|
||||
from specklepy.paths import accounts_path
|
||||
from specklepy.transports.sqlite import SQLiteTransport
|
||||
|
||||
|
||||
def test_parse_stream():
|
||||
@@ -60,7 +60,8 @@ def test_parse_globals_as_commit():
|
||||
assert wrap.type == "commit"
|
||||
|
||||
|
||||
#! NOTE: the following three tests may not pass locally if you have a `speckle.xyz` account in manager
|
||||
#! NOTE: the following three tests may not pass locally
|
||||
# if you have a `speckle.xyz` account in manager
|
||||
def test_get_client_without_auth():
|
||||
wrap = StreamWrapper("https://speckle.xyz/streams/4c3ce1459c/commits/8b9b831792")
|
||||
client = wrap.get_client()
|
||||
@@ -88,16 +89,16 @@ def test_get_transport_with_token():
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def user_path() -> Path:
|
||||
def user_path() -> Iterable[Path]:
|
||||
path = accounts_path().joinpath("test_acc.json")
|
||||
# hey, py37 doesn't support the missing_ok argument
|
||||
try:
|
||||
path.unlink()
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
path.unlink(missing_ok=True)
|
||||
except:
|
||||
except Exception:
|
||||
pass
|
||||
path.parent.absolute().mkdir(exist_ok=True)
|
||||
yield path
|
||||
|
||||
Reference in New Issue
Block a user