Skip to content

Commit a21573d

Browse files
committed
[Python] Keep newly deprecated fields in Python code
1 parent 52578a5 commit a21573d

File tree

15 files changed

+161
-22
lines changed

15 files changed

+161
-22
lines changed

bundle/docsgen/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ func assignAnnotation(s *jsonschema.Schema, a annotation.Descriptor) {
137137
s.Deprecated = true
138138
s.DeprecationMessage = a.DeprecationMessage
139139
}
140-
if a.ForceNotDeprecated {
140+
if a.PythonKeepDeprecated == annotation.PythonKeepDeprecatedTrue {
141141
s.Deprecated = false
142142
s.DeprecationMessage = ""
143143
}

bundle/internal/annotation/descriptor.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
package annotation
22

3+
type PythonKeepDeprecated string
4+
5+
const (
6+
PythonKeepDeprecatedTrue PythonKeepDeprecated = "true"
7+
PythonKeepDeprecatedUnset PythonKeepDeprecated = ""
8+
)
9+
310
type Descriptor struct {
411
Description string `json:"description,omitempty"`
512
MarkdownDescription string `json:"markdown_description,omitempty"`
@@ -10,8 +17,8 @@ type Descriptor struct {
1017
DeprecationMessage string `json:"deprecation_message,omitempty"`
1118
Preview string `json:"x-databricks-preview,omitempty"`
1219

13-
// If true, takes priority over 'DeprecationMessage'
14-
ForceNotDeprecated bool `json:"force_not_deprecated,omitempty"`
20+
// If true, keep the field in Python code even if it is deprecated.
21+
PythonKeepDeprecated PythonKeepDeprecated `json:"x-databricks-python-keep-deprecated,omitempty"`
1522
}
1623

1724
const Placeholder = "PLACEHOLDER"

bundle/internal/schema/annotations.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,8 @@ func assignAnnotation(s *jsonschema.Schema, a annotation.Descriptor) {
138138
s.Preview = a.Preview
139139
}
140140

141-
if a.ForceNotDeprecated {
142-
s.Deprecated = false
143-
s.DeprecationMessage = ""
141+
if a.PythonKeepDeprecated != annotation.PythonKeepDeprecatedUnset {
142+
s.PythonKeepDeprecated = a.PythonKeepDeprecated == annotation.PythonKeepDeprecatedTrue
144143
}
145144

146145
s.MarkdownDescription = convertLinksToAbsoluteUrl(a.MarkdownDescription)

bundle/internal/schema/annotations_openapi_overrides.yml

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,8 @@ github.com/databricks/cli/bundle/config/resources.Job:
210210
```
211211
212212
For information about defining job tasks and overriding job settings, see [_](/dev-tools/bundles/job-task-types.md), [_](/dev-tools/bundles/job-task-override.md), and [_](/dev-tools/bundles/cluster-override.md).
213+
"format":
214+
"x-databricks-python-keep-deprecated": "false"
213215
"health":
214216
"description": |-
215217
PLACEHOLDER
@@ -311,6 +313,8 @@ github.com/databricks/cli/bundle/config/resources.ModelServingEndpoint:
311313
"permissions":
312314
"description": |-
313315
PLACEHOLDER
316+
"rate_limits":
317+
"x-databricks-python-keep-deprecated": "false"
314318
github.com/databricks/cli/bundle/config/resources.ModelServingEndpointPermissionLevel:
315319
"_":
316320
"enum":
@@ -354,11 +358,11 @@ github.com/databricks/cli/bundle/config/resources.Pipeline:
354358
"description": |-
355359
PLACEHOLDER
356360
"target":
357-
"force_not_deprecated": |-
358-
true
361+
"x-databricks-python-keep-deprecated": "true"
359362
"trigger":
360363
"deprecation_message": |-
361364
Use continuous instead
365+
"x-databricks-python-keep-deprecated": "false"
362366
github.com/databricks/cli/bundle/config/resources.PipelinePermissionLevel:
363367
"_":
364368
"enum":
@@ -710,17 +714,26 @@ github.com/databricks/databricks-sdk-go/service/compute.DockerImage:
710714
"description": |-
711715
PLACEHOLDER
712716
github.com/databricks/databricks-sdk-go/service/compute.Environment:
717+
"client":
718+
"x-databricks-python-keep-deprecated": "true"
713719
"dependencies":
714720
"description": |-
715721
List of pip dependencies, as supported by the version of pip in this environment.
716722
github.com/databricks/databricks-sdk-go/service/compute.GcpAttributes:
717723
"availability":
718724
"description": |-
719725
PLACEHOLDER
726+
"use_preemptible_executors":
727+
"x-databricks-python-keep-deprecated": "false"
720728
github.com/databricks/databricks-sdk-go/service/compute.InitScriptInfo:
721729
"abfss":
722730
"description": |-
723731
Contains the Azure Data Lake Storage destination path
732+
"dbfs":
733+
"x-databricks-python-keep-deprecated": "false"
734+
github.com/databricks/databricks-sdk-go/service/compute.Library:
735+
"egg":
736+
"x-databricks-python-keep-deprecated": "false"
724737
github.com/databricks/databricks-sdk-go/service/compute.LogAnalyticsInfo:
725738
"log_analytics_primary_key":
726739
"description": |-
@@ -743,6 +756,9 @@ github.com/databricks/databricks-sdk-go/service/jobs.GitSource:
743756
"git_snapshot":
744757
"description": |-
745758
PLACEHOLDER
759+
github.com/databricks/databricks-sdk-go/service/jobs.JobEmailNotifications:
760+
"no_alert_for_skipped_runs":
761+
"x-databricks-python-keep-deprecated": "false"
746762
github.com/databricks/databricks-sdk-go/service/jobs.JobEnvironment:
747763
"spec":
748764
"description": |-
@@ -762,6 +778,11 @@ github.com/databricks/databricks-sdk-go/service/jobs.RunJobTask:
762778
"python_named_params":
763779
"description": |-
764780
PLACEHOLDER
781+
github.com/databricks/databricks-sdk-go/service/jobs.SparkJarTask:
782+
"jar_uri":
783+
"x-databricks-python-keep-deprecated": "false"
784+
"run_as_repl":
785+
"x-databricks-python-keep-deprecated": "false"
765786
github.com/databricks/databricks-sdk-go/service/jobs.Subscription:
766787
"subscribers":
767788
"description": |-
@@ -783,6 +804,9 @@ github.com/databricks/databricks-sdk-go/service/jobs.Task:
783804
"health":
784805
"description": |-
785806
PLACEHOLDER
807+
github.com/databricks/databricks-sdk-go/service/jobs.TaskEmailNotifications:
808+
"no_alert_for_skipped_runs":
809+
"x-databricks-python-keep-deprecated": "false"
786810
github.com/databricks/databricks-sdk-go/service/jobs.TriggerSettings:
787811
"table_update":
788812
"description": |-
@@ -798,17 +822,26 @@ github.com/databricks/databricks-sdk-go/service/pipelines.CronTrigger:
798822
"timezone_id":
799823
"description": |-
800824
PLACEHOLDER
825+
github.com/databricks/databricks-sdk-go/service/pipelines.IngestionGatewayPipelineDefinition:
826+
"connection_id":
827+
"x-databricks-python-keep-deprecated": "false"
801828
github.com/databricks/databricks-sdk-go/service/pipelines.PipelineLibrary:
802829
"whl":
803830
"deprecation_message": |-
804831
This field is deprecated
832+
"x-databricks-python-keep-deprecated": "false"
805833
github.com/databricks/databricks-sdk-go/service/pipelines.PipelineTrigger:
806834
"cron":
807835
"description": |-
808836
PLACEHOLDER
809837
"manual":
810838
"description": |-
811839
PLACEHOLDER
840+
github.com/databricks/databricks-sdk-go/service/serving.AiGatewayGuardrailParameters:
841+
"invalid_keywords":
842+
"x-databricks-python-keep-deprecated": "false"
843+
"valid_topics":
844+
"x-databricks-python-keep-deprecated": "false"
812845
github.com/databricks/databricks-sdk-go/service/serving.Route:
813846
"served_entity_name":
814847
"description": |-

bundle/internal/schema/parser.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,11 @@ func (p *openapiParser) extractAnnotations(typ reflect.Type, outputPath, overrid
196196
if description == "" {
197197
addEmptyOverride(k, basePath, overrides)
198198
}
199+
200+
// if field got deprecated outside of preview it can't be just removed and we keep it
201+
if refProp.Deprecated && refProp.Preview != "PRIVATE" {
202+
addPythonKeepDeprecatedOverride(k, basePath, overrides)
203+
}
199204
} else {
200205
addEmptyOverride(k, basePath, overrides)
201206
}
@@ -241,22 +246,46 @@ func prependCommentToFile(outputPath, comment string) error {
241246
return err
242247
}
243248

244-
func addEmptyOverride(key, pkg string, overridesFile annotation.File) {
249+
// addPythonKeepDeprecatedOverride adds an override with "x-databricks-python-keep-deprecated: true" to
250+
// annotations_openapi_overrides.yaml unless it already specifies a value for "x-databricks-python-keep-deprecated".
251+
//
252+
// This way if field got deprecated, we add an override to keep it in Python code, until we revisit deprecation.
253+
func addPythonKeepDeprecatedOverride(key, pkg string, overridesFile annotation.File) {
245254
if overridesFile[pkg] == nil {
246255
overridesFile[pkg] = map[string]annotation.Descriptor{}
247256
}
248257

249258
overrides := overridesFile[pkg]
250-
if overrides[key].Description == "" {
251-
overrides[key] = annotation.Descriptor{Description: annotation.Placeholder}
259+
260+
a, ok := overrides[key]
261+
if !ok {
262+
a = annotation.Descriptor{}
263+
}
264+
265+
// if we don't have explicit value, it means that field just got deprecated,
266+
// and we should keep it in Python code
267+
if a.PythonKeepDeprecated == annotation.PythonKeepDeprecatedUnset {
268+
a.PythonKeepDeprecated = annotation.PythonKeepDeprecatedTrue
269+
}
270+
271+
overrides[key] = a
272+
}
273+
274+
func addEmptyOverride(key, pkg string, overridesFile annotation.File) {
275+
if overridesFile[pkg] == nil {
276+
overridesFile[pkg] = map[string]annotation.Descriptor{}
252277
}
253278

279+
overrides := overridesFile[pkg]
280+
254281
a, ok := overrides[key]
255282
if !ok {
256283
a = annotation.Descriptor{}
257284
}
285+
258286
if a.Description == "" {
259287
a.Description = annotation.Placeholder
260288
}
289+
261290
overrides[key] = a
262291
}

bundle/schema/jsonschema.json

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

experimental/python/codegen/codegen/generated_dataclass.py

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ class GeneratedField:
102102
be marked as experimental in docstring.
103103
"""
104104

105+
deprecated: bool
106+
"""
107+
If true, the field is deprecated and should be marked as deprecated in docstring.
108+
"""
109+
105110
def __post_init__(self):
106111
if self.default_factory is not None and self.default is not None:
107112
raise ValueError("Can't have both default and default_factory", self)
@@ -131,6 +136,7 @@ class GeneratedDataclass:
131136
fields: list[GeneratedField]
132137
extends: list[GeneratedType]
133138
experimental: bool
139+
deprecated: bool
134140

135141

136142
def generate_field(
@@ -156,6 +162,7 @@ def generate_field(
156162
default_factory="dict",
157163
create_func_default="None",
158164
experimental=prop.stage == Stage.PRIVATE,
165+
deprecated=prop.deprecated or False,
159166
)
160167
elif field_type.name == "VariableOrList":
161168
return GeneratedField(
@@ -168,6 +175,7 @@ def generate_field(
168175
default_factory="list",
169176
create_func_default="None",
170177
experimental=prop.stage == Stage.PRIVATE,
178+
deprecated=prop.deprecated or False,
171179
)
172180
elif is_required:
173181
return GeneratedField(
@@ -180,6 +188,7 @@ def generate_field(
180188
default_factory=None,
181189
create_func_default=None,
182190
experimental=prop.stage == Stage.PRIVATE,
191+
deprecated=prop.deprecated or False,
183192
)
184193
else:
185194
return GeneratedField(
@@ -192,6 +201,7 @@ def generate_field(
192201
default_factory=None,
193202
create_func_default="None",
194203
experimental=prop.stage == Stage.PRIVATE,
204+
deprecated=prop.deprecated or False,
195205
)
196206

197207

@@ -326,6 +336,7 @@ def generate_dataclass(
326336
fields=fields,
327337
extends=extends,
328338
experimental=schema.stage == Stage.PRIVATE,
339+
deprecated=schema.deprecated or False,
329340
)
330341

331342

@@ -365,10 +376,19 @@ def _append_dataclass(b: CodeBuilder, generated: GeneratedDataclass):
365376
b.append(":").newline()
366377

367378
# FIXME should contain class docstring
368-
if not generated.description and not generated.experimental:
379+
if (
380+
not generated.description
381+
and not generated.experimental
382+
and not generated.deprecated
383+
):
369384
b.indent().append_triple_quote().append_triple_quote().newline().newline()
370385
else:
371-
_append_description(b, generated.description, generated.experimental)
386+
_append_description(
387+
b,
388+
generated.description,
389+
experimental=generated.experimental,
390+
deprecated=generated.deprecated,
391+
)
372392

373393

374394
def _append_field(b: CodeBuilder, field: GeneratedField):
@@ -446,7 +466,12 @@ def _append_typed_dict(b: CodeBuilder, generated: GeneratedDataclass):
446466
b.indent().append_triple_quote().append_triple_quote().newline().newline()
447467

448468

449-
def _append_description(b: CodeBuilder, description: Optional[str], experimental: bool):
469+
def _append_description(
470+
b: CodeBuilder, description: Optional[str], *, experimental: bool, deprecated: bool
471+
):
472+
if deprecated:
473+
description = "[DEPRECATED] " + (description or "")
474+
450475
if description or experimental:
451476
b.indent().append_triple_quote().newline()
452477
if experimental:
@@ -472,7 +497,12 @@ def get_code(generated: GeneratedDataclass) -> str:
472497

473498
for field in generated.fields:
474499
_append_field(b, field)
475-
_append_description(b, field.description, field.experimental)
500+
_append_description(
501+
b,
502+
field.description,
503+
experimental=field.experimental,
504+
deprecated=field.deprecated,
505+
)
476506

477507
b.newline()
478508

@@ -485,7 +515,12 @@ def get_code(generated: GeneratedDataclass) -> str:
485515

486516
for field in generated.fields:
487517
_append_typed_dict_field(b, field)
488-
_append_description(b, field.description, field.experimental)
518+
_append_description(
519+
b,
520+
field.description,
521+
experimental=field.experimental,
522+
deprecated=field.deprecated,
523+
)
489524

490525
b.newline()
491526

experimental/python/codegen/codegen/generated_enum.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ class GeneratedEnum:
1515
values: dict[str, str]
1616
description: Optional[str]
1717
experimental: bool
18+
deprecated: bool
1819

1920

2021
def generate_enum(namespace: str, schema_name: str, schema: Schema) -> GeneratedEnum:
@@ -35,6 +36,7 @@ def generate_enum(namespace: str, schema_name: str, schema: Schema) -> Generated
3536
values=values,
3637
description=schema.description,
3738
experimental=schema.stage == Stage.PRIVATE,
39+
deprecated=schema.deprecated or False,
3840
)
3941

4042

@@ -48,7 +50,12 @@ def get_code(generated: GeneratedEnum) -> str:
4850
b.append(f"class {generated.class_name}(Enum):")
4951
b.newline()
5052

51-
_append_description(b, generated.description, generated.experimental)
53+
_append_description(
54+
b,
55+
generated.description,
56+
experimental=generated.experimental,
57+
deprecated=generated.deprecated,
58+
)
5259

5360
# Example:
5461
#

0 commit comments

Comments
 (0)