From 48ea497be1acc72b59c80d18dfa4ab4091722000 Mon Sep 17 00:00:00 2001 From: Naomi Pentrel <5212232+npentrel@users.noreply.github.com> Date: Fri, 5 Dec 2025 20:18:50 +0100 Subject: [PATCH 1/2] DOCS-4615: Update reconfigure usage --- docs/data-ai/ai/act.md | 28 ++++++++------- docs/dev/reference/changelog.md | 6 ++++ .../hello-world/tutorial-desk-safari.md | 29 +++++++-------- docs/operate/modules/advanced/dependencies.md | 35 ++++++++++--------- .../modules/support-hardware/_index.md | 12 ++++--- .../reference/services/motion/_index.md | 11 +++--- 6 files changed, 68 insertions(+), 53 deletions(-) diff --git a/docs/data-ai/ai/act.md b/docs/data-ai/ai/act.md index e891059b7b..ebd3aa51c2 100644 --- a/docs/data-ai/ai/act.md +++ b/docs/data-ai/ai/act.md @@ -203,10 +203,11 @@ Update the `reconfigure` method to initialize all the variables: {{% tab name="Python" %}} ```python {class="line-numbers linkable-line-numbers" data-start="79" } - def reconfigure( - self, config: ComponentConfig, - dependencies: Mapping[ResourceName, ResourceBase] - ): + @classmethod + def new( + cls, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase] + ) -> Self: + obj = super().new(config, dependencies) camera_name = config.attributes.fields["camera_name"].string_value vision_name = config.attributes.fields["vision_name"].string_value @@ -221,10 +222,10 @@ Update the `reconfigure` method to initialize all the variables: f"{list(dependencies.keys())}") vision_resource = dependencies[vision_resource_name] - self.vision_service = cast(VisionClient, vision_resource) - self.camera_name = camera_name + obj.vision_service = cast(VisionClient, vision_resource) + obj.camera_name = camera_name - return super().reconfigure(config, dependencies) + return obj ``` {{% /tab %}} @@ -236,10 +237,11 @@ Update the `reconfigure` method to initialize all the variables: {{% tab name="Python" %}} ```python {class="line-numbers linkable-line-numbers" data-start="79" } - def reconfigure( - self, config: ComponentConfig, - dependencies: Mapping[ResourceName, ResourceBase] - ): + @classmethod + def new( + cls, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase] + ) -> Self: + obj = super().new(config, dependencies) # ... arm_name = config.attributes.fields["arm_name"].string_value arm_resource_name = Arm.get_resource_name(arm_name) @@ -250,9 +252,9 @@ Update the `reconfigure` method to initialize all the variables: f"{list(dependencies.keys())}") arm_resource = dependencies[arm_resource_name] - self.arm = cast(Arm, arm_resource) + obj.arm = cast(Arm, arm_resource) - return super().reconfigure(config, dependencies) + return obj ``` {{% /tab %}} diff --git a/docs/dev/reference/changelog.md b/docs/dev/reference/changelog.md index b4465d3407..1cb643b0d0 100644 --- a/docs/dev/reference/changelog.md +++ b/docs/dev/reference/changelog.md @@ -44,6 +44,12 @@ date: "2024-09-18" # updated: "" # When the content was last entirely checked --- +{{% changelog color="changed" title="Use new() instead of reconfigure() in Python modules" date="2025-12-05" %}} + +The Python module `reconfigure()` method has been removed in favour of using `new()`. + +{{% /changelog %}} + {{% changelog color="changed" title="GetImages replaced GetImage" date="2025-10-31" %}} [`GetImage`](/dev/reference/apis/components/camera/#getimage) is deprecated. diff --git a/docs/operate/hello-world/tutorial-desk-safari.md b/docs/operate/hello-world/tutorial-desk-safari.md index 8c5bdcc1a7..738b6ddb5a 100644 --- a/docs/operate/hello-world/tutorial-desk-safari.md +++ b/docs/operate/hello-world/tutorial-desk-safari.md @@ -444,8 +444,8 @@ In the hello-world-game-py/src/models/game_logic.py file, find the **Initialize all variables.** Unlike class attributes, instance attributes are unique to a single instance of the button running on your machine. -You use them to initialize instance parameters, like `self.new_game`, in the `reconfigure` method. -`viam-server` calls the `reconfigure` method whenever the module starts or a configuration change occurs. +You use them to initialize instance parameters, like `self.new_game`, in the `new` method. +`viam-server` calls the `new` method whenever the module starts or a configuration change occurs. Whenever you change the config of the button, the parameters get set to the values assigned in the reconfigure method. You must initialize all variables that can and may be accessed before they are assigned elsewhere in the code. @@ -460,18 +460,19 @@ On top of game state variables, you also need to initialize the vision service a The dependencies parameter contains all the resources this component can access. By using `cast` you tell Python that the vision resource is specifically a VisionClient. -Update the `reconfigure` method to initialize all the variables: +Update the `new` method to initialize all the variables: ```python {class="line-numbers linkable-line-numbers" data-start="79" } - def reconfigure( - self, config: ComponentConfig, - dependencies: Mapping[ResourceName, ResourceBase] - ): + @classmethod + def new( + cls, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase] + ) -> Self: + obj = super().new(config, dependencies) # Game state - self.new_game: bool = False - self.score: int = 0 - self.time_round_start: Optional[datetime] = None - self.item_to_detect: str = "" + obj.new_game: bool = False + obj.score: int = 0 + obj.time_round_start: Optional[datetime] = None + obj.item_to_detect: str = "" camera_name = config.attributes.fields["camera_name"].string_value detector_name = config.attributes.fields["detector_name"].string_value @@ -487,10 +488,10 @@ Update the `reconfigure` method to initialize all the variables: f"{list(dependencies.keys())}") vision_resource = dependencies[vision_resource_name] - self.detector = cast(VisionClient, vision_resource) - self.camera_name = camera_name + obj.detector = cast(VisionClient, vision_resource) + obj.camera_name = camera_name - return super().reconfigure(config, dependencies) + return obj ``` {{% /tab %}} diff --git a/docs/operate/modules/advanced/dependencies.md b/docs/operate/modules/advanced/dependencies.md index 694bcde225..e0a99194fb 100644 --- a/docs/operate/modules/advanced/dependencies.md +++ b/docs/operate/modules/advanced/dependencies.md @@ -161,39 +161,41 @@ Accessing dependencies from the resource works differently for different program {{< tabs >}} {{% tab name="Python" %}} -To be able to access the dependencies, use the `reconfigure` method to: +To be able to access the dependencies, use the `new` method to: - Access the dependency by using its name as a key in the `dependencies` mapping. - Cast the dependency to the correct type and store it. ```python {class="line-numbers linkable-line-numbers"} -def reconfigure( - self, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase] -): + @classmethod + def new( + cls, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase] + ) -> Self: + obj = super().new(config, dependencies) camera_name = config.attributes.fields["camera_name"].string_value camera_resource = dependencies[Camera.get_resource_name(camera_name)] - self.camera = cast(Camera, camera_resource) + obj.camera = cast(Camera, camera_resource) # If you need to use the camera name in your module, # for example to pass it to a vision service method, # you can store it in an instance variable. - self.camera_name = camera_name + obj.camera_name = camera_name sensor_name = config.attributes.fields["sensor_name"].string_value sensor_resource = dependencies[Sensor.get_resource_name(sensor_name)] - self.sensor = cast(Sensor, sensor_resource) + obj.sensor = cast(Sensor, sensor_resource) # Optional dependencies may not be present in the config - self.vision_svc = None + obj.vision_svc = None if "vision_name" in config.attributes.fields: vision_name = config.attributes.fields["vision_name"].string_value # For optional dependencies, use .get() and handle None vision_resource = dependencies.get(VisionClient.get_resource_name(vision_name)) if vision_resource is not None: - self.vision_svc = cast(VisionClient, vision_resource) + obj.vision_svc = cast(VisionClient, vision_resource) - return super().reconfigure(config, dependencies) + return obj ``` {{% /tab %}} @@ -429,14 +431,15 @@ def validate_config( # Get and store motion service instance -def reconfigure( - self, config: ComponentConfig, dependencies: Mapping[ - ResourceName, ResourceBase] -): +@classmethod +def new( + cls, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase] +) -> Self: + obj = super().new(config, dependencies) motion_resource = dependencies[MotionClient.get_resource_name("builtin")] - self.motion_service = cast(MotionClient, motion_resource) + obj.motion_service = cast(MotionClient, motion_resource) - return super().reconfigure(config, dependencies) + return obj ``` {{% /tab %}} diff --git a/docs/operate/modules/support-hardware/_index.md b/docs/operate/modules/support-hardware/_index.md index b4a8cc0ff1..a53043378a 100644 --- a/docs/operate/modules/support-hardware/_index.md +++ b/docs/operate/modules/support-hardware/_index.md @@ -615,13 +615,15 @@ The reconfiguration step serves two purposes: 2. Edit the `reconfigure` function to: ```python {class="line-numbers" data-start="51" data-line="4-5"} - def reconfigure( - self, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase] - ): + @classmethod + def new( + cls, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase] + ) -> Self: + obj = super().new(config, dependencies) attrs = struct_to_dict(config.attributes) - self.image_path = str(attrs.get("image_path")) + obj.image_path = str(attrs.get("image_path")) - return super().reconfigure(config, dependencies) + return obj ``` 3. Add the following import to the top of the file: diff --git a/docs/operate/reference/services/motion/_index.md b/docs/operate/reference/services/motion/_index.md index 3b3ae097ad..4116e14bd6 100644 --- a/docs/operate/reference/services/motion/_index.md +++ b/docs/operate/reference/services/motion/_index.md @@ -101,16 +101,17 @@ For example: return req_deps, [] ``` -1. Edit your `reconfigure` function to add the motion service as an instance variable so that you can use it in your module: +1. Edit your `new` function to add the motion service as an instance variable so that you can use it in your module: ```python {class="line-numbers linkable-line-numbers"} - def reconfigure( - self, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase] - ): + def new( + cls, config: ComponentConfig, dependencies: Mapping[ResourceName, ResourceBase] + ) -> Self: + obj = super().new(config, dependencies) motion_resource = dependencies[Motion.get_resource_name("builtin")] self.motion_service = cast(MotionClient, motion_resource) - return super().reconfigure(config, dependencies) + return obj ``` 1. You can now use the motion service in your module, for example: From aed1c00b07022cf68fafd9f1b2fc4a39e04cea9c Mon Sep 17 00:00:00 2001 From: Naomi Pentrel <5212232+npentrel@users.noreply.github.com> Date: Fri, 5 Dec 2025 20:23:21 +0100 Subject: [PATCH 2/2] More --- docs/data-ai/ai/act.md | 4 ++-- docs/operate/hello-world/tutorial-desk-safari.md | 4 ++-- docs/operate/modules/control-logic.md | 4 ++-- docs/operate/modules/lifecycle-module.md | 2 +- docs/operate/modules/support-hardware/_index.md | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/data-ai/ai/act.md b/docs/data-ai/ai/act.md index ebd3aa51c2..771171b826 100644 --- a/docs/data-ai/ai/act.md +++ b/docs/data-ai/ai/act.md @@ -192,12 +192,12 @@ For the safe arm example, you also need to get the name of the existing arm reso {{% tablestep %}} **Initialize all variables.** -`viam-server` calls the `reconfigure` method whenever the module starts or a configuration change occurs. +`viam-server` calls the `new` method whenever the module starts or a configuration change occurs. Use this method to initialize the vision service and camera name, as well as any other resources you plan to use. The dependencies parameter contains all the resources this component can access. By using `cast`, you tell Python the type of the resource. -Update the `reconfigure` method to initialize all the variables: +Update the `new` method to initialize all the variables: {{< tabs >}} {{% tab name="Python" %}} diff --git a/docs/operate/hello-world/tutorial-desk-safari.md b/docs/operate/hello-world/tutorial-desk-safari.md index 738b6ddb5a..3ea4cc3ab0 100644 --- a/docs/operate/hello-world/tutorial-desk-safari.md +++ b/docs/operate/hello-world/tutorial-desk-safari.md @@ -380,7 +380,7 @@ Your game needs to know which camera and vision service to use. While you could hardcode these names, you'll get them from the button's configuration. This makes your game flexible if you change component names later. To get parameters from the configuration object, you use the `validate_config` method. -`viam-server` calls the `validate_config` method before calling `reconfigure` to: +`viam-server` calls the `validate_config` method before calling `new` to: 1. Ensure the expected fields are in the config and have the right type. This method makes sure the camera name and vision service name are present and raises errors if they are not provided. @@ -446,7 +446,7 @@ In the hello-world-game-py/src/models/game_logic.py file, find the Unlike class attributes, instance attributes are unique to a single instance of the button running on your machine. You use them to initialize instance parameters, like `self.new_game`, in the `new` method. `viam-server` calls the `new` method whenever the module starts or a configuration change occurs. -Whenever you change the config of the button, the parameters get set to the values assigned in the reconfigure method. +Whenever you change the config of the button, the parameters get set to the values assigned in the `new` method. You must initialize all variables that can and may be accessed before they are assigned elsewhere in the code. For the Desk Safari game, you'll initialize the following game state variables: diff --git a/docs/operate/modules/control-logic.md b/docs/operate/modules/control-logic.md index d0b1e103f6..26fdc28ff3 100644 --- a/docs/operate/modules/control-logic.md +++ b/docs/operate/modules/control-logic.md @@ -90,7 +90,7 @@ The following example shows how you might implement logic that toggles an LED on Any resources that you wish to access from your control logic need to be identified and instantiated. To keep your code loosely coupled, we recommend passing the resource names in the configuration attributes of the control logic. -We must modify the `validate_config` method to ensure all required values are passed in correctly and then instantiate the resource in the `reconfigure` method. +We must modify the `validate_config` method to ensure all required values are passed in correctly and then instantiate the resource in the `new` method. {{< table >}} {{% tablestep start=1 %}} @@ -162,7 +162,7 @@ from viam.components.board import Board The `new` method gets called whenever the control logic module starts or when a configuration change occurs for the resource itself. -If this is a problem, consider writing state to a file on disk and adding logic to handle subsequent calls to the reconfigure method gracefully. +If this is a problem, consider writing state to a file on disk and adding logic to handle subsequent calls to the `new` method gracefully. {{% /tablestep %}} {{% tablestep %}} diff --git a/docs/operate/modules/lifecycle-module.md b/docs/operate/modules/lifecycle-module.md index 3d8a984540..e8e0aa4132 100644 --- a/docs/operate/modules/lifecycle-module.md +++ b/docs/operate/modules/lifecycle-module.md @@ -28,7 +28,7 @@ The lifecycle of a module and the resources it provides are as follows: If a required dependency is not found or fails to start, `viam-server` does not start the resource that depends on it. 1. `viam-server` calls the resource's constructor to build the resource based on its configuration. - Typically, the constructor calls the `reconfigure` function. + Typically, the constructor calls the `new` method. 1. Modular resources can fail to start for various reasons: diff --git a/docs/operate/modules/support-hardware/_index.md b/docs/operate/modules/support-hardware/_index.md index a53043378a..2d6159b6cd 100644 --- a/docs/operate/modules/support-hardware/_index.md +++ b/docs/operate/modules/support-hardware/_index.md @@ -597,7 +597,7 @@ For the sensor model, you do not need to edit any of the validation or configura {{% tablestep %}} **Reconfiguration** -`viam-server` calls the `reconfigure` method when the user adds the model or changes its configuration. +`viam-server` calls the `new` method when the user adds the model or changes its configuration. The reconfiguration step serves two purposes: @@ -605,14 +605,14 @@ The reconfiguration step serves two purposes: - Obtain access to dependencies. For information on how to use dependencies, see [Module dependencies](/operate/modules/advanced/dependencies/). -**Example module**: For the camera model, the reconfigure method serves to set the image path for use in API methods. +**Example module**: For the camera model, the `new` method serves to set the image path for use in API methods. {{< tabs >}} {{% tab name="Python" %}} 1. Open /src/models/hello_camera.py. -2. Edit the `reconfigure` function to: +2. Edit the `new` function to: ```python {class="line-numbers" data-start="51" data-line="4-5"} @classmethod