Repository: meltano/sdk (python)

Issue:
feat: Support using JSON Schema's `deprecated` keyword to mark deprecated settings
### Feature scope

Configuration (settings parsing, validation, etc.)

### Description

https://github.com/meltano/sdk/blob/40b633385b3ec5462d90042213bfb236c57ccbab/singer_sdk/typing.py#L520-L530

is the place where this change would need to be applied. Also, this would be a great opportunity to add `kwargs` to that init method that are directly passed to the generated type dict.

This would be even better if paired with https://github.com/python-jsonschema/jsonschema/issues/1170, as well as Hub and Meltano support.

### Related

- https://github.com/meltano/meltano/issues/9023
- https://github.com/meltano/sdk/pull/2830

### References

* https://json-schema.org/draft/2020-12/json-schema-validation#name-deprecated

Pull request description:
feat: Allow developers to mark stream schema and settings fields as deprecated
Closes #2116

<!-- readthedocs-preview meltano-sdk start -->
----
📚 Documentation preview 📚: https://meltano-sdk--2830.org.readthedocs.build/en/2830/

<!-- readthedocs-preview meltano-sdk end -->

Patch:
diff --git a/singer_sdk/typing.py b/singer_sdk/typing.py
index 338973d9..74eb7623 100644
--- a/singer_sdk/typing.py
+++ b/singer_sdk/typing.py
@@ -649,6 +649,8 @@ class Property(JSONTypeHelper[T], t.Generic[T]):
         *,
         nullable: bool | None = None,
         title: str | None = None,
+        deprecated: bool | None = None,
+        **kwargs: t.Any,
     ) -> None:
         """Initialize Property object.
 
@@ -671,6 +673,8 @@ class Property(JSONTypeHelper[T], t.Generic[T]):
                 displayed to the user as hints of the expected format of inputs.
             nullable: If True, the property may be null.
             title: Optional. A short, human-readable title for the property.
+            deprecated: If True, mark this property as deprecated.
+            **kwargs: Additional keyword arguments to pass to the parent class.
         """
         self.name = name
         self.wrapped = wrapped
@@ -682,6 +686,8 @@ class Property(JSONTypeHelper[T], t.Generic[T]):
         self.examples = examples or None
         self.nullable = nullable
         self.title = title
+        self.deprecated = deprecated
+        self.kwargs = kwargs
 
     @property
     def type_dict(self) -> dict:  # type: ignore[override]
@@ -739,6 +745,12 @@ class Property(JSONTypeHelper[T], t.Generic[T]):
             type_dict.update({"enum": self.allowed_values})
         if self.examples:
             type_dict.update({"examples": self.examples})
+
+        if self.deprecated is not None:
+            type_dict["deprecated"] = self.deprecated
+
+        type_dict.update(self.kwargs)
+
         return {self.name: type_dict}
 
 


Test patch:
diff --git a/tests/core/test_jsonschema_helpers.py b/tests/core/test_jsonschema_helpers.py
index 8729012a..dbaf89a6 100644
--- a/tests/core/test_jsonschema_helpers.py
+++ b/tests/core/test_jsonschema_helpers.py
@@ -495,12 +495,14 @@ def test_inbuilt_type(json_type: JSONTypeHelper, expected_json_schema: dict):
                 IntegerType,
                 allowed_values=[1, 2, 3, 4, 5, 6, 7, 8, 9],
                 examples=[1, 2, 3],
+                deprecated=True,
             ),
             {
                 "my_prop9": {
                     "type": ["integer", "null"],
                     "enum": [1, 2, 3, 4, 5, 6, 7, 8, 9],
                     "examples": [1, 2, 3],
+                    "deprecated": True,
                 },
             },
             {is_integer_type},