Skip to content

Commit df62309

Browse files
committed
[Python] Keep newly deprecated fields in Python code
1 parent 0a7bd1a commit df62309

File tree

15 files changed

+168
-27
lines changed

15 files changed

+168
-27
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: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,8 @@ github.com/databricks/cli/bundle/config/resources.Job:
201201
```
202202
203203
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).
204+
"format":
205+
"x-databricks-python-keep-deprecated": "false"
204206
"health":
205207
"description": |-
206208
PLACEHOLDER
@@ -302,6 +304,8 @@ github.com/databricks/cli/bundle/config/resources.ModelServingEndpoint:
302304
"permissions":
303305
"description": |-
304306
PLACEHOLDER
307+
"rate_limits":
308+
"x-databricks-python-keep-deprecated": "false"
305309
github.com/databricks/cli/bundle/config/resources.ModelServingEndpointPermissionLevel:
306310
"_":
307311
"enum":
@@ -345,11 +349,11 @@ github.com/databricks/cli/bundle/config/resources.Pipeline:
345349
"description": |-
346350
PLACEHOLDER
347351
"target":
348-
"force_not_deprecated": |-
349-
true
352+
"x-databricks-python-keep-deprecated": "true"
350353
"trigger":
351354
"deprecation_message": |-
352355
Use continuous instead
356+
"x-databricks-python-keep-deprecated": "false"
353357
github.com/databricks/cli/bundle/config/resources.PipelinePermissionLevel:
354358
"_":
355359
"enum":
@@ -475,6 +479,13 @@ github.com/databricks/cli/bundle/config/resources.SecretScopePermissionLevel:
475479
- |-
476480
MANAGE
477481
github.com/databricks/cli/bundle/config/resources.SqlWarehouse:
482+
"enable_photon":
483+
"description": |-
484+
Configures whether the warehouse should use Photon optimized clusters.
485+
486+
Defaults to true.
487+
"instance_profile_arn":
488+
"x-databricks-python-keep-deprecated": "false"
478489
"permissions":
479490
"description": |-
480491
PLACEHOLDER
@@ -484,11 +495,6 @@ github.com/databricks/cli/bundle/config/resources.SqlWarehouse:
484495
"warehouse_type":
485496
"description": |-
486497
PLACEHOLDER
487-
"enable_photon":
488-
"description": |-
489-
Configures whether the warehouse should use Photon optimized clusters.
490-
491-
Defaults to true.
492498
github.com/databricks/cli/bundle/config/resources.SqlWarehousePermissionLevel:
493499
"_":
494500
"enum":
@@ -685,17 +691,26 @@ github.com/databricks/databricks-sdk-go/service/compute.DockerImage:
685691
"description": |-
686692
PLACEHOLDER
687693
github.com/databricks/databricks-sdk-go/service/compute.Environment:
694+
"client":
695+
"x-databricks-python-keep-deprecated": "true"
688696
"dependencies":
689697
"description": |-
690698
List of pip dependencies, as supported by the version of pip in this environment.
691699
github.com/databricks/databricks-sdk-go/service/compute.GcpAttributes:
692700
"availability":
693701
"description": |-
694702
PLACEHOLDER
703+
"use_preemptible_executors":
704+
"x-databricks-python-keep-deprecated": "false"
695705
github.com/databricks/databricks-sdk-go/service/compute.InitScriptInfo:
696706
"abfss":
697707
"description": |-
698708
Contains the Azure Data Lake Storage destination path
709+
"dbfs":
710+
"x-databricks-python-keep-deprecated": "false"
711+
github.com/databricks/databricks-sdk-go/service/compute.Library:
712+
"egg":
713+
"x-databricks-python-keep-deprecated": "false"
699714
github.com/databricks/databricks-sdk-go/service/compute.LogAnalyticsInfo:
700715
"log_analytics_primary_key":
701716
"description": |-
@@ -718,6 +733,9 @@ github.com/databricks/databricks-sdk-go/service/jobs.GitSource:
718733
"git_snapshot":
719734
"description": |-
720735
PLACEHOLDER
736+
github.com/databricks/databricks-sdk-go/service/jobs.JobEmailNotifications:
737+
"no_alert_for_skipped_runs":
738+
"x-databricks-python-keep-deprecated": "false"
721739
github.com/databricks/databricks-sdk-go/service/jobs.JobEnvironment:
722740
"spec":
723741
"description": |-
@@ -737,6 +755,11 @@ github.com/databricks/databricks-sdk-go/service/jobs.RunJobTask:
737755
"python_named_params":
738756
"description": |-
739757
PLACEHOLDER
758+
github.com/databricks/databricks-sdk-go/service/jobs.SparkJarTask:
759+
"jar_uri":
760+
"x-databricks-python-keep-deprecated": "false"
761+
"run_as_repl":
762+
"x-databricks-python-keep-deprecated": "false"
740763
github.com/databricks/databricks-sdk-go/service/jobs.Subscription:
741764
"subscribers":
742765
"description": |-
@@ -758,6 +781,9 @@ github.com/databricks/databricks-sdk-go/service/jobs.Task:
758781
"health":
759782
"description": |-
760783
PLACEHOLDER
784+
github.com/databricks/databricks-sdk-go/service/jobs.TaskEmailNotifications:
785+
"no_alert_for_skipped_runs":
786+
"x-databricks-python-keep-deprecated": "false"
761787
github.com/databricks/databricks-sdk-go/service/jobs.TriggerSettings:
762788
"table_update":
763789
"description": |-
@@ -773,17 +799,26 @@ github.com/databricks/databricks-sdk-go/service/pipelines.CronTrigger:
773799
"timezone_id":
774800
"description": |-
775801
PLACEHOLDER
802+
github.com/databricks/databricks-sdk-go/service/pipelines.IngestionGatewayPipelineDefinition:
803+
"connection_id":
804+
"x-databricks-python-keep-deprecated": "false"
776805
github.com/databricks/databricks-sdk-go/service/pipelines.PipelineLibrary:
777806
"whl":
778807
"deprecation_message": |-
779808
This field is deprecated
809+
"x-databricks-python-keep-deprecated": "false"
780810
github.com/databricks/databricks-sdk-go/service/pipelines.PipelineTrigger:
781811
"cron":
782812
"description": |-
783813
PLACEHOLDER
784814
"manual":
785815
"description": |-
786816
PLACEHOLDER
817+
github.com/databricks/databricks-sdk-go/service/serving.AiGatewayGuardrailParameters:
818+
"invalid_keywords":
819+
"x-databricks-python-keep-deprecated": "false"
820+
"valid_topics":
821+
"x-databricks-python-keep-deprecated": "false"
787822
github.com/databricks/databricks-sdk-go/service/serving.Route:
788823
"served_entity_name":
789824
"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(
@@ -155,6 +161,7 @@ def generate_field(
155161
default_factory="dict",
156162
create_func_default="None",
157163
experimental=prop.stage == Stage.PRIVATE,
164+
deprecated=prop.deprecated or False,
158165
)
159166
elif field_type.name == "VariableOrList":
160167
return GeneratedField(
@@ -167,6 +174,7 @@ def generate_field(
167174
default_factory="list",
168175
create_func_default="None",
169176
experimental=prop.stage == Stage.PRIVATE,
177+
deprecated=prop.deprecated or False,
170178
)
171179
elif is_required:
172180
return GeneratedField(
@@ -179,6 +187,7 @@ def generate_field(
179187
default_factory=None,
180188
create_func_default=None,
181189
experimental=prop.stage == Stage.PRIVATE,
190+
deprecated=prop.deprecated or False,
182191
)
183192
else:
184193
return GeneratedField(
@@ -191,6 +200,7 @@ def generate_field(
191200
default_factory=None,
192201
create_func_default="None",
193202
experimental=prop.stage == Stage.PRIVATE,
203+
deprecated=prop.deprecated or False,
194204
)
195205

196206

@@ -320,6 +330,7 @@ def generate_dataclass(schema_name: str, schema: Schema) -> GeneratedDataclass:
320330
fields=fields,
321331
extends=extends,
322332
experimental=schema.stage == Stage.PRIVATE,
333+
deprecated=schema.deprecated or False,
323334
)
324335

325336

@@ -359,10 +370,19 @@ def _append_dataclass(b: CodeBuilder, generated: GeneratedDataclass):
359370
b.append(":").newline()
360371

361372
# FIXME should contain class docstring
362-
if not generated.description and not generated.experimental:
373+
if (
374+
not generated.description
375+
and not generated.experimental
376+
and not generated.deprecated
377+
):
363378
b.indent().append_triple_quote().append_triple_quote().newline().newline()
364379
else:
365-
_append_description(b, generated.description, generated.experimental)
380+
_append_description(
381+
b,
382+
generated.description,
383+
experimental=generated.experimental,
384+
deprecated=generated.deprecated,
385+
)
366386

367387

368388
def _append_field(b: CodeBuilder, field: GeneratedField):
@@ -440,7 +460,12 @@ def _append_typed_dict(b: CodeBuilder, generated: GeneratedDataclass):
440460
b.indent().append_triple_quote().append_triple_quote().newline().newline()
441461

442462

443-
def _append_description(b: CodeBuilder, description: Optional[str], experimental: bool):
463+
def _append_description(
464+
b: CodeBuilder, description: Optional[str], *, experimental: bool, deprecated: bool
465+
):
466+
if deprecated:
467+
description = "[DEPRECATED] " + (description or "")
468+
444469
if description or experimental:
445470
b.indent().append_triple_quote().newline()
446471
if experimental:
@@ -466,7 +491,12 @@ def get_code(generated: GeneratedDataclass) -> str:
466491

467492
for field in generated.fields:
468493
_append_field(b, field)
469-
_append_description(b, field.description, field.experimental)
494+
_append_description(
495+
b,
496+
field.description,
497+
experimental=field.experimental,
498+
deprecated=field.deprecated,
499+
)
470500

471501
b.newline()
472502

@@ -479,7 +509,12 @@ def get_code(generated: GeneratedDataclass) -> str:
479509

480510
for field in generated.fields:
481511
_append_typed_dict_field(b, field)
482-
_append_description(b, field.description, field.experimental)
512+
_append_description(
513+
b,
514+
field.description,
515+
experimental=field.experimental,
516+
deprecated=field.deprecated,
517+
)
483518

484519
b.newline()
485520

0 commit comments

Comments
 (0)