Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a26618a4f7 | |||
| eaf370407d | |||
| a2b50fe5a1 | |||
| 7e62f76841 | |||
| fc804f16d3 | |||
| 6c7da24595 | |||
| b284d39328 | |||
| 907185c9bb | |||
| a189a2e1c0 | |||
| 1fad926275 | |||
| 99c147fe2f | |||
| e2adf710b3 | |||
| 9509344533 | |||
| 6fabc6cae6 | |||
| c39298687d | |||
| bcdddbf930 | |||
| b5684e34f6 | |||
| 2203fe98f8 | |||
| bbfdf2863b | |||
| f25f6cb16c | |||
| 9e4e533ba8 | |||
| 8db12ca9b9 | |||
| 366c864247 | |||
| 52136d3ef6 | |||
| fe764d7f0c | |||
| 669dd67521 | |||
| f74b2c37f0 | |||
| ebb4e32fff | |||
| 25903baf83 | |||
| cb6d6d7ad8 | |||
| fd2687aa3c | |||
| f5c65068de | |||
| 235b49d8c6 | |||
| a1ec137c67 | |||
| b95f621272 | |||
| a1fcdad0e3 | |||
| 584e543964 | |||
| ef20c5240c | |||
| 9fe12a018a | |||
| 8411c01f1b | |||
| 63b82a30cb | |||
| 0b6e39cf38 | |||
| b7efcec517 | |||
| 0ab0096aac | |||
| cbd8fc99bb | |||
| 2a9287e762 | |||
| 98c70f237c | |||
| 048047cf05 | |||
| 6118215cae | |||
| 8e06432fe6 | |||
| cb8620ff8a | |||
| e0eddea8ab | |||
| 8497d0c195 | |||
| 1ce394c08f | |||
| 35b96eaa4e | |||
| c229bb2414 | |||
| 318bd086c0 | |||
| 977994e141 | |||
| d9cbc80ee7 | |||
| 45038fad79 | |||
| cda621d735 | |||
| 2d052d1379 | |||
| 46ce2bc0df | |||
| 80e2216aa0 | |||
| 10d69aa44b |
@@ -1,7 +1,7 @@
|
||||
import bpy
|
||||
from bpy_speckle.installer import ensure_dependencies
|
||||
|
||||
ensure_dependencies()
|
||||
ensure_dependencies(f"Blender {bpy.app.version[0]}.{bpy.app.version[1]}")
|
||||
|
||||
from specklepy.logging import metrics
|
||||
|
||||
@@ -36,8 +36,13 @@ loading a Blender file
|
||||
|
||||
@persistent
|
||||
def load_handler(dummy):
|
||||
bpy.ops.speckle.users_load()
|
||||
|
||||
pass
|
||||
# Calling users_load is an expensive operation, one that force users to wait a good 10s every time blender loads.
|
||||
# Until we can do this non-blocking, we will make the user hit the refresh button each time.
|
||||
#bpy.ops.speckle.users_load()
|
||||
|
||||
# Instead, we shall just reset the user selection to an uninitiailised state
|
||||
bpy.ops.speckle.users_reset()
|
||||
|
||||
"""
|
||||
Permanent handle on callbacks
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
from typing import Deque, Dict, List, Optional, Set, Tuple, Union
|
||||
import bpy
|
||||
from bpy.types import Object, Collection, ID
|
||||
from specklepy.objects.base import Base
|
||||
from bpy_speckle.functions import _report
|
||||
from bpy_speckle.specklepy_extras.commit_object_builder import CommitObjectBuilder, ROOT
|
||||
from specklepy.objects import Base
|
||||
from specklepy.objects.other import Collection as SCollection
|
||||
from attrs import define
|
||||
|
||||
ELEMENTS = "elements"
|
||||
|
||||
def _id(natvive_object: ID) -> str:
|
||||
#NOTE: to avoid naming collisions, we prefix collections and objects differently
|
||||
return f"{type(natvive_object).__name__}:{natvive_object.name_full}"
|
||||
|
||||
def _try_id(natvive_object: Optional[Union[Collection, Object]]) -> Optional[str]:
|
||||
return _id(natvive_object) if natvive_object else None
|
||||
|
||||
def convert_collection_to_speckle(col: Collection) -> SCollection:
|
||||
convered_collection = SCollection(name = col.name_full, collectionType = "Blender Collection", elements = [])
|
||||
convered_collection.applicationId = _id(col)
|
||||
return convered_collection
|
||||
|
||||
@define(slots=True)
|
||||
class BlenderCommitObjectBuilder(CommitObjectBuilder[Object]):
|
||||
|
||||
_collections: Dict[str, SCollection]
|
||||
|
||||
def __init__(self) -> None:
|
||||
super().__init__()
|
||||
self._collections = {}
|
||||
|
||||
def include_object(self, conversion_result: Base, native_object: Object) -> None:
|
||||
|
||||
# Set the Child -> Parent relationships
|
||||
parent = native_object.parent
|
||||
|
||||
parent_collections: Tuple[Collection] = native_object.users_collection # type: ignore
|
||||
parent_collection = parent_collections[0] if len(parent_collections) > 0 else None #NOTE: we don't support objects appearing in more than one collection, for now, we will just take the zeroth one
|
||||
|
||||
app_id = _id(native_object)
|
||||
conversion_result.applicationId = app_id
|
||||
self.converted[app_id] = conversion_result
|
||||
|
||||
# in order or priority, direct parent, direct parent collection, root
|
||||
self.set_relationship(app_id, (_try_id(parent), ELEMENTS), (_try_id(parent_collection), ELEMENTS), (ROOT, ELEMENTS))
|
||||
# if parent_collection:
|
||||
# self._include_collection(parent_collection)
|
||||
|
||||
def ensure_collection(self, col: Collection) -> SCollection:
|
||||
id = _id(col)
|
||||
if id in self._collections:
|
||||
return self._collections[id] # collection already converted!
|
||||
|
||||
# Set the Parent -> Children relationships
|
||||
for c in col.children:
|
||||
#NOTE: There's no falling back to the grandparent, if the direct parent collection wasn't converted, then we we fallback to the root
|
||||
self.set_relationship(_id(c), (id, ELEMENTS), (ROOT, ELEMENTS))
|
||||
|
||||
# Set Child -> Parent relationship
|
||||
# parent = self.find_collection_parent(col)
|
||||
# self.set_relationship(id, (_try_builder_id(parent), ELEMENTS), (ROOT, ELEMENTS))
|
||||
|
||||
convered_collection = convert_collection_to_speckle(col)
|
||||
self.converted[id] = convered_collection
|
||||
self._collections[id] = convered_collection
|
||||
|
||||
return convered_collection
|
||||
|
||||
# def find_collection_parent(self, col: Collection) -> Optional[Collection]:
|
||||
# for p in bpy.data.collections:
|
||||
# if col.name in p.children.keys():
|
||||
# return p
|
||||
# return None
|
||||
|
||||
#TODO: I've started an approach that will not work
|
||||
# Goal #1 get all collections sending
|
||||
# Sync with Claire, ask how we handle this in Rhino with partial selection of layers (proably how I'm expecting it works, but good to double check)
|
||||
# Goal #2 Figure out how to send collections
|
||||
# - all collections
|
||||
# - all collections that contain a child collection that has geometry...
|
||||
# - only collections explicitly selected
|
||||
|
||||
def build_commit_object(self, root_commit_object: Base) -> None:
|
||||
assert(root_commit_object.applicationId in self.converted)
|
||||
|
||||
# Create all collections
|
||||
root_col = self.ensure_collection(bpy.context.scene.collection)
|
||||
root_col.collectionType = "Scene Collection"
|
||||
for col in bpy.context.scene.collection.children_recursive:
|
||||
self.ensure_collection(col)
|
||||
|
||||
objects_to_build = set(self.converted.values())
|
||||
objects_to_build.remove(root_commit_object)
|
||||
|
||||
self.apply_relationships(objects_to_build, root_commit_object)
|
||||
|
||||
assert(isinstance(root_commit_object, SCollection))
|
||||
# Kill unused collections
|
||||
|
||||
def should_remove_unuseful_collection(col: SCollection) -> bool: #TODO: this maybe could be optimised
|
||||
elements = col.elements
|
||||
if not elements: return True
|
||||
|
||||
should_remove_this_col = True
|
||||
|
||||
i = 0
|
||||
while i < len(elements):
|
||||
c = elements[i]
|
||||
if not isinstance(c, SCollection):
|
||||
# col has objects (c)
|
||||
should_remove_this_col = False
|
||||
i += 1
|
||||
continue
|
||||
|
||||
if should_remove_unuseful_collection(c):
|
||||
# c is not useful, kill it
|
||||
del elements[i]
|
||||
else:
|
||||
# col has a child (c) with objects
|
||||
should_remove_this_col = False
|
||||
i += 1
|
||||
continue
|
||||
|
||||
return should_remove_this_col
|
||||
|
||||
if should_remove_unuseful_collection(root_commit_object):
|
||||
_report("WARNING: Only empty collections have been converted!") #TODO: consider raising exception here, to halt the send operation
|
||||
|
||||
|
||||
|
||||
|
||||
# def build_commit_object(self, root_commit_object: Base) -> None:
|
||||
|
||||
# convertedObjects = [x for x in self.converted.values()] # Converted objects, but no collections!
|
||||
# for (id, col) in self._collections.items():
|
||||
# self.converted[id] = col
|
||||
|
||||
# # Apply relationships for all non-collection objects
|
||||
# self.apply_relationships(convertedObjects, root_commit_object)
|
||||
|
||||
# # Remove empty collections
|
||||
# for (id, col) in self._collections.items(): #TODO: XXX: How to ensure empty collections are avoided! Potentially need to traverse from root object down...
|
||||
# if not col.elements:
|
||||
# self.converted.pop(id)
|
||||
|
||||
# self.apply_relationships(convertedObjects, root_commit_object)
|
||||
|
||||
# return
|
||||
+523
-229
@@ -1,13 +1,23 @@
|
||||
import math
|
||||
from typing import Union
|
||||
from typing import Tuple, Union, Collection
|
||||
from bpy_speckle.functions import get_scale_length, _report
|
||||
import mathutils
|
||||
import bpy, bmesh, bpy_types
|
||||
from specklepy.objects.other import *
|
||||
from mathutils import (
|
||||
Matrix as MMatrix,
|
||||
Vector as MVector,
|
||||
Quaternion as MQuaternion,
|
||||
)
|
||||
import bpy, bmesh
|
||||
from specklepy.objects.other import (
|
||||
Instance,
|
||||
Transform,
|
||||
BlockDefinition,
|
||||
)
|
||||
from specklepy.objects.geometry import *
|
||||
from bpy.types import Object
|
||||
from .util import (
|
||||
add_blender_material,
|
||||
get_render_material,
|
||||
link_object_to_collection_nested,
|
||||
render_material_to_native,
|
||||
add_custom_properties,
|
||||
add_vertices,
|
||||
add_faces,
|
||||
@@ -15,147 +25,248 @@ from .util import (
|
||||
add_uv_coords,
|
||||
)
|
||||
|
||||
SUPPORTED_CURVES = (Line, Polyline, Curve, Arc, Polycurve)
|
||||
|
||||
SUPPORTED_CURVES = (Line, Polyline, Curve, Arc, Polycurve, Ellipse, Circle)
|
||||
CAN_CONVERT_TO_NATIVE = (
|
||||
|
||||
Mesh,
|
||||
Brep,
|
||||
*SUPPORTED_CURVES,
|
||||
Transform,
|
||||
BlockDefinition,
|
||||
BlockInstance,
|
||||
Instance,
|
||||
)
|
||||
|
||||
|
||||
def can_convert_to_native(speckle_object: Base) -> bool:
|
||||
if type(speckle_object) in CAN_CONVERT_TO_NATIVE:
|
||||
return True
|
||||
if getattr(
|
||||
speckle_object, "displayValue", getattr(speckle_object, "displayMesh", None)
|
||||
):
|
||||
return True
|
||||
def _has_native_convesion(speckle_object: Base) -> bool:
|
||||
return any(isinstance(speckle_object, t) for t in CAN_CONVERT_TO_NATIVE) #or "View" in speckle_object.speckle_type #hack
|
||||
|
||||
_report(f"Could not convert unsupported Speckle object: {speckle_object}")
|
||||
def _has_fallback_conversion(speckle_object: Base) -> bool:
|
||||
return any(getattr(speckle_object, alias, None) for alias in DISPLAY_VALUE_PROPERTY_ALIASES)
|
||||
|
||||
def can_convert_to_native(speckle_object: Base) -> bool:
|
||||
|
||||
if(_has_native_convesion(speckle_object) or _has_fallback_conversion(speckle_object)):
|
||||
return True
|
||||
return False
|
||||
|
||||
def create_new_object(obj_data: Optional[bpy.types.ID], desired_name: str, counter: int = 0) -> bpy.types.Object:
|
||||
"""
|
||||
Creates a new blender object with a unique name,
|
||||
if the desired_name is already taken
|
||||
we'll append a number, with the format .xxx to the desired_name to ensure the name is unique.
|
||||
"""
|
||||
name = desired_name if counter == 0 else f"{desired_name[:OBJECT_NAME_MAX_LENGTH - 4]}.{counter:03d}" # format counter as name.xxx, truncate to ensure we don't exceed the object name max length
|
||||
|
||||
def convert_to_native(speckle_object: Base, name: Optional[str] = None) -> Optional[Union[list, Object]]:
|
||||
speckle_type = type(speckle_object)
|
||||
speckle_name = (
|
||||
name
|
||||
or getattr(speckle_object, "name", None)
|
||||
or f"{speckle_object.speckle_type} -- {speckle_object.id}"
|
||||
)
|
||||
# convert unsupported types with display values
|
||||
if speckle_type not in CAN_CONVERT_TO_NATIVE:
|
||||
elements = getattr(speckle_object, "elements", []) or []
|
||||
display = getattr(
|
||||
speckle_object, "displayValue", getattr(speckle_object, "displayMesh", None)
|
||||
)
|
||||
if not elements and not display:
|
||||
_report(f"Could not convert unsupported Speckle object: {speckle_object}")
|
||||
return None
|
||||
if isinstance(display, list):
|
||||
elements.extend(display)
|
||||
else:
|
||||
elements.append(display)
|
||||
# TODO: depreciate the parent type
|
||||
# add parent type here so we can use it as a blender custom prop
|
||||
# not making it hidden, so it will get added on send as i think it might be helpful? can reconsider
|
||||
converted = []
|
||||
for item in elements:
|
||||
if not isinstance(item, Base):
|
||||
continue
|
||||
item.parent_speckle_type = speckle_object.speckle_type
|
||||
blender_object = convert_to_native(item)
|
||||
if isinstance(blender_object, list):
|
||||
converted.extend(blender_object)
|
||||
else:
|
||||
add_custom_properties(speckle_object, blender_object)
|
||||
converted.append(blender_object)
|
||||
return converted
|
||||
|
||||
try:
|
||||
# convert breps
|
||||
if speckle_type is Brep:
|
||||
meshes = getattr(
|
||||
speckle_object, "displayValue", getattr(speckle_object, "displayMesh", iter([]))
|
||||
)
|
||||
if material := getattr(speckle_object, "renderMaterial", getattr(speckle_object, "@renderMaterial", None),):
|
||||
for mesh in meshes:
|
||||
mesh["renderMaterial"] = material
|
||||
|
||||
return [convert_to_native(mesh) for mesh in meshes]
|
||||
|
||||
scale = 1.0
|
||||
if units := getattr(speckle_object, "units", None):
|
||||
scale = get_scale_length(units) / bpy.context.scene.unit_settings.scale_length
|
||||
# convert supported geometry
|
||||
if isinstance(speckle_object, Mesh):
|
||||
obj_data = mesh_to_native(speckle_object, name=speckle_name, scale=scale)
|
||||
elif speckle_type in SUPPORTED_CURVES:
|
||||
obj_data = icurve_to_native(speckle_object, name=speckle_name, scale=scale)
|
||||
elif isinstance(speckle_object, Transform):
|
||||
obj_data = transform_to_native(speckle_object, scale=scale)
|
||||
elif isinstance(speckle_object, BlockDefinition):
|
||||
obj_data = block_def_to_native(speckle_object, scale=scale)
|
||||
elif isinstance(speckle_object, BlockInstance): # speckle_type is BlockInstance:
|
||||
obj_data = block_instance_to_native(speckle_object, scale=scale)
|
||||
else:
|
||||
_report(f"Unsupported type {speckle_type}")
|
||||
return None
|
||||
except Exception as ex: # conversion error
|
||||
_report(f"Error converting {speckle_object} \n{ex}")
|
||||
return None
|
||||
|
||||
if speckle_name in bpy.data.objects.keys():
|
||||
blender_object = bpy.data.objects[speckle_name]
|
||||
blender_object.data = (
|
||||
obj_data.data if isinstance(obj_data, bpy_types.Object) else obj_data
|
||||
)
|
||||
blender_object.matrix_world = (
|
||||
blender_object.matrix_world
|
||||
if speckle_type is BlockInstance
|
||||
else mathutils.Matrix()
|
||||
)
|
||||
if hasattr(obj_data, "materials"):
|
||||
blender_object.data.materials.clear()
|
||||
else:
|
||||
blender_object = (
|
||||
obj_data
|
||||
if isinstance(obj_data, bpy_types.Object)
|
||||
else bpy.data.objects.new(speckle_name, obj_data)
|
||||
)
|
||||
|
||||
blender_object.speckle.object_id = str(speckle_object.id)
|
||||
blender_object.speckle.enabled = True
|
||||
add_custom_properties(speckle_object, blender_object)
|
||||
add_blender_material(speckle_object, blender_object)
|
||||
#TODO: This is very slow, and gets slower the more objects you receive with the same name...
|
||||
# We could use a binary/galloping search, and/or cache the name -> index within a receive.
|
||||
if name in bpy.data.objects.keys():
|
||||
#Object already exists, increment counter and try again!
|
||||
return create_new_object(obj_data, desired_name, counter + 1)
|
||||
|
||||
blender_object = bpy.data.objects.new(name, obj_data)
|
||||
return blender_object
|
||||
|
||||
convert_instances_as: str #HACK: This is hacky, we need a better way to pass settings down to the converter
|
||||
def set_convert_instances_as(value: str):
|
||||
global convert_instances_as
|
||||
convert_instances_as = value
|
||||
|
||||
#TODO: Check usages handle exceptions
|
||||
|
||||
def mesh_to_native(speckle_mesh: Mesh, name: str, scale=1.0) -> bpy.types.Mesh:
|
||||
def convert_to_native(speckle_object: Base) -> Object:
|
||||
|
||||
if name in bpy.data.meshes.keys():
|
||||
blender_mesh = bpy.data.meshes[name]
|
||||
speckle_type = type(speckle_object)
|
||||
|
||||
object_name = _generate_object_name(speckle_object)
|
||||
scale = get_scale_factor(speckle_object)
|
||||
|
||||
converted: Union[bpy.types.ID, bpy.types.Object, None] = None
|
||||
children: list[Object] = []
|
||||
|
||||
# convert elements/breps
|
||||
if not _has_native_convesion(speckle_object):
|
||||
(converted, children) = display_value_to_native(speckle_object, object_name, scale)
|
||||
if not converted and not children:
|
||||
raise Exception(f"Zero geometry converted from displayValues for {speckle_object}")
|
||||
|
||||
# convert supported geometry
|
||||
elif isinstance(speckle_object, Mesh):
|
||||
converted = mesh_to_native(speckle_object, object_name, scale)
|
||||
elif speckle_type in SUPPORTED_CURVES:
|
||||
converted = icurve_to_native(speckle_object, object_name, scale)
|
||||
# elif "View" in speckle_object.speckle_type:
|
||||
# return view_to_native(speckle_object, object_name, scale)
|
||||
elif isinstance(speckle_object, Instance):
|
||||
if convert_instances_as == "linked_duplicates":
|
||||
(converted, children) = instance_to_native_object(speckle_object, scale)
|
||||
elif convert_instances_as == "collection_instance":
|
||||
converted = instance_to_native_collection_instance(speckle_object, scale)
|
||||
else:
|
||||
_report(f"convert_instances_as = '{convert_instances_as}' is not implemented, Instances will be converted as collection instances!")
|
||||
converted = instance_to_native_collection_instance(speckle_object, scale)
|
||||
else:
|
||||
blender_mesh = bpy.data.meshes.new(name=name)
|
||||
raise Exception(f"Unsupported type {speckle_type}")
|
||||
|
||||
|
||||
if not isinstance(converted, Object):
|
||||
converted = create_new_object(converted, object_name)
|
||||
|
||||
converted.speckle.object_id = str(speckle_object.id)
|
||||
converted.speckle.enabled = True
|
||||
add_custom_properties(speckle_object, converted)
|
||||
|
||||
for child in children:
|
||||
child.parent = converted
|
||||
|
||||
return converted
|
||||
|
||||
|
||||
DISPLAY_VALUE_PROPERTY_ALIASES = ["displayValue", "@displayValue"]
|
||||
ELEMENTS_PROPERTY_ALIASES = ["elements", "@elements"]
|
||||
|
||||
|
||||
def display_value_to_native(speckle_object: Base, name: str, scale: float) -> tuple[Optional[bpy.types.Mesh], list[bpy.types.Object]]:
|
||||
return _members_to_native(speckle_object, name, scale, DISPLAY_VALUE_PROPERTY_ALIASES, True)
|
||||
|
||||
def elements_to_native(speckle_object: Base, name: str, scale: float) -> list[bpy.types.Object]:
|
||||
(_, elements) = _members_to_native(speckle_object, name, scale, ELEMENTS_PROPERTY_ALIASES, False)
|
||||
return elements
|
||||
|
||||
def _members_to_native(speckle_object: Base, name: str, scale: float, members: List[str], combineMeshes: bool) -> tuple[Optional[bpy.types.Mesh], list[bpy.types.Object]]:
|
||||
"""
|
||||
Converts a given speckle_object by converting specified members
|
||||
|
||||
if combineMeshes == True
|
||||
Converts mesh members as one mesh
|
||||
Converts non-mesh members as child Objects
|
||||
if combineMeshes == False
|
||||
Converts all members as child objects (first item of the returned tuple will be None)
|
||||
:returns: converted mesh, and any other converted child objects (may happen if members contained non-meshes)
|
||||
"""
|
||||
meshes: list[Mesh] = []
|
||||
others: list[Base] = []
|
||||
|
||||
for alias in members:
|
||||
display = getattr(speckle_object, alias, None)
|
||||
|
||||
count = 0
|
||||
MAX_DEPTH = 255 # some large value, to prevent infinite reccursion
|
||||
def seperate(value: Any) -> bool:
|
||||
nonlocal meshes, others, count, MAX_DEPTH
|
||||
|
||||
if combineMeshes and isinstance(value, Mesh):
|
||||
meshes.append(value)
|
||||
elif isinstance(value, Base):
|
||||
others.append(value)
|
||||
elif isinstance(value, list):
|
||||
count += 1
|
||||
if(count > MAX_DEPTH):
|
||||
return True
|
||||
for x in value:
|
||||
seperate(x)
|
||||
|
||||
return False
|
||||
|
||||
did_halt = seperate(display)
|
||||
|
||||
if did_halt:
|
||||
_report(f"Traversal of {speckle_object.speckle_type} {speckle_object.id} halted after traversal depth exceeds MAX_DEPTH={MAX_DEPTH}. Are there circular references object structure?")
|
||||
|
||||
|
||||
children: list[Object] = []
|
||||
mesh = None
|
||||
|
||||
if meshes:
|
||||
mesh = meshes_to_native(speckle_object, meshes, name, scale) #TODO: reconsider passing scale around...
|
||||
|
||||
for item in others:
|
||||
try:
|
||||
blender_object = convert_to_native(item)
|
||||
children.append(blender_object)
|
||||
except Exception as ex:
|
||||
_report(f"Failed to convert display value {item}: {ex}")
|
||||
|
||||
return (mesh, children)
|
||||
|
||||
|
||||
|
||||
def view_to_native(speckle_view, name: str, scale: float) -> bpy.types.Object:
|
||||
native_cam: bpy.types.Camera
|
||||
if name in bpy.data.cameras.keys():
|
||||
native_cam = bpy.data.cameras[name]
|
||||
else:
|
||||
native_cam = bpy.data.cameras.new(name=name)
|
||||
native_cam.lens = 18 # 90° horizontal fov
|
||||
|
||||
cam_obj = create_new_object(native_cam, name)
|
||||
|
||||
scale_factor = get_scale_factor(speckle_view, scale)
|
||||
tx = (speckle_view.origin.x * scale_factor)
|
||||
ty = (speckle_view.origin.y * scale_factor)
|
||||
tz = (speckle_view.origin.z * scale_factor)
|
||||
|
||||
forward = MVector((speckle_view.forwardDirection.x, speckle_view.forwardDirection.y, speckle_view.forwardDirection.z))
|
||||
up = MVector((speckle_view.upDirection.x, speckle_view.upDirection.y, speckle_view.upDirection.z))
|
||||
right = forward.cross(up).normalized()
|
||||
|
||||
cam_obj.matrix_world = MMatrix((
|
||||
(right.x, up.x, -forward.x, tx),
|
||||
(right.y, up.y, -forward.y, ty),
|
||||
(right.z, up.z, -forward.z, tz),
|
||||
(0, 0, 0, 1 )
|
||||
))
|
||||
return cam_obj
|
||||
|
||||
def mesh_to_native(speckle_mesh: Mesh, name: str, scale: float) -> bpy.types.Mesh:
|
||||
return meshes_to_native(speckle_mesh, [speckle_mesh], name, scale)
|
||||
|
||||
def meshes_to_native(element: Base, meshes: Collection[Mesh], name: str, scale: float) -> bpy.types.Mesh:
|
||||
if name in bpy.data.meshes.keys():
|
||||
return bpy.data.meshes[name]
|
||||
|
||||
blender_mesh = bpy.data.meshes.new(name=name)
|
||||
|
||||
fallback_material = get_render_material(element)
|
||||
|
||||
bm = bmesh.new()
|
||||
|
||||
add_vertices(speckle_mesh, bm, scale)
|
||||
add_faces(speckle_mesh, bm)
|
||||
add_colors(speckle_mesh, bm)
|
||||
add_uv_coords(speckle_mesh, bm)
|
||||
# First pass, add vertex data
|
||||
for mesh in meshes:
|
||||
scale = get_scale_factor(mesh, scale)
|
||||
add_vertices(mesh, bm, scale)
|
||||
|
||||
bm.verts.ensure_lookup_table()
|
||||
|
||||
# Second pass, add face data
|
||||
offset = 0
|
||||
for i, mesh in enumerate(meshes):
|
||||
add_faces(mesh, bm, offset, i)
|
||||
|
||||
render_material = get_render_material(mesh) or fallback_material
|
||||
if render_material is not None:
|
||||
native_material = render_material_to_native(render_material)
|
||||
blender_mesh.materials.append(native_material)
|
||||
|
||||
offset += len(mesh.vertices) // 3
|
||||
|
||||
bm.faces.ensure_lookup_table()
|
||||
bm.verts.index_update()
|
||||
|
||||
# Third pass, add vertex instance data
|
||||
for mesh in meshes:
|
||||
add_colors(mesh, bm)
|
||||
add_uv_coords(mesh, bm)
|
||||
|
||||
bmesh.ops.recalc_face_normals(bm, faces=bm.faces)
|
||||
bm.to_mesh(blender_mesh)
|
||||
bm.free()
|
||||
bm.free()
|
||||
|
||||
return blender_mesh
|
||||
|
||||
def line_to_native(speckle_curve: Line, blender_curve: bpy.types.Curve, scale: float) -> Optional[bpy.types.Spline]:
|
||||
|
||||
"""
|
||||
Curves
|
||||
"""
|
||||
|
||||
def line_to_native(speckle_curve: Line, blender_curve: bpy.types.Curve, scale: float) -> list[bpy.types.Spline]:
|
||||
if not speckle_curve.end: return []
|
||||
|
||||
line = blender_curve.splines.new("POLY")
|
||||
line.points.add(1)
|
||||
|
||||
@@ -166,95 +277,90 @@ def line_to_native(speckle_curve: Line, blender_curve: bpy.types.Curve, scale: f
|
||||
1,
|
||||
)
|
||||
|
||||
if speckle_curve.end:
|
||||
line.points[1].co = (
|
||||
float(speckle_curve.end.x) * scale,
|
||||
float(speckle_curve.end.y) * scale,
|
||||
float(speckle_curve.end.z) * scale,
|
||||
1,
|
||||
)
|
||||
|
||||
line.points[1].co = (
|
||||
float(speckle_curve.end.x) * scale,
|
||||
float(speckle_curve.end.y) * scale,
|
||||
float(speckle_curve.end.z) * scale,
|
||||
return [line]
|
||||
|
||||
|
||||
def polyline_to_native(scurve: Polyline, bcurve: bpy.types.Curve, scale: float) -> list[bpy.types.Spline]:
|
||||
if not (value := scurve.value): return []
|
||||
N = len(value) // 3
|
||||
|
||||
polyline = bcurve.splines.new("POLY")
|
||||
|
||||
if hasattr(scurve, "closed"):
|
||||
polyline.use_cyclic_u = scurve.closed
|
||||
|
||||
polyline.points.add(N - 1)
|
||||
for i in range(N):
|
||||
polyline.points[i].co = (
|
||||
float(value[i * 3]) * scale,
|
||||
float(value[i * 3 + 1]) * scale,
|
||||
float(value[i * 3 + 2]) * scale,
|
||||
1,
|
||||
)
|
||||
|
||||
return line
|
||||
return [polyline]
|
||||
|
||||
|
||||
|
||||
def polyline_to_native(scurve: Polyline, bcurve: bpy.types.Curve, scale: float) -> Optional[bpy.types.Spline]:
|
||||
if value := scurve.value:
|
||||
N = len(value) // 3
|
||||
def nurbs_to_native(scurve: Curve, bcurve: bpy.types.Curve, scale: float) -> list[bpy.types.Spline]:
|
||||
if not (points := scurve.points): return []
|
||||
|
||||
polyline = bcurve.splines.new("POLY")
|
||||
# Closed curves from rhino will have n + degree points. We ignore the extras
|
||||
num_points = len(points) // 3 - scurve.degree if (scurve.closed) else (
|
||||
len(points) // 3)
|
||||
|
||||
nurbs = bcurve.splines.new("NURBS")
|
||||
nurbs.use_cyclic_u = scurve.closed
|
||||
nurbs.use_endpoint_u = not scurve.periodic
|
||||
|
||||
nurbs.points.add(num_points - 1)
|
||||
use_weights = len(scurve.weights) >= num_points
|
||||
for i in range(num_points):
|
||||
nurbs.points[i].co = (
|
||||
float(points[i * 3]) * scale,
|
||||
float(points[i * 3 + 1]) * scale,
|
||||
float(points[i * 3 + 2]) * scale,
|
||||
1,
|
||||
)
|
||||
|
||||
nurbs.points[i].weight = scurve.weights[i] if use_weights else 1
|
||||
|
||||
if hasattr(scurve, "closed"):
|
||||
polyline.use_cyclic_u = scurve.closed
|
||||
nurbs.order_u = scurve.degree + 1
|
||||
|
||||
# if "closed" in scurve.keys():
|
||||
# polyline.use_cyclic_u = scurve["closed"]
|
||||
|
||||
polyline.points.add(N - 1)
|
||||
for i in range(N):
|
||||
polyline.points[i].co = (
|
||||
float(value[i * 3]) * scale,
|
||||
float(value[i * 3 + 1]) * scale,
|
||||
float(value[i * 3 + 2]) * scale,
|
||||
1,
|
||||
)
|
||||
|
||||
return polyline
|
||||
|
||||
|
||||
def nurbs_to_native(scurve: Curve, bcurve: bpy.types.Curve, scale: float) -> Optional[bpy.types.Spline]:
|
||||
if points := scurve.points:
|
||||
N = len(points) // 3
|
||||
|
||||
nurbs = bcurve.splines.new("NURBS")
|
||||
|
||||
if hasattr(scurve, "closed"):
|
||||
nurbs.use_cyclic_u = scurve.closed != 0
|
||||
|
||||
nurbs.points.add(N - 1)
|
||||
for i in range(N):
|
||||
nurbs.points[i].co = (
|
||||
float(points[i * 3]) * scale,
|
||||
float(points[i * 3 + 1]) * scale,
|
||||
float(points[i * 3 + 2]) * scale,
|
||||
1,
|
||||
)
|
||||
|
||||
if len(scurve.weights) == len(nurbs.points):
|
||||
for i, w in enumerate(scurve.weights):
|
||||
nurbs.points[i].weight = w
|
||||
|
||||
# TODO: anaylize curve knots to decide if use_endpoint_u or use_bezier_u should be enabled
|
||||
# nurbs.use_endpoint_u = True
|
||||
nurbs.order_u = scurve.degree + 1
|
||||
|
||||
return nurbs
|
||||
return [nurbs]
|
||||
|
||||
|
||||
def arc_to_native(rcurve: Arc, bcurve: bpy.types.Curve, scale: float) -> Optional[bpy.types.Spline]:
|
||||
# TODO: improve Blender representation of arc
|
||||
# TODO: improve Blender representation of arc - check autocad test stream
|
||||
|
||||
plane = rcurve.plane
|
||||
if not plane:
|
||||
return None
|
||||
|
||||
normal = mathutils.Vector([plane.normal.x, plane.normal.y, plane.normal.z])
|
||||
normal = MVector([plane.normal.x, plane.normal.y, plane.normal.z])
|
||||
|
||||
radius = rcurve.radius * scale
|
||||
startAngle = rcurve.startAngle
|
||||
endAngle = rcurve.endAngle
|
||||
|
||||
startQuat = mathutils.Quaternion(normal, startAngle)
|
||||
endQuat = mathutils.Quaternion(normal, endAngle)
|
||||
startQuat = MQuaternion(normal, startAngle)
|
||||
endQuat = MQuaternion(normal, endAngle)
|
||||
|
||||
# Get start and end vectors, centre point, angles, etc.
|
||||
r1 = mathutils.Vector([plane.xdir.x, plane.xdir.y, plane.xdir.z])
|
||||
r1 = MVector([plane.xdir.x, plane.xdir.y, plane.xdir.z])
|
||||
r1.rotate(startQuat)
|
||||
|
||||
r2 = mathutils.Vector([plane.xdir.x, plane.xdir.y, plane.xdir.z])
|
||||
r2 = MVector([plane.xdir.x, plane.xdir.y, plane.xdir.z])
|
||||
r2.rotate(endQuat)
|
||||
|
||||
c = mathutils.Vector([plane.origin.x, plane.origin.y, plane.origin.z]) * scale
|
||||
c = MVector([plane.origin.x, plane.origin.y, plane.origin.z]) * scale
|
||||
|
||||
spt = c + r1 * radius
|
||||
ept = c + r2 * radius
|
||||
@@ -270,7 +376,7 @@ def arc_to_native(rcurve: Arc, bcurve: bpy.types.Curve, scale: float) -> Optiona
|
||||
|
||||
Ndiv = max(int(math.floor(angle / 0.3)), 2)
|
||||
step = angle / float(Ndiv)
|
||||
stepQuat = mathutils.Quaternion(normal, step)
|
||||
stepQuat = MQuaternion(normal, step)
|
||||
tan = math.tan(step / 2) * radius
|
||||
|
||||
arc.points.add(Ndiv + 1)
|
||||
@@ -293,7 +399,7 @@ def arc_to_native(rcurve: Arc, bcurve: bpy.types.Curve, scale: float) -> Optiona
|
||||
return arc
|
||||
|
||||
|
||||
def polycurve_to_native(scurve: Polycurve, bcurve: bpy.types.Curve, scale: float):
|
||||
def polycurve_to_native(scurve: Polycurve, bcurve: bpy.types.Curve, scale: float) -> list[bpy.types.Spline]:
|
||||
"""
|
||||
Convert Polycurve object
|
||||
"""
|
||||
@@ -305,48 +411,108 @@ def polycurve_to_native(scurve: Polycurve, bcurve: bpy.types.Curve, scale: float
|
||||
speckle_type = type(seg)
|
||||
|
||||
if speckle_type in SUPPORTED_CURVES:
|
||||
curves.append(icurve_to_native_spline(seg, bcurve, scale=scale))
|
||||
curves.append(icurve_to_native_spline(seg, bcurve, scale))
|
||||
else:
|
||||
_report(f"Unsupported curve type: {speckle_type}")
|
||||
|
||||
return curves
|
||||
|
||||
def ellipse_to_native(ellipse: Union[Ellipse, Circle], bcurve: bpy.types.Curve, units_scale: float) -> list[bpy.types.Spline]:
|
||||
|
||||
radX: float
|
||||
radY: float
|
||||
if isinstance(ellipse, Ellipse):
|
||||
radX = ellipse.firstRadius * units_scale
|
||||
radY = ellipse.secondRadius * units_scale
|
||||
else:
|
||||
radX = ellipse.radius * units_scale
|
||||
radY = ellipse.radius * units_scale
|
||||
|
||||
|
||||
D = 0.5522847498307936 # (4/3)*tan(pi/8)
|
||||
|
||||
right_handles = [
|
||||
(+radX, +radY * D, 0.0),
|
||||
(-radX * D, +radY, 0.0),
|
||||
(-radX, -radY * D, 0.0),
|
||||
(+radX * D, -radY, 0.0),
|
||||
]
|
||||
|
||||
left_handles = [
|
||||
(+radX, -radY * D, 0.0),
|
||||
(+radX * D, +radY, 0.0),
|
||||
(-radX, +radY * D, 0.0),
|
||||
(-radX * D, -radY, 0.0),
|
||||
]
|
||||
|
||||
points = [
|
||||
(+radX, 0.0, 0.0),
|
||||
(0.0, +radY, 0.0),
|
||||
(-radX, 0.0, 0.0),
|
||||
(0.0, -radY, 0.0),
|
||||
]
|
||||
transform = plane_to_native_transform(ellipse.plane, units_scale)
|
||||
|
||||
spline = bcurve.splines.new("BEZIER")
|
||||
spline.bezier_points.add(len(points) - 1)
|
||||
|
||||
for i in range(len(points)):
|
||||
spline.bezier_points[i].co = transform @ MVector(points[i])
|
||||
spline.bezier_points[i].handle_left = transform @ MVector(left_handles[i])
|
||||
spline.bezier_points[i].handle_right = transform @ MVector(right_handles[i])
|
||||
|
||||
spline.use_cyclic_u = True
|
||||
|
||||
#TODO support trims?
|
||||
return [spline]
|
||||
|
||||
|
||||
def icurve_to_native_spline(speckle_curve: Base, blender_curve: bpy.types.Curve, scale=1.0):
|
||||
curve_type = type(speckle_curve)
|
||||
if curve_type is Line:
|
||||
return line_to_native(speckle_curve, blender_curve, scale)
|
||||
if curve_type is Polyline:
|
||||
return polyline_to_native(speckle_curve, blender_curve, scale)
|
||||
if curve_type is Curve:
|
||||
return nurbs_to_native(speckle_curve, blender_curve, scale)
|
||||
if curve_type is Polycurve:
|
||||
def icurve_to_native_spline(speckle_curve: Base, blender_curve: bpy.types.Curve, scale: float) -> list[bpy.types.Spline]:
|
||||
# polycurves
|
||||
if isinstance(speckle_curve, Polycurve):
|
||||
return polycurve_to_native(speckle_curve, blender_curve, scale)
|
||||
if curve_type is Arc:
|
||||
return arc_to_native(speckle_curve, blender_curve, scale)
|
||||
|
||||
# single curves
|
||||
if isinstance(speckle_curve, Line):
|
||||
spline = line_to_native(speckle_curve, blender_curve, scale)
|
||||
elif isinstance(speckle_curve, Curve):
|
||||
spline = nurbs_to_native(speckle_curve, blender_curve, scale)
|
||||
elif isinstance(speckle_curve, Polyline):
|
||||
spline = polyline_to_native(speckle_curve, blender_curve, scale)
|
||||
elif isinstance(speckle_curve, Arc):
|
||||
spline = arc_to_native(speckle_curve, blender_curve, scale)
|
||||
elif isinstance(speckle_curve, Ellipse) or isinstance(speckle_curve, Circle):
|
||||
spline = ellipse_to_native(speckle_curve, blender_curve, scale)
|
||||
else:
|
||||
raise TypeError(f"{speckle_curve} is not a supported curve type. Supported types: {SUPPORTED_CURVES}")
|
||||
|
||||
return [spline] if spline is not None else []
|
||||
|
||||
|
||||
def icurve_to_native(speckle_curve: Base, name=None, scale=1.0) -> Optional[Curve]:
|
||||
def icurve_to_native(speckle_curve: Base, name: str, scale: float) -> bpy.types.Curve:
|
||||
curve_type = type(speckle_curve)
|
||||
if curve_type not in SUPPORTED_CURVES:
|
||||
_report(f"Unsupported curve type: {curve_type}")
|
||||
return None
|
||||
name = name or f"{curve_type} -- {speckle_curve.id}"
|
||||
raise Exception(f"Unsupported curve type: {curve_type}")
|
||||
|
||||
blender_curve = (
|
||||
bpy.data.curves[name]
|
||||
if name in bpy.data.curves.keys()
|
||||
else bpy.data.curves.new(name, type="CURVE")
|
||||
)
|
||||
blender_curve.dimensions = "3D"
|
||||
blender_curve.resolution_u = 12
|
||||
blender_curve.resolution_u = 12 #TODO: We could maybe decern the resolution from the ployline displayValue
|
||||
|
||||
icurve_to_native_spline(speckle_curve, blender_curve, scale)
|
||||
|
||||
return blender_curve
|
||||
|
||||
|
||||
def transform_to_native(transform: Transform, scale=1.0) -> mathutils.Matrix:
|
||||
mat = mathutils.Matrix(
|
||||
"""
|
||||
Transforms and Intances
|
||||
"""
|
||||
|
||||
def transform_to_native(transform: Transform, scale: float) -> MMatrix:
|
||||
mat = MMatrix(
|
||||
[
|
||||
transform.value[:4],
|
||||
transform.value[4:8],
|
||||
@@ -359,38 +525,166 @@ def transform_to_native(transform: Transform, scale=1.0) -> mathutils.Matrix:
|
||||
mat[i][3] *= scale
|
||||
return mat
|
||||
|
||||
def plane_to_native_transform(plane: Plane, fallback_scale:float = 1) -> MMatrix:
|
||||
scale_factor = get_scale_factor(plane, fallback_scale)
|
||||
tx = (plane.origin.x * scale_factor)
|
||||
ty = (plane.origin.y * scale_factor)
|
||||
tz = (plane.origin.z * scale_factor)
|
||||
|
||||
def block_def_to_native(definition: BlockDefinition, scale=1.0) -> bpy.types.Collection:
|
||||
native_def = bpy.data.collections.get(definition.name)
|
||||
|
||||
return MMatrix((
|
||||
(plane.xdir.x, plane.ydir.x, plane.normal.x, tx),
|
||||
(plane.xdir.y, plane.ydir.y, plane.normal.y, ty),
|
||||
(plane.xdir.z, plane.ydir.z, plane.normal.z, tz),
|
||||
(0, 0, 0, 1 )
|
||||
))
|
||||
|
||||
|
||||
"""
|
||||
Instances / Blocks
|
||||
"""
|
||||
|
||||
def _get_instance_name(instance: Instance) -> str:
|
||||
name_prefix = _get_friendly_object_name(instance) or _get_friendly_object_name(instance.definition) or _simplified_speckle_type(instance.speckle_type)
|
||||
return f"{name_prefix}{OBJECT_NAME_SEPERATOR}{instance.id}"
|
||||
|
||||
|
||||
def instance_to_native_object(instance: Instance, scale: float) -> Tuple[bpy.types.Object, List[bpy.types.Object]]:
|
||||
"""
|
||||
Converts Instance to a unique object with (potentially) shared data (linked duplicate)
|
||||
"""
|
||||
if not instance.definition: raise Exception(f"Instance is missing a definition")
|
||||
if not instance.transform: raise Exception(f"Instance is missing a transform")
|
||||
|
||||
name = _get_instance_name(instance)
|
||||
definition = instance.definition
|
||||
|
||||
native_instance: Object
|
||||
native_elements: List[Object] = []
|
||||
elements_on_instance: List[Object] = []
|
||||
|
||||
if isinstance(definition, BlockDefinition): #NOTE: We have to handle BlockDefinitions specially here, since they don't follow normal traversal rules
|
||||
native_instance = create_new_object(None, name) #Instance will be empty
|
||||
native_instance.empty_display_size = 0
|
||||
for geo in definition.geometry:
|
||||
native_elements.append(convert_to_native(geo))
|
||||
else:
|
||||
native_instance = convert_to_native(instance.definition)
|
||||
|
||||
instance_transform = transform_to_native(instance.transform, scale)
|
||||
instance_transform_inverted = instance_transform.inverted()
|
||||
native_instance.matrix_world = instance_transform
|
||||
|
||||
elements_on_instance = elements_to_native(instance, name, scale)
|
||||
for c in elements_on_instance:
|
||||
c.matrix_world = instance_transform_inverted @ c.matrix_world #Undo the instance transform on elements
|
||||
|
||||
native_elements.extend(elements_on_instance)
|
||||
|
||||
return (native_instance, native_elements) #TODO: need to double check that all child objects have custom props attached correctly
|
||||
|
||||
def instance_to_native_collection_instance(instance: Instance, scale: float) -> bpy.types.Object:
|
||||
"""
|
||||
Convert an Instance as a transformed Object with the `instance_collection` property
|
||||
set to be the `instance.Definition` converted as a collection
|
||||
|
||||
The definition collection won't be linked to the current scene
|
||||
Any Elements on the instance object will also be converted (and spacially transformed)
|
||||
"""
|
||||
if not instance.definition: raise Exception(f"Instance is missing a definition")
|
||||
if not instance.transform: raise Exception(f"Instance is missing a transform")
|
||||
|
||||
name = _get_instance_name(instance)
|
||||
|
||||
# Get/Convert definition collection
|
||||
collection_def = _instance_definition_to_native(instance.definition)
|
||||
|
||||
# Convert elements as children of collection instance object
|
||||
elements = elements_to_native(instance, name, scale)
|
||||
|
||||
instance_transform = transform_to_native(instance.transform, scale)
|
||||
instance_transform_inverted = instance_transform.inverted()
|
||||
|
||||
native_instance = bpy.data.objects.new(name, None)
|
||||
|
||||
#add_custom_properties(instance, native_instance)
|
||||
# hide the instance axes so they don't clutter the viewport
|
||||
native_instance.empty_display_size = 0
|
||||
native_instance.instance_collection = collection_def
|
||||
native_instance.instance_type = "COLLECTION"
|
||||
native_instance.matrix_world =instance_transform
|
||||
|
||||
for c in elements:
|
||||
c.matrix_world = instance_transform_inverted @ c.matrix_world #Undo the instance transform on elements
|
||||
c.parent = native_instance #TODO: need to double check that all child objects have custom props attached correctly
|
||||
|
||||
return native_instance
|
||||
|
||||
def _instance_definition_to_native(definition: Union[Base, BlockDefinition]) -> bpy.types.Collection:
|
||||
"""
|
||||
Converts a geometry carrying Base as a collection (does not link it to the scene)
|
||||
"""
|
||||
name = _generate_object_name(definition)
|
||||
native_def = bpy.data.collections.get(name)
|
||||
if native_def:
|
||||
return native_def
|
||||
|
||||
native_def = bpy.data.collections.new(definition.name)
|
||||
native_def = bpy.data.collections.new(name)
|
||||
native_def["applicationId"] = definition.applicationId
|
||||
for geo in definition.geometry:
|
||||
if b_obj := convert_to_native(geo):
|
||||
native_def.objects.link(
|
||||
b_obj
|
||||
if isinstance(b_obj, bpy_types.Object)
|
||||
else bpy.data.objects.new(b_obj.name, b_obj)
|
||||
)
|
||||
|
||||
#TODO could maybe replace BlockDefinition awareness with a single traverse member call
|
||||
geometry = definition.geometry if isinstance(definition, BlockDefinition) else [definition]
|
||||
|
||||
for geo in geometry:
|
||||
if not geo: continue
|
||||
converted = convert_to_native(geo) #NOTE: we assume the last item is the root converted item
|
||||
link_object_to_collection_nested(converted, native_def)
|
||||
|
||||
|
||||
return native_def
|
||||
|
||||
|
||||
def block_instance_to_native(instance: BlockInstance, scale=1.0) -> bpy.types.Object:
|
||||
"""
|
||||
Convert BlockInstance to native
|
||||
"""
|
||||
name = f"{getattr(instance, 'name', None) or instance.blockDefinition.name} -- {instance.id}"
|
||||
native_def = block_def_to_native(instance.blockDefinition, scale)
|
||||
"""
|
||||
Object Naming
|
||||
"""
|
||||
|
||||
native_instance = bpy.data.objects.new(name, None)
|
||||
add_custom_properties(instance, native_instance)
|
||||
native_instance["name"] = getattr(instance, 'name', None) or instance.blockDefinition.name
|
||||
# hide the instance axes so they don't clutter the viewport
|
||||
native_instance.empty_display_size = 0
|
||||
native_instance.instance_collection = native_def
|
||||
native_instance.instance_type = "COLLECTION"
|
||||
native_instance.matrix_world = transform_to_native(instance.transform, scale)
|
||||
return native_instance
|
||||
def _get_friendly_object_name(speckle_object: Base) -> Optional[str]:
|
||||
return (getattr(speckle_object, "name", None)
|
||||
or getattr(speckle_object, "Name", None)
|
||||
or getattr(speckle_object, "family", None)
|
||||
)
|
||||
|
||||
|
||||
# Blender object names must not exceed 62 characters
|
||||
# We need to ensure the complete ID is included in the name (to prevent identity collisions)
|
||||
# So we if the name is too long, we need to truncate
|
||||
OBJECT_NAME_MAX_LENGTH = 62
|
||||
SPECKLE_ID_LENGTH = 32
|
||||
OBJECT_NAME_SEPERATOR = " -- "
|
||||
|
||||
def _truncate_object_name(name: str) -> str:
|
||||
|
||||
MAX_NAME_LENGTH = OBJECT_NAME_MAX_LENGTH - SPECKLE_ID_LENGTH - len(OBJECT_NAME_SEPERATOR)
|
||||
|
||||
return name[:MAX_NAME_LENGTH]
|
||||
|
||||
|
||||
def _simplified_speckle_type(speckle_type: str) -> str:
|
||||
return(speckle_type.rsplit('.')[-1]) #Take only the most specific object type name (without namespace)
|
||||
|
||||
def _generate_object_name(speckle_object: Base) -> str:
|
||||
prefix: str
|
||||
name = _get_friendly_object_name(speckle_object)
|
||||
if name:
|
||||
prefix = _truncate_object_name(name)
|
||||
else:
|
||||
prefix = _simplified_speckle_type(speckle_object.speckle_type)
|
||||
|
||||
return f"{prefix}{OBJECT_NAME_SEPERATOR}{speckle_object.id}"
|
||||
|
||||
|
||||
def get_scale_factor(speckle_object: Base, fallback: float = 1.0) -> float:
|
||||
scale = fallback
|
||||
if units := getattr(speckle_object, "units", None):
|
||||
scale = get_scale_length(units) / bpy.context.scene.unit_settings.scale_length
|
||||
return scale
|
||||
+328
-166
@@ -1,127 +1,174 @@
|
||||
from typing import Optional
|
||||
from typing import Dict, Iterable, List, Optional, Tuple, Union, cast
|
||||
import bpy
|
||||
from bpy.types import Depsgraph, MeshVertColor, MeshVertex, Object
|
||||
from specklepy.objects.geometry import Mesh, Curve, Interval, Box, Point, Polyline
|
||||
from specklepy.objects.other import *
|
||||
from bpy_speckle.functions import _report
|
||||
from bpy.types import (
|
||||
Depsgraph,
|
||||
MeshPolygon,
|
||||
Object,
|
||||
Curve as NCurve,
|
||||
Mesh as NMesh,
|
||||
)
|
||||
from deprecated import deprecated
|
||||
from mathutils.geometry import interpolate_bezier
|
||||
from mathutils import (
|
||||
Matrix as MMatrix,
|
||||
Vector as MVector,
|
||||
)
|
||||
from specklepy.objects import Base
|
||||
from specklepy.objects.other import BlockInstance, BlockDefinition, RenderMaterial, Transform
|
||||
from specklepy.objects.geometry import (
|
||||
Mesh, Curve, Interval, Box, Point, Polyline
|
||||
)
|
||||
from bpy_speckle.convert.to_native import OBJECT_NAME_SEPERATOR, SPECKLE_ID_LENGTH
|
||||
from bpy_speckle.convert.util import (
|
||||
get_blender_custom_properties,
|
||||
make_knots,
|
||||
nurb_make_curve,
|
||||
to_argb_int,
|
||||
)
|
||||
from bpy_speckle.functions import _report
|
||||
|
||||
UNITS = "m"
|
||||
class ConversionSkippedException(Exception):
|
||||
pass
|
||||
|
||||
Units: str = "m" # The desired final units to send
|
||||
UnitsScale: float = 1 # The scale factor conversions need to apply to position data to get to the desired units
|
||||
|
||||
CAN_CONVERT_TO_SPECKLE = ("MESH", "CURVE", "EMPTY")
|
||||
|
||||
|
||||
def convert_to_speckle(blender_object: Object, scale: float, units: str, desgraph: Optional[Depsgraph]) -> Optional[list]:
|
||||
global UNITS
|
||||
UNITS = units
|
||||
blender_type = blender_object.type
|
||||
def convert_to_speckle(raw_blender_object: Object, units_scale: float, units: str, depsgraph: Optional[Depsgraph]) -> Base:
|
||||
"""
|
||||
Converts supported 1 blender objects to 1 speckle object (potentially with children)
|
||||
:param raw_blender_object: the blender object (unevaluated by a Depsgraph) to convert
|
||||
:param units_scale: The scale factor conversions need to apply to position data to get to the desired units
|
||||
:param units: The desired final units to send
|
||||
:param depsgraph: Optional depsgraph if provided will evaluate modifiers on geometry data
|
||||
:return: The Converted blender object
|
||||
"""
|
||||
global Units, UnitsScale
|
||||
Units = units
|
||||
UnitsScale = units_scale
|
||||
|
||||
blender_type = raw_blender_object.type
|
||||
if blender_type not in CAN_CONVERT_TO_SPECKLE:
|
||||
return None
|
||||
raise ConversionSkippedException(f"Objects of type {blender_type} are not supported")
|
||||
|
||||
speckle_objects = []
|
||||
speckle_material = material_to_speckle(blender_object)
|
||||
if desgraph:
|
||||
blender_object = blender_object.evaluated_get(desgraph)
|
||||
converted = None
|
||||
blender_object = cast(Object, (
|
||||
raw_blender_object.evaluated_get(depsgraph)
|
||||
if depsgraph
|
||||
else raw_blender_object
|
||||
))
|
||||
|
||||
converted: Optional[Base] = None
|
||||
if blender_type == "MESH":
|
||||
converted = mesh_to_speckle(blender_object, blender_object.data, scale)
|
||||
converted = mesh_to_speckle(blender_object, cast(NMesh, blender_object.data))
|
||||
elif blender_type == "CURVE":
|
||||
converted = icurve_to_speckle(blender_object, blender_object.data, scale)
|
||||
converted = curve_to_speckle(blender_object, cast(NCurve, blender_object.data))
|
||||
elif blender_type == "EMPTY":
|
||||
converted = empty_to_speckle(blender_object, scale)
|
||||
converted = empty_to_speckle(blender_object)
|
||||
|
||||
if not converted:
|
||||
return None
|
||||
raise Exception("Conversion returned None")
|
||||
|
||||
if isinstance(converted, list):
|
||||
speckle_objects.extend([c for c in converted if c != None])
|
||||
else:
|
||||
speckle_objects.append(converted)
|
||||
for so in speckle_objects:
|
||||
so.properties = get_blender_custom_properties(blender_object)
|
||||
so.applicationId = so.properties.pop("applicationId", None)
|
||||
converted["properties"] = get_blender_custom_properties(raw_blender_object) #NOTE: Depsgraph copies don't have custom properties so we use the raw version
|
||||
|
||||
if speckle_material:
|
||||
so["renderMaterial"] = speckle_material
|
||||
# Set object transform #TODO: this could be deprecated once we add proper geometry instancing support
|
||||
if blender_type != "EMPTY":
|
||||
converted["properties"]["transform"] = transform_to_speckle(
|
||||
blender_object.matrix_world
|
||||
)
|
||||
|
||||
# Set object transform
|
||||
if blender_type != "EMPTY":
|
||||
so.properties["transform"] = transform_to_speckle(
|
||||
blender_object.matrix_world
|
||||
)
|
||||
return converted
|
||||
|
||||
return speckle_objects
|
||||
def mesh_to_speckle(blender_object: Object, data: bpy.types.Mesh) -> Base:
|
||||
b = Base()
|
||||
b["name"] = to_speckle_name(blender_object)
|
||||
b["@displayValue"] = mesh_to_speckle_meshes(blender_object, data)
|
||||
return b
|
||||
|
||||
def mesh_to_speckle_meshes(blender_object: Object, data: bpy.types.Mesh) -> List[Mesh]:
|
||||
|
||||
# Categorise polygons by material index
|
||||
submesh_data: Dict[int, List[MeshPolygon]] = {}
|
||||
|
||||
for p in data.polygons:
|
||||
if p.material_index not in submesh_data:
|
||||
submesh_data[p.material_index] = []
|
||||
submesh_data[p.material_index].append(p)
|
||||
|
||||
transform = cast(MMatrix, blender_object.matrix_world)
|
||||
scaled_vertices = [tuple(transform @ x.co * UnitsScale) for x in data.vertices]
|
||||
|
||||
# Create Speckle meshes for each material
|
||||
submeshes = []
|
||||
index_counter = 0
|
||||
for i in submesh_data:
|
||||
index_mapping: Dict[int, int] = {}
|
||||
|
||||
#Loop through each polygon, and map indicies to their new index in m_verts
|
||||
|
||||
mesh_area = 0
|
||||
m_verts: List[float] = []
|
||||
m_faces: List[int] = []
|
||||
m_texcoords: List[float] = []
|
||||
for face in submesh_data[i]:
|
||||
u_indices = face.vertices
|
||||
m_faces.append(len(u_indices))
|
||||
|
||||
mesh_area += face.area
|
||||
for u_index in u_indices:
|
||||
if u_index not in index_mapping:
|
||||
# Create mapping between index in blender mesh, and new index in speckle submesh
|
||||
index_mapping[u_index] = len(m_verts) // 3
|
||||
vert = scaled_vertices[u_index]
|
||||
m_verts.append(vert[0])
|
||||
m_verts.append(vert[1])
|
||||
m_verts.append(vert[2])
|
||||
|
||||
if data.uv_layers.active:
|
||||
vt = data.uv_layers.active.data[index_counter]
|
||||
uv = cast(MVector, vt.uv)
|
||||
m_texcoords.extend([uv.x, uv.y])
|
||||
|
||||
m_faces.append(index_mapping[u_index])
|
||||
index_counter += 1
|
||||
|
||||
speckle_mesh = Mesh(
|
||||
vertices=m_verts,
|
||||
faces=m_faces,
|
||||
colors=[],
|
||||
textureCoordinates=m_texcoords,
|
||||
units=Units,
|
||||
area = mesh_area,
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
)
|
||||
|
||||
if i < len(data.materials):
|
||||
material = data.materials[i]
|
||||
if material is not None:
|
||||
speckle_mesh["renderMaterial"] = material_to_speckle(material)
|
||||
submeshes.append(speckle_mesh)
|
||||
|
||||
return submeshes
|
||||
|
||||
|
||||
def mesh_to_speckle(blender_object: Object, data: bpy.types.Mesh, scale=1.0) -> List[Mesh]:
|
||||
if data.loop_triangles is None or len(data.loop_triangles) < 1:
|
||||
data.calc_loop_triangles()
|
||||
|
||||
|
||||
mat = blender_object.matrix_world
|
||||
|
||||
verts = [tuple(mat @ x.co * scale) for x in data.vertices]
|
||||
|
||||
flattend_verts = []
|
||||
for row in verts: flattend_verts.extend(row)
|
||||
|
||||
faces = [p.vertices for p in data.polygons]
|
||||
unit_system = bpy.context.scene.unit_settings.system
|
||||
|
||||
sm = Mesh(
|
||||
name=blender_object.name,
|
||||
vertices=flattend_verts,
|
||||
faces=[],
|
||||
colors=[],
|
||||
textureCoordinates=[],
|
||||
units=UNITS,
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
)
|
||||
|
||||
if data.uv_layers.active:
|
||||
for vt in data.uv_layers.active.data:
|
||||
sm.textureCoordinates.extend([vt.uv.x, vt.uv.y])
|
||||
|
||||
for f in faces:
|
||||
n = len(f)
|
||||
if n == 3:
|
||||
sm.faces.append(0)
|
||||
elif n == 4:
|
||||
sm.faces.append(1)
|
||||
else:
|
||||
sm.faces.append(n)
|
||||
sm.faces.extend(f)
|
||||
|
||||
# TODO: figure out how to align vertex colors and vertices consistantly in receiving applications
|
||||
# we are seeing the same issue as with texture coordinate alignment
|
||||
#if data.color_attributes.active_color:
|
||||
# sm.colors = [to_argb_int(x.color) for x in data.color_attributes.active_color.data]
|
||||
|
||||
|
||||
return [sm]
|
||||
|
||||
|
||||
def bezier_to_speckle(matrix: List[float], spline: bpy.types.Spline, scale: float, name: Optional[str] = None) -> Curve:
|
||||
def bezier_to_speckle(matrix: MMatrix, spline: bpy.types.Spline, name: Optional[str] = None) -> Curve:
|
||||
degree = 3
|
||||
closed = spline.use_cyclic_u
|
||||
|
||||
points = []
|
||||
points: List[Tuple[MVector]] = []
|
||||
for i, bp in enumerate(spline.bezier_points):
|
||||
if i > 0:
|
||||
points.append(tuple(matrix @ bp.handle_left * scale))
|
||||
points.append(tuple(matrix @ bp.co * scale))
|
||||
points.append(tuple(matrix @ bp.handle_left * UnitsScale))
|
||||
points.append(tuple(matrix @ bp.co * UnitsScale))
|
||||
if i < len(spline.bezier_points) - 1:
|
||||
points.append(tuple(matrix @ bp.handle_right * scale))
|
||||
points.append(tuple(matrix @ bp.handle_right * UnitsScale))
|
||||
|
||||
if closed:
|
||||
points.extend(
|
||||
(
|
||||
tuple(matrix @ spline.bezier_points[-1].handle_right * scale),
|
||||
tuple(matrix @ spline.bezier_points[0].handle_left * scale),
|
||||
tuple(matrix @ spline.bezier_points[0].co * scale),
|
||||
tuple(matrix @ spline.bezier_points[-1].handle_right * UnitsScale),
|
||||
tuple(matrix @ spline.bezier_points[0].handle_left * UnitsScale),
|
||||
tuple(matrix @ spline.bezier_points[0].co * UnitsScale),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -142,51 +189,131 @@ def bezier_to_speckle(matrix: List[float], spline: bpy.types.Spline, scale: floa
|
||||
name=name,
|
||||
degree=degree,
|
||||
closed=spline.use_cyclic_u,
|
||||
periodic=spline.use_cyclic_u,
|
||||
periodic= not spline.use_endpoint_u,
|
||||
points=flattend_points,
|
||||
weights=[1] * num_points,
|
||||
knots=knots,
|
||||
rational=False,
|
||||
rational=True,
|
||||
area=0,
|
||||
volume=0,
|
||||
length=length,
|
||||
domain=domain,
|
||||
units=UNITS,
|
||||
units=Units,
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
displayValue = bezier_to_speckle_polyline(matrix, spline, length),
|
||||
)
|
||||
|
||||
|
||||
def nurbs_to_speckle(matrix: List[float], spline: bpy.types.Spline, scale: float, name: Optional[str] = None) -> Curve:
|
||||
knots = make_knots(spline)
|
||||
points = [tuple(matrix @ pt.co.xyz * scale) for pt in spline.points]
|
||||
def nurbs_to_speckle(matrix: MMatrix, spline: bpy.types.Spline, name: Optional[str] = None) -> Curve:
|
||||
|
||||
degree = spline.order_u - 1
|
||||
knots = make_knots(spline)
|
||||
|
||||
length = spline.calc_length()
|
||||
domain = Interval(start=0, end=length, totalChildrenCount=0)
|
||||
|
||||
weights = [pt.weight for pt in spline.points]
|
||||
is_rational = all(w == weights[0] for w in weights)
|
||||
|
||||
points = [tuple(matrix @ pt.co.xyz * UnitsScale) for pt in spline.points]
|
||||
|
||||
flattend_points = []
|
||||
for row in points: flattend_points.extend(row)
|
||||
|
||||
if spline.use_cyclic_u:
|
||||
for i in range(0, degree * 3, 3):
|
||||
# Rhino expects n + degree number of points (for closed curves). So we need to add an extra point for each degree
|
||||
flattend_points.append(flattend_points[i + 0])
|
||||
flattend_points.append(flattend_points[i + 1])
|
||||
flattend_points.append(flattend_points[i + 2])
|
||||
|
||||
for i in range(0, degree):
|
||||
weights.append(weights[i])
|
||||
|
||||
return Curve(
|
||||
name=name,
|
||||
degree=degree,
|
||||
closed=spline.use_cyclic_u,
|
||||
periodic=spline.use_cyclic_u,
|
||||
periodic= not spline.use_endpoint_u,
|
||||
points=flattend_points,
|
||||
weights=[pt.weight for pt in spline.points],
|
||||
weights=weights,
|
||||
knots=knots,
|
||||
rational=False,
|
||||
rational=is_rational,
|
||||
area=0,
|
||||
volume=0,
|
||||
length=length,
|
||||
domain=domain,
|
||||
units=UNITS,
|
||||
units=Units,
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
displayValue=nurbs_to_speckle_polyline(matrix, spline, length),
|
||||
)
|
||||
|
||||
def nurbs_to_speckle_polyline(matrix: MMatrix, spline: bpy.types.Spline, length: Optional[float] = None) -> Polyline:
|
||||
"""
|
||||
Samples a nurbs curve with resolution_u creating a polyline
|
||||
"""
|
||||
points = []
|
||||
sampled_points = nurb_make_curve(spline, spline.resolution_u, 3)
|
||||
for i in range(0, len(sampled_points), 3):
|
||||
scaled_point = matrix @ MVector((
|
||||
sampled_points[i + 0],
|
||||
sampled_points[i + 1],
|
||||
sampled_points[i + 2])) * UnitsScale
|
||||
|
||||
def poly_to_speckle(matrix: List[float], spline: bpy.types.Spline, scale: float, name: Optional[str] = None) -> Polyline:
|
||||
points = [tuple(matrix @ pt.co.xyz * scale) for pt in spline.points]
|
||||
points.append(scaled_point.x)
|
||||
points.append(scaled_point.y)
|
||||
points.append(scaled_point.z)
|
||||
|
||||
length = length or spline.calc_length()
|
||||
domain = Interval(start=0, end=length, totalChildrenCount=0)
|
||||
return Polyline(value=points, closed = spline.use_cyclic_u, domain=domain, area=0, len=length)
|
||||
|
||||
|
||||
#Inspired by https://blender.stackexchange.com/a/689 (CC BY-SA 3.0)
|
||||
def bezier_to_speckle_polyline(matrix: MMatrix, spline: bpy.types.Spline, length: Optional[float] = None) -> Optional[Polyline]:
|
||||
"""
|
||||
Samples a Bézier curve with resolution_u creating a polyline
|
||||
"""
|
||||
segments = len(spline.bezier_points)
|
||||
if segments < 2: return None
|
||||
|
||||
R = spline.resolution_u + 1
|
||||
|
||||
points = []
|
||||
if not spline.use_cyclic_u:
|
||||
segments -= 1
|
||||
|
||||
points: List[float] = []
|
||||
for i in range(segments):
|
||||
inext = (i + 1) % len(spline.bezier_points)
|
||||
|
||||
knot1 = spline.bezier_points[i].co
|
||||
handle1 = spline.bezier_points[i].handle_right
|
||||
handle2 = spline.bezier_points[inext].handle_left
|
||||
knot2 = spline.bezier_points[inext].co
|
||||
|
||||
_points = interpolate_bezier(knot1, handle1, handle2, knot2, R)
|
||||
for p in _points:
|
||||
scaled_point = matrix @ p * UnitsScale
|
||||
points.append(scaled_point.x)
|
||||
points.append(scaled_point.y)
|
||||
points.append(scaled_point.z)
|
||||
|
||||
length = length or spline.calc_length()
|
||||
domain = Interval(start=0, end=length, totalChildrenCount=0)
|
||||
return Polyline(value=points, closed = spline.use_cyclic_u, domain=domain, area=0, len=length)
|
||||
|
||||
_QUICK_TEST_NAME_LENGTH = SPECKLE_ID_LENGTH + len(OBJECT_NAME_SEPERATOR)
|
||||
|
||||
def to_speckle_name(blender_object: bpy.types.ID) -> str:
|
||||
does_name_contain_id = len(blender_object.name) > _QUICK_TEST_NAME_LENGTH and OBJECT_NAME_SEPERATOR in blender_object.name
|
||||
if does_name_contain_id:
|
||||
return blender_object.name.rsplit(OBJECT_NAME_SEPERATOR, 1)[0]
|
||||
else:
|
||||
return blender_object.name
|
||||
|
||||
def poly_to_speckle(matrix: MMatrix, spline: bpy.types.Spline, name: Optional[str] = None) -> Polyline:
|
||||
points = [tuple(matrix @ pt.co.xyz * UnitsScale) for pt in spline.points]
|
||||
|
||||
flattend_points = []
|
||||
for row in points: flattend_points.extend(row)
|
||||
@@ -201,40 +328,48 @@ def poly_to_speckle(matrix: List[float], spline: bpy.types.Spline, scale: float,
|
||||
domain=domain,
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
area=0,
|
||||
units=UNITS,
|
||||
units=Units,
|
||||
)
|
||||
|
||||
|
||||
def icurve_to_speckle(blender_object: Object, data: bpy.types.Curve, scale=1.0) -> Optional[List[Base]]:
|
||||
UNITS = "m" if bpy.context.scene.unit_settings.system == "METRIC" else "ft"
|
||||
def curve_to_speckle(blender_object: Object, data: bpy.types.Curve) -> Base:
|
||||
b = Base()
|
||||
(meshes, curves) = curve_to_speckle_geometry(blender_object, data)
|
||||
if meshes:
|
||||
b["@displayValue"] = meshes
|
||||
|
||||
if blender_object.type != "CURVE":
|
||||
return None
|
||||
b["name"] = to_speckle_name(blender_object)
|
||||
b["@elements"] = curves
|
||||
return b
|
||||
|
||||
blender_object = blender_object.evaluated_get(bpy.context.view_layer.depsgraph)
|
||||
def curve_to_speckle_geometry(blender_object: Object, data: bpy.types.Curve) -> Tuple[List[Mesh], List[Base]]:
|
||||
assert(blender_object.type == "CURVE")
|
||||
|
||||
mat = blender_object.matrix_world
|
||||
blender_object = cast(Object, blender_object.evaluated_get(bpy.context.view_layer.depsgraph))
|
||||
|
||||
curves = []
|
||||
matrix = cast(MMatrix, blender_object.matrix_world)
|
||||
|
||||
meshes: List[Mesh] = []
|
||||
curves: List[Base] = []
|
||||
|
||||
#TODO: Could we support this better?
|
||||
if data.bevel_mode == "OBJECT" and data.bevel_object != None:
|
||||
mesh = mesh_to_speckle(blender_object, blender_object.to_mesh(), scale)
|
||||
curves.extend(mesh)
|
||||
meshes = mesh_to_speckle_meshes(blender_object, blender_object.to_mesh())
|
||||
|
||||
for spline in data.splines:
|
||||
if spline.type == "BEZIER":
|
||||
curves.append(bezier_to_speckle(mat, spline, scale, blender_object.name))
|
||||
curves.append(bezier_to_speckle(matrix, spline, to_speckle_name(blender_object)))
|
||||
|
||||
elif spline.type == "NURBS":
|
||||
curves.append(nurbs_to_speckle(mat, spline, scale, blender_object.name))
|
||||
curves.append(nurbs_to_speckle(matrix, spline, to_speckle_name(blender_object)))
|
||||
|
||||
elif spline.type == "POLY":
|
||||
curves.append(poly_to_speckle(mat, spline, scale, blender_object.name))
|
||||
curves.append(poly_to_speckle(matrix, spline, to_speckle_name(blender_object)))
|
||||
|
||||
return curves
|
||||
return (meshes, curves)
|
||||
|
||||
|
||||
def ngons_to_speckle_polylines(blender_object: Object, data: bpy.types.Mesh, scale=1.0) -> Optional[List[Polyline]]:
|
||||
@deprecated
|
||||
def ngons_to_speckle_polylines(blender_object: Object, data: bpy.types.Mesh) -> Optional[List[Polyline]]:
|
||||
UNITS = "m" if bpy.context.scene.unit_settings.system == "METRIC" else "ft"
|
||||
|
||||
if blender_object.type != "MESH":
|
||||
@@ -247,13 +382,13 @@ def ngons_to_speckle_polylines(blender_object: Object, data: bpy.types.Mesh, sca
|
||||
for i, poly in enumerate(data.polygons):
|
||||
value = []
|
||||
for v in poly.vertices:
|
||||
value.extend(mat @ verts[v].co * scale)
|
||||
value.extend(mat @ verts[v].co * UnitsScale)
|
||||
|
||||
domain = Interval(start=0, end=1)
|
||||
poly = Polyline(
|
||||
name="{}_{}".format(blender_object.name, i),
|
||||
closed=True,
|
||||
value=value, # magic (flatten list of tuples)
|
||||
value=value,
|
||||
length=0,
|
||||
domain=domain,
|
||||
bbox=Box(area=0.0, volume=0.0),
|
||||
@@ -266,7 +401,35 @@ def ngons_to_speckle_polylines(blender_object: Object, data: bpy.types.Mesh, sca
|
||||
return polylines
|
||||
|
||||
|
||||
def material_to_speckle(blender_object: Object) -> Optional[RenderMaterial]:
|
||||
def material_to_speckle(blender_mat: bpy.types.Material) -> RenderMaterial:
|
||||
speckle_mat = RenderMaterial()
|
||||
speckle_mat.name = blender_mat.name
|
||||
|
||||
if blender_mat.use_nodes:
|
||||
if blender_mat.node_tree.nodes.get("Principled BSDF"):
|
||||
inputs = blender_mat.node_tree.nodes["Principled BSDF"].inputs
|
||||
speckle_mat.diffuse = to_argb_int(inputs["Base Color"].default_value)
|
||||
speckle_mat.emissive = to_argb_int(inputs["Emission"].default_value)
|
||||
speckle_mat.roughness = inputs["Roughness"].default_value
|
||||
speckle_mat.metalness = inputs["Metallic"].default_value
|
||||
speckle_mat.opacity = inputs["Alpha"].default_value
|
||||
return speckle_mat
|
||||
elif blender_mat.node_tree.nodes.get("Diffuse BSDF"):
|
||||
inputs = blender_mat.node_tree.nodes["Diffuse BSDF"].inputs
|
||||
speckle_mat.diffuse = to_argb_int(inputs["Color"].default_value)
|
||||
speckle_mat.roughness = inputs["Roughness"].default_value
|
||||
return speckle_mat
|
||||
#TODO: Support more shaders
|
||||
|
||||
# fallback to standard material props
|
||||
speckle_mat.diffuse = to_argb_int(blender_mat.diffuse_color)
|
||||
speckle_mat.metalness = blender_mat.metallic
|
||||
speckle_mat.roughness = blender_mat.roughness
|
||||
|
||||
return speckle_mat
|
||||
|
||||
@deprecated
|
||||
def material_to_speckle_old(blender_object: Object) -> Optional[RenderMaterial]:
|
||||
"""Create and return a render material from a blender object"""
|
||||
if not getattr(blender_object.data, "materials", None):
|
||||
return None
|
||||
@@ -275,69 +438,68 @@ def material_to_speckle(blender_object: Object) -> Optional[RenderMaterial]:
|
||||
if not blender_mat:
|
||||
return None
|
||||
|
||||
speckle_mat = RenderMaterial()
|
||||
speckle_mat.name = blender_mat.name
|
||||
|
||||
if blender_mat.use_nodes is True and blender_mat.node_tree.nodes.get(
|
||||
"Principled BSDF"
|
||||
):
|
||||
inputs = blender_mat.node_tree.nodes["Principled BSDF"].inputs
|
||||
speckle_mat.diffuse = to_argb_int(inputs["Base Color"].default_value)
|
||||
speckle_mat.emissive = to_argb_int(inputs["Emission"].default_value)
|
||||
speckle_mat.roughness = inputs["Roughness"].default_value
|
||||
speckle_mat.metalness = inputs["Metallic"].default_value
|
||||
speckle_mat.opacity = inputs["Alpha"].default_value
|
||||
|
||||
else:
|
||||
speckle_mat.diffuse = to_argb_int(blender_mat.diffuse_color)
|
||||
speckle_mat.metalness = blender_mat.metallic
|
||||
speckle_mat.roughness = blender_mat.roughness
|
||||
|
||||
return speckle_mat
|
||||
return material_to_speckle(blender_mat)
|
||||
|
||||
|
||||
def transform_to_speckle(blender_transform: List[float], scale=1.0) -> Transform:
|
||||
value = [y for x in blender_transform for y in x]
|
||||
def transform_to_speckle(blender_transform: Union[Iterable[Iterable[float]], MMatrix]) -> Transform:
|
||||
iterable_transform = cast(Iterable[Iterable[float]], blender_transform) #NOTE: Matrix are itterable, even if type hinting says they are not
|
||||
value = [y for x in iterable_transform for y in x]
|
||||
# scale the translation
|
||||
for i in (3, 7, 11):
|
||||
value[i] *= scale
|
||||
value[i] *= UnitsScale
|
||||
|
||||
return Transform(value=value, units=UNITS)
|
||||
return Transform(value=value, units=Units)
|
||||
|
||||
|
||||
def block_def_to_speckle(blender_definition: bpy.types.Collection, scale=1.0) -> BlockDefinition:
|
||||
def block_def_to_speckle(blender_definition: bpy.types.Collection) -> BlockDefinition:
|
||||
geometry = []
|
||||
for geo in blender_definition.objects:
|
||||
geometry.extend(convert_to_speckle(geo, scale, UNITS, None))
|
||||
try:
|
||||
#TODO: right now, geometry will be a flat list of objects. Eventually we will want to preseve the parent relationship
|
||||
geometry.append(convert_to_speckle(geo, UnitsScale, Units, None))
|
||||
except ConversionSkippedException as ex:
|
||||
_report(f"Skipped converting '{geo.name_full}' inside collection instance: '{ex}")
|
||||
except Exception as ex:
|
||||
_report(f"Failed to converted '{geo.name_full}' inside collection instance: '{ex}'")
|
||||
|
||||
block_def = BlockDefinition(
|
||||
units=UNITS,
|
||||
name=blender_definition.name,
|
||||
units=Units,
|
||||
name=to_speckle_name(blender_definition),
|
||||
geometry=geometry,
|
||||
basePoint=Point(units=UNITS),
|
||||
basePoint=Point(units=Units),
|
||||
)
|
||||
blender_props = get_blender_custom_properties(blender_definition)
|
||||
block_def.applicationId = blender_props.pop("applicationId", None)
|
||||
# blender_props = get_blender_custom_properties(blender_definition)
|
||||
# block_def.applicationId = blender_props.pop("applicationId", None) #TODO: remove?
|
||||
return block_def
|
||||
|
||||
|
||||
def block_instance_to_speckle(blender_instance: Object, scale=1.0) -> BlockInstance:
|
||||
def block_instance_to_speckle(blender_instance: Object) -> BlockInstance:
|
||||
return BlockInstance(
|
||||
blockDefinition=block_def_to_speckle(
|
||||
blender_instance.instance_collection, scale
|
||||
blender_instance.instance_collection
|
||||
),
|
||||
transform=transform_to_speckle(blender_instance.matrix_world),
|
||||
name=blender_instance.name,
|
||||
units=UNITS,
|
||||
name=to_speckle_name(blender_instance),
|
||||
units=Units,
|
||||
)
|
||||
|
||||
|
||||
def empty_to_speckle(blender_object: Object, scale=1.0) -> Optional[BlockInstance]:
|
||||
def empty_to_speckle(blender_object: Object) -> Union[BlockInstance, Base]:
|
||||
# probably an instance collection (block) so let's try it
|
||||
try:
|
||||
geo = blender_object.instance_collection.objects.items()
|
||||
return block_instance_to_speckle(blender_object, scale)
|
||||
except AttributeError as err:
|
||||
_report(
|
||||
f"No instance collection found in empty. Skipping object {blender_object.name}"
|
||||
)
|
||||
return None
|
||||
|
||||
if blender_object.instance_collection and blender_object.instance_type == "COLLECTION":
|
||||
return block_instance_to_speckle(blender_object)
|
||||
else:
|
||||
#raise ConversionSkippedException("Sending non-collection instance empties are not currently supported")
|
||||
wrapper = Base()
|
||||
wrapper["@displayValue"] = matrix_to_speckle_point(cast(MMatrix, blender_object.matrix_world))
|
||||
return wrapper
|
||||
#TODO: we could do a Empty -> Point conversion here. However, the viewer (and likly other apps) don't support a pont with "elements"
|
||||
#return matrix_to_speckle_point(cast(MMatrix, blender_object.matrix_world))
|
||||
|
||||
|
||||
def matrix_to_speckle_point(matrix: MMatrix, units_scale: float = 1.0) -> Point:
|
||||
transformed_pos = cast(MVector, matrix @ MVector((0,0,0)) * units_scale)
|
||||
return Point(x = transformed_pos.x,
|
||||
y = transformed_pos.y,
|
||||
z = transformed_pos.z)
|
||||
+185
-67
@@ -1,13 +1,13 @@
|
||||
import math
|
||||
from typing import Tuple
|
||||
from typing import Any, Optional, Tuple
|
||||
from bmesh.types import BMesh
|
||||
import bpy, struct, idprop
|
||||
|
||||
from specklepy.objects.base import Base
|
||||
from specklepy.objects.geometry import Mesh
|
||||
from specklepy.serialization.base_object_serializer import BaseObjectSerializer
|
||||
from specklepy.objects.geometry import Circle, Mesh, Ellipse
|
||||
from specklepy.objects.other import RenderMaterial
|
||||
from bpy_speckle.functions import _report
|
||||
from bpy.types import Object
|
||||
from bpy.types import Material, Object
|
||||
|
||||
IGNORED_PROPERTY_KEYS = {
|
||||
"id",
|
||||
@@ -25,7 +25,7 @@ IGNORED_PROPERTY_KEYS = {
|
||||
}
|
||||
|
||||
|
||||
def to_rgba(argb_int: int) -> Tuple[float]:
|
||||
def to_rgba(argb_int: int) -> Tuple[float, float, float, float]:
|
||||
"""Converts the int representation of a colour into a percent RGBA tuple"""
|
||||
alpha = ((argb_int >> 24) & 255) / 255
|
||||
red = ((argb_int >> 16) & 255) / 255
|
||||
@@ -35,18 +35,27 @@ def to_rgba(argb_int: int) -> Tuple[float]:
|
||||
return (red, green, blue, alpha)
|
||||
|
||||
|
||||
def to_argb_int(diffuse_colour) -> int:
|
||||
def to_argb_int(rgba_color: list[float]) -> int:
|
||||
"""Converts an RGBA array to an ARGB integer"""
|
||||
diffuse_colour = diffuse_colour[-1:] + diffuse_colour[:3]
|
||||
diffuse_colour = [int(val * 255) for val in diffuse_colour]
|
||||
argb_color = rgba_color[-1:] + rgba_color[:3]
|
||||
int_color = [int(val * 255) for val in argb_color]
|
||||
|
||||
return int.from_bytes(diffuse_colour, byteorder="big", signed=True)
|
||||
return int.from_bytes(int_color, byteorder="big", signed=True)
|
||||
|
||||
def set_custom_property(key: str, value: Any, blender_object: Object) -> None:
|
||||
try:
|
||||
#Expected c types: float, int, string, float[], int[]
|
||||
blender_object[key] = value
|
||||
except (OverflowError, TypeError) as ex:
|
||||
print(f"Skipping setting property ({key}={value}) on {blender_object.name_full}, Reason: {ex}")
|
||||
except Exception as ex:
|
||||
#TODO: Log this as it's unexpected!!!
|
||||
print(f"Skipping setting property ({key}={value}) on {blender_object.name_full}, Reason: {ex}")
|
||||
|
||||
def add_custom_properties(speckle_object: Base, blender_object: Object):
|
||||
if blender_object is None:
|
||||
return
|
||||
|
||||
serializer = BaseObjectSerializer()
|
||||
blender_object["_speckle_type"] = type(speckle_object).__name__
|
||||
|
||||
app_id = getattr(speckle_object, "applicationId", None)
|
||||
@@ -59,39 +68,28 @@ def add_custom_properties(speckle_object: Base, blender_object: Object):
|
||||
continue
|
||||
|
||||
if isinstance(val, (int, str, float)):
|
||||
blender_object[key] = val
|
||||
set_custom_property(key, val, blender_object)
|
||||
elif key == "properties" and isinstance(val, Base):
|
||||
val["applicationId"] = None
|
||||
add_custom_properties(val, blender_object)
|
||||
elif isinstance(val, list):
|
||||
items = [item for item in val if not isinstance(item, Base)]
|
||||
if items:
|
||||
blender_object[key] = items
|
||||
set_custom_property(key, items, blender_object)
|
||||
elif isinstance(val,dict):
|
||||
for (k,v) in val.items():
|
||||
if not isinstance(v, Base):
|
||||
blender_object[k] = v
|
||||
set_custom_property(k, v, blender_object)
|
||||
|
||||
|
||||
def add_blender_material(speckle_object: Base, blender_object: Object) -> None:
|
||||
"""Add material to a blender object if the corresponding speckle object has a render material"""
|
||||
if blender_object.data is None:
|
||||
return
|
||||
|
||||
speckle_mat = getattr(
|
||||
speckle_object,
|
||||
"renderMaterial",
|
||||
getattr(speckle_object, "@renderMaterial", None),
|
||||
)
|
||||
if not speckle_mat:
|
||||
return
|
||||
|
||||
mat_name = getattr(speckle_mat, "name", None) or speckle_mat.__dict__.get("@name")
|
||||
def render_material_to_native(speckle_mat: RenderMaterial) -> Material:
|
||||
|
||||
mat_name = speckle_mat.name
|
||||
if not mat_name:
|
||||
mat_name = speckle_mat.applicationId or speckle_mat.id or speckle_mat.get_id()
|
||||
|
||||
blender_mat = bpy.data.materials.get(mat_name)
|
||||
if not blender_mat:
|
||||
if blender_mat is None:
|
||||
blender_mat = bpy.data.materials.new(mat_name)
|
||||
|
||||
# for now, we're not updating these materials. as per tom's suggestion, we should have a toggle
|
||||
@@ -105,10 +103,24 @@ def add_blender_material(speckle_object: Base, blender_object: Object) -> None:
|
||||
inputs["Metallic"].default_value = speckle_mat.metalness
|
||||
inputs["Alpha"].default_value = speckle_mat.opacity
|
||||
|
||||
if speckle_mat.opacity < 1:
|
||||
if speckle_mat.opacity < 1.0:
|
||||
blender_mat.blend_method = "BLEND"
|
||||
|
||||
blender_object.data.materials.append(blender_mat)
|
||||
return blender_mat
|
||||
|
||||
def get_render_material(speckle_object: Base) -> Optional[RenderMaterial]:
|
||||
"""Trys to get a RenderMaterial on given speckle_object and convert it to a blender material"""
|
||||
|
||||
speckle_mat = getattr(
|
||||
speckle_object,
|
||||
"renderMaterial",
|
||||
getattr(speckle_object, "@renderMaterial", None),
|
||||
)
|
||||
if not isinstance(speckle_mat, RenderMaterial):
|
||||
return None
|
||||
|
||||
return speckle_mat
|
||||
|
||||
|
||||
|
||||
def add_vertices(speckle_mesh: Mesh, blender_mesh: BMesh, scale=1.0):
|
||||
@@ -124,12 +136,11 @@ def add_vertices(speckle_mesh: Mesh, blender_mesh: BMesh, scale=1.0):
|
||||
)
|
||||
)
|
||||
|
||||
blender_mesh.verts.ensure_lookup_table()
|
||||
|
||||
|
||||
def add_faces(speckle_mesh: Mesh, blender_mesh: BMesh, smooth=False):
|
||||
def add_faces(speckle_mesh: Mesh, blender_mesh: BMesh, indexOffset: int, materialIndex: int = 0, smooth:bool = True):
|
||||
sfaces = speckle_mesh.faces
|
||||
|
||||
|
||||
if sfaces and len(sfaces) > 0:
|
||||
i = 0
|
||||
while i < len(sfaces):
|
||||
@@ -140,16 +151,14 @@ def add_faces(speckle_mesh: Mesh, blender_mesh: BMesh, smooth=False):
|
||||
i += 1
|
||||
try:
|
||||
f = blender_mesh.faces.new(
|
||||
[blender_mesh.verts[int(x)] for x in sfaces[i : i + n]]
|
||||
[blender_mesh.verts[x + indexOffset] for x in sfaces[i : i + n]]
|
||||
)
|
||||
f.material_index = materialIndex
|
||||
f.smooth = smooth
|
||||
except Exception as e:
|
||||
_report(f"Failed to create face for mesh {speckle_mesh.id} \n{e}")
|
||||
i += n
|
||||
|
||||
blender_mesh.faces.ensure_lookup_table()
|
||||
blender_mesh.verts.index_update()
|
||||
|
||||
|
||||
def add_colors(speckle_mesh: Mesh, blender_mesh: BMesh):
|
||||
|
||||
@@ -196,7 +205,7 @@ def add_uv_coords(speckle_mesh: Mesh, blender_mesh: BMesh):
|
||||
)
|
||||
else:
|
||||
_report(
|
||||
f"Failed to match UV coordinates to vert data. Blender mesh verts: {len(blender_mesh.verts)}, Speckle UVs * 2: {len(s_uvs) * 2}"
|
||||
f"Failed to match UV coordinates to vert data. Blender mesh verts: {len(blender_mesh.verts)}, Speckle UVs: {len(s_uvs) // 2}"
|
||||
)
|
||||
return
|
||||
|
||||
@@ -226,7 +235,7 @@ ignored_keys = {
|
||||
"_chunkable",
|
||||
}
|
||||
|
||||
def get_blender_custom_properties(obj, max_depth=1000):
|
||||
def get_blender_custom_properties(obj, max_depth: int = 200):
|
||||
if max_depth < 0:
|
||||
return obj
|
||||
|
||||
@@ -243,41 +252,37 @@ def get_blender_custom_properties(obj, max_depth=1000):
|
||||
|
||||
return obj
|
||||
|
||||
|
||||
"""
|
||||
Python implementation of Blender's NURBS curve generation for to Speckle conversion
|
||||
from: https://blender.stackexchange.com/a/34276
|
||||
based on https://projects.blender.org/blender/blender/src/branch/main/source/blender/blenkernel/intern/curve.cc (check old version)
|
||||
"""
|
||||
|
||||
|
||||
def macro_knotsu(nu):
|
||||
def macro_knotsu(nu: bpy.types.Spline) -> int:
|
||||
return nu.order_u + nu.point_count_u + (nu.order_u - 1 if nu.use_cyclic_u else 0)
|
||||
|
||||
|
||||
def macro_segmentsu(nu):
|
||||
def macro_segmentsu(nu: bpy.types.Spline) -> int:
|
||||
return nu.point_count_u if nu.use_cyclic_u else nu.point_count_u - 1
|
||||
|
||||
|
||||
def make_knots(nu):
|
||||
knots = [0.0] * (4 + macro_knotsu(nu))
|
||||
def make_knots(nu: bpy.types.Spline) -> list[float]:
|
||||
knots = [0.0] * macro_knotsu(nu)
|
||||
flag = nu.use_endpoint_u + (nu.use_bezier_u << 1)
|
||||
if nu.use_cyclic_u:
|
||||
calc_knots(knots, nu.point_count_u, nu.order_u, 0)
|
||||
makecyclicknots(knots, nu.point_count_u, nu.order_u)
|
||||
else:
|
||||
calc_knots(knots, nu.point_count_u, nu.order_u, flag)
|
||||
return knots
|
||||
|
||||
|
||||
def calc_knots(knots, point_count, order, flag):
|
||||
def calc_knots(knots: list[float], point_count: int, order: int, flag: int) -> None:
|
||||
pts_order = point_count + order
|
||||
if flag == 1:
|
||||
if flag == 1: # CU_NURB_ENDPOINT
|
||||
k = 0.0
|
||||
for a in range(1, pts_order + 1):
|
||||
knots[a - 1] = k
|
||||
if a >= order and a <= point_count:
|
||||
k += 1.0
|
||||
elif flag == 2:
|
||||
elif flag == 2: # CU_NURB_BEZIER
|
||||
if order == 4:
|
||||
k = 0.34
|
||||
for a in range(pts_order):
|
||||
@@ -290,24 +295,137 @@ def calc_knots(knots, point_count, order, flag):
|
||||
k += 0.5
|
||||
knots[a] = math.floor(k)
|
||||
else:
|
||||
for a in range(pts_order):
|
||||
knots[a] = a
|
||||
for a in range(1, len(knots) - 1):
|
||||
knots[a] = a - 1
|
||||
|
||||
knots[-1] = knots[-2]
|
||||
|
||||
def makecyclicknots(knots, point_count, order):
|
||||
order2 = order - 1
|
||||
def basis_nurb(t: float, order: int, point_count: int, knots: list[float], basis: list[float], start: int, end: int) -> Tuple[int, int]:
|
||||
i1 = i2 = 0
|
||||
orderpluspnts = order + point_count
|
||||
opp2 = orderpluspnts - 1
|
||||
|
||||
if order > 2:
|
||||
b = point_count + order2
|
||||
for a in range(1, order2):
|
||||
if knots[b] != knots[b - a]:
|
||||
break
|
||||
# this is for float inaccuracy
|
||||
if t < knots[0]:
|
||||
t = knots[0]
|
||||
elif t > knots[opp2]:
|
||||
t = knots[opp2]
|
||||
|
||||
if a == order2:
|
||||
knots[point_count + order - 2] += 1.0
|
||||
# this part is order '1'
|
||||
o2 = order + 1
|
||||
for i in range(opp2):
|
||||
if knots[i] != knots[i + 1] and t >= knots[i] and t <= knots[i + 1]:
|
||||
basis[i] = 1.0
|
||||
i1 = i - o2
|
||||
if i1 < 0:
|
||||
i1 = 0
|
||||
i2 = i
|
||||
i += 1
|
||||
while i < opp2:
|
||||
basis[i] = 0.0
|
||||
i += 1
|
||||
break
|
||||
|
||||
b = order
|
||||
c = point_count + order + order2
|
||||
for a in range(point_count + order2, c):
|
||||
knots[a] = knots[a - 1] + (knots[b] - knots[b - 1])
|
||||
b -= 1
|
||||
else:
|
||||
basis[i] = 0.0
|
||||
|
||||
basis[i] = 0.0
|
||||
|
||||
# this is order 2, 3, ...
|
||||
for j in range(2, order + 1):
|
||||
|
||||
if i2 + j >= orderpluspnts:
|
||||
i2 = opp2 - j
|
||||
|
||||
for i in range(i1, i2 + 1):
|
||||
if basis[i] != 0.0:
|
||||
d = ((t - knots[i]) * basis[i]) / (knots[i + j - 1] - knots[i])
|
||||
else:
|
||||
d = 0.0
|
||||
|
||||
if basis[i + 1] != 0.0:
|
||||
e = ((knots[i + j] - t) * basis[i + 1]) / (knots[i + j] - knots[i + 1])
|
||||
else:
|
||||
e = 0.0
|
||||
|
||||
basis[i] = d + e
|
||||
|
||||
start = 1000
|
||||
end = 0
|
||||
|
||||
for i in range(i1, i2 + 1):
|
||||
if basis[i] > 0.0:
|
||||
end = i
|
||||
if start == 1000:
|
||||
start = i
|
||||
|
||||
return start, end
|
||||
|
||||
def nurb_make_curve(nu: bpy.types.Spline, resolu: int, stride: int = 3) -> list[float]:
|
||||
""""BKE_nurb_makeCurve"""
|
||||
EPS = 1e-6
|
||||
coord_index = istart = iend = 0
|
||||
|
||||
coord_array = [0.0] * (3 * nu.resolution_u * macro_segmentsu(nu))
|
||||
sum_array = [0] * nu.point_count_u
|
||||
basisu = [0.0] * macro_knotsu(nu)
|
||||
knots = make_knots(nu)
|
||||
|
||||
resolu = resolu * macro_segmentsu(nu)
|
||||
ustart = knots[nu.order_u - 1]
|
||||
uend = knots[nu.point_count_u + nu.order_u - 1] if nu.use_cyclic_u else \
|
||||
knots[nu.point_count_u]
|
||||
ustep = (uend - ustart) / (resolu - (0 if nu.use_cyclic_u else 1))
|
||||
cycl = nu.order_u - 1 if nu.use_cyclic_u else 0
|
||||
|
||||
u = ustart
|
||||
while resolu:
|
||||
resolu -= 1
|
||||
istart, iend = basis_nurb(u, nu.order_u, nu.point_count_u + cycl, knots, basisu, istart, iend)
|
||||
|
||||
#/* calc sum */
|
||||
sumdiv = 0.0
|
||||
sum_index = 0
|
||||
pt_index = istart - 1
|
||||
for i in range(istart, iend + 1):
|
||||
if i >= nu.point_count_u:
|
||||
pt_index = i - nu.point_count_u
|
||||
else:
|
||||
pt_index += 1
|
||||
|
||||
sum_array[sum_index] = basisu[i] * nu.points[pt_index].co[3]
|
||||
sumdiv += sum_array[sum_index]
|
||||
sum_index += 1
|
||||
|
||||
if (sumdiv != 0.0) and (sumdiv < 1.0 - EPS or sumdiv > 1.0 + EPS):
|
||||
sum_index = 0
|
||||
for i in range(istart, iend + 1):
|
||||
sum_array[sum_index] /= sumdiv
|
||||
sum_index += 1
|
||||
|
||||
coord_array[coord_index: coord_index + 3] = (0.0, 0.0, 0.0)
|
||||
|
||||
sum_index = 0
|
||||
pt_index = istart - 1
|
||||
for i in range(istart, iend + 1):
|
||||
if i >= nu.point_count_u:
|
||||
pt_index = i - nu.point_count_u
|
||||
else:
|
||||
pt_index += 1
|
||||
|
||||
if sum_array[sum_index] != 0.0:
|
||||
for j in range(3):
|
||||
coord_array[coord_index + j] += sum_array[sum_index] * nu.points[pt_index].co[j]
|
||||
sum_index += 1
|
||||
|
||||
coord_index += stride
|
||||
u += ustep
|
||||
|
||||
return coord_array
|
||||
|
||||
def link_object_to_collection_nested(obj: bpy.types.Object, col: bpy.types.Collection):
|
||||
if obj.name not in col.objects:
|
||||
col.objects.link(obj)
|
||||
|
||||
for child in obj.children:
|
||||
link_object_to_collection_nested(child, col)
|
||||
+27
-18
@@ -1,4 +1,10 @@
|
||||
from bpy_speckle.clients import speckle_clients
|
||||
from typing import Callable, Set
|
||||
|
||||
import bpy
|
||||
from specklepy.objects.base import Base
|
||||
from bpy_speckle.properties.scene import SpeckleSceneSettings
|
||||
|
||||
from bpy_speckle.specklepy_extras.traversal import GraphTraversal, TraversalRule
|
||||
|
||||
"""
|
||||
Speckle functions
|
||||
@@ -44,29 +50,32 @@ def get_scale_length(units: str) -> float:
|
||||
Client, user, and stream functions
|
||||
"""
|
||||
|
||||
elements_aliases: Set[str] = {"elements", "@elements"}
|
||||
ignore_props: Set[str] = {"@blockDefinition", "displayValue", "@displayValue", "units", "id", "applicationId"}
|
||||
|
||||
def _check_speckle_client_user_stream(scene):
|
||||
def get_default_traversal_func(can_convert_to_native: Callable[[Base], bool]) -> GraphTraversal:
|
||||
"""
|
||||
Verify that there is a valid user and stream
|
||||
Traversal func for traversing a speckle commit object
|
||||
"""
|
||||
speckle = scene.speckle
|
||||
|
||||
user = (
|
||||
speckle.users[int(speckle.active_user)]
|
||||
if len(speckle.users) > int(speckle.active_user)
|
||||
else None
|
||||
convertable_rule = TraversalRule(
|
||||
[can_convert_to_native],
|
||||
lambda _: [i for i in elements_aliases if i not in ignore_props],
|
||||
)
|
||||
|
||||
if user is None:
|
||||
print("No users loaded.")
|
||||
|
||||
stream = (
|
||||
user.streams[user.active_stream]
|
||||
if len(user.streams) > user.active_stream
|
||||
else None
|
||||
ignore_result_rule = TraversalRule(
|
||||
[lambda o: "Objects.Structural.Results" in o.speckle_type, #Sadly, this one is nessasary to avoid double conversion...
|
||||
lambda o: "Objects.BuiltElements.Revit.Parameter" in o.speckle_type], #This one is just for traversal performance of revit commits
|
||||
lambda _: [],
|
||||
)
|
||||
|
||||
if stream is None:
|
||||
print("Account contains no streams.")
|
||||
default_rule = TraversalRule(
|
||||
[lambda _: True],
|
||||
lambda o: o.get_member_names(), #TODO: avoid deprecated members
|
||||
)
|
||||
|
||||
return (user, stream)
|
||||
return GraphTraversal([convertable_rule, ignore_result_rule, default_rule])
|
||||
|
||||
|
||||
def get_speckle(context: bpy.types.Context) -> 'SpeckleSceneSettings':
|
||||
return context.scene.speckle #type: ignore
|
||||
+114
-35
@@ -1,29 +1,118 @@
|
||||
"""
|
||||
Provides uniform and consistent path helpers for `specklepy`
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
from importlib import import_module, invalidate_caches
|
||||
|
||||
import bpy
|
||||
import sys
|
||||
_user_data_env_var = "SPECKLE_USERDATA_PATH"
|
||||
|
||||
print("Starting Speckle Blender installation")
|
||||
|
||||
def _path() -> Optional[Path]:
|
||||
"""Read the user data path override setting."""
|
||||
path_override = os.environ.get(_user_data_env_var)
|
||||
if path_override:
|
||||
return Path(path_override)
|
||||
return None
|
||||
|
||||
|
||||
_application_name = "Speckle"
|
||||
|
||||
|
||||
def override_application_name(application_name: str) -> None:
|
||||
"""Override the global Speckle application name."""
|
||||
global _application_name
|
||||
_application_name = application_name
|
||||
|
||||
|
||||
def override_application_data_path(path: Optional[str]) -> None:
|
||||
"""
|
||||
Override the global Speckle application data path.
|
||||
|
||||
If the value of path is `None` the environment variable gets deleted.
|
||||
"""
|
||||
if path:
|
||||
os.environ[_user_data_env_var] = path
|
||||
else:
|
||||
os.environ.pop(_user_data_env_var, None)
|
||||
|
||||
|
||||
def _ensure_folder_exists(base_path: Path, folder_name: str) -> Path:
|
||||
path = base_path.joinpath(folder_name)
|
||||
path.mkdir(exist_ok=True, parents=True)
|
||||
return path
|
||||
|
||||
|
||||
def user_application_data_path() -> Path:
|
||||
"""Get the platform specific user configuration folder path"""
|
||||
path_override = _path()
|
||||
if path_override:
|
||||
return path_override
|
||||
|
||||
try:
|
||||
if sys.platform.startswith("win"):
|
||||
app_data_path = os.getenv("APPDATA")
|
||||
if not app_data_path:
|
||||
raise Exception(
|
||||
"Cannot get appdata path from environment."
|
||||
)
|
||||
return Path(app_data_path)
|
||||
else:
|
||||
# try getting the standard XDG_DATA_HOME value
|
||||
# as that is used as an override
|
||||
app_data_path = os.getenv("XDG_DATA_HOME")
|
||||
if app_data_path:
|
||||
return Path(app_data_path)
|
||||
else:
|
||||
return _ensure_folder_exists(Path.home(), ".config")
|
||||
except Exception as ex:
|
||||
raise Exception(
|
||||
"Failed to initialize user application data path.", ex
|
||||
)
|
||||
|
||||
|
||||
def user_speckle_folder_path() -> Path:
|
||||
"""Get the folder where the user's Speckle data should be stored."""
|
||||
return _ensure_folder_exists(user_application_data_path(), _application_name)
|
||||
|
||||
|
||||
def user_speckle_connector_installation_path(host_application: str) -> Path:
|
||||
"""
|
||||
Gets a connector specific installation folder.
|
||||
|
||||
In this folder we can put our connector installation and all python packages.
|
||||
"""
|
||||
return _ensure_folder_exists(
|
||||
_ensure_folder_exists(user_speckle_folder_path(), "connector_installations"),
|
||||
host_application,
|
||||
)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
print("Starting module dependency installation")
|
||||
print(sys.executable)
|
||||
|
||||
PYTHON_PATH = sys.executable
|
||||
|
||||
|
||||
|
||||
def modules_path() -> Path:
|
||||
modules_path = Path(bpy.utils.script_path_user(), "addons", "modules")
|
||||
modules_path.mkdir(exist_ok=True, parents=True)
|
||||
def connector_installation_path(host_application: str) -> Path:
|
||||
connector_installation_path = user_speckle_connector_installation_path(host_application)
|
||||
connector_installation_path.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
# set user modules path at beginning of paths for earlier hit
|
||||
if sys.path[1] != modules_path:
|
||||
sys.path.insert(1, modules_path)
|
||||
if sys.path[0] != connector_installation_path:
|
||||
sys.path.insert(0, str(connector_installation_path))
|
||||
|
||||
return modules_path
|
||||
print(f"Using connector installation path {connector_installation_path}")
|
||||
return connector_installation_path
|
||||
|
||||
|
||||
print(f"Found blender modules path {modules_path()}")
|
||||
|
||||
|
||||
def is_pip_available() -> bool:
|
||||
try:
|
||||
@@ -34,7 +123,7 @@ def is_pip_available() -> bool:
|
||||
|
||||
|
||||
def ensure_pip() -> None:
|
||||
print("Installing pip... "),
|
||||
print("Installing pip... ")
|
||||
|
||||
from subprocess import run
|
||||
|
||||
@@ -43,7 +132,7 @@ def ensure_pip() -> None:
|
||||
if completed_process.returncode == 0:
|
||||
print("Successfully installed pip")
|
||||
else:
|
||||
raise Exception("Failed to install pip.")
|
||||
raise Exception(f"Failed to install pip, got {completed_process.returncode} return code")
|
||||
|
||||
|
||||
def get_requirements_path() -> Path:
|
||||
@@ -53,11 +142,11 @@ def get_requirements_path() -> Path:
|
||||
return path
|
||||
|
||||
|
||||
def install_requirements() -> None:
|
||||
def install_requirements(host_application: str) -> None:
|
||||
# set up addons/modules under the user
|
||||
# script path. Here we'll install the
|
||||
# dependencies
|
||||
path = modules_path()
|
||||
path = connector_installation_path(host_application)
|
||||
print(f"Installing Speckle dependencies to {path}")
|
||||
|
||||
from subprocess import run
|
||||
@@ -78,20 +167,16 @@ def install_requirements() -> None:
|
||||
)
|
||||
|
||||
if completed_process.returncode != 0:
|
||||
print("Please try manually installing speckle-blender")
|
||||
raise Exception(
|
||||
"""
|
||||
Failed to install speckle-blender.
|
||||
See console for manual install instruction.
|
||||
"""
|
||||
)
|
||||
m = f"Failed to install dependenices through pip, got {completed_process.returncode} return code"
|
||||
print(m)
|
||||
raise Exception(m)
|
||||
|
||||
|
||||
def install_dependencies() -> None:
|
||||
def install_dependencies(host_application: str) -> None:
|
||||
if not is_pip_available():
|
||||
ensure_pip()
|
||||
|
||||
install_requirements()
|
||||
install_requirements(host_application)
|
||||
|
||||
|
||||
def _import_dependencies() -> None:
|
||||
@@ -110,19 +195,13 @@ def _import_dependencies() -> None:
|
||||
# print(req)
|
||||
# import_module("specklepy")
|
||||
|
||||
|
||||
def ensure_dependencies() -> None:
|
||||
def ensure_dependencies(host_application: str) -> None:
|
||||
try:
|
||||
_import_dependencies()
|
||||
print("Found all dependencies, proceed with loading")
|
||||
except ImportError:
|
||||
print("Failed to load all dependencies, trying to install them...")
|
||||
install_dependencies()
|
||||
|
||||
install_dependencies(host_application)
|
||||
invalidate_caches()
|
||||
_import_dependencies()
|
||||
print("Successfully found dependencies")
|
||||
except ImportError:
|
||||
raise Exception(f"Cannot automatically ensure Speckle dependencies. Please try restarting the host application {host_application}!")
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
ensure_dependencies()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from .users import LoadUsers, LoadUserStreams
|
||||
from .users import LoadUsers, LoadUserStreams, ResetUsers
|
||||
from .object import (
|
||||
UpdateObject,
|
||||
ResetObject,
|
||||
@@ -27,6 +27,7 @@ from .misc import OpenSpeckleGuide, OpenSpeckleTutorials, OpenSpeckleForum
|
||||
|
||||
operator_classes = [
|
||||
LoadUsers,
|
||||
ResetUsers,
|
||||
ReceiveStreamObjects,
|
||||
SendStreamObjects,
|
||||
LoadUserStreams,
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
"""
|
||||
Commit operators
|
||||
"""
|
||||
from typing import cast
|
||||
import bpy
|
||||
from bpy.props import BoolProperty
|
||||
from bpy_speckle.functions import _check_speckle_client_user_stream
|
||||
from bpy_speckle.functions import _report, get_speckle
|
||||
from bpy_speckle.clients import speckle_clients
|
||||
from bpy_speckle.properties.scene import SpeckleSceneSettings
|
||||
|
||||
|
||||
class DeleteCommit(bpy.types.Operator):
|
||||
"""
|
||||
Delete stream
|
||||
Deletes the selected commit from the selected stream.
|
||||
To execute from code, call: `bpy.ops.speckle.delete_commit(are_you_sure=True)`
|
||||
"""
|
||||
|
||||
bl_idname = "speckle.delete_commit"
|
||||
@@ -28,36 +31,37 @@ class DeleteCommit(bpy.types.Operator):
|
||||
col.prop(self, "are_you_sure")
|
||||
|
||||
def invoke(self, context, event):
|
||||
speckle = get_speckle(context)
|
||||
wm = context.window_manager
|
||||
if len(context.scene.speckle.users) > 0:
|
||||
if len(speckle.users) > 0:
|
||||
return wm.invoke_props_dialog(self)
|
||||
|
||||
return {"CANCELLED"}
|
||||
|
||||
def execute(self, context):
|
||||
try:
|
||||
self.delete_commit(context)
|
||||
return {"FINISHED"}
|
||||
except Exception as ex:
|
||||
print(f"{self.bl_idname}: failed: {ex}")
|
||||
return {"CANCELLED"}
|
||||
|
||||
def delete_commit(self, context: bpy.types.Context) -> None:
|
||||
|
||||
if not self.are_you_sure:
|
||||
return {"CANCELLED"}
|
||||
raise Exception("Cancelled by user")
|
||||
|
||||
self.are_you_sure = False
|
||||
|
||||
speckle = context.scene.speckle
|
||||
speckle = get_speckle(context)
|
||||
|
||||
check = _check_speckle_client_user_stream(context.scene)
|
||||
if check is None:
|
||||
return {"CANCELLED"}
|
||||
(_, stream, _, commit) = speckle.validate_commit_selection()
|
||||
|
||||
user, stream = check
|
||||
client = speckle_clients[int(context.scene.speckle.active_user)]
|
||||
|
||||
stream = user.streams[user.active_stream]
|
||||
if len(stream.branches) < 1:
|
||||
return {"CANCELLED"}
|
||||
branch = stream.branches[int(stream.branch)]
|
||||
if len(branch.commits) < 1:
|
||||
return {"CANCELLED"}
|
||||
commit = branch.commits[int(branch.commit)]
|
||||
client = speckle_clients[int(speckle.active_user)]
|
||||
|
||||
deleted = client.commit.delete(stream_id=stream.id, commit_id=commit.id)
|
||||
if not deleted:
|
||||
raise Exception("Delete operation failed")
|
||||
|
||||
print(f"{self.bl_idname}: succeeded - commit {commit.id} ({commit.message}) has been deleted from stream {stream.id}")
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -4,6 +4,7 @@ Object operators
|
||||
|
||||
import bpy
|
||||
from bpy.props import BoolProperty, EnumProperty
|
||||
from deprecated import deprecated
|
||||
from bpy_speckle.convert.to_speckle import (
|
||||
convert_to_speckle,
|
||||
ngons_to_speckle_polylines,
|
||||
@@ -28,7 +29,6 @@ class UpdateObject(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
user = context.scene.speckle.users[int(context.scene.speckle.active_user)]
|
||||
client = speckle_clients[int(context.scene.speckle.active_user)]
|
||||
stream = user.streams[user.active_stream]
|
||||
|
||||
active = context.active_object
|
||||
_report(active)
|
||||
@@ -127,7 +127,7 @@ class DeleteObject(bpy.types.Operator):
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@deprecated
|
||||
class UploadNgonsAsPolylines(bpy.types.Operator):
|
||||
"""
|
||||
Upload mesh ngon faces as polyline outlines
|
||||
|
||||
+375
-302
File diff suppressed because it is too large
Load Diff
@@ -1,15 +1,39 @@
|
||||
"""
|
||||
User account operators
|
||||
"""
|
||||
from typing import cast
|
||||
import bpy
|
||||
from bpy_speckle.functions import _report
|
||||
from bpy.types import Context
|
||||
from bpy_speckle.functions import _report, get_speckle
|
||||
from bpy_speckle.clients import speckle_clients
|
||||
from bpy_speckle.properties.scene import SpeckleSceneSettings
|
||||
from bpy_speckle.properties.scene import SpeckleCommitObject, SpeckleSceneSettings, SpeckleUserObject
|
||||
from specklepy.api.client import SpeckleClient
|
||||
from specklepy.api.models import Stream, User
|
||||
from specklepy.api.models import Stream
|
||||
from specklepy.api.credentials import get_local_accounts
|
||||
from datetime import datetime
|
||||
|
||||
class ResetUsers(bpy.types.Operator):
|
||||
"""
|
||||
Reset loaded users
|
||||
"""
|
||||
|
||||
bl_idname = "speckle.users_reset"
|
||||
bl_label = "Reset users"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
self.reset_ui(context)
|
||||
|
||||
bpy.context.view_layer.update()
|
||||
if context.area:
|
||||
context.area.tag_redraw()
|
||||
return {"FINISHED"}
|
||||
|
||||
@staticmethod
|
||||
def reset_ui(context: Context):
|
||||
speckle = get_speckle(context)
|
||||
|
||||
speckle.users.clear()
|
||||
speckle_clients.clear()
|
||||
|
||||
class LoadUsers(bpy.types.Operator):
|
||||
"""
|
||||
@@ -24,11 +48,10 @@ class LoadUsers(bpy.types.Operator):
|
||||
|
||||
_report("Loading users...")
|
||||
|
||||
speckle : SpeckleSceneSettings = context.scene.speckle
|
||||
speckle = cast(SpeckleSceneSettings, context.scene.speckle) #type: ignore
|
||||
users = speckle.users
|
||||
|
||||
speckle.users.clear()
|
||||
speckle_clients.clear()
|
||||
ResetUsers.reset_ui(context)
|
||||
|
||||
profiles = get_local_accounts()
|
||||
active_user_index = 0
|
||||
@@ -37,16 +60,18 @@ class LoadUsers(bpy.types.Operator):
|
||||
user = users.add()
|
||||
user.server_name = profile.serverInfo.name or "Speckle Server"
|
||||
user.server_url = profile.serverInfo.url
|
||||
user.id = profile.userInfo.id
|
||||
user.name = profile.userInfo.name
|
||||
user.email = profile.userInfo.email
|
||||
user.company = profile.userInfo.company or ""
|
||||
user.authToken = profile.token
|
||||
try:
|
||||
url = profile.serverInfo.url
|
||||
assert(url)
|
||||
client = SpeckleClient(
|
||||
host=profile.serverInfo.url,
|
||||
use_ssl="https" in profile.serverInfo.url,
|
||||
host=url,
|
||||
use_ssl="https" in url,
|
||||
)
|
||||
client.authenticate(user.authToken)
|
||||
client.authenticate_with_account(profile)
|
||||
speckle_clients.append(client)
|
||||
except Exception as ex:
|
||||
_report(ex)
|
||||
@@ -54,7 +79,6 @@ class LoadUsers(bpy.types.Operator):
|
||||
if profile.isDefault:
|
||||
active_user_index = len(users) - 1
|
||||
|
||||
speckle.active_user_index = int(speckle.active_user) #TODO: what is this?
|
||||
speckle.active_user = str(active_user_index)
|
||||
bpy.context.view_layer.update()
|
||||
|
||||
@@ -63,7 +87,7 @@ class LoadUsers(bpy.types.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
def add_user_stream(user: User, stream: Stream):
|
||||
def add_user_stream(user: SpeckleUserObject, stream: Stream):
|
||||
s = user.streams.add()
|
||||
s.name = stream.name
|
||||
s.id = stream.id
|
||||
@@ -81,16 +105,17 @@ def add_user_stream(user: User, stream: Stream):
|
||||
continue
|
||||
|
||||
for c in b.commits.items:
|
||||
commit = branch.commits.add()
|
||||
commit: SpeckleCommitObject = branch.commits.add()
|
||||
commit.id = commit.name = c.id
|
||||
commit.message = c.message or ""
|
||||
commit.author_name = c.authorName
|
||||
commit.author_id = c.authorId
|
||||
commit.created_at = datetime.strftime(c.createdAt, "%Y-%m-%d %H:%M:%S.%f%Z")
|
||||
commit.created_at = c.createdAt.strftime("%Y-%m-%d %H:%M:%S.%f%Z") if c.createdAt else ""
|
||||
commit.source_application = str(c.sourceApplication)
|
||||
commit.referenced_object = c.referencedObject
|
||||
|
||||
if hasattr(s, "baseProperties"):
|
||||
s.units = stream.baseProperties.units
|
||||
s.units = stream.baseProperties.units # type: ignore
|
||||
else:
|
||||
s.units = "Meters"
|
||||
|
||||
@@ -106,33 +131,40 @@ class LoadUserStreams(bpy.types.Operator):
|
||||
bl_description = "(Re)load all available user streams"
|
||||
|
||||
def execute(self, context):
|
||||
speckle = context.scene.speckle
|
||||
|
||||
if len(speckle.users) > 0:
|
||||
user = speckle.users[int(context.scene.speckle.active_user)]
|
||||
client = speckle_clients[int(context.scene.speckle.active_user)]
|
||||
|
||||
try:
|
||||
streams = client.stream.list(stream_limit=20)
|
||||
except Exception as e:
|
||||
_report(f"Failed to retrieve streams: {e}")
|
||||
return
|
||||
if not streams:
|
||||
_report("Failed to retrieve streams.")
|
||||
return
|
||||
|
||||
user.streams.clear()
|
||||
|
||||
default_units = "Meters"
|
||||
|
||||
for s in streams:
|
||||
sstream = client.stream.get(id=s.id, branch_limit=20)
|
||||
add_user_stream(user, sstream)
|
||||
|
||||
bpy.context.view_layer.update()
|
||||
|
||||
try:
|
||||
self.add_stream_from_url(context)
|
||||
return {"FINISHED"}
|
||||
except Exception as ex:
|
||||
_report(f"{self.bl_idname} failed: {ex}")
|
||||
return {"CANCELLED"}
|
||||
|
||||
def add_stream_from_url(self, context: Context) -> None:
|
||||
speckle = get_speckle(context)
|
||||
|
||||
user = speckle.validate_user_selection()
|
||||
|
||||
client = speckle_clients[int(speckle.active_user)]
|
||||
|
||||
try:
|
||||
streams = client.stream.list(stream_limit=20)
|
||||
except Exception as e:
|
||||
_report(f"Failed to retrieve streams: {e}")
|
||||
return
|
||||
if not streams:
|
||||
_report("Failed to retrieve streams.")
|
||||
return
|
||||
|
||||
user.streams.clear()
|
||||
|
||||
default_units = "Meters"
|
||||
|
||||
for s in streams:
|
||||
assert(s.id)
|
||||
sstream = client.stream.get(id=s.id, branch_limit=20)
|
||||
add_user_stream(user, sstream)
|
||||
|
||||
bpy.context.view_layer.update()
|
||||
|
||||
if context.area:
|
||||
context.area.tag_redraw()
|
||||
return {"CANCELLED"}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""
|
||||
Scene properties
|
||||
"""
|
||||
from typing import Optional, Tuple
|
||||
import bpy
|
||||
from bpy.props import (
|
||||
StringProperty,
|
||||
@@ -18,12 +19,13 @@ class SpeckleSceneObject(bpy.types.PropertyGroup):
|
||||
|
||||
|
||||
class SpeckleCommitObject(bpy.types.PropertyGroup):
|
||||
id: StringProperty(default="abc")
|
||||
message: StringProperty(default="A simple commit")
|
||||
author_name: StringProperty(default="Author name")
|
||||
author_id: StringProperty(default="Author ID")
|
||||
created_at: StringProperty(default="Today")
|
||||
source_application: StringProperty(default="Unknown")
|
||||
id: StringProperty(default="")
|
||||
message: StringProperty(default="")
|
||||
author_name: StringProperty(default="")
|
||||
author_id: StringProperty(default="")
|
||||
created_at: StringProperty(default="")
|
||||
source_application: StringProperty(default="")
|
||||
referenced_object: StringProperty(default="")
|
||||
|
||||
|
||||
class SpeckleBranchObject(bpy.types.PropertyGroup):
|
||||
@@ -42,6 +44,12 @@ class SpeckleBranchObject(bpy.types.PropertyGroup):
|
||||
description="Active commit",
|
||||
items=get_commits,
|
||||
)
|
||||
|
||||
def get_active_commit(self) -> Optional[SpeckleCommitObject]:
|
||||
selected_index = int(self.commit)
|
||||
if 0 <= selected_index < len(self.commits):
|
||||
return self.commits[selected_index]
|
||||
return None
|
||||
|
||||
|
||||
class SpeckleStreamObject(bpy.types.PropertyGroup):
|
||||
@@ -66,17 +74,28 @@ class SpeckleStreamObject(bpy.types.PropertyGroup):
|
||||
items=get_branches,
|
||||
)
|
||||
|
||||
def get_active_branch(self) -> Optional[SpeckleBranchObject]:
|
||||
selected_index = int(self.branch)
|
||||
if 0 <= selected_index < len(self.branches):
|
||||
return self.branches[selected_index]
|
||||
return None
|
||||
|
||||
|
||||
class SpeckleUserObject(bpy.types.PropertyGroup):
|
||||
server_name: StringProperty(default="SpeckleXYZ")
|
||||
server_url: StringProperty(default="https://speckle.xyz")
|
||||
id: StringProperty(default="")
|
||||
name: StringProperty(default="Speckle User")
|
||||
email: StringProperty(default="user@speckle.xyz")
|
||||
company: StringProperty(default="SpeckleSystems")
|
||||
authToken: StringProperty(default="", subtype='PASSWORD')
|
||||
streams: CollectionProperty(type=SpeckleStreamObject)
|
||||
active_stream: IntProperty(default=0)
|
||||
|
||||
def get_active_stream(self) -> Optional[SpeckleStreamObject]:
|
||||
selected_index = int(self.active_stream)
|
||||
if 0 <= selected_index < len(self.streams):
|
||||
return self.streams[selected_index]
|
||||
return None
|
||||
|
||||
class SpeckleSceneSettings(bpy.types.PropertyGroup):
|
||||
def get_scripts(self, context):
|
||||
@@ -104,8 +123,8 @@ class SpeckleSceneSettings(bpy.types.PropertyGroup):
|
||||
|
||||
active_user: EnumProperty(
|
||||
items=get_users,
|
||||
name="User",
|
||||
description="Select user",
|
||||
name="Account",
|
||||
description="Select account",
|
||||
update=set_user,
|
||||
get=None,
|
||||
set=None,
|
||||
@@ -132,3 +151,44 @@ class SpeckleSceneSettings(bpy.types.PropertyGroup):
|
||||
description="Script to run when sending stream objects.",
|
||||
items=get_scripts,
|
||||
)
|
||||
|
||||
def get_active_user(self) -> Optional[SpeckleUserObject]:
|
||||
selected_index = int(self.active_user)
|
||||
if 0 <= selected_index < len(self.users):
|
||||
return self.users[selected_index]
|
||||
return None
|
||||
|
||||
|
||||
def validate_user_selection(self) -> SpeckleUserObject:
|
||||
user = self.get_active_user()
|
||||
if not user:
|
||||
raise SelectionException("No user selected/found")
|
||||
return user
|
||||
|
||||
def validate_stream_selection(self) -> Tuple[SpeckleUserObject, SpeckleStreamObject]:
|
||||
user = self.validate_user_selection()
|
||||
|
||||
stream = user.get_active_stream()
|
||||
if not stream:
|
||||
raise SelectionException("No stream selected/found")
|
||||
|
||||
return (user, stream)
|
||||
|
||||
def validate_branch_selection(self) -> Tuple[SpeckleUserObject, SpeckleStreamObject, SpeckleBranchObject]:
|
||||
(user, stream) = self.validate_stream_selection()
|
||||
|
||||
branch = stream.get_active_branch()
|
||||
if not branch:
|
||||
raise SelectionException("No branch selected/found")
|
||||
return (user, stream, branch)
|
||||
|
||||
def validate_commit_selection(self) ->Tuple[SpeckleUserObject, SpeckleStreamObject, SpeckleBranchObject, SpeckleCommitObject]:
|
||||
(user, stream, branch) = self.validate_branch_selection()
|
||||
commit = branch.get_active_commit()
|
||||
if commit is None:
|
||||
raise SelectionException("No commit selected/found")
|
||||
|
||||
return (user, stream, branch, commit)
|
||||
|
||||
class SelectionException(Exception):
|
||||
pass
|
||||
@@ -0,0 +1,83 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Collection, Dict, Generic, Iterable, List, Optional, Tuple, TypeVar
|
||||
from attrs import define
|
||||
from specklepy.objects.base import Base
|
||||
|
||||
ROOT: str = "__Root"
|
||||
|
||||
T = TypeVar('T')
|
||||
PARENT_INFO = Tuple[Optional[str], str]
|
||||
|
||||
@define(slots=True)
|
||||
class CommitObjectBuilder(ABC, Generic[T]):
|
||||
|
||||
converted: Dict[str, Base]
|
||||
_parent_infos: Dict[str, Collection[PARENT_INFO]]
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.converted = {}
|
||||
self._parent_infos = {}
|
||||
|
||||
@abstractmethod
|
||||
def include_object(self, conversion_result: Base, native_object: T) -> None:
|
||||
pass
|
||||
|
||||
def build_commit_object(self, root_commit_object: Base) -> None:
|
||||
self.apply_relationships(self.converted.values(), root_commit_object)
|
||||
|
||||
def set_relationship(self, app_id: Optional[str], *parent_info : PARENT_INFO) -> None:
|
||||
|
||||
if not app_id:
|
||||
return
|
||||
|
||||
self._parent_infos[app_id] = parent_info
|
||||
|
||||
def apply_relationships(self, to_add: Iterable[Base], root_commit_object: Base) -> None:
|
||||
for c in to_add:
|
||||
try:
|
||||
self.apply_relationship(c, root_commit_object)
|
||||
except Exception as ex:
|
||||
print(f"Failed to add object {type(c)} to commit object: {ex}")
|
||||
|
||||
def apply_relationship(self, current: Base, root_commit_object: Base):
|
||||
if not current.applicationId: raise Exception(f"Expected applicationId to have been set")
|
||||
|
||||
parents = self._parent_infos[current.applicationId]
|
||||
|
||||
for (parent_id, prop_name) in parents:
|
||||
if not parent_id: continue
|
||||
|
||||
parent: Optional[Base]
|
||||
if parent_id == ROOT:
|
||||
parent = root_commit_object
|
||||
else:
|
||||
parent = self.converted[parent_id] if parent_id in self.converted else None
|
||||
|
||||
if not parent: continue
|
||||
|
||||
try:
|
||||
elements = get_detached_prop(parent, prop_name)
|
||||
if not isinstance(elements, list):
|
||||
elements = []
|
||||
set_detached_prop(parent, prop_name, elements)
|
||||
|
||||
elements.append(current)
|
||||
return
|
||||
except Exception as ex:
|
||||
# A parent was found, but it was invalid (Likely because of a type mismatch on a `elements` property)
|
||||
print(f"Failed to add object {type(current)} to a converted parent; {ex}")
|
||||
|
||||
raise Exception(f"Could not find a valid parent for object of type {type(current)}. Checked {len(parents)} potential parent, and non were converted!")
|
||||
|
||||
|
||||
def get_detached_prop(speckle_object: Base, prop_name: str) -> Optional[Any]:
|
||||
detached_prop_name = get_detached_prop_name(speckle_object, prop_name)
|
||||
return getattr(speckle_object, detached_prop_name, None)
|
||||
|
||||
def set_detached_prop(speckle_object: Base, prop_name: str, value: Optional[Any]) -> None:
|
||||
detached_prop_name = get_detached_prop_name(speckle_object, prop_name)
|
||||
setattr(speckle_object, detached_prop_name, value)
|
||||
|
||||
def get_detached_prop_name(speckle_object: Base, prop_name: str) -> str:
|
||||
return prop_name if hasattr(speckle_object, prop_name) else f"@{prop_name}"
|
||||
@@ -0,0 +1,121 @@
|
||||
from typing import Any, Callable, Collection, Iterable, Iterator, List, Optional, Set
|
||||
|
||||
from attrs import define
|
||||
from typing_extensions import Protocol, final
|
||||
|
||||
from specklepy.objects import Base
|
||||
|
||||
|
||||
class ITraversalRule(Protocol):
|
||||
def get_members_to_traverse(self, o: Base) -> Set[str]:
|
||||
"""Get the members to traverse."""
|
||||
pass
|
||||
|
||||
def does_rule_hold(self, o: Base) -> bool:
|
||||
"""Make sure the rule still holds."""
|
||||
pass
|
||||
|
||||
|
||||
@final
|
||||
class DefaultRule:
|
||||
def get_members_to_traverse(self, _) -> Set[str]:
|
||||
return set()
|
||||
|
||||
def does_rule_hold(self, _) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
# we're creating a local protected "singleton"
|
||||
_default_rule = DefaultRule()
|
||||
|
||||
|
||||
@final
|
||||
@define(slots=True, frozen=True)
|
||||
class TraversalContext:
|
||||
current: Base
|
||||
member_name: Optional[str] = None
|
||||
parent: Optional["TraversalContext"] = None
|
||||
|
||||
|
||||
@final
|
||||
@define(slots=True, frozen=True)
|
||||
class GraphTraversal:
|
||||
|
||||
_rules: List[ITraversalRule]
|
||||
|
||||
def traverse(self, root: Base) -> Iterator[TraversalContext]:
|
||||
stack: List[TraversalContext] = []
|
||||
|
||||
stack.append(TraversalContext(root))
|
||||
|
||||
while len(stack) > 0:
|
||||
head = stack.pop()
|
||||
yield head
|
||||
|
||||
current = head.current
|
||||
active_rule = self._get_active_rule_or_default_rule(current)
|
||||
members_to_traverse = active_rule.get_members_to_traverse(current)
|
||||
for child_prop in members_to_traverse:
|
||||
try:
|
||||
if child_prop in {"speckle_type", "units", "applicationId"}: continue #debug: to avoid noisy exceptions, explicitly avoid checking ones we know will fail, this is not exhaustive
|
||||
value = current[child_prop]
|
||||
self._traverse_member_to_stack(
|
||||
stack, value, child_prop, head
|
||||
)
|
||||
except KeyError as ex:
|
||||
# Unset application ids, and class variables like SpeckleType will throw when __getitem__ is called
|
||||
pass
|
||||
@staticmethod
|
||||
def _traverse_member_to_stack(
|
||||
stack: List[TraversalContext],
|
||||
value: Any,
|
||||
member_name: Optional[str] = None,
|
||||
parent: Optional[TraversalContext] = None,
|
||||
):
|
||||
if isinstance(value, Base):
|
||||
stack.append(TraversalContext(value, member_name, parent))
|
||||
elif isinstance(value, list):
|
||||
for obj in value:
|
||||
GraphTraversal._traverse_member_to_stack(stack, obj, member_name, parent)
|
||||
elif isinstance(value, dict):
|
||||
for obj in value.values():
|
||||
GraphTraversal._traverse_member_to_stack(stack, obj, member_name, parent)
|
||||
|
||||
@staticmethod
|
||||
def traverse_member(value: Optional[Any]) -> Iterator[Base]:
|
||||
if isinstance(value, Base):
|
||||
yield value
|
||||
elif isinstance(value, list):
|
||||
for obj in value:
|
||||
for o in GraphTraversal.traverse_member(obj):
|
||||
yield o
|
||||
elif isinstance(value, dict):
|
||||
for obj in value.values():
|
||||
for o in GraphTraversal.traverse_member(obj):
|
||||
yield o
|
||||
|
||||
|
||||
def _get_active_rule_or_default_rule(self, o: Base) -> ITraversalRule:
|
||||
return self._get_active_rule(o) or _default_rule
|
||||
|
||||
def _get_active_rule(self, o: Base) -> Optional[ITraversalRule]:
|
||||
for rule in self._rules:
|
||||
if rule.does_rule_hold(o):
|
||||
return rule
|
||||
return None
|
||||
|
||||
|
||||
@final
|
||||
@define(slots=True, frozen=True)
|
||||
class TraversalRule:
|
||||
_conditions: Collection[Callable[[Base], bool]]
|
||||
_members_to_traverse: Callable[[Base], Iterable[str]]
|
||||
|
||||
def get_members_to_traverse(self, o: Base) -> Set[str]:
|
||||
return set(self._members_to_traverse(o))
|
||||
|
||||
def does_rule_hold(self, o: Base) -> bool:
|
||||
for condition in self._conditions:
|
||||
if condition(o):
|
||||
return True
|
||||
return False
|
||||
@@ -115,7 +115,7 @@ class VIEW3D_PT_SpeckleUser(bpy.types.Panel):
|
||||
col = layout.column()
|
||||
|
||||
if len(speckle.users) < 1:
|
||||
col.label(text="No users found.")
|
||||
col.label(text="Refresh to initialise")
|
||||
else:
|
||||
col.prop(speckle, "active_user", text="")
|
||||
user = speckle.users[int(speckle.active_user)]
|
||||
|
||||
Generated
+377
-360
@@ -8,7 +8,7 @@ python-versions = "*"
|
||||
|
||||
[[package]]
|
||||
name = "astroid"
|
||||
version = "2.13.2"
|
||||
version = "2.15.5"
|
||||
description = "An abstract syntax tree for Python with inference support."
|
||||
category = "dev"
|
||||
optional = false
|
||||
@@ -16,12 +16,27 @@ python-versions = ">=3.7.2"
|
||||
|
||||
[package.dependencies]
|
||||
lazy-object-proxy = ">=1.4.0"
|
||||
typing-extensions = ">=4.0.0"
|
||||
typing-extensions = {version = ">=4.0.0", markers = "python_version < \"3.11\""}
|
||||
wrapt = [
|
||||
{version = ">=1.11,<2", markers = "python_version < \"3.11\""},
|
||||
{version = ">=1.14,<2", markers = "python_version >= \"3.11\""},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "attrs"
|
||||
version = "23.1.0"
|
||||
description = "Classes Without Boilerplate"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.extras]
|
||||
cov = ["attrs[tests]", "coverage[toml] (>=5.3)"]
|
||||
dev = ["attrs[docs,tests]", "pre-commit"]
|
||||
docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"]
|
||||
tests = ["attrs[tests-no-zope]", "zope-interface"]
|
||||
tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"]
|
||||
|
||||
[[package]]
|
||||
name = "backoff"
|
||||
version = "2.2.1"
|
||||
@@ -54,7 +69,7 @@ uvloop = ["uvloop (>=0.15.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2022.12.7"
|
||||
version = "2023.5.7"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
category = "main"
|
||||
optional = false
|
||||
@@ -62,11 +77,11 @@ python-versions = ">=3.6"
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.0.1"
|
||||
version = "3.1.0"
|
||||
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
python-versions = ">=3.7.0"
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
@@ -89,7 +104,7 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7
|
||||
|
||||
[[package]]
|
||||
name = "deprecated"
|
||||
version = "1.2.13"
|
||||
version = "1.2.14"
|
||||
description = "Python @deprecated decorator to deprecate old python classes, functions or methods."
|
||||
category = "main"
|
||||
optional = false
|
||||
@@ -99,7 +114,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
wrapt = ">=1.10,<2"
|
||||
|
||||
[package.extras]
|
||||
dev = ["PyTest", "PyTest (<5)", "PyTest-Cov", "PyTest-Cov (<2.6)", "bump2version (<1)", "configparser (<5)", "importlib-metadata (<3)", "importlib-resources (<4)", "sphinx (<2)", "sphinxcontrib-websupport (<2)", "tox", "zipp (<2)"]
|
||||
dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"]
|
||||
|
||||
[[package]]
|
||||
name = "dill"
|
||||
@@ -114,7 +129,7 @@ graph = ["objgraph (>=1.7.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "fake-bpy-module-latest"
|
||||
version = "20221006"
|
||||
version = "20230117"
|
||||
description = "Collection of the fake Blender Python API module for the code completion."
|
||||
category = "dev"
|
||||
optional = false
|
||||
@@ -122,7 +137,7 @@ python-versions = ">=3.7"
|
||||
|
||||
[[package]]
|
||||
name = "gql"
|
||||
version = "3.4.0"
|
||||
version = "3.4.1"
|
||||
description = "GraphQL client for Python"
|
||||
category = "main"
|
||||
optional = false
|
||||
@@ -133,17 +148,17 @@ backoff = ">=1.11.1,<3.0"
|
||||
graphql-core = ">=3.2,<3.3"
|
||||
requests = {version = ">=2.26,<3", optional = true, markers = "extra == \"requests\""}
|
||||
requests-toolbelt = {version = ">=0.9.1,<1", optional = true, markers = "extra == \"requests\""}
|
||||
urllib3 = {version = ">=1.26", optional = true, markers = "extra == \"requests\""}
|
||||
urllib3 = {version = ">=1.26,<2", optional = true, markers = "extra == \"requests\""}
|
||||
websockets = {version = ">=10,<11", optional = true, markers = "python_version > \"3.6\" and extra == \"websockets\""}
|
||||
yarl = ">=1.6,<2.0"
|
||||
|
||||
[package.extras]
|
||||
aiohttp = ["aiohttp (>=3.7.1,<3.9.0)"]
|
||||
all = ["aiohttp (>=3.7.1,<3.9.0)", "botocore (>=1.21,<2)", "requests (>=2.26,<3)", "requests-toolbelt (>=0.9.1,<1)", "urllib3 (>=1.26)", "websockets (>=10,<11)", "websockets (>=9,<10)"]
|
||||
all = ["aiohttp (>=3.7.1,<3.9.0)", "botocore (>=1.21,<2)", "requests (>=2.26,<3)", "requests-toolbelt (>=0.9.1,<1)", "urllib3 (>=1.26,<2)", "websockets (>=10,<11)", "websockets (>=9,<10)"]
|
||||
botocore = ["botocore (>=1.21,<2)"]
|
||||
dev = ["aiofiles", "aiohttp (>=3.7.1,<3.9.0)", "black (==22.3.0)", "botocore (>=1.21,<2)", "check-manifest (>=0.42,<1)", "flake8 (==3.8.1)", "isort (==4.3.21)", "mock (==4.0.2)", "mypy (==0.910)", "parse (==1.15.0)", "pytest (==6.2.5)", "pytest-asyncio (==0.16.0)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=0.9.1,<1)", "sphinx (>=3.0.0,<4)", "sphinx-argparse (==0.2.5)", "sphinx-rtd-theme (>=0.4,<1)", "types-aiofiles", "types-mock", "types-requests", "urllib3 (>=1.26)", "vcrpy (==4.0.2)", "websockets (>=10,<11)", "websockets (>=9,<10)"]
|
||||
requests = ["requests (>=2.26,<3)", "requests-toolbelt (>=0.9.1,<1)", "urllib3 (>=1.26)"]
|
||||
test = ["aiofiles", "aiohttp (>=3.7.1,<3.9.0)", "botocore (>=1.21,<2)", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==6.2.5)", "pytest-asyncio (==0.16.0)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=0.9.1,<1)", "urllib3 (>=1.26)", "vcrpy (==4.0.2)", "websockets (>=10,<11)", "websockets (>=9,<10)"]
|
||||
dev = ["aiofiles", "aiohttp (>=3.7.1,<3.9.0)", "black (==22.3.0)", "botocore (>=1.21,<2)", "check-manifest (>=0.42,<1)", "flake8 (==3.8.1)", "isort (==4.3.21)", "mock (==4.0.2)", "mypy (==0.910)", "parse (==1.15.0)", "pytest (==6.2.5)", "pytest-asyncio (==0.16.0)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=0.9.1,<1)", "sphinx (>=3.0.0,<4)", "sphinx-argparse (==0.2.5)", "sphinx-rtd-theme (>=0.4,<1)", "types-aiofiles", "types-mock", "types-requests", "urllib3 (>=1.26,<2)", "vcrpy (==4.0.2)", "websockets (>=10,<11)", "websockets (>=9,<10)"]
|
||||
requests = ["requests (>=2.26,<3)", "requests-toolbelt (>=0.9.1,<1)", "urllib3 (>=1.26,<2)"]
|
||||
test = ["aiofiles", "aiohttp (>=3.7.1,<3.9.0)", "botocore (>=1.21,<2)", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==6.2.5)", "pytest-asyncio (==0.16.0)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "requests (>=2.26,<3)", "requests-toolbelt (>=0.9.1,<1)", "urllib3 (>=1.26,<2)", "vcrpy (==4.0.2)", "websockets (>=10,<11)", "websockets (>=9,<10)"]
|
||||
test-no-transport = ["aiofiles", "mock (==4.0.2)", "parse (==1.15.0)", "pytest (==6.2.5)", "pytest-asyncio (==0.16.0)", "pytest-console-scripts (==1.3.1)", "pytest-cov (==3.0.0)", "vcrpy (==4.0.2)"]
|
||||
websockets = ["websockets (>=10,<11)", "websockets (>=9,<10)"]
|
||||
|
||||
@@ -165,15 +180,15 @@ python-versions = ">=3.5"
|
||||
|
||||
[[package]]
|
||||
name = "isort"
|
||||
version = "5.11.4"
|
||||
version = "5.12.0"
|
||||
description = "A Python utility / library to sort Python imports."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
python-versions = ">=3.8.0"
|
||||
|
||||
[package.extras]
|
||||
colors = ["colorama (>=0.4.3,<0.5.0)"]
|
||||
pipfile-deprecated-finder = ["pipreqs", "requirementslib"]
|
||||
colors = ["colorama (>=0.4.3)"]
|
||||
pipfile-deprecated-finder = ["pip-shims (>=0.5.2)", "pipreqs", "requirementslib"]
|
||||
plugins = ["setuptools"]
|
||||
requirements-deprecated-finder = ["pip-api", "pipreqs"]
|
||||
|
||||
@@ -203,15 +218,15 @@ python-versions = ">=3.7"
|
||||
|
||||
[[package]]
|
||||
name = "mypy-extensions"
|
||||
version = "0.4.3"
|
||||
description = "Experimental type system extensions for programs checked with the mypy typechecker."
|
||||
version = "1.0.0"
|
||||
description = "Type system extensions for programs checked with the mypy type checker."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
python-versions = ">=3.5"
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "1.24.1"
|
||||
version = "1.24.3"
|
||||
description = "Fundamental package for array computing in Python"
|
||||
category = "dev"
|
||||
optional = false
|
||||
@@ -219,7 +234,7 @@ python-versions = ">=3.8"
|
||||
|
||||
[[package]]
|
||||
name = "pathspec"
|
||||
version = "0.10.3"
|
||||
version = "0.11.1"
|
||||
description = "Utility library for gitignore style pattern matching of file paths."
|
||||
category = "dev"
|
||||
optional = false
|
||||
@@ -227,19 +242,19 @@ python-versions = ">=3.7"
|
||||
|
||||
[[package]]
|
||||
name = "platformdirs"
|
||||
version = "2.6.2"
|
||||
version = "3.5.1"
|
||||
description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo (>=2022.12.7)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.5)"]
|
||||
test = ["appdirs (==1.4.4)", "covdefaults (>=2.2.2)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
|
||||
docs = ["furo (>=2023.3.27)", "proselint (>=0.13)", "sphinx (>=6.2.1)", "sphinx-autodoc-typehints (>=1.23,!=1.23.4)"]
|
||||
test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.3.1)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "1.10.4"
|
||||
version = "1.10.8"
|
||||
description = "Data validation and settings management using python type hints"
|
||||
category = "main"
|
||||
optional = false
|
||||
@@ -254,14 +269,14 @@ email = ["email-validator (>=1.0.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "pylint"
|
||||
version = "2.15.10"
|
||||
version = "2.17.4"
|
||||
description = "python code static checker"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7.2"
|
||||
|
||||
[package.dependencies]
|
||||
astroid = ">=2.12.13,<=2.14.0-dev0"
|
||||
astroid = ">=2.15.4,<=2.17.0-dev0"
|
||||
colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
|
||||
dill = [
|
||||
{version = ">=0.2", markers = "python_version < \"3.11\""},
|
||||
@@ -280,17 +295,17 @@ testutils = ["gitpython (>3)"]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.28.2"
|
||||
version = "2.31.0"
|
||||
description = "Python HTTP for Humans."
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7, <4"
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=2017.4.17"
|
||||
charset-normalizer = ">=2,<4"
|
||||
idna = ">=2.5,<4"
|
||||
urllib3 = ">=1.21.1,<1.27"
|
||||
urllib3 = ">=1.21.1,<3"
|
||||
|
||||
[package.extras]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||
@@ -317,7 +332,7 @@ python-versions = ">=3.7"
|
||||
|
||||
[[package]]
|
||||
name = "specklepy"
|
||||
version = "2.11.4"
|
||||
version = "2.14.0"
|
||||
description = "The Python SDK for Speckle 2.0"
|
||||
category = "main"
|
||||
optional = false
|
||||
@@ -349,15 +364,15 @@ python-versions = ">=3.7"
|
||||
|
||||
[[package]]
|
||||
name = "tomlkit"
|
||||
version = "0.11.6"
|
||||
version = "0.11.8"
|
||||
description = "Style preserving TOML library"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
python-versions = ">=3.7"
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.4.0"
|
||||
version = "4.6.2"
|
||||
description = "Backported and Experimental Type Hints for Python 3.7+"
|
||||
category = "main"
|
||||
optional = false
|
||||
@@ -373,7 +388,7 @@ python-versions = ">=3.7"
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "1.26.14"
|
||||
version = "1.26.16"
|
||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
category = "main"
|
||||
optional = false
|
||||
@@ -394,7 +409,7 @@ python-versions = ">=3.7"
|
||||
|
||||
[[package]]
|
||||
name = "wrapt"
|
||||
version = "1.14.1"
|
||||
version = "1.15.0"
|
||||
description = "Module for decorators, wrappers and monkey patching."
|
||||
category = "main"
|
||||
optional = false
|
||||
@@ -402,7 +417,7 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
|
||||
|
||||
[[package]]
|
||||
name = "yarl"
|
||||
version = "1.8.2"
|
||||
version = "1.9.2"
|
||||
description = "Yet another URL library"
|
||||
category = "main"
|
||||
optional = false
|
||||
@@ -415,7 +430,7 @@ multidict = ">=4.0"
|
||||
[metadata]
|
||||
lock-version = "1.1"
|
||||
python-versions = ">=3.8, <4.0.0"
|
||||
content-hash = "3f076527ffe644678e70b173cb65154c053f7abd0b69c6e763a741cb73dd81ed"
|
||||
content-hash = "22d03350287bdc78108c523e3cedf45c8b6345e0a12b99b8d027e4f0f27bab1b"
|
||||
|
||||
[metadata.files]
|
||||
appdirs = [
|
||||
@@ -423,8 +438,12 @@ appdirs = [
|
||||
{file = "appdirs-1.4.4.tar.gz", hash = "sha256:7d5d0167b2b1ba821647616af46a749d1c653740dd0d2415100fe26e27afdf41"},
|
||||
]
|
||||
astroid = [
|
||||
{file = "astroid-2.13.2-py3-none-any.whl", hash = "sha256:8f6a8d40c4ad161d6fc419545ae4b2f275ed86d1c989c97825772120842ee0d2"},
|
||||
{file = "astroid-2.13.2.tar.gz", hash = "sha256:3bc7834720e1a24ca797fd785d77efb14f7a28ee8e635ef040b6e2d80ccb3303"},
|
||||
{file = "astroid-2.15.5-py3-none-any.whl", hash = "sha256:078e5212f9885fa85fbb0cf0101978a336190aadea6e13305409d099f71b2324"},
|
||||
{file = "astroid-2.15.5.tar.gz", hash = "sha256:1039262575027b441137ab4a62a793a9b43defb42c32d5670f38686207cd780f"},
|
||||
]
|
||||
attrs = [
|
||||
{file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"},
|
||||
{file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"},
|
||||
]
|
||||
backoff = [
|
||||
{file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"},
|
||||
@@ -445,98 +464,85 @@ black = [
|
||||
{file = "black-22.12.0.tar.gz", hash = "sha256:229351e5a18ca30f447bf724d007f890f97e13af070bb6ad4c0a441cd7596a2f"},
|
||||
]
|
||||
certifi = [
|
||||
{file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"},
|
||||
{file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"},
|
||||
{file = "certifi-2023.5.7-py3-none-any.whl", hash = "sha256:c6c2e98f5c7869efca1f8916fed228dd91539f9f1b444c314c06eef02980c716"},
|
||||
{file = "certifi-2023.5.7.tar.gz", hash = "sha256:0f0d56dc5a6ad56fd4ba36484d6cc34451e1c6548c61daad8c320169f91eddc7"},
|
||||
]
|
||||
charset-normalizer = [
|
||||
{file = "charset-normalizer-3.0.1.tar.gz", hash = "sha256:ebea339af930f8ca5d7a699b921106c6e29c617fe9606fa7baa043c1cdae326f"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:88600c72ef7587fe1708fd242b385b6ed4b8904976d5da0893e31df8b3480cb6"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c75ffc45f25324e68ab238cb4b5c0a38cd1c3d7f1fb1f72b5541de469e2247db"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:db72b07027db150f468fbada4d85b3b2729a3db39178abf5c543b784c1254539"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:62595ab75873d50d57323a91dd03e6966eb79c41fa834b7a1661ed043b2d404d"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ff6f3db31555657f3163b15a6b7c6938d08df7adbfc9dd13d9d19edad678f1e8"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:772b87914ff1152b92a197ef4ea40efe27a378606c39446ded52c8f80f79702e"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70990b9c51340e4044cfc394a81f614f3f90d41397104d226f21e66de668730d"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:292d5e8ba896bbfd6334b096e34bffb56161c81408d6d036a7dfa6929cff8783"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2edb64ee7bf1ed524a1da60cdcd2e1f6e2b4f66ef7c077680739f1641f62f555"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:31a9ddf4718d10ae04d9b18801bd776693487cbb57d74cc3458a7673f6f34639"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:44ba614de5361b3e5278e1241fda3dc1838deed864b50a10d7ce92983797fa76"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:12db3b2c533c23ab812c2b25934f60383361f8a376ae272665f8e48b88e8e1c6"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c512accbd6ff0270939b9ac214b84fb5ada5f0409c44298361b2f5e13f9aed9e"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-win32.whl", hash = "sha256:502218f52498a36d6bf5ea77081844017bf7982cdbe521ad85e64cabee1b608b"},
|
||||
{file = "charset_normalizer-3.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:601f36512f9e28f029d9481bdaf8e89e5148ac5d89cffd3b05cd533eeb423b59"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0298eafff88c99982a4cf66ba2efa1128e4ddaca0b05eec4c456bbc7db691d8d"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a8d0fc946c784ff7f7c3742310cc8a57c5c6dc31631269876a88b809dbeff3d3"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:87701167f2a5c930b403e9756fab1d31d4d4da52856143b609e30a1ce7160f3c"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:14e76c0f23218b8f46c4d87018ca2e441535aed3632ca134b10239dfb6dadd6b"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0c0a590235ccd933d9892c627dec5bc7511ce6ad6c1011fdf5b11363022746c1"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c7fe7afa480e3e82eed58e0ca89f751cd14d767638e2550c77a92a9e749c317"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79909e27e8e4fcc9db4addea88aa63f6423ebb171db091fb4373e3312cb6d603"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ac7b6a045b814cf0c47f3623d21ebd88b3e8cf216a14790b455ea7ff0135d18"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:72966d1b297c741541ca8cf1223ff262a6febe52481af742036a0b296e35fa5a"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f9d0c5c045a3ca9bedfc35dca8526798eb91a07aa7a2c0fee134c6c6f321cbd7"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:5995f0164fa7df59db4746112fec3f49c461dd6b31b841873443bdb077c13cfc"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4a8fcf28c05c1f6d7e177a9a46a1c52798bfe2ad80681d275b10dcf317deaf0b"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:761e8904c07ad053d285670f36dd94e1b6ab7f16ce62b9805c475b7aa1cffde6"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-win32.whl", hash = "sha256:71140351489970dfe5e60fc621ada3e0f41104a5eddaca47a7acb3c1b851d6d3"},
|
||||
{file = "charset_normalizer-3.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:9ab77acb98eba3fd2a85cd160851816bfce6871d944d885febf012713f06659c"},
|
||||
{file = "charset_normalizer-3.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:84c3990934bae40ea69a82034912ffe5a62c60bbf6ec5bc9691419641d7d5c9a"},
|
||||
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74292fc76c905c0ef095fe11e188a32ebd03bc38f3f3e9bcb85e4e6db177b7ea"},
|
||||
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c95a03c79bbe30eec3ec2b7f076074f4281526724c8685a42872974ef4d36b72"},
|
||||
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f4c39b0e3eac288fedc2b43055cfc2ca7a60362d0e5e87a637beac5d801ef478"},
|
||||
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df2c707231459e8a4028eabcd3cfc827befd635b3ef72eada84ab13b52e1574d"},
|
||||
{file = "charset_normalizer-3.0.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93ad6d87ac18e2a90b0fe89df7c65263b9a99a0eb98f0a3d2e079f12a0735837"},
|
||||
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:59e5686dd847347e55dffcc191a96622f016bc0ad89105e24c14e0d6305acbc6"},
|
||||
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:cd6056167405314a4dc3c173943f11249fa0f1b204f8b51ed4bde1a9cd1834dc"},
|
||||
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:083c8d17153ecb403e5e1eb76a7ef4babfc2c48d58899c98fcaa04833e7a2f9a"},
|
||||
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:f5057856d21e7586765171eac8b9fc3f7d44ef39425f85dbcccb13b3ebea806c"},
|
||||
{file = "charset_normalizer-3.0.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:7eb33a30d75562222b64f569c642ff3dc6689e09adda43a082208397f016c39a"},
|
||||
{file = "charset_normalizer-3.0.1-cp36-cp36m-win32.whl", hash = "sha256:95dea361dd73757c6f1c0a1480ac499952c16ac83f7f5f4f84f0658a01b8ef41"},
|
||||
{file = "charset_normalizer-3.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:eaa379fcd227ca235d04152ca6704c7cb55564116f8bc52545ff357628e10602"},
|
||||
{file = "charset_normalizer-3.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:3e45867f1f2ab0711d60c6c71746ac53537f1684baa699f4f668d4c6f6ce8e14"},
|
||||
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cadaeaba78750d58d3cc6ac4d1fd867da6fc73c88156b7a3212a3cd4819d679d"},
|
||||
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:911d8a40b2bef5b8bbae2e36a0b103f142ac53557ab421dc16ac4aafee6f53dc"},
|
||||
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:503e65837c71b875ecdd733877d852adbc465bd82c768a067badd953bf1bc5a3"},
|
||||
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a60332922359f920193b1d4826953c507a877b523b2395ad7bc716ddd386d866"},
|
||||
{file = "charset_normalizer-3.0.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16a8663d6e281208d78806dbe14ee9903715361cf81f6d4309944e4d1e59ac5b"},
|
||||
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a16418ecf1329f71df119e8a65f3aa68004a3f9383821edcb20f0702934d8087"},
|
||||
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:9d9153257a3f70d5f69edf2325357251ed20f772b12e593f3b3377b5f78e7ef8"},
|
||||
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:02a51034802cbf38db3f89c66fb5d2ec57e6fe7ef2f4a44d070a593c3688667b"},
|
||||
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:2e396d70bc4ef5325b72b593a72c8979999aa52fb8bcf03f701c1b03e1166918"},
|
||||
{file = "charset_normalizer-3.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:11b53acf2411c3b09e6af37e4b9005cba376c872503c8f28218c7243582df45d"},
|
||||
{file = "charset_normalizer-3.0.1-cp37-cp37m-win32.whl", hash = "sha256:0bf2dae5291758b6f84cf923bfaa285632816007db0330002fa1de38bfcb7154"},
|
||||
{file = "charset_normalizer-3.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:2c03cc56021a4bd59be889c2b9257dae13bf55041a3372d3295416f86b295fb5"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:024e606be3ed92216e2b6952ed859d86b4cfa52cd5bc5f050e7dc28f9b43ec42"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4b0d02d7102dd0f997580b51edc4cebcf2ab6397a7edf89f1c73b586c614272c"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:358a7c4cb8ba9b46c453b1dd8d9e431452d5249072e4f56cfda3149f6ab1405e"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81d6741ab457d14fdedc215516665050f3822d3e56508921cc7239f8c8e66a58"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8b8af03d2e37866d023ad0ddea594edefc31e827fee64f8de5611a1dbc373174"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9cf4e8ad252f7c38dd1f676b46514f92dc0ebeb0db5552f5f403509705e24753"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e696f0dd336161fca9adbb846875d40752e6eba585843c768935ba5c9960722b"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c22d3fe05ce11d3671297dc8973267daa0f938b93ec716e12e0f6dee81591dc1"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:109487860ef6a328f3eec66f2bf78b0b72400280d8f8ea05f69c51644ba6521a"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:37f8febc8ec50c14f3ec9637505f28e58d4f66752207ea177c1d67df25da5aed"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:f97e83fa6c25693c7a35de154681fcc257c1c41b38beb0304b9c4d2d9e164479"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:a152f5f33d64a6be73f1d30c9cc82dfc73cec6477ec268e7c6e4c7d23c2d2291"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:39049da0ffb96c8cbb65cbf5c5f3ca3168990adf3551bd1dee10c48fce8ae820"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-win32.whl", hash = "sha256:4457ea6774b5611f4bed5eaa5df55f70abde42364d498c5134b7ef4c6958e20e"},
|
||||
{file = "charset_normalizer-3.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:e62164b50f84e20601c1ff8eb55620d2ad25fb81b59e3cd776a1902527a788af"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8eade758719add78ec36dc13201483f8e9b5d940329285edcd5f70c0a9edbd7f"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8499ca8f4502af841f68135133d8258f7b32a53a1d594aa98cc52013fff55678"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3fc1c4a2ffd64890aebdb3f97e1278b0cc72579a08ca4de8cd2c04799a3a22be"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:00d3ffdaafe92a5dc603cb9bd5111aaa36dfa187c8285c543be562e61b755f6b"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c2ac1b08635a8cd4e0cbeaf6f5e922085908d48eb05d44c5ae9eabab148512ca"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f6f45710b4459401609ebebdbcfb34515da4fc2aa886f95107f556ac69a9147e"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ae1de54a77dc0d6d5fcf623290af4266412a7c4be0b1ff7444394f03f5c54e3"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b590df687e3c5ee0deef9fc8c547d81986d9a1b56073d82de008744452d6541"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab5de034a886f616a5668aa5d098af2b5385ed70142090e2a31bcbd0af0fdb3d"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9cb3032517f1627cc012dbc80a8ec976ae76d93ea2b5feaa9d2a5b8882597579"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:608862a7bf6957f2333fc54ab4399e405baad0163dc9f8d99cb236816db169d4"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0f438ae3532723fb6ead77e7c604be7c8374094ef4ee2c5e03a3a17f1fca256c"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:356541bf4381fa35856dafa6a965916e54bed415ad8a24ee6de6e37deccf2786"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-win32.whl", hash = "sha256:39cf9ed17fe3b1bc81f33c9ceb6ce67683ee7526e65fde1447c772afc54a1bb8"},
|
||||
{file = "charset_normalizer-3.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:0a11e971ed097d24c534c037d298ad32c6ce81a45736d31e0ff0ad37ab437d59"},
|
||||
{file = "charset_normalizer-3.0.1-py3-none-any.whl", hash = "sha256:7e189e2e1d3ed2f4aebabd2d5b0f931e883676e51c7624826e0a4e5fe8a0bf24"},
|
||||
{file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"},
|
||||
{file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"},
|
||||
{file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"},
|
||||
{file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"},
|
||||
{file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"},
|
||||
{file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"},
|
||||
{file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"},
|
||||
]
|
||||
click = [
|
||||
{file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"},
|
||||
@@ -547,20 +553,20 @@ colorama = [
|
||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||
]
|
||||
deprecated = [
|
||||
{file = "Deprecated-1.2.13-py2.py3-none-any.whl", hash = "sha256:64756e3e14c8c5eea9795d93c524551432a0be75629f8f29e67ab8caf076c76d"},
|
||||
{file = "Deprecated-1.2.13.tar.gz", hash = "sha256:43ac5335da90c31c24ba028af536a91d41d53f9e6901ddb021bcc572ce44e38d"},
|
||||
{file = "Deprecated-1.2.14-py2.py3-none-any.whl", hash = "sha256:6fac8b097794a90302bdbb17b9b815e732d3c4720583ff1b198499d78470466c"},
|
||||
{file = "Deprecated-1.2.14.tar.gz", hash = "sha256:e5323eb936458dccc2582dc6f9c322c852a775a27065ff2b0c4970b9d53d01b3"},
|
||||
]
|
||||
dill = [
|
||||
{file = "dill-0.3.6-py3-none-any.whl", hash = "sha256:a07ffd2351b8c678dfc4a856a3005f8067aea51d6ba6c700796a4d9e280f39f0"},
|
||||
{file = "dill-0.3.6.tar.gz", hash = "sha256:e5db55f3687856d8fbdab002ed78544e1c4559a130302693d839dfe8f93f2373"},
|
||||
]
|
||||
fake-bpy-module-latest = [
|
||||
{file = "fake-bpy-module-latest-20221006.tar.gz", hash = "sha256:26513339e36b976ae3a7540e3f9ef5130f29eb262114591c643bae5ddeb58647"},
|
||||
{file = "fake_bpy_module_latest-20221006-py3-none-any.whl", hash = "sha256:76b6b52dff83827605ae93ad579712ca100c7d18f13eb00d26933ac24a6610e8"},
|
||||
{file = "fake-bpy-module-latest-20230117.tar.gz", hash = "sha256:b58957036fe5573b2374a159aeb7a4cbd92255f447e55a49e16ff7c06850cdd1"},
|
||||
{file = "fake_bpy_module_latest-20230117-py3-none-any.whl", hash = "sha256:73613c27418446bc2942baed6220f8ac4ddde694a3712dd595aa97f902a79242"},
|
||||
]
|
||||
gql = [
|
||||
{file = "gql-3.4.0-py2.py3-none-any.whl", hash = "sha256:59c8a0b8f0a2f3b0b2ff970c94de86f82f65cb1da3340bfe57143e5f7ea82f71"},
|
||||
{file = "gql-3.4.0.tar.gz", hash = "sha256:ca81aa8314fa88a8c57dd1ce34941278e0c352d762eb721edcba0387829ea7c0"},
|
||||
{file = "gql-3.4.1-py2.py3-none-any.whl", hash = "sha256:315624ca0f4d571ef149d455033ebd35e45c1a13f18a059596aeddcea99135cf"},
|
||||
{file = "gql-3.4.1.tar.gz", hash = "sha256:11dc5d8715a827f2c2899593439a4f36449db4f0eafa5b1ea63948f8a2f8c545"},
|
||||
]
|
||||
graphql-core = [
|
||||
{file = "graphql-core-3.2.3.tar.gz", hash = "sha256:06d2aad0ac723e35b1cb47885d3e5c45e956a53bc1b209a9fc5369007fe46676"},
|
||||
@@ -571,8 +577,8 @@ idna = [
|
||||
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
|
||||
]
|
||||
isort = [
|
||||
{file = "isort-5.11.4-py3-none-any.whl", hash = "sha256:c033fd0edb91000a7f09527fe5c75321878f98322a77ddcc81adbd83724afb7b"},
|
||||
{file = "isort-5.11.4.tar.gz", hash = "sha256:6db30c5ded9815d813932c04c2f85a360bcdd35fed496f4d8f35495ef0a261b6"},
|
||||
{file = "isort-5.12.0-py3-none-any.whl", hash = "sha256:f84c2818376e66cf843d497486ea8fed8700b340f308f076c6fb1229dff318b6"},
|
||||
{file = "isort-5.12.0.tar.gz", hash = "sha256:8bef7dde241278824a6d83f44a544709b065191b95b6e50894bdc722fcba0504"},
|
||||
]
|
||||
lazy-object-proxy = [
|
||||
{file = "lazy-object-proxy-1.9.0.tar.gz", hash = "sha256:659fb5809fa4629b8a1ac5106f669cfc7bef26fbb389dda53b3e010d1ac4ebae"},
|
||||
@@ -693,92 +699,92 @@ multidict = [
|
||||
{file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"},
|
||||
]
|
||||
mypy-extensions = [
|
||||
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
|
||||
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
|
||||
{file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"},
|
||||
{file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"},
|
||||
]
|
||||
numpy = [
|
||||
{file = "numpy-1.24.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:179a7ef0889ab769cc03573b6217f54c8bd8e16cef80aad369e1e8185f994cd7"},
|
||||
{file = "numpy-1.24.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b09804ff570b907da323b3d762e74432fb07955701b17b08ff1b5ebaa8cfe6a9"},
|
||||
{file = "numpy-1.24.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1b739841821968798947d3afcefd386fa56da0caf97722a5de53e07c4ccedc7"},
|
||||
{file = "numpy-1.24.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e3463e6ac25313462e04aea3fb8a0a30fb906d5d300f58b3bc2c23da6a15398"},
|
||||
{file = "numpy-1.24.1-cp310-cp310-win32.whl", hash = "sha256:b31da69ed0c18be8b77bfce48d234e55d040793cebb25398e2a7d84199fbc7e2"},
|
||||
{file = "numpy-1.24.1-cp310-cp310-win_amd64.whl", hash = "sha256:b07b40f5fb4fa034120a5796288f24c1fe0e0580bbfff99897ba6267af42def2"},
|
||||
{file = "numpy-1.24.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7094891dcf79ccc6bc2a1f30428fa5edb1e6fb955411ffff3401fb4ea93780a8"},
|
||||
{file = "numpy-1.24.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:28e418681372520c992805bb723e29d69d6b7aa411065f48216d8329d02ba032"},
|
||||
{file = "numpy-1.24.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e274f0f6c7efd0d577744f52032fdd24344f11c5ae668fe8d01aac0422611df1"},
|
||||
{file = "numpy-1.24.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0044f7d944ee882400890f9ae955220d29b33d809a038923d88e4e01d652acd9"},
|
||||
{file = "numpy-1.24.1-cp311-cp311-win32.whl", hash = "sha256:442feb5e5bada8408e8fcd43f3360b78683ff12a4444670a7d9e9824c1817d36"},
|
||||
{file = "numpy-1.24.1-cp311-cp311-win_amd64.whl", hash = "sha256:de92efa737875329b052982e37bd4371d52cabf469f83e7b8be9bb7752d67e51"},
|
||||
{file = "numpy-1.24.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b162ac10ca38850510caf8ea33f89edcb7b0bb0dfa5592d59909419986b72407"},
|
||||
{file = "numpy-1.24.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:26089487086f2648944f17adaa1a97ca6aee57f513ba5f1c0b7ebdabbe2b9954"},
|
||||
{file = "numpy-1.24.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:caf65a396c0d1f9809596be2e444e3bd4190d86d5c1ce21f5fc4be60a3bc5b36"},
|
||||
{file = "numpy-1.24.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b0677a52f5d896e84414761531947c7a330d1adc07c3a4372262f25d84af7bf7"},
|
||||
{file = "numpy-1.24.1-cp38-cp38-win32.whl", hash = "sha256:dae46bed2cb79a58d6496ff6d8da1e3b95ba09afeca2e277628171ca99b99db1"},
|
||||
{file = "numpy-1.24.1-cp38-cp38-win_amd64.whl", hash = "sha256:6ec0c021cd9fe732e5bab6401adea5a409214ca5592cd92a114f7067febcba0c"},
|
||||
{file = "numpy-1.24.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:28bc9750ae1f75264ee0f10561709b1462d450a4808cd97c013046073ae64ab6"},
|
||||
{file = "numpy-1.24.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:84e789a085aabef2f36c0515f45e459f02f570c4b4c4c108ac1179c34d475ed7"},
|
||||
{file = "numpy-1.24.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e669fbdcdd1e945691079c2cae335f3e3a56554e06bbd45d7609a6cf568c700"},
|
||||
{file = "numpy-1.24.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef85cf1f693c88c1fd229ccd1055570cb41cdf4875873b7728b6301f12cd05bf"},
|
||||
{file = "numpy-1.24.1-cp39-cp39-win32.whl", hash = "sha256:87a118968fba001b248aac90e502c0b13606721b1343cdaddbc6e552e8dfb56f"},
|
||||
{file = "numpy-1.24.1-cp39-cp39-win_amd64.whl", hash = "sha256:ddc7ab52b322eb1e40521eb422c4e0a20716c271a306860979d450decbb51b8e"},
|
||||
{file = "numpy-1.24.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ed5fb71d79e771ec930566fae9c02626b939e37271ec285e9efaf1b5d4370e7d"},
|
||||
{file = "numpy-1.24.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad2925567f43643f51255220424c23d204024ed428afc5aad0f86f3ffc080086"},
|
||||
{file = "numpy-1.24.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:cfa1161c6ac8f92dea03d625c2d0c05e084668f4a06568b77a25a89111621566"},
|
||||
{file = "numpy-1.24.1.tar.gz", hash = "sha256:2386da9a471cc00a1f47845e27d916d5ec5346ae9696e01a8a34760858fe9dd2"},
|
||||
{file = "numpy-1.24.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3c1104d3c036fb81ab923f507536daedc718d0ad5a8707c6061cdfd6d184e570"},
|
||||
{file = "numpy-1.24.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:202de8f38fc4a45a3eea4b63e2f376e5f2dc64ef0fa692838e31a808520efaf7"},
|
||||
{file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8535303847b89aa6b0f00aa1dc62867b5a32923e4d1681a35b5eef2d9591a463"},
|
||||
{file = "numpy-1.24.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d926b52ba1367f9acb76b0df6ed21f0b16a1ad87c6720a1121674e5cf63e2b6"},
|
||||
{file = "numpy-1.24.3-cp310-cp310-win32.whl", hash = "sha256:f21c442fdd2805e91799fbe044a7b999b8571bb0ab0f7850d0cb9641a687092b"},
|
||||
{file = "numpy-1.24.3-cp310-cp310-win_amd64.whl", hash = "sha256:ab5f23af8c16022663a652d3b25dcdc272ac3f83c3af4c02eb8b824e6b3ab9d7"},
|
||||
{file = "numpy-1.24.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9a7721ec204d3a237225db3e194c25268faf92e19338a35f3a224469cb6039a3"},
|
||||
{file = "numpy-1.24.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d6cc757de514c00b24ae8cf5c876af2a7c3df189028d68c0cb4eaa9cd5afc2bf"},
|
||||
{file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76e3f4e85fc5d4fd311f6e9b794d0c00e7002ec122be271f2019d63376f1d385"},
|
||||
{file = "numpy-1.24.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a1d3c026f57ceaad42f8231305d4653d5f05dc6332a730ae5c0bea3513de0950"},
|
||||
{file = "numpy-1.24.3-cp311-cp311-win32.whl", hash = "sha256:c91c4afd8abc3908e00a44b2672718905b8611503f7ff87390cc0ac3423fb096"},
|
||||
{file = "numpy-1.24.3-cp311-cp311-win_amd64.whl", hash = "sha256:5342cf6aad47943286afa6f1609cad9b4266a05e7f2ec408e2cf7aea7ff69d80"},
|
||||
{file = "numpy-1.24.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7776ea65423ca6a15255ba1872d82d207bd1e09f6d0894ee4a64678dd2204078"},
|
||||
{file = "numpy-1.24.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ae8d0be48d1b6ed82588934aaaa179875e7dc4f3d84da18d7eae6eb3f06c242c"},
|
||||
{file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecde0f8adef7dfdec993fd54b0f78183051b6580f606111a6d789cd14c61ea0c"},
|
||||
{file = "numpy-1.24.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4749e053a29364d3452c034827102ee100986903263e89884922ef01a0a6fd2f"},
|
||||
{file = "numpy-1.24.3-cp38-cp38-win32.whl", hash = "sha256:d933fabd8f6a319e8530d0de4fcc2e6a61917e0b0c271fded460032db42a0fe4"},
|
||||
{file = "numpy-1.24.3-cp38-cp38-win_amd64.whl", hash = "sha256:56e48aec79ae238f6e4395886b5eaed058abb7231fb3361ddd7bfdf4eed54289"},
|
||||
{file = "numpy-1.24.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4719d5aefb5189f50887773699eaf94e7d1e02bf36c1a9d353d9f46703758ca4"},
|
||||
{file = "numpy-1.24.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ec87a7084caa559c36e0a2309e4ecb1baa03b687201d0a847c8b0ed476a7187"},
|
||||
{file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea8282b9bcfe2b5e7d491d0bf7f3e2da29700cec05b49e64d6246923329f2b02"},
|
||||
{file = "numpy-1.24.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:210461d87fb02a84ef243cac5e814aad2b7f4be953b32cb53327bb49fd77fbb4"},
|
||||
{file = "numpy-1.24.3-cp39-cp39-win32.whl", hash = "sha256:784c6da1a07818491b0ffd63c6bbe5a33deaa0e25a20e1b3ea20cf0e43f8046c"},
|
||||
{file = "numpy-1.24.3-cp39-cp39-win_amd64.whl", hash = "sha256:d5036197ecae68d7f491fcdb4df90082b0d4960ca6599ba2659957aafced7c17"},
|
||||
{file = "numpy-1.24.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:352ee00c7f8387b44d19f4cada524586f07379c0d49270f87233983bc5087ca0"},
|
||||
{file = "numpy-1.24.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a7d6acc2e7524c9955e5c903160aa4ea083736fde7e91276b0e5d98e6332812"},
|
||||
{file = "numpy-1.24.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:35400e6a8d102fd07c71ed7dcadd9eb62ee9a6e84ec159bd48c28235bbb0f8e4"},
|
||||
{file = "numpy-1.24.3.tar.gz", hash = "sha256:ab344f1bf21f140adab8e47fdbc7c35a477dc01408791f8ba00d018dd0bc5155"},
|
||||
]
|
||||
pathspec = [
|
||||
{file = "pathspec-0.10.3-py3-none-any.whl", hash = "sha256:3c95343af8b756205e2aba76e843ba9520a24dd84f68c22b9f93251507509dd6"},
|
||||
{file = "pathspec-0.10.3.tar.gz", hash = "sha256:56200de4077d9d0791465aa9095a01d421861e405b5096955051deefd697d6f6"},
|
||||
{file = "pathspec-0.11.1-py3-none-any.whl", hash = "sha256:d8af70af76652554bd134c22b3e8a1cc46ed7d91edcdd721ef1a0c51a84a5293"},
|
||||
{file = "pathspec-0.11.1.tar.gz", hash = "sha256:2798de800fa92780e33acca925945e9a19a133b715067cf165b8866c15a31687"},
|
||||
]
|
||||
platformdirs = [
|
||||
{file = "platformdirs-2.6.2-py3-none-any.whl", hash = "sha256:83c8f6d04389165de7c9b6f0c682439697887bca0aa2f1c87ef1826be3584490"},
|
||||
{file = "platformdirs-2.6.2.tar.gz", hash = "sha256:e1fea1fe471b9ff8332e229df3cb7de4f53eeea4998d3b6bfff542115e998bd2"},
|
||||
{file = "platformdirs-3.5.1-py3-none-any.whl", hash = "sha256:e2378146f1964972c03c085bb5662ae80b2b8c06226c54b2ff4aa9483e8a13a5"},
|
||||
{file = "platformdirs-3.5.1.tar.gz", hash = "sha256:412dae91f52a6f84830f39a8078cecd0e866cb72294a5c66808e74d5e88d251f"},
|
||||
]
|
||||
pydantic = [
|
||||
{file = "pydantic-1.10.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b5635de53e6686fe7a44b5cf25fcc419a0d5e5c1a1efe73d49d48fe7586db854"},
|
||||
{file = "pydantic-1.10.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6dc1cc241440ed7ca9ab59d9929075445da6b7c94ced281b3dd4cfe6c8cff817"},
|
||||
{file = "pydantic-1.10.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51bdeb10d2db0f288e71d49c9cefa609bca271720ecd0c58009bd7504a0c464c"},
|
||||
{file = "pydantic-1.10.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:78cec42b95dbb500a1f7120bdf95c401f6abb616bbe8785ef09887306792e66e"},
|
||||
{file = "pydantic-1.10.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:8775d4ef5e7299a2f4699501077a0defdaac5b6c4321173bcb0f3c496fbadf85"},
|
||||
{file = "pydantic-1.10.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:572066051eeac73d23f95ba9a71349c42a3e05999d0ee1572b7860235b850cc6"},
|
||||
{file = "pydantic-1.10.4-cp310-cp310-win_amd64.whl", hash = "sha256:7feb6a2d401f4d6863050f58325b8d99c1e56f4512d98b11ac64ad1751dc647d"},
|
||||
{file = "pydantic-1.10.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:39f4a73e5342b25c2959529f07f026ef58147249f9b7431e1ba8414a36761f53"},
|
||||
{file = "pydantic-1.10.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:983e720704431a6573d626b00662eb78a07148c9115129f9b4351091ec95ecc3"},
|
||||
{file = "pydantic-1.10.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75d52162fe6b2b55964fbb0af2ee58e99791a3138588c482572bb6087953113a"},
|
||||
{file = "pydantic-1.10.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fdf8d759ef326962b4678d89e275ffc55b7ce59d917d9f72233762061fd04a2d"},
|
||||
{file = "pydantic-1.10.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:05a81b006be15655b2a1bae5faa4280cf7c81d0e09fcb49b342ebf826abe5a72"},
|
||||
{file = "pydantic-1.10.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d88c4c0e5c5dfd05092a4b271282ef0588e5f4aaf345778056fc5259ba098857"},
|
||||
{file = "pydantic-1.10.4-cp311-cp311-win_amd64.whl", hash = "sha256:6a05a9db1ef5be0fe63e988f9617ca2551013f55000289c671f71ec16f4985e3"},
|
||||
{file = "pydantic-1.10.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:887ca463c3bc47103c123bc06919c86720e80e1214aab79e9b779cda0ff92a00"},
|
||||
{file = "pydantic-1.10.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fdf88ab63c3ee282c76d652fc86518aacb737ff35796023fae56a65ced1a5978"},
|
||||
{file = "pydantic-1.10.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a48f1953c4a1d9bd0b5167ac50da9a79f6072c63c4cef4cf2a3736994903583e"},
|
||||
{file = "pydantic-1.10.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a9f2de23bec87ff306aef658384b02aa7c32389766af3c5dee9ce33e80222dfa"},
|
||||
{file = "pydantic-1.10.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:cd8702c5142afda03dc2b1ee6bc358b62b3735b2cce53fc77b31ca9f728e4bc8"},
|
||||
{file = "pydantic-1.10.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6e7124d6855b2780611d9f5e1e145e86667eaa3bd9459192c8dc1a097f5e9903"},
|
||||
{file = "pydantic-1.10.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b53e1d41e97063d51a02821b80538053ee4608b9a181c1005441f1673c55423"},
|
||||
{file = "pydantic-1.10.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:55b1625899acd33229c4352ce0ae54038529b412bd51c4915349b49ca575258f"},
|
||||
{file = "pydantic-1.10.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:301d626a59edbe5dfb48fcae245896379a450d04baeed50ef40d8199f2733b06"},
|
||||
{file = "pydantic-1.10.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b6f9d649892a6f54a39ed56b8dfd5e08b5f3be5f893da430bed76975f3735d15"},
|
||||
{file = "pydantic-1.10.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d7b5a3821225f5c43496c324b0d6875fde910a1c2933d726a743ce328fbb2a8c"},
|
||||
{file = "pydantic-1.10.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f2f7eb6273dd12472d7f218e1fef6f7c7c2f00ac2e1ecde4db8824c457300416"},
|
||||
{file = "pydantic-1.10.4-cp38-cp38-win_amd64.whl", hash = "sha256:4b05697738e7d2040696b0a66d9f0a10bec0efa1883ca75ee9e55baf511909d6"},
|
||||
{file = "pydantic-1.10.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a9a6747cac06c2beb466064dda999a13176b23535e4c496c9d48e6406f92d42d"},
|
||||
{file = "pydantic-1.10.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eb992a1ef739cc7b543576337bebfc62c0e6567434e522e97291b251a41dad7f"},
|
||||
{file = "pydantic-1.10.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:990406d226dea0e8f25f643b370224771878142155b879784ce89f633541a024"},
|
||||
{file = "pydantic-1.10.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e82a6d37a95e0b1b42b82ab340ada3963aea1317fd7f888bb6b9dfbf4fff57c"},
|
||||
{file = "pydantic-1.10.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9193d4f4ee8feca58bc56c8306bcb820f5c7905fd919e0750acdeeeef0615b28"},
|
||||
{file = "pydantic-1.10.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2b3ce5f16deb45c472dde1a0ee05619298c864a20cded09c4edd820e1454129f"},
|
||||
{file = "pydantic-1.10.4-cp39-cp39-win_amd64.whl", hash = "sha256:9cbdc268a62d9a98c56e2452d6c41c0263d64a2009aac69246486f01b4f594c4"},
|
||||
{file = "pydantic-1.10.4-py3-none-any.whl", hash = "sha256:4948f264678c703f3877d1c8877c4e3b2e12e549c57795107f08cf70c6ec7774"},
|
||||
{file = "pydantic-1.10.4.tar.gz", hash = "sha256:b9a3859f24eb4e097502a3be1fb4b2abb79b6103dd9e2e0edb70613a4459a648"},
|
||||
{file = "pydantic-1.10.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1243d28e9b05003a89d72e7915fdb26ffd1d39bdd39b00b7dbe4afae4b557f9d"},
|
||||
{file = "pydantic-1.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0ab53b609c11dfc0c060d94335993cc2b95b2150e25583bec37a49b2d6c6c3f"},
|
||||
{file = "pydantic-1.10.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9613fadad06b4f3bc5db2653ce2f22e0de84a7c6c293909b48f6ed37b83c61f"},
|
||||
{file = "pydantic-1.10.8-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df7800cb1984d8f6e249351139667a8c50a379009271ee6236138a22a0c0f319"},
|
||||
{file = "pydantic-1.10.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:0c6fafa0965b539d7aab0a673a046466d23b86e4b0e8019d25fd53f4df62c277"},
|
||||
{file = "pydantic-1.10.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e82d4566fcd527eae8b244fa952d99f2ca3172b7e97add0b43e2d97ee77f81ab"},
|
||||
{file = "pydantic-1.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:ab523c31e22943713d80d8d342d23b6f6ac4b792a1e54064a8d0cf78fd64e800"},
|
||||
{file = "pydantic-1.10.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:666bdf6066bf6dbc107b30d034615d2627e2121506c555f73f90b54a463d1f33"},
|
||||
{file = "pydantic-1.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:35db5301b82e8661fa9c505c800d0990bc14e9f36f98932bb1d248c0ac5cada5"},
|
||||
{file = "pydantic-1.10.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f90c1e29f447557e9e26afb1c4dbf8768a10cc676e3781b6a577841ade126b85"},
|
||||
{file = "pydantic-1.10.8-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:93e766b4a8226e0708ef243e843105bf124e21331694367f95f4e3b4a92bbb3f"},
|
||||
{file = "pydantic-1.10.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:88f195f582851e8db960b4a94c3e3ad25692c1c1539e2552f3df7a9e972ef60e"},
|
||||
{file = "pydantic-1.10.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:34d327c81e68a1ecb52fe9c8d50c8a9b3e90d3c8ad991bfc8f953fb477d42fb4"},
|
||||
{file = "pydantic-1.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:d532bf00f381bd6bc62cabc7d1372096b75a33bc197a312b03f5838b4fb84edd"},
|
||||
{file = "pydantic-1.10.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:7d5b8641c24886d764a74ec541d2fc2c7fb19f6da2a4001e6d580ba4a38f7878"},
|
||||
{file = "pydantic-1.10.8-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7b1f6cb446470b7ddf86c2e57cd119a24959af2b01e552f60705910663af09a4"},
|
||||
{file = "pydantic-1.10.8-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c33b60054b2136aef8cf190cd4c52a3daa20b2263917c49adad20eaf381e823b"},
|
||||
{file = "pydantic-1.10.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1952526ba40b220b912cdc43c1c32bcf4a58e3f192fa313ee665916b26befb68"},
|
||||
{file = "pydantic-1.10.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:bb14388ec45a7a0dc429e87def6396f9e73c8c77818c927b6a60706603d5f2ea"},
|
||||
{file = "pydantic-1.10.8-cp37-cp37m-win_amd64.whl", hash = "sha256:16f8c3e33af1e9bb16c7a91fc7d5fa9fe27298e9f299cff6cb744d89d573d62c"},
|
||||
{file = "pydantic-1.10.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1ced8375969673929809d7f36ad322934c35de4af3b5e5b09ec967c21f9f7887"},
|
||||
{file = "pydantic-1.10.8-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:93e6bcfccbd831894a6a434b0aeb1947f9e70b7468f274154d03d71fabb1d7c6"},
|
||||
{file = "pydantic-1.10.8-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:191ba419b605f897ede9892f6c56fb182f40a15d309ef0142212200a10af4c18"},
|
||||
{file = "pydantic-1.10.8-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:052d8654cb65174d6f9490cc9b9a200083a82cf5c3c5d3985db765757eb3b375"},
|
||||
{file = "pydantic-1.10.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ceb6a23bf1ba4b837d0cfe378329ad3f351b5897c8d4914ce95b85fba96da5a1"},
|
||||
{file = "pydantic-1.10.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f2e754d5566f050954727c77f094e01793bcb5725b663bf628fa6743a5a9108"},
|
||||
{file = "pydantic-1.10.8-cp38-cp38-win_amd64.whl", hash = "sha256:6a82d6cda82258efca32b40040228ecf43a548671cb174a1e81477195ed3ed56"},
|
||||
{file = "pydantic-1.10.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3e59417ba8a17265e632af99cc5f35ec309de5980c440c255ab1ca3ae96a3e0e"},
|
||||
{file = "pydantic-1.10.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:84d80219c3f8d4cad44575e18404099c76851bc924ce5ab1c4c8bb5e2a2227d0"},
|
||||
{file = "pydantic-1.10.8-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e4148e635994d57d834be1182a44bdb07dd867fa3c2d1b37002000646cc5459"},
|
||||
{file = "pydantic-1.10.8-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:12f7b0bf8553e310e530e9f3a2f5734c68699f42218bf3568ef49cd9b0e44df4"},
|
||||
{file = "pydantic-1.10.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:42aa0c4b5c3025483240a25b09f3c09a189481ddda2ea3a831a9d25f444e03c1"},
|
||||
{file = "pydantic-1.10.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17aef11cc1b997f9d574b91909fed40761e13fac438d72b81f902226a69dac01"},
|
||||
{file = "pydantic-1.10.8-cp39-cp39-win_amd64.whl", hash = "sha256:66a703d1983c675a6e0fed8953b0971c44dba48a929a2000a493c3772eb61a5a"},
|
||||
{file = "pydantic-1.10.8-py3-none-any.whl", hash = "sha256:7456eb22ed9aaa24ff3e7b4757da20d9e5ce2a81018c1b3ebd81a0b88a18f3b2"},
|
||||
{file = "pydantic-1.10.8.tar.gz", hash = "sha256:1410275520dfa70effadf4c21811d755e7ef9bb1f1d077a21958153a92c8d9ca"},
|
||||
]
|
||||
pylint = [
|
||||
{file = "pylint-2.15.10-py3-none-any.whl", hash = "sha256:9df0d07e8948a1c3ffa3b6e2d7e6e63d9fb457c5da5b961ed63106594780cc7e"},
|
||||
{file = "pylint-2.15.10.tar.gz", hash = "sha256:b3dc5ef7d33858f297ac0d06cc73862f01e4f2e74025ec3eff347ce0bc60baf5"},
|
||||
{file = "pylint-2.17.4-py3-none-any.whl", hash = "sha256:7a1145fb08c251bdb5cca11739722ce64a63db479283d10ce718b2460e54123c"},
|
||||
{file = "pylint-2.17.4.tar.gz", hash = "sha256:5dcf1d9e19f41f38e4e85d10f511e5b9c35e1aa74251bf95cdd8cb23584e2db1"},
|
||||
]
|
||||
requests = [
|
||||
{file = "requests-2.28.2-py3-none-any.whl", hash = "sha256:64299f4909223da747622c030b781c0d7811e359c37124b4bd368fb8c6518baa"},
|
||||
{file = "requests-2.28.2.tar.gz", hash = "sha256:98b1b2782e3c6c4904938b84c0eb932721069dfdb9134313beff7c83c2df24bf"},
|
||||
{file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
|
||||
{file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
|
||||
]
|
||||
requests-toolbelt = [
|
||||
{file = "requests-toolbelt-0.10.1.tar.gz", hash = "sha256:62e09f7ff5ccbda92772a29f394a49c3ad6cb181d568b1337626b2abb628a63d"},
|
||||
@@ -803,8 +809,8 @@ ruff = [
|
||||
{file = "ruff-0.0.166.tar.gz", hash = "sha256:804fa54aa04e0253b2f39a0ce7089359ea6ba2f037f299f5d8606605e5e37bfa"},
|
||||
]
|
||||
specklepy = [
|
||||
{file = "specklepy-2.11.4-py3-none-any.whl", hash = "sha256:cb8481a98c0072c680bb57a59e7381e1d81a9c627d001f53e7ebce7ff4668930"},
|
||||
{file = "specklepy-2.11.4.tar.gz", hash = "sha256:605b07e308b9284cec55c1ac910e4a448009181ed81551a9e8c25a7bbcbb32fa"},
|
||||
{file = "specklepy-2.14.0-py3-none-any.whl", hash = "sha256:c5b912155346ace934b26f745e80d2b23d5bf73ce914c625dccaa1a310e18ad0"},
|
||||
{file = "specklepy-2.14.0.tar.gz", hash = "sha256:7c7fbdd1809cfa722066be5e2fd45562b9d97a9d5a06308c1dc993ac1860931e"},
|
||||
]
|
||||
stringcase = [
|
||||
{file = "stringcase-1.2.0.tar.gz", hash = "sha256:48a06980661908efe8d9d34eab2b6c13aefa2163b3ced26972902e3bdfd87008"},
|
||||
@@ -814,12 +820,12 @@ tomli = [
|
||||
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
||||
]
|
||||
tomlkit = [
|
||||
{file = "tomlkit-0.11.6-py3-none-any.whl", hash = "sha256:07de26b0d8cfc18f871aec595fda24d95b08fef89d147caa861939f37230bf4b"},
|
||||
{file = "tomlkit-0.11.6.tar.gz", hash = "sha256:71b952e5721688937fb02cf9d354dbcf0785066149d2855e44531ebdd2b65d73"},
|
||||
{file = "tomlkit-0.11.8-py3-none-any.whl", hash = "sha256:8c726c4c202bdb148667835f68d68780b9a003a9ec34167b6c673b38eff2a171"},
|
||||
{file = "tomlkit-0.11.8.tar.gz", hash = "sha256:9330fc7faa1db67b541b28e62018c17d20be733177d290a13b24c62d1614e0c3"},
|
||||
]
|
||||
typing-extensions = [
|
||||
{file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"},
|
||||
{file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"},
|
||||
{file = "typing_extensions-4.6.2-py3-none-any.whl", hash = "sha256:3a8b36f13dd5fdc5d1b16fe317f5668545de77fa0b8e02006381fd49d731ab98"},
|
||||
{file = "typing_extensions-4.6.2.tar.gz", hash = "sha256:06006244c70ac8ee83fa8282cb188f697b8db25bc8b4df07be1873c43897060c"},
|
||||
]
|
||||
ujson = [
|
||||
{file = "ujson-5.7.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5eba5e69e4361ac3a311cf44fa71bc619361b6e0626768a494771aacd1c2f09b"},
|
||||
@@ -889,8 +895,8 @@ ujson = [
|
||||
{file = "ujson-5.7.0.tar.gz", hash = "sha256:e788e5d5dcae8f6118ac9b45d0b891a0d55f7ac480eddcb7f07263f2bcf37b23"},
|
||||
]
|
||||
urllib3 = [
|
||||
{file = "urllib3-1.26.14-py2.py3-none-any.whl", hash = "sha256:75edcdc2f7d85b137124a6c3c9fc3933cdeaa12ecb9a6a959f22797a0feca7e1"},
|
||||
{file = "urllib3-1.26.14.tar.gz", hash = "sha256:076907bf8fd355cde77728471316625a4d2f7e713c125f51953bb5b3eecf4f72"},
|
||||
{file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"},
|
||||
{file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"},
|
||||
]
|
||||
websockets = [
|
||||
{file = "websockets-10.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d58804e996d7d2307173d56c297cf7bc132c52df27a3efaac5e8d43e36c21c48"},
|
||||
@@ -964,144 +970,155 @@ websockets = [
|
||||
{file = "websockets-10.4.tar.gz", hash = "sha256:eef610b23933c54d5d921c92578ae5f89813438fded840c2e9809d378dc765d3"},
|
||||
]
|
||||
wrapt = [
|
||||
{file = "wrapt-1.14.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:1b376b3f4896e7930f1f772ac4b064ac12598d1c38d04907e696cc4d794b43d3"},
|
||||
{file = "wrapt-1.14.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:903500616422a40a98a5a3c4ff4ed9d0066f3b4c951fa286018ecdf0750194ef"},
|
||||
{file = "wrapt-1.14.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5a9a0d155deafd9448baff28c08e150d9b24ff010e899311ddd63c45c2445e28"},
|
||||
{file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ddaea91abf8b0d13443f6dac52e89051a5063c7d014710dcb4d4abb2ff811a59"},
|
||||
{file = "wrapt-1.14.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:36f582d0c6bc99d5f39cd3ac2a9062e57f3cf606ade29a0a0d6b323462f4dd87"},
|
||||
{file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:7ef58fb89674095bfc57c4069e95d7a31cfdc0939e2a579882ac7d55aadfd2a1"},
|
||||
{file = "wrapt-1.14.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e2f83e18fe2f4c9e7db597e988f72712c0c3676d337d8b101f6758107c42425b"},
|
||||
{file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ee2b1b1769f6707a8a445162ea16dddf74285c3964f605877a20e38545c3c462"},
|
||||
{file = "wrapt-1.14.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:833b58d5d0b7e5b9832869f039203389ac7cbf01765639c7309fd50ef619e0b1"},
|
||||
{file = "wrapt-1.14.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:80bb5c256f1415f747011dc3604b59bc1f91c6e7150bd7db03b19170ee06b320"},
|
||||
{file = "wrapt-1.14.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:07f7a7d0f388028b2df1d916e94bbb40624c59b48ecc6cbc232546706fac74c2"},
|
||||
{file = "wrapt-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:02b41b633c6261feff8ddd8d11c711df6842aba629fdd3da10249a53211a72c4"},
|
||||
{file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fe803deacd09a233e4762a1adcea5db5d31e6be577a43352936179d14d90069"},
|
||||
{file = "wrapt-1.14.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:257fd78c513e0fb5cdbe058c27a0624c9884e735bbd131935fd49e9fe719d310"},
|
||||
{file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4fcc4649dc762cddacd193e6b55bc02edca674067f5f98166d7713b193932b7f"},
|
||||
{file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:11871514607b15cfeb87c547a49bca19fde402f32e2b1c24a632506c0a756656"},
|
||||
{file = "wrapt-1.14.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8ad85f7f4e20964db4daadcab70b47ab05c7c1cf2a7c1e51087bfaa83831854c"},
|
||||
{file = "wrapt-1.14.1-cp310-cp310-win32.whl", hash = "sha256:a9a52172be0b5aae932bef82a79ec0a0ce87288c7d132946d645eba03f0ad8a8"},
|
||||
{file = "wrapt-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:6d323e1554b3d22cfc03cd3243b5bb815a51f5249fdcbb86fda4bf62bab9e164"},
|
||||
{file = "wrapt-1.14.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:43ca3bbbe97af00f49efb06e352eae40434ca9d915906f77def219b88e85d907"},
|
||||
{file = "wrapt-1.14.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:6b1a564e6cb69922c7fe3a678b9f9a3c54e72b469875aa8018f18b4d1dd1adf3"},
|
||||
{file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:00b6d4ea20a906c0ca56d84f93065b398ab74b927a7a3dbd470f6fc503f95dc3"},
|
||||
{file = "wrapt-1.14.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:a85d2b46be66a71bedde836d9e41859879cc54a2a04fad1191eb50c2066f6e9d"},
|
||||
{file = "wrapt-1.14.1-cp35-cp35m-win32.whl", hash = "sha256:dbcda74c67263139358f4d188ae5faae95c30929281bc6866d00573783c422b7"},
|
||||
{file = "wrapt-1.14.1-cp35-cp35m-win_amd64.whl", hash = "sha256:b21bb4c09ffabfa0e85e3a6b623e19b80e7acd709b9f91452b8297ace2a8ab00"},
|
||||
{file = "wrapt-1.14.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:9e0fd32e0148dd5dea6af5fee42beb949098564cc23211a88d799e434255a1f4"},
|
||||
{file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9736af4641846491aedb3c3f56b9bc5568d92b0692303b5a305301a95dfd38b1"},
|
||||
{file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b02d65b9ccf0ef6c34cba6cf5bf2aab1bb2f49c6090bafeecc9cd81ad4ea1c1"},
|
||||
{file = "wrapt-1.14.1-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21ac0156c4b089b330b7666db40feee30a5d52634cc4560e1905d6529a3897ff"},
|
||||
{file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:9f3e6f9e05148ff90002b884fbc2a86bd303ae847e472f44ecc06c2cd2fcdb2d"},
|
||||
{file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:6e743de5e9c3d1b7185870f480587b75b1cb604832e380d64f9504a0535912d1"},
|
||||
{file = "wrapt-1.14.1-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d79d7d5dc8a32b7093e81e97dad755127ff77bcc899e845f41bf71747af0c569"},
|
||||
{file = "wrapt-1.14.1-cp36-cp36m-win32.whl", hash = "sha256:81b19725065dcb43df02b37e03278c011a09e49757287dca60c5aecdd5a0b8ed"},
|
||||
{file = "wrapt-1.14.1-cp36-cp36m-win_amd64.whl", hash = "sha256:b014c23646a467558be7da3d6b9fa409b2c567d2110599b7cf9a0c5992b3b471"},
|
||||
{file = "wrapt-1.14.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:88bd7b6bd70a5b6803c1abf6bca012f7ed963e58c68d76ee20b9d751c74a3248"},
|
||||
{file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5901a312f4d14c59918c221323068fad0540e34324925c8475263841dbdfe68"},
|
||||
{file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d77c85fedff92cf788face9bfa3ebaa364448ebb1d765302e9af11bf449ca36d"},
|
||||
{file = "wrapt-1.14.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d649d616e5c6a678b26d15ece345354f7c2286acd6db868e65fcc5ff7c24a77"},
|
||||
{file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7d2872609603cb35ca513d7404a94d6d608fc13211563571117046c9d2bcc3d7"},
|
||||
{file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:ee6acae74a2b91865910eef5e7de37dc6895ad96fa23603d1d27ea69df545015"},
|
||||
{file = "wrapt-1.14.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:2b39d38039a1fdad98c87279b48bc5dce2c0ca0d73483b12cb72aa9609278e8a"},
|
||||
{file = "wrapt-1.14.1-cp37-cp37m-win32.whl", hash = "sha256:60db23fa423575eeb65ea430cee741acb7c26a1365d103f7b0f6ec412b893853"},
|
||||
{file = "wrapt-1.14.1-cp37-cp37m-win_amd64.whl", hash = "sha256:709fe01086a55cf79d20f741f39325018f4df051ef39fe921b1ebe780a66184c"},
|
||||
{file = "wrapt-1.14.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8c0ce1e99116d5ab21355d8ebe53d9460366704ea38ae4d9f6933188f327b456"},
|
||||
{file = "wrapt-1.14.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e3fb1677c720409d5f671e39bac6c9e0e422584e5f518bfd50aa4cbbea02433f"},
|
||||
{file = "wrapt-1.14.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:642c2e7a804fcf18c222e1060df25fc210b9c58db7c91416fb055897fc27e8cc"},
|
||||
{file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7c050ae976e286906dd3f26009e117eb000fb2cf3533398c5ad9ccc86867b1"},
|
||||
{file = "wrapt-1.14.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ef3f72c9666bba2bab70d2a8b79f2c6d2c1a42a7f7e2b0ec83bb2f9e383950af"},
|
||||
{file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01c205616a89d09827986bc4e859bcabd64f5a0662a7fe95e0d359424e0e071b"},
|
||||
{file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:5a0f54ce2c092aaf439813735584b9537cad479575a09892b8352fea5e988dc0"},
|
||||
{file = "wrapt-1.14.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2cf71233a0ed05ccdabe209c606fe0bac7379fdcf687f39b944420d2a09fdb57"},
|
||||
{file = "wrapt-1.14.1-cp38-cp38-win32.whl", hash = "sha256:aa31fdcc33fef9eb2552cbcbfee7773d5a6792c137b359e82879c101e98584c5"},
|
||||
{file = "wrapt-1.14.1-cp38-cp38-win_amd64.whl", hash = "sha256:d1967f46ea8f2db647c786e78d8cc7e4313dbd1b0aca360592d8027b8508e24d"},
|
||||
{file = "wrapt-1.14.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:3232822c7d98d23895ccc443bbdf57c7412c5a65996c30442ebe6ed3df335383"},
|
||||
{file = "wrapt-1.14.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:988635d122aaf2bdcef9e795435662bcd65b02f4f4c1ae37fbee7401c440b3a7"},
|
||||
{file = "wrapt-1.14.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cca3c2cdadb362116235fdbd411735de4328c61425b0aa9f872fd76d02c4e86"},
|
||||
{file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d52a25136894c63de15a35bc0bdc5adb4b0e173b9c0d07a2be9d3ca64a332735"},
|
||||
{file = "wrapt-1.14.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40e7bc81c9e2b2734ea4bc1aceb8a8f0ceaac7c5299bc5d69e37c44d9081d43b"},
|
||||
{file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b9b7a708dd92306328117d8c4b62e2194d00c365f18eff11a9b53c6f923b01e3"},
|
||||
{file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6a9a25751acb379b466ff6be78a315e2b439d4c94c1e99cb7266d40a537995d3"},
|
||||
{file = "wrapt-1.14.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:34aa51c45f28ba7f12accd624225e2b1e5a3a45206aa191f6f9aac931d9d56fe"},
|
||||
{file = "wrapt-1.14.1-cp39-cp39-win32.whl", hash = "sha256:dee0ce50c6a2dd9056c20db781e9c1cfd33e77d2d569f5d1d9321c641bb903d5"},
|
||||
{file = "wrapt-1.14.1-cp39-cp39-win_amd64.whl", hash = "sha256:dee60e1de1898bde3b238f18340eec6148986da0455d8ba7848d50470a7a32fb"},
|
||||
{file = "wrapt-1.14.1.tar.gz", hash = "sha256:380a85cf89e0e69b7cfbe2ea9f765f004ff419f34194018a6827ac0e3edfed4d"},
|
||||
{file = "wrapt-1.15.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:ca1cccf838cd28d5a0883b342474c630ac48cac5df0ee6eacc9c7290f76b11c1"},
|
||||
{file = "wrapt-1.15.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:e826aadda3cae59295b95343db8f3d965fb31059da7de01ee8d1c40a60398b29"},
|
||||
{file = "wrapt-1.15.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5fc8e02f5984a55d2c653f5fea93531e9836abbd84342c1d1e17abc4a15084c2"},
|
||||
{file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:96e25c8603a155559231c19c0349245eeb4ac0096fe3c1d0be5c47e075bd4f46"},
|
||||
{file = "wrapt-1.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:40737a081d7497efea35ab9304b829b857f21558acfc7b3272f908d33b0d9d4c"},
|
||||
{file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:f87ec75864c37c4c6cb908d282e1969e79763e0d9becdfe9fe5473b7bb1e5f09"},
|
||||
{file = "wrapt-1.15.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:1286eb30261894e4c70d124d44b7fd07825340869945c79d05bda53a40caa079"},
|
||||
{file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:493d389a2b63c88ad56cdc35d0fa5752daac56ca755805b1b0c530f785767d5e"},
|
||||
{file = "wrapt-1.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:58d7a75d731e8c63614222bcb21dd992b4ab01a399f1f09dd82af17bbfc2368a"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:21f6d9a0d5b3a207cdf7acf8e58d7d13d463e639f0c7e01d82cdb671e6cb7923"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ce42618f67741d4697684e501ef02f29e758a123aa2d669e2d964ff734ee00ee"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41d07d029dd4157ae27beab04d22b8e261eddfc6ecd64ff7000b10dc8b3a5727"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54accd4b8bc202966bafafd16e69da9d5640ff92389d33d28555c5fd4f25ccb7"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fbfbca668dd15b744418265a9607baa970c347eefd0db6a518aaf0cfbd153c0"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:76e9c727a874b4856d11a32fb0b389afc61ce8aaf281ada613713ddeadd1cfec"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e20076a211cd6f9b44a6be58f7eeafa7ab5720eb796975d0c03f05b47d89eb90"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a74d56552ddbde46c246b5b89199cb3fd182f9c346c784e1a93e4dc3f5ec9975"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-win32.whl", hash = "sha256:26458da5653aa5b3d8dc8b24192f574a58984c749401f98fff994d41d3f08da1"},
|
||||
{file = "wrapt-1.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:75760a47c06b5974aa5e01949bf7e66d2af4d08cb8c1d6516af5e39595397f5e"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ba1711cda2d30634a7e452fc79eabcadaffedf241ff206db2ee93dd2c89a60e7"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56374914b132c702aa9aa9959c550004b8847148f95e1b824772d453ac204a72"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a89ce3fd220ff144bd9d54da333ec0de0399b52c9ac3d2ce34b569cf1a5748fb"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3bbe623731d03b186b3d6b0d6f51865bf598587c38d6f7b0be2e27414f7f214e"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3abbe948c3cbde2689370a262a8d04e32ec2dd4f27103669a45c6929bcdbfe7c"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b67b819628e3b748fd3c2192c15fb951f549d0f47c0449af0764d7647302fda3"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7eebcdbe3677e58dd4c0e03b4f2cfa346ed4049687d839adad68cc38bb559c92"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:74934ebd71950e3db69960a7da29204f89624dde411afbfb3b4858c1409b1e98"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-win32.whl", hash = "sha256:bd84395aab8e4d36263cd1b9308cd504f6cf713b7d6d3ce25ea55670baec5416"},
|
||||
{file = "wrapt-1.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:a487f72a25904e2b4bbc0817ce7a8de94363bd7e79890510174da9d901c38705"},
|
||||
{file = "wrapt-1.15.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:4ff0d20f2e670800d3ed2b220d40984162089a6e2c9646fdb09b85e6f9a8fc29"},
|
||||
{file = "wrapt-1.15.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:9ed6aa0726b9b60911f4aed8ec5b8dd7bf3491476015819f56473ffaef8959bd"},
|
||||
{file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:896689fddba4f23ef7c718279e42f8834041a21342d95e56922e1c10c0cc7afb"},
|
||||
{file = "wrapt-1.15.0-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:75669d77bb2c071333417617a235324a1618dba66f82a750362eccbe5b61d248"},
|
||||
{file = "wrapt-1.15.0-cp35-cp35m-win32.whl", hash = "sha256:fbec11614dba0424ca72f4e8ba3c420dba07b4a7c206c8c8e4e73f2e98f4c559"},
|
||||
{file = "wrapt-1.15.0-cp35-cp35m-win_amd64.whl", hash = "sha256:fd69666217b62fa5d7c6aa88e507493a34dec4fa20c5bd925e4bc12fce586639"},
|
||||
{file = "wrapt-1.15.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:b0724f05c396b0a4c36a3226c31648385deb6a65d8992644c12a4963c70326ba"},
|
||||
{file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbeccb1aa40ab88cd29e6c7d8585582c99548f55f9b2581dfc5ba68c59a85752"},
|
||||
{file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:38adf7198f8f154502883242f9fe7333ab05a5b02de7d83aa2d88ea621f13364"},
|
||||
{file = "wrapt-1.15.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:578383d740457fa790fdf85e6d346fda1416a40549fe8db08e5e9bd281c6a475"},
|
||||
{file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:a4cbb9ff5795cd66f0066bdf5947f170f5d63a9274f99bdbca02fd973adcf2a8"},
|
||||
{file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:af5bd9ccb188f6a5fdda9f1f09d9f4c86cc8a539bd48a0bfdc97723970348418"},
|
||||
{file = "wrapt-1.15.0-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:b56d5519e470d3f2fe4aa7585f0632b060d532d0696c5bdfb5e8319e1d0f69a2"},
|
||||
{file = "wrapt-1.15.0-cp36-cp36m-win32.whl", hash = "sha256:77d4c1b881076c3ba173484dfa53d3582c1c8ff1f914c6461ab70c8428b796c1"},
|
||||
{file = "wrapt-1.15.0-cp36-cp36m-win_amd64.whl", hash = "sha256:077ff0d1f9d9e4ce6476c1a924a3332452c1406e59d90a2cf24aeb29eeac9420"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5c5aa28df055697d7c37d2099a7bc09f559d5053c3349b1ad0c39000e611d317"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a8564f283394634a7a7054b7983e47dbf39c07712d7b177b37e03f2467a024e"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:780c82a41dc493b62fc5884fb1d3a3b81106642c5c5c78d6a0d4cbe96d62ba7e"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e169e957c33576f47e21864cf3fc9ff47c223a4ebca8960079b8bd36cb014fd0"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b02f21c1e2074943312d03d243ac4388319f2456576b2c6023041c4d57cd7019"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:f2e69b3ed24544b0d3dbe2c5c0ba5153ce50dcebb576fdc4696d52aa22db6034"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d787272ed958a05b2c86311d3a4135d3c2aeea4fc655705f074130aa57d71653"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-win32.whl", hash = "sha256:02fce1852f755f44f95af51f69d22e45080102e9d00258053b79367d07af39c0"},
|
||||
{file = "wrapt-1.15.0-cp37-cp37m-win_amd64.whl", hash = "sha256:abd52a09d03adf9c763d706df707c343293d5d106aea53483e0ec8d9e310ad5e"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdb4f085756c96a3af04e6eca7f08b1345e94b53af8921b25c72f096e704e145"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:230ae493696a371f1dbffaad3dafbb742a4d27a0afd2b1aecebe52b740167e7f"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63424c681923b9f3bfbc5e3205aafe790904053d42ddcc08542181a30a7a51bd"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6bcbfc99f55655c3d93feb7ef3800bd5bbe963a755687cbf1f490a71fb7794b"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c99f4309f5145b93eca6e35ac1a988f0dc0a7ccf9ccdcd78d3c0adf57224e62f"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b130fe77361d6771ecf5a219d8e0817d61b236b7d8b37cc045172e574ed219e6"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:96177eb5645b1c6985f5c11d03fc2dbda9ad24ec0f3a46dcce91445747e15094"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:d5fe3e099cf07d0fb5a1e23d399e5d4d1ca3e6dfcbe5c8570ccff3e9208274f7"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-win32.whl", hash = "sha256:abd8f36c99512755b8456047b7be10372fca271bf1467a1caa88db991e7c421b"},
|
||||
{file = "wrapt-1.15.0-cp38-cp38-win_amd64.whl", hash = "sha256:b06fa97478a5f478fb05e1980980a7cdf2712015493b44d0c87606c1513ed5b1"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2e51de54d4fb8fb50d6ee8327f9828306a959ae394d3e01a1ba8b2f937747d86"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0970ddb69bba00670e58955f8019bec4a42d1785db3faa043c33d81de2bf843c"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:76407ab327158c510f44ded207e2f76b657303e17cb7a572ffe2f5a8a48aa04d"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cd525e0e52a5ff16653a3fc9e3dd827981917d34996600bbc34c05d048ca35cc"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9d37ac69edc5614b90516807de32d08cb8e7b12260a285ee330955604ed9dd29"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:078e2a1a86544e644a68422f881c48b84fef6d18f8c7a957ffd3f2e0a74a0d4a"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2cf56d0e237280baed46f0b5316661da892565ff58309d4d2ed7dba763d984b8"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7dc0713bf81287a00516ef43137273b23ee414fe41a3c14be10dd95ed98a2df9"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-win32.whl", hash = "sha256:46ed616d5fb42f98630ed70c3529541408166c22cdfd4540b88d5f21006b0eff"},
|
||||
{file = "wrapt-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:eef4d64c650f33347c1f9266fa5ae001440b232ad9b98f1f43dfe7a79435c0a6"},
|
||||
{file = "wrapt-1.15.0-py3-none-any.whl", hash = "sha256:64b1df0f83706b4ef4cfb4fb0e4c2669100fd7ecacfb59e091fad300d4e04640"},
|
||||
{file = "wrapt-1.15.0.tar.gz", hash = "sha256:d06730c6aed78cee4126234cf2d071e01b44b915e725a6cb439a879ec9754a3a"},
|
||||
]
|
||||
yarl = [
|
||||
{file = "yarl-1.8.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bb81f753c815f6b8e2ddd2eef3c855cf7da193b82396ac013c661aaa6cc6b0a5"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:47d49ac96156f0928f002e2424299b2c91d9db73e08c4cd6742923a086f1c863"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3fc056e35fa6fba63248d93ff6e672c096f95f7836938241ebc8260e062832fe"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58a3c13d1c3005dbbac5c9f0d3210b60220a65a999b1833aa46bd6677c69b08e"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10b08293cda921157f1e7c2790999d903b3fd28cd5c208cf8826b3b508026996"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de986979bbd87272fe557e0a8fcb66fd40ae2ddfe28a8b1ce4eae22681728fef"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c4fcfa71e2c6a3cb568cf81aadc12768b9995323186a10827beccf5fa23d4f8"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae4d7ff1049f36accde9e1ef7301912a751e5bae0a9d142459646114c70ecba6"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bf071f797aec5b96abfc735ab97da9fd8f8768b43ce2abd85356a3127909d146"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:74dece2bfc60f0f70907c34b857ee98f2c6dd0f75185db133770cd67300d505f"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:df60a94d332158b444301c7f569659c926168e4d4aad2cfbf4bce0e8fb8be826"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:63243b21c6e28ec2375f932a10ce7eda65139b5b854c0f6b82ed945ba526bff3"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cfa2bbca929aa742b5084fd4663dd4b87c191c844326fcb21c3afd2d11497f80"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-win32.whl", hash = "sha256:b05df9ea7496df11b710081bd90ecc3a3db6adb4fee36f6a411e7bc91a18aa42"},
|
||||
{file = "yarl-1.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:24ad1d10c9db1953291f56b5fe76203977f1ed05f82d09ec97acb623a7976574"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2a1fca9588f360036242f379bfea2b8b44cae2721859b1c56d033adfd5893634"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f37db05c6051eff17bc832914fe46869f8849de5b92dc4a3466cd63095d23dfd"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:77e913b846a6b9c5f767b14dc1e759e5aff05502fe73079f6f4176359d832581"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0978f29222e649c351b173da2b9b4665ad1feb8d1daa9d971eb90df08702668a"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388a45dc77198b2460eac0aca1efd6a7c09e976ee768b0d5109173e521a19daf"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2305517e332a862ef75be8fad3606ea10108662bc6fe08509d5ca99503ac2aee"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42430ff511571940d51e75cf42f1e4dbdded477e71c1b7a17f4da76c1da8ea76"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3150078118f62371375e1e69b13b48288e44f6691c1069340081c3fd12c94d5b"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c15163b6125db87c8f53c98baa5e785782078fbd2dbeaa04c6141935eb6dab7a"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4d04acba75c72e6eb90745447d69f84e6c9056390f7a9724605ca9c56b4afcc6"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e7fd20d6576c10306dea2d6a5765f46f0ac5d6f53436217913e952d19237efc4"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:75c16b2a900b3536dfc7014905a128a2bea8fb01f9ee26d2d7d8db0a08e7cb2c"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6d88056a04860a98341a0cf53e950e3ac9f4e51d1b6f61a53b0609df342cc8b2"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-win32.whl", hash = "sha256:fb742dcdd5eec9f26b61224c23baea46c9055cf16f62475e11b9b15dfd5c117b"},
|
||||
{file = "yarl-1.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8c46d3d89902c393a1d1e243ac847e0442d0196bbd81aecc94fcebbc2fd5857c"},
|
||||
{file = "yarl-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ceff9722e0df2e0a9e8a79c610842004fa54e5b309fe6d218e47cd52f791d7ef"},
|
||||
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f6b4aca43b602ba0f1459de647af954769919c4714706be36af670a5f44c9c1"},
|
||||
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1684a9bd9077e922300ecd48003ddae7a7474e0412bea38d4631443a91d61077"},
|
||||
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ebb78745273e51b9832ef90c0898501006670d6e059f2cdb0e999494eb1450c2"},
|
||||
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3adeef150d528ded2a8e734ebf9ae2e658f4c49bf413f5f157a470e17a4a2e89"},
|
||||
{file = "yarl-1.8.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57a7c87927a468e5a1dc60c17caf9597161d66457a34273ab1760219953f7f4c"},
|
||||
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:efff27bd8cbe1f9bd127e7894942ccc20c857aa8b5a0327874f30201e5ce83d0"},
|
||||
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a783cd344113cb88c5ff7ca32f1f16532a6f2142185147822187913eb989f739"},
|
||||
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:705227dccbe96ab02c7cb2c43e1228e2826e7ead880bb19ec94ef279e9555b5b"},
|
||||
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:34c09b43bd538bf6c4b891ecce94b6fa4f1f10663a8d4ca589a079a5018f6ed7"},
|
||||
{file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a48f4f7fea9a51098b02209d90297ac324241bf37ff6be6d2b0149ab2bd51b37"},
|
||||
{file = "yarl-1.8.2-cp37-cp37m-win32.whl", hash = "sha256:0414fd91ce0b763d4eadb4456795b307a71524dbacd015c657bb2a39db2eab89"},
|
||||
{file = "yarl-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:d881d152ae0007809c2c02e22aa534e702f12071e6b285e90945aa3c376463c5"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5df5e3d04101c1e5c3b1d69710b0574171cc02fddc4b23d1b2813e75f35a30b1"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7a66c506ec67eb3159eea5096acd05f5e788ceec7b96087d30c7d2865a243918"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b4fa2606adf392051d990c3b3877d768771adc3faf2e117b9de7eb977741229"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e21fb44e1eff06dd6ef971d4bdc611807d6bd3691223d9c01a18cec3677939e"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93202666046d9edadfe9f2e7bf5e0782ea0d497b6d63da322e541665d65a044e"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fc77086ce244453e074e445104f0ecb27530d6fd3a46698e33f6c38951d5a0f1"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dd68a92cab699a233641f5929a40f02a4ede8c009068ca8aa1fe87b8c20ae3"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b372aad2b5f81db66ee7ec085cbad72c4da660d994e8e590c997e9b01e44901"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e6f3515aafe0209dd17fb9bdd3b4e892963370b3de781f53e1746a521fb39fc0"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dfef7350ee369197106805e193d420b75467b6cceac646ea5ed3049fcc950a05"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:728be34f70a190566d20aa13dc1f01dc44b6aa74580e10a3fb159691bc76909d"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ff205b58dc2929191f68162633d5e10e8044398d7a45265f90a0f1d51f85f72c"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baf211dcad448a87a0d9047dc8282d7de59473ade7d7fdf22150b1d23859f946"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-win32.whl", hash = "sha256:272b4f1599f1b621bf2aabe4e5b54f39a933971f4e7c9aa311d6d7dc06965165"},
|
||||
{file = "yarl-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:326dd1d3caf910cd26a26ccbfb84c03b608ba32499b5d6eeb09252c920bcbe4f"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f8ca8ad414c85bbc50f49c0a106f951613dfa5f948ab69c10ce9b128d368baf8"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:418857f837347e8aaef682679f41e36c24250097f9e2f315d39bae3a99a34cbf"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ae0eec05ab49e91a78700761777f284c2df119376e391db42c38ab46fd662b77"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:009a028127e0a1755c38b03244c0bea9d5565630db9c4cf9572496e947137a87"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3edac5d74bb3209c418805bda77f973117836e1de7c000e9755e572c1f7850d0"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da65c3f263729e47351261351b8679c6429151ef9649bba08ef2528ff2c423b2"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ef8fb25e52663a1c85d608f6dd72e19bd390e2ecaf29c17fb08f730226e3a08"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcd7bb1e5c45274af9a1dd7494d3c52b2be5e6bd8d7e49c612705fd45420b12d"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44ceac0450e648de86da8e42674f9b7077d763ea80c8ceb9d1c3e41f0f0a9951"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:97209cc91189b48e7cfe777237c04af8e7cc51eb369004e061809bcdf4e55220"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:48dd18adcf98ea9cd721a25313aef49d70d413a999d7d89df44f469edfb38a06"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e59399dda559688461762800d7fb34d9e8a6a7444fd76ec33220a926c8be1516"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d617c241c8c3ad5c4e78a08429fa49e4b04bedfc507b34b4d8dceb83b4af3588"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-win32.whl", hash = "sha256:cb6d48d80a41f68de41212f3dfd1a9d9898d7841c8f7ce6696cf2fd9cb57ef83"},
|
||||
{file = "yarl-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:6604711362f2dbf7160df21c416f81fac0de6dbcf0b5445a2ef25478ecc4c778"},
|
||||
{file = "yarl-1.8.2.tar.gz", hash = "sha256:49d43402c6e3013ad0978602bf6bf5328535c48d192304b91b97a3c6790b1562"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8c2ad583743d16ddbdf6bb14b5cd76bf43b0d0006e918809d5d4ddf7bde8dd82"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:82aa6264b36c50acfb2424ad5ca537a2060ab6de158a5bd2a72a032cc75b9eb8"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c0c77533b5ed4bcc38e943178ccae29b9bcf48ffd1063f5821192f23a1bd27b9"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee4afac41415d52d53a9833ebae7e32b344be72835bbb589018c9e938045a560"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bf345c3a4f5ba7f766430f97f9cc1320786f19584acc7086491f45524a551ac"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2a96c19c52ff442a808c105901d0bdfd2e28575b3d5f82e2f5fd67e20dc5f4ea"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:891c0e3ec5ec881541f6c5113d8df0315ce5440e244a716b95f2525b7b9f3608"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c3a53ba34a636a256d767c086ceb111358876e1fb6b50dfc4d3f4951d40133d5"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:566185e8ebc0898b11f8026447eacd02e46226716229cea8db37496c8cdd26e0"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2b0738fb871812722a0ac2154be1f049c6223b9f6f22eec352996b69775b36d4"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:32f1d071b3f362c80f1a7d322bfd7b2d11e33d2adf395cc1dd4df36c9c243095"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:e9fdc7ac0d42bc3ea78818557fab03af6181e076a2944f43c38684b4b6bed8e3"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:56ff08ab5df8429901ebdc5d15941b59f6253393cb5da07b4170beefcf1b2528"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-win32.whl", hash = "sha256:8ea48e0a2f931064469bdabca50c2f578b565fc446f302a79ba6cc0ee7f384d3"},
|
||||
{file = "yarl-1.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:50f33040f3836e912ed16d212f6cc1efb3231a8a60526a407aeb66c1c1956dde"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:646d663eb2232d7909e6601f1a9107e66f9791f290a1b3dc7057818fe44fc2b6"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aff634b15beff8902d1f918012fc2a42e0dbae6f469fce134c8a0dc51ca423bb"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a83503934c6273806aed765035716216cc9ab4e0364f7f066227e1aaea90b8d0"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b25322201585c69abc7b0e89e72790469f7dad90d26754717f3310bfe30331c2"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:22a94666751778629f1ec4280b08eb11815783c63f52092a5953faf73be24191"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ec53a0ea2a80c5cd1ab397925f94bff59222aa3cf9c6da938ce05c9ec20428d"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:159d81f22d7a43e6eabc36d7194cb53f2f15f498dbbfa8edc8a3239350f59fe7"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832b7e711027c114d79dffb92576acd1bd2decc467dec60e1cac96912602d0e6"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:95d2ecefbcf4e744ea952d073c6922e72ee650ffc79028eb1e320e732898d7e8"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d4e2c6d555e77b37288eaf45b8f60f0737c9efa3452c6c44626a5455aeb250b9"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:783185c75c12a017cc345015ea359cc801c3b29a2966c2655cd12b233bf5a2be"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:b8cc1863402472f16c600e3e93d542b7e7542a540f95c30afd472e8e549fc3f7"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:822b30a0f22e588b32d3120f6d41e4ed021806418b4c9f0bc3048b8c8cb3f92a"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-win32.whl", hash = "sha256:a60347f234c2212a9f0361955007fcf4033a75bf600a33c88a0a8e91af77c0e8"},
|
||||
{file = "yarl-1.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:be6b3fdec5c62f2a67cb3f8c6dbf56bbf3f61c0f046f84645cd1ca73532ea051"},
|
||||
{file = "yarl-1.9.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:38a3928ae37558bc1b559f67410df446d1fbfa87318b124bf5032c31e3447b74"},
|
||||
{file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac9bb4c5ce3975aeac288cfcb5061ce60e0d14d92209e780c93954076c7c4367"},
|
||||
{file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3da8a678ca8b96c8606bbb8bfacd99a12ad5dd288bc6f7979baddd62f71c63ef"},
|
||||
{file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13414591ff516e04fcdee8dc051c13fd3db13b673c7a4cb1350e6b2ad9639ad3"},
|
||||
{file = "yarl-1.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf74d08542c3a9ea97bb8f343d4fcbd4d8f91bba5ec9d5d7f792dbe727f88938"},
|
||||
{file = "yarl-1.9.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e7221580dc1db478464cfeef9b03b95c5852cc22894e418562997df0d074ccc"},
|
||||
{file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:494053246b119b041960ddcd20fd76224149cfea8ed8777b687358727911dd33"},
|
||||
{file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:52a25809fcbecfc63ac9ba0c0fb586f90837f5425edfd1ec9f3372b119585e45"},
|
||||
{file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:e65610c5792870d45d7b68c677681376fcf9cc1c289f23e8e8b39c1485384185"},
|
||||
{file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:1b1bba902cba32cdec51fca038fd53f8beee88b77efc373968d1ed021024cc04"},
|
||||
{file = "yarl-1.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:662e6016409828ee910f5d9602a2729a8a57d74b163c89a837de3fea050c7582"},
|
||||
{file = "yarl-1.9.2-cp37-cp37m-win32.whl", hash = "sha256:f364d3480bffd3aa566e886587eaca7c8c04d74f6e8933f3f2c996b7f09bee1b"},
|
||||
{file = "yarl-1.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6a5883464143ab3ae9ba68daae8e7c5c95b969462bbe42e2464d60e7e2698368"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5610f80cf43b6202e2c33ba3ec2ee0a2884f8f423c8f4f62906731d876ef4fac"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b9a4e67ad7b646cd6f0938c7ebfd60e481b7410f574c560e455e938d2da8e0f4"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:83fcc480d7549ccebe9415d96d9263e2d4226798c37ebd18c930fce43dfb9574"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fcd436ea16fee7d4207c045b1e340020e58a2597301cfbcfdbe5abd2356c2fb"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84e0b1599334b1e1478db01b756e55937d4614f8654311eb26012091be109d59"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3458a24e4ea3fd8930e934c129b676c27452e4ebda80fbe47b56d8c6c7a63a9e"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:838162460b3a08987546e881a2bfa573960bb559dfa739e7800ceeec92e64417"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f4e2d08f07a3d7d3e12549052eb5ad3eab1c349c53ac51c209a0e5991bbada78"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:de119f56f3c5f0e2fb4dee508531a32b069a5f2c6e827b272d1e0ff5ac040333"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:149ddea5abf329752ea5051b61bd6c1d979e13fbf122d3a1f9f0c8be6cb6f63c"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:674ca19cbee4a82c9f54e0d1eee28116e63bc6fd1e96c43031d11cbab8b2afd5"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:9b3152f2f5677b997ae6c804b73da05a39daa6a9e85a512e0e6823d81cdad7cc"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5415d5a4b080dc9612b1b63cba008db84e908b95848369aa1da3686ae27b6d2b"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-win32.whl", hash = "sha256:f7a3d8146575e08c29ed1cd287068e6d02f1c7bdff8970db96683b9591b86ee7"},
|
||||
{file = "yarl-1.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:63c48f6cef34e6319a74c727376e95626f84ea091f92c0250a98e53e62c77c72"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:75df5ef94c3fdc393c6b19d80e6ef1ecc9ae2f4263c09cacb178d871c02a5ba9"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c027a6e96ef77d401d8d5a5c8d6bc478e8042f1e448272e8d9752cb0aff8b5c8"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3b078dbe227f79be488ffcfc7a9edb3409d018e0952cf13f15fd6512847f3f7"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59723a029760079b7d991a401386390c4be5bfec1e7dd83e25a6a0881859e716"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b03917871bf859a81ccb180c9a2e6c1e04d2f6a51d953e6a5cdd70c93d4e5a2a"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c1012fa63eb6c032f3ce5d2171c267992ae0c00b9e164efe4d73db818465fac3"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a74dcbfe780e62f4b5a062714576f16c2f3493a0394e555ab141bf0d746bb955"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8c56986609b057b4839968ba901944af91b8e92f1725d1a2d77cbac6972b9ed1"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:2c315df3293cd521033533d242d15eab26583360b58f7ee5d9565f15fee1bef4"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:b7232f8dfbd225d57340e441d8caf8652a6acd06b389ea2d3222b8bc89cbfca6"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:53338749febd28935d55b41bf0bcc79d634881195a39f6b2f767870b72514caf"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:066c163aec9d3d073dc9ffe5dd3ad05069bcb03fcaab8d221290ba99f9f69ee3"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8288d7cd28f8119b07dd49b7230d6b4562f9b61ee9a4ab02221060d21136be80"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-win32.whl", hash = "sha256:b124e2a6d223b65ba8768d5706d103280914d61f5cae3afbc50fc3dfcc016623"},
|
||||
{file = "yarl-1.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:61016e7d582bc46a5378ffdd02cd0314fb8ba52f40f9cf4d9a5e7dbef88dee18"},
|
||||
{file = "yarl-1.9.2.tar.gz", hash = "sha256:04ab9d4b9f587c06d801c2abfe9317b77cdf996c65a90d5e84ecc45010823571"},
|
||||
]
|
||||
|
||||
+3
-2
@@ -7,14 +7,15 @@ license = "Apache-2.0"
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.8, <4.0.0"
|
||||
specklepy = "^2.11.4"
|
||||
specklepy = "^2.14.0"
|
||||
attrs = "^23.1.0"
|
||||
|
||||
# [tool.poetry.group.local_specklepy.dependencies]
|
||||
# specklepy = {path = "../specklepy", develop = true}
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
numpy = "^1.23.5"
|
||||
fake-bpy-module-latest = "^20221006"
|
||||
fake-bpy-module-latest = "^20230117"
|
||||
black = "^22.10.0"
|
||||
pylint = "^2.15.7"
|
||||
ruff = "^0.0.166"
|
||||
|
||||
Reference in New Issue
Block a user