Allow deprecating fields of interfaces#945
Conversation
Signed-off-by: Michael Carlstrom <rmc@carlstrom.com>
Signed-off-by: Michael Carlstrom <rmc@carlstrom.com>
Signed-off-by: Michael Carlstrom <rmc@carlstrom.com>
|
Pulls: #945, ros2/rosidl_typesupport_fastrtps#145 |
|
Pulls: #945, ros2/rosidl_typesupport_fastrtps#145 |
Signed-off-by: Michael Carlstrom <rmc@carlstrom.com>
|
Pulls: #945, ros2/rosidl_typesupport_fastrtps#145 Rebuild |
Signed-off-by: Michael Carlstrom <rmc@carlstrom.com>
|
Pulls: #945, ros2/rosidl_typesupport_fastrtps#145 |
Signed-off-by: Michael Carlstrom <rmc@carlstrom.com>
|
@InvincibleRMC Tanks for the PR ! Looks good to me at first glance, could you post a generated header from this ? |
|
Greetings mate @InvincibleRMC, I too were interested in this request and did a PR. I'll simply withdraw mine, should you need any help, I'd be more than willing to assist:) |
|
@Pengkun-ZHU can you review the patch ? |
Here is the detail/deprecated__struct.hpp for example. We deprecated the If we had private fields and only public getters and setters we wouldn't need any internal deprecation suppression. // generated from rosidl_generator_cpp/resource/idl__struct.hpp.em
// with input from rosidl_generator_tests:msg/Deprecated.idl
// generated code does not contain a copyright notice
// IWYU pragma: private, include "rosidl_generator_tests/msg/deprecated.hpp"
#ifndef ROSIDL_GENERATOR_TESTS__MSG__DETAIL__DEPRECATED__STRUCT_HPP_
#define ROSIDL_GENERATOR_TESTS__MSG__DETAIL__DEPRECATED__STRUCT_HPP_
#include <algorithm>
#include <array>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "rosidl_runtime_c/deprecation.h"
#include "rosidl_runtime_cpp/bounded_vector.hpp"
#include "rosidl_runtime_cpp/message_initialization.hpp"
#ifndef _WIN32
# define DEPRECATED__rosidl_generator_tests__msg__Deprecated __attribute__((deprecated))
#else
# define DEPRECATED__rosidl_generator_tests__msg__Deprecated __declspec(deprecated)
#endif
namespace rosidl_generator_tests
{
namespace msg
{
// message struct
template<class ContainerAllocator>
struct Deprecated_
{
using Type = Deprecated_<ContainerAllocator>;
DISABLE_DEPRECATED_PUSH
explicit Deprecated_(rosidl_runtime_cpp::MessageInitialization _init = rosidl_runtime_cpp::MessageInitialization::ALL)
{
if (rosidl_runtime_cpp::MessageInitialization::ALL == _init ||
rosidl_runtime_cpp::MessageInitialization::ZERO == _init)
{
this->x = 0l;
this->new_x = 0l;
}
}
explicit Deprecated_(const ContainerAllocator & _alloc, rosidl_runtime_cpp::MessageInitialization _init = rosidl_runtime_cpp::MessageInitialization::ALL)
{
(void)_alloc;
if (rosidl_runtime_cpp::MessageInitialization::ALL == _init ||
rosidl_runtime_cpp::MessageInitialization::ZERO == _init)
{
this->x = 0l;
this->new_x = 0l;
}
}
DISABLE_DEPRECATED_POP
// field types and members
using _x_type =
int32_t;
[[deprecated("Use new_x")]]
_x_type x;
using _new_x_type =
int32_t;
_new_x_type new_x;
// setters for named parameter idiom
[[deprecated("Use new_x")]]
Type & set__x(
const int32_t & _arg)
{
DISABLE_DEPRECATED_PUSH
this->x = _arg;
DISABLE_DEPRECATED_POP
return *this;
}
Type & set__new_x(
const int32_t & _arg)
{
this->new_x = _arg;
return *this;
}
// constant declarations
// pointer types
using RawPtr =
rosidl_generator_tests::msg::Deprecated_<ContainerAllocator> *;
using ConstRawPtr =
const rosidl_generator_tests::msg::Deprecated_<ContainerAllocator> *;
using SharedPtr =
std::shared_ptr<rosidl_generator_tests::msg::Deprecated_<ContainerAllocator>>;
using ConstSharedPtr =
std::shared_ptr<rosidl_generator_tests::msg::Deprecated_<ContainerAllocator> const>;
template<typename Deleter = std::default_delete<
rosidl_generator_tests::msg::Deprecated_<ContainerAllocator>>>
using UniquePtrWithDeleter =
std::unique_ptr<rosidl_generator_tests::msg::Deprecated_<ContainerAllocator>, Deleter>;
using UniquePtr = UniquePtrWithDeleter<>;
template<typename Deleter = std::default_delete<
rosidl_generator_tests::msg::Deprecated_<ContainerAllocator>>>
using ConstUniquePtrWithDeleter =
std::unique_ptr<rosidl_generator_tests::msg::Deprecated_<ContainerAllocator> const, Deleter>;
using ConstUniquePtr = ConstUniquePtrWithDeleter<>;
using WeakPtr =
std::weak_ptr<rosidl_generator_tests::msg::Deprecated_<ContainerAllocator>>;
using ConstWeakPtr =
std::weak_ptr<rosidl_generator_tests::msg::Deprecated_<ContainerAllocator> const>;
// pointer types similar to ROS 1, use SharedPtr / ConstSharedPtr instead
// NOTE: Can't use 'using' here because GNU C++ can't parse attributes properly
typedef DEPRECATED__rosidl_generator_tests__msg__Deprecated
std::shared_ptr<rosidl_generator_tests::msg::Deprecated_<ContainerAllocator>>
Ptr;
typedef DEPRECATED__rosidl_generator_tests__msg__Deprecated
std::shared_ptr<rosidl_generator_tests::msg::Deprecated_<ContainerAllocator> const>
ConstPtr;
// comparison operators
bool operator==(const Deprecated_ & other) const
{
DISABLE_DEPRECATED_PUSH
if (this->x != other.x) {
return false;
}
DISABLE_DEPRECATED_POP
if (this->new_x != other.new_x) {
return false;
}
return true;
}
bool operator!=(const Deprecated_ & other) const
{
return !this->operator==(other);
}
}; // struct Deprecated_
// alias to use template instance with default allocator
using Deprecated =
rosidl_generator_tests::msg::Deprecated_<std::allocator<void>>;
// constant definitions
} // namespace msg
} // namespace rosidl_generator_tests
#endif // ROSIDL_GENERATOR_TESTS__MSG__DETAIL__DEPRECATED__STRUCT_HPP_ |
|
If approved could be used on ros2/common_interfaces#254 for instance. |
|
Hi @InvincibleRMC, @jmachowinski, all the code looks sound to me. For the Python generator support, I actually have a working implementation that adds deprecation warnings to Python message properties. I'd be happy to collaborate on that side if you'd like a hand. |
|
I don't think we should warn in cli tools. Deprecation warnings should affect maintainers of packages not necessarily users of packages. |
|
Hm, I am confused, you seem to focus on deprecation of single members of messages. I thought this was about deprecation of messages altogether. |
|
I set out to solve this ros2/ros2#1679 But for overall deprecation of messages you could just mark all fields deprecated and point towards the new message if one exists. Which should work for all messages except Empty. |
|
I assume IDL parser already parses struct-level annotations?
|
|
I think you can't deprecate a message in all corner cases correctly with only marking its members as deprecated. Anyway this was what I had in mind : namespace test_msgs
{
namespace msg
{
// message struct
template<class ContainerAllocator>
struct [[deprecates("Reason")]] Empty_
{
.
.
.
};
} // namespace msg
} // namespace test_msgs |
|
I don't disagree that in all case this a not necessarily a clean replacement for struct level deprecation. My goal was to solve ros2/ros2#1679 which is about field level deprecation. The hope is that this would help us evolve message definitions. Rather then need to replace them with new ones every time. I would rather keep these prs focused on addressing this issue. And we can discuss struct level in the future. |
Implements the Python generator side of field-level deprecation support. This PR is based on and should be merged as a companion to ros2/rosidl#945, which establishes the IDL annotation pipeline for C and C++ generators. When a message field is annotated with @deprecated(text=...) in an .idl file, the generated Python message class will: - Decorate the property getter and setter with @typing_extensions.deprecated(text) (PEP 702), enabling static analysis tools (mypy, pyright, IDEs) to flag deprecated field usage at development time - Emit a DeprecationWarning at runtime when the field is accessed or set The C extension (_msg_support.c.em) wraps internal accesses to deprecated fields with DISABLE_DEPRECATED_PUSH/POP to suppress warnings in generated conversion code. Changes: - resource/_msg.py.em: import and apply @_deprecated decorator on getter/setter when field has @deprecated annotation - resource/_msg_support.c.em: suppress deprecation warnings around internal PyObject_GetAttrString/SetAttrString calls - package.xml: add python3-typing-extensions exec_depend - CMakeLists.txt: add TestDeprecated.idl test message and test_deprecated.py regression test Signed-off-by: Pengkun-ZHU <q1091803103@gmail.com>
Description
Proposes adding support for annotatoins with the form
@deprecated ( text='foo' ).For now only supports
.idlsince this shouldn't happen often. This method allows us to add support in the future if we desire.Fixes ros2/ros2#1679
Note: I can do python also if this methodology is approved.
Is this user-facing behavior change?
Did you use Generative AI?
Additional Information