def new_object_type_source(parent: ObjectTypeMeta, child: ObjectTypeMeta) -> str: assert parent.type == child.base tree = Module(body=[], type_ignores=[]) if parent.type in built_in_types_names(): import_from = arcor2.object_types.__name__ else: import_from = camel_case_to_snake_case(parent.type) tree.body.append( ImportFrom(module=import_from, names=[alias(name=parent.type, asname=None)], level=0)) c = ClassDef(name=child.type, bases=[get_name(parent.type)], keywords=[], body=[], decorator_list=[]) # TODO add docstring with description (if provided) c.body.append(Pass()) tree.body.append(c) return tree_to_str(tree)
def program_src(project: Project, scene: Scene, built_in_objects: Set[str], add_logic: bool = True) -> str: tree = empty_script_tree(add_main_loop=add_logic) # get object instances from resources object for obj in scene.objects: if obj.type in built_in_objects: add_import(tree, arcor2.object_types.__name__, obj.type, try_to_import=False) else: add_import(tree, "object_types." + camel_case_to_snake_case(obj.type), obj.type, try_to_import=False) object_instance_from_res(tree, obj.name, obj.id, obj.type, "objects") for srv in scene.services: add_import(tree, "services." + camel_case_to_snake_case(srv.type), srv.type, try_to_import=False) object_instance_from_res(tree, srv.type, srv.type, srv.type, "services") if add_logic: add_logic_to_loop(tree, scene, project) return SCRIPT_HEADER + tree_to_str(tree)
def test_meta_to_source() -> None: parent = ObjectTypeMeta(type="Generic") child = ObjectTypeMeta(type="NewType", description="blabla bla", base="Generic") source = tree_to_str(new_object_type(parent, child)) assert "class NewType(Generic)" in source
def program_src(type_defs: TypesDict, project: CProject, scene: CScene, add_logic: bool = True) -> str: tree = empty_script_tree(project.id, add_main_loop=add_logic) # get object instances from resources object main = find_function("main", tree) last_assign = find_last_assign(main) for obj in scene.objects: add_import(tree, "object_types." + humps.depascalize(obj.type), obj.type, try_to_import=False) last_assign += 1 main.body.insert(last_assign, object_instance_from_res(obj.name, obj.id, obj.type)) # TODO temporary solution - should be (probably) handled by plugin(s) from arcor2 import json # TODO should we put there even unused parameters? for param in project.parameters: val = json.loads(param.value) aval: Optional[expr] = None if isinstance(val, bool): # subclass of int aval = NameConstant(value=val, kind=None) elif isinstance(val, (int, float)): aval = Num(n=val, kind=None) elif isinstance(val, str): aval = Str(s=val, kind="") if not aval: raise Arcor2Exception( f"Unsupported project parameter type ({param.type}) or value ({val})." ) last_assign += 1 main.body.insert( last_assign, Assign( # TODO use rather AnnAssign? targets=[Name(id=param.name, ctx=Store())], value=aval, type_comment=None), ) if add_logic: add_logic_to_loop(type_defs, tree, scene, project) return SCRIPT_HEADER + tree_to_str(tree)
async def update_object_model_cb(req: srpc.o.UpdateObjectModel.Request, ui: WsClient) -> None: can_modify_scene() glob.LOCK.scene_or_exception(True) # only allow while editing scene obj_data = glob.OBJECT_TYPES[req.args.object_type_id] if not obj_data.type_def: raise Arcor2Exception("ObjectType disabled.") if not issubclass(obj_data.type_def, CollisionObject): raise Arcor2Exception("Not a CollisionObject.") assert obj_data.meta.object_model assert obj_data.ast if req.args.object_model == obj_data.meta.object_model: raise Arcor2Exception("No change requested.") await ensure_write_locked(req.args.object_type_id, glob.USERS.user_name(ui)) if req.dry_run: return await update_object_model(obj_data.meta, req.args.object_model) obj_data.meta.object_model = req.args.object_model ot = obj_data.meta.to_object_type() ot.source = tree_to_str(obj_data.ast) obj_data.meta.modified = await storage.update_object_type(ot) evt = sevts.o.ChangedObjectTypes([obj_data.meta]) evt.change_type = events.Event.Type.UPDATE asyncio.ensure_future(notif.broadcast_event(evt))
def global_action_points_class(project: CachedProject) -> str: tree = Module(body=[]) tree.body.append( ImportFrom( module=arcor2.data.common.__name__, names=[ alias(name=ActionPoint.__name__, asname=None), alias(name=Position.__name__, asname=None), alias(name=Pose.__name__, asname=None), alias(name=ProjectRobotJoints.__name__, asname=None), ], level=0, )) tree.body.append( ImportFrom( module=copy.__name__, names=[alias(name=copy.deepcopy.__name__, asname=None)], level=0, )) tree.body.append( ImportFrom( module=RES_MODULE, names=[alias(name=RES_CLS, asname=None)], level=0, )) aps_init_body: List[Union[Assign, Pass]] = [] for ap in project.action_points: ap_cls_body: List[Assign] = [ Assign( targets=[ Attribute(value=Name(id="self", ctx=Load()), attr="_position", ctx=Store()) ], value=Attribute( value=Call( func=Attribute( value=Attribute(value=Name(id="res", ctx=Load()), attr="project", ctx=Load()), attr=CachedProject.bare_action_point.__name__, ctx=Load(), ), args=[Str(s=ap.id, kind="")], keywords=[], ), attr="position", ctx=Load(), ), type_comment=None, ) ] ap_type_name = humps.pascalize(ap.name) ap_joints_init_body: List[Assign] = [] for joints in project.ap_joints(ap.id): ap_joints_init_body.append( Assign( targets=[ Attribute(value=Name(id="self", ctx=Load()), attr=f"_{joints.name}", ctx=Store()) ], value=Call( func=Attribute( value=Attribute(value=Name(id="res", ctx=Load()), attr="project", ctx=Load()), attr="joints", ctx=Load(), ), args=[Str(s=joints.id, kind="")], keywords=[], ), type_comment=None, )) if ap_joints_init_body: ap_joints_cls_def = ClassDef( name=f"{ap_type_name}Joints", bases=[], keywords=[], body=[ FunctionDef( name="__init__", args=arguments( args=[ arg(arg="self", annotation=None, type_comment=None), arg(arg="res", annotation=Name(id=RES_CLS, ctx=Load()), type_comment=None), ], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[], ), body=ap_joints_init_body, decorator_list=[], returns=None, type_comment=None, ) ], decorator_list=[], ) for joints in project.ap_joints(ap.id): ap_joints_cls_def.body.append( FunctionDef( name=joints.name, args=arguments( args=[ arg(arg="self", annotation=None, type_comment=None) ], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[], ), body=[ Return(value=Call( func=Name(id=copy.deepcopy.__name__, ctx=Load()), args=[ Attribute(value=Name(id="self", ctx=Load()), attr=f"_{joints.name}", ctx=Load()) ], keywords=[], )) ], decorator_list=[Name(id="property", ctx=Load())], returns=Name(id=ProjectRobotJoints.__name__, ctx=Load()), type_comment=None, )) tree.body.append(ap_joints_cls_def) ap_cls_body.append( Assign( targets=[ Attribute(value=Name(id="self", ctx=Load()), attr="joints", ctx=Store()) ], value=Call( func=Name(id=f"{ap_type_name}Joints", ctx=Load()), args=[Name(id="res", ctx=Load())], keywords=[], ), type_comment=None, )) ap_orientations_init_body: List[Assign] = [] for ori in project.ap_orientations(ap.id): ap_orientations_init_body.append( Assign( targets=[ Attribute(value=Name(id="self", ctx=Load()), attr=f"_{ori.name}", ctx=Store()) ], value=Call( func=Attribute( value=Attribute(value=Name(id="res", ctx=Load()), attr="project", ctx=Load()), attr="pose", ctx=Load(), ), args=[Str(s=ori.id, kind="")], keywords=[], ), type_comment=None, )) if ap_orientations_init_body: ap_orientations_cls_def = ClassDef( name=f"{ap_type_name}Poses", bases=[], keywords=[], body=[ FunctionDef( name="__init__", args=arguments( args=[ arg(arg="self", annotation=None, type_comment=None), arg(arg="res", annotation=Name(id=RES_CLS, ctx=Load()), type_comment=None), ], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[], ), body=ap_orientations_init_body, decorator_list=[], returns=None, type_comment=None, ) ], decorator_list=[], ) for ori in project.ap_orientations(ap.id): ap_orientations_cls_def.body.append( FunctionDef( name=ori.name, args=arguments( args=[ arg(arg="self", annotation=None, type_comment=None) ], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[], ), body=[ Return(value=Call( func=Name(id=copy.deepcopy.__name__, ctx=Load()), args=[ Attribute(value=Name(id="self", ctx=Load()), attr=f"_{ori.name}", ctx=Load()) ], keywords=[], )) ], decorator_list=[Name(id="property", ctx=Load())], returns=Name(id=Pose.__name__, ctx=Load()), type_comment=None, )) tree.body.append(ap_orientations_cls_def) ap_cls_body.append( Assign( targets=[ Attribute(value=Name(id="self", ctx=Load()), attr="poses", ctx=Store()) ], value=Call( func=Name(id=f"{ap_type_name}Poses", ctx=Load()), args=[Name(id="res", ctx=Load())], keywords=[], ), type_comment=None, )) ap_cls_def = ClassDef( name=ap_type_name, bases=[], keywords=[], body=[ FunctionDef( name="__init__", args=arguments( args=[ arg(arg="self", annotation=None, type_comment=None), arg(arg="res", annotation=Name(id=RES_CLS, ctx=Load()), type_comment=None), ], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[], ), body=ap_cls_body, decorator_list=[], returns=None, type_comment=None, ) ], decorator_list=[], ) # add copy property for position ap_cls_def.body.append( FunctionDef( name="position", args=arguments( args=[arg(arg="self", annotation=None, type_comment=None)], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[], ), body=[ Return(value=Call( func=Name(id=copy.deepcopy.__name__, ctx=Load()), args=[ Attribute(value=Name(id="self", ctx=Load()), attr="_position", ctx=Load()) ], keywords=[], )) ], decorator_list=[Name(id="property", ctx=Load())], returns=Name(id=Position.__name__, ctx=Load()), type_comment=None, )) tree.body.append(ap_cls_def) aps_init_body.append( Assign( targets=[ Attribute(value=Name(id="self", ctx=Load()), attr=ap.name, ctx=Store()) ], value=Call(func=Name(id=ap_type_name, ctx=Load()), args=[Name(id="res", ctx=Load())], keywords=[]), type_comment=None, )) if not aps_init_body: # there are no action points aps_init_body.append(Pass()) aps_cls_def = ClassDef( name="ActionPoints", bases=[], keywords=[], body=[ FunctionDef( name="__init__", args=arguments( args=[ arg(arg="self", annotation=None, type_comment=None), arg(arg="res", annotation=Name(id=RES_CLS, ctx=Load()), type_comment=None), ], vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[], ), body=aps_init_body, decorator_list=[], returns=None, type_comment=None, ) ], decorator_list=[], ) tree.body.append(aps_cls_def) return tree_to_str(tree)
async def new_object_type_cb(req: srpc.o.NewObjectType.Request, ui: WsClient) -> None: async with ctx_write_lock(glob.LOCK.SpecialValues.ADDING_OBJECT, ui): meta = req.args if meta.type in glob.OBJECT_TYPES: raise Arcor2Exception("Object type already exists.") hlp.is_valid_type(meta.type) if meta.base not in glob.OBJECT_TYPES: raise Arcor2Exception( f"Unknown base object type '{meta.base}', " f"known types are: {', '.join(glob.OBJECT_TYPES.keys())}.") base = glob.OBJECT_TYPES[meta.base] if base.meta.disabled: raise Arcor2Exception("Base object is disabled.") assert base.type_def is not None if issubclass(base.type_def, Robot): raise Arcor2Exception("Can't subclass Robot.") meta.has_pose = issubclass(base.type_def, GenericWithPose) if not meta.has_pose and meta.object_model: raise Arcor2Exception( "Object without pose can't have collision model.") if req.dry_run: return None obj = meta.to_object_type() ast = new_object_type(glob.OBJECT_TYPES[meta.base].meta, meta) obj.source = tree_to_str(ast) if meta.object_model: if meta.object_model.type == Model3dType.MESH: # TODO check whether mesh id exists - if so, then use existing mesh, if not, upload a new one # ...get whole mesh (focus_points) based on mesh id assert meta.object_model.mesh try: meta.object_model.mesh = await storage.get_mesh( meta.object_model.mesh.id) except storage.ProjectServiceException as e: glob.logger.error(e) raise Arcor2Exception( f"Mesh ID {meta.object_model.mesh.id} does not exist.") else: meta.object_model.model().id = meta.type await storage.put_model(meta.object_model.model()) type_def = await hlp.run_in_executor( hlp.save_and_import_type_def, obj.source, obj.id, base.type_def, settings.OBJECT_TYPE_PATH, settings.OBJECT_TYPE_MODULE, ) assert issubclass(type_def, base.type_def) actions = object_actions(type_def, ast) await storage.update_object_type(obj) glob.OBJECT_TYPES[meta.type] = ObjectTypeData(meta, type_def, actions, ast) add_ancestor_actions(meta.type, glob.OBJECT_TYPES) evt = sevts.o.ChangedObjectTypes([meta]) evt.change_type = events.Event.Type.ADD asyncio.ensure_future(notif.broadcast_event(evt)) return None
async def new_object_type_cb(req: srpc.o.NewObjectType.Request, ui: WsClient) -> None: async with ctx_write_lock(glob.LOCK.SpecialValues.ADDING_OBJECT, glob.USERS.user_name(ui)): meta = req.args if meta.type in glob.OBJECT_TYPES: raise Arcor2Exception("Object type already exists.") hlp.is_valid_type(meta.type) if meta.base not in glob.OBJECT_TYPES: raise Arcor2Exception( f"Unknown base object type '{meta.base}', " f"known types are: {', '.join(glob.OBJECT_TYPES.keys())}.") base = glob.OBJECT_TYPES[meta.base] if base.meta.disabled: raise Arcor2Exception("Base object is disabled.") assert base.type_def is not None if issubclass(base.type_def, Robot): raise Arcor2Exception("Can't subclass Robot.") meta.has_pose = issubclass(base.type_def, GenericWithPose) if issubclass(base.type_def, CollisionObject): if not meta.object_model: raise Arcor2Exception( "Objects based on CollisionObject must have collision model." ) else: if meta.object_model: raise Arcor2Exception( "Only objects based on CollisionObject can have collision model." ) if req.dry_run: return None obj = meta.to_object_type() ast = new_object_type(glob.OBJECT_TYPES[meta.base].meta, meta) obj.source = tree_to_str(ast) if meta.object_model: await update_object_model(meta, meta.object_model) type_def = await hlp.run_in_executor( hlp.save_and_import_type_def, obj.source, obj.id, base.type_def, settings.OBJECT_TYPE_PATH, settings.OBJECT_TYPE_MODULE, ) assert issubclass(type_def, base.type_def) actions = object_actions(type_def, ast) meta.modified = await storage.update_object_type(obj) glob.OBJECT_TYPES[meta.type] = ObjectTypeData(meta, type_def, actions, ast) add_ancestor_actions(meta.type, glob.OBJECT_TYPES) evt = sevts.o.ChangedObjectTypes([meta]) evt.change_type = events.Event.Type.ADD asyncio.ensure_future(notif.broadcast_event(evt)) return None