quicktype 18.0.6 → 19.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/{cli/CompressedJSONFromStream.d.ts → CompressedJSONFromStream.d.ts} +1 -1
- package/dist/{cli/CompressedJSONFromStream.js → CompressedJSONFromStream.js} +2 -2
- package/dist/{cli/GraphQLIntrospection.d.ts → GraphQLIntrospection.d.ts} +0 -0
- package/dist/{cli/GraphQLIntrospection.js → GraphQLIntrospection.js} +1 -1
- package/dist/{cli/TypeSource.d.ts → TypeSource.d.ts} +2 -2
- package/dist/{cli/TypeSource.js → TypeSource.js} +0 -0
- package/dist/{cli/URLGrammar.d.ts → URLGrammar.d.ts} +0 -0
- package/dist/{cli/URLGrammar.js → URLGrammar.js} +1 -1
- package/dist/{cli/index.d.ts → index.d.ts} +1 -1
- package/dist/{cli/index.js → index.js} +4 -5
- package/package.json +61 -77
- package/dist/quicktype-core/Annotation.d.ts +0 -8
- package/dist/quicktype-core/Annotation.js +0 -16
- package/dist/quicktype-core/ConvenienceRenderer.d.ts +0 -138
- package/dist/quicktype-core/ConvenienceRenderer.js +0 -668
- package/dist/quicktype-core/DateTime.d.ts +0 -10
- package/dist/quicktype-core/DateTime.js +0 -57
- package/dist/quicktype-core/DeclarationIR.d.ts +0 -14
- package/dist/quicktype-core/DeclarationIR.js +0 -167
- package/dist/quicktype-core/EncodedMarkovChain.d.ts +0 -1
- package/dist/quicktype-core/EncodedMarkovChain.js +0 -4
- package/dist/quicktype-core/GatherNames.d.ts +0 -2
- package/dist/quicktype-core/GatherNames.js +0 -333
- package/dist/quicktype-core/Graph.d.ts +0 -12
- package/dist/quicktype-core/Graph.js +0 -220
- package/dist/quicktype-core/GraphRewriting.d.ts +0 -87
- package/dist/quicktype-core/GraphRewriting.js +0 -421
- package/dist/quicktype-core/MakeTransformations.d.ts +0 -4
- package/dist/quicktype-core/MakeTransformations.js +0 -193
- package/dist/quicktype-core/MarkovChain.d.ts +0 -15
- package/dist/quicktype-core/MarkovChain.js +0 -154
- package/dist/quicktype-core/Messages.d.ts +0 -294
- package/dist/quicktype-core/Messages.js +0 -105
- package/dist/quicktype-core/Naming.d.ts +0 -64
- package/dist/quicktype-core/Naming.js +0 -356
- package/dist/quicktype-core/Renderer.d.ts +0 -50
- package/dist/quicktype-core/Renderer.js +0 -274
- package/dist/quicktype-core/RendererOptions.d.ts +0 -71
- package/dist/quicktype-core/RendererOptions.js +0 -141
- package/dist/quicktype-core/Run.d.ts +0 -174
- package/dist/quicktype-core/Run.js +0 -393
- package/dist/quicktype-core/Source.d.ts +0 -65
- package/dist/quicktype-core/Source.js +0 -204
- package/dist/quicktype-core/TargetLanguage.d.ts +0 -34
- package/dist/quicktype-core/TargetLanguage.js +0 -66
- package/dist/quicktype-core/Transformers.d.ts +0 -209
- package/dist/quicktype-core/Transformers.js +0 -836
- package/dist/quicktype-core/Type.d.ts +0 -206
- package/dist/quicktype-core/Type.js +0 -716
- package/dist/quicktype-core/TypeBuilder.d.ts +0 -61
- package/dist/quicktype-core/TypeBuilder.js +0 -324
- package/dist/quicktype-core/TypeGraph.d.ts +0 -75
- package/dist/quicktype-core/TypeGraph.js +0 -420
- package/dist/quicktype-core/TypeUtils.d.ts +0 -33
- package/dist/quicktype-core/TypeUtils.js +0 -230
- package/dist/quicktype-core/UnifyClasses.d.ts +0 -16
- package/dist/quicktype-core/UnifyClasses.js +0 -159
- package/dist/quicktype-core/UnionBuilder.d.ts +0 -49
- package/dist/quicktype-core/UnionBuilder.js +0 -282
- package/dist/quicktype-core/attributes/AccessorNames.d.ts +0 -18
- package/dist/quicktype-core/attributes/AccessorNames.js +0 -182
- package/dist/quicktype-core/attributes/Constraints.d.ts +0 -38
- package/dist/quicktype-core/attributes/Constraints.js +0 -172
- package/dist/quicktype-core/attributes/Description.d.ts +0 -9
- package/dist/quicktype-core/attributes/Description.js +0 -97
- package/dist/quicktype-core/attributes/EnumValues.d.ts +0 -8
- package/dist/quicktype-core/attributes/EnumValues.js +0 -31
- package/dist/quicktype-core/attributes/StringTypes.d.ts +0 -28
- package/dist/quicktype-core/attributes/StringTypes.js +0 -189
- package/dist/quicktype-core/attributes/TypeAttributes.d.ts +0 -34
- package/dist/quicktype-core/attributes/TypeAttributes.js +0 -119
- package/dist/quicktype-core/attributes/TypeNames.d.ts +0 -46
- package/dist/quicktype-core/attributes/TypeNames.js +0 -274
- package/dist/quicktype-core/attributes/URIAttributes.d.ts +0 -8
- package/dist/quicktype-core/attributes/URIAttributes.js +0 -85
- package/dist/quicktype-core/index.d.ts +0 -48
- package/dist/quicktype-core/index.js +0 -180
- package/dist/quicktype-core/input/CompressedJSON.d.ts +0 -69
- package/dist/quicktype-core/input/CompressedJSON.js +0 -276
- package/dist/quicktype-core/input/FetchingJSONSchemaStore.d.ts +0 -6
- package/dist/quicktype-core/input/FetchingJSONSchemaStore.js +0 -18
- package/dist/quicktype-core/input/Inference.d.ts +0 -22
- package/dist/quicktype-core/input/Inference.js +0 -240
- package/dist/quicktype-core/input/Inputs.d.ts +0 -48
- package/dist/quicktype-core/input/Inputs.js +0 -145
- package/dist/quicktype-core/input/JSONSchemaInput.d.ts +0 -91
- package/dist/quicktype-core/input/JSONSchemaInput.js +0 -1041
- package/dist/quicktype-core/input/JSONSchemaStore.d.ts +0 -8
- package/dist/quicktype-core/input/JSONSchemaStore.js +0 -36
- package/dist/quicktype-core/input/PostmanCollection.d.ts +0 -5
- package/dist/quicktype-core/input/PostmanCollection.js +0 -60
- package/dist/quicktype-core/input/io/NodeIO.d.ts +0 -3
- package/dist/quicktype-core/input/io/NodeIO.js +0 -87
- package/dist/quicktype-core/input/io/get-stream/buffer-stream.d.ts +0 -2
- package/dist/quicktype-core/input/io/get-stream/buffer-stream.js +0 -45
- package/dist/quicktype-core/input/io/get-stream/index.d.ts +0 -9
- package/dist/quicktype-core/input/io/get-stream/index.js +0 -52
- package/dist/quicktype-core/language/All.d.ts +0 -3
- package/dist/quicktype-core/language/All.js +0 -57
- package/dist/quicktype-core/language/CPlusPlus.d.ts +0 -241
- package/dist/quicktype-core/language/CPlusPlus.js +0 -1847
- package/dist/quicktype-core/language/CSharp.d.ts +0 -201
- package/dist/quicktype-core/language/CSharp.js +0 -1850
- package/dist/quicktype-core/language/Crystal.d.ts +0 -37
- package/dist/quicktype-core/language/Crystal.js +0 -337
- package/dist/quicktype-core/language/Dart.d.ts +0 -66
- package/dist/quicktype-core/language/Dart.js +0 -576
- package/dist/quicktype-core/language/Elm.d.ts +0 -58
- package/dist/quicktype-core/language/Elm.js +0 -522
- package/dist/quicktype-core/language/Golang.d.ts +0 -51
- package/dist/quicktype-core/language/Golang.js +0 -460
- package/dist/quicktype-core/language/Haskell.d.ts +0 -56
- package/dist/quicktype-core/language/Haskell.js +0 -411
- package/dist/quicktype-core/language/JSONSchema.d.ts +0 -31
- package/dist/quicktype-core/language/JSONSchema.js +0 -169
- package/dist/quicktype-core/language/Java.d.ts +0 -125
- package/dist/quicktype-core/language/Java.js +0 -1081
- package/dist/quicktype-core/language/JavaScript.d.ts +0 -68
- package/dist/quicktype-core/language/JavaScript.js +0 -435
- package/dist/quicktype-core/language/JavaScriptPropTypes.d.ts +0 -40
- package/dist/quicktype-core/language/JavaScriptPropTypes.js +0 -213
- package/dist/quicktype-core/language/JavaScriptUnicodeMaps.d.ts +0 -2
- package/dist/quicktype-core/language/JavaScriptUnicodeMaps.js +0 -134
- package/dist/quicktype-core/language/Kotlin.d.ts +0 -109
- package/dist/quicktype-core/language/Kotlin.js +0 -832
- package/dist/quicktype-core/language/Objective-C.d.ts +0 -79
- package/dist/quicktype-core/language/Objective-C.js +0 -777
- package/dist/quicktype-core/language/Php.d.ts +0 -80
- package/dist/quicktype-core/language/Php.js +0 -702
- package/dist/quicktype-core/language/Pike.d.ts +0 -37
- package/dist/quicktype-core/language/Pike.js +0 -276
- package/dist/quicktype-core/language/Python.d.ts +0 -107
- package/dist/quicktype-core/language/Python.js +0 -969
- package/dist/quicktype-core/language/Rust.d.ts +0 -56
- package/dist/quicktype-core/language/Rust.js +0 -309
- package/dist/quicktype-core/language/Swift.d.ts +0 -96
- package/dist/quicktype-core/language/Swift.js +0 -1211
- package/dist/quicktype-core/language/TypeScriptFlow.d.ts +0 -77
- package/dist/quicktype-core/language/TypeScriptFlow.js +0 -286
- package/dist/quicktype-core/language/ruby/index.d.ts +0 -52
- package/dist/quicktype-core/language/ruby/index.js +0 -557
- package/dist/quicktype-core/language/ruby/keywords.d.ts +0 -3
- package/dist/quicktype-core/language/ruby/keywords.js +0 -358
- package/dist/quicktype-core/rewrites/CombineClasses.d.ts +0 -3
- package/dist/quicktype-core/rewrites/CombineClasses.js +0 -125
- package/dist/quicktype-core/rewrites/ExpandStrings.d.ts +0 -4
- package/dist/quicktype-core/rewrites/ExpandStrings.js +0 -143
- package/dist/quicktype-core/rewrites/FlattenStrings.d.ts +0 -3
- package/dist/quicktype-core/rewrites/FlattenStrings.js +0 -45
- package/dist/quicktype-core/rewrites/FlattenUnions.d.ts +0 -3
- package/dist/quicktype-core/rewrites/FlattenUnions.js +0 -47
- package/dist/quicktype-core/rewrites/InferMaps.d.ts +0 -3
- package/dist/quicktype-core/rewrites/InferMaps.js +0 -117
- package/dist/quicktype-core/rewrites/ReplaceObjectType.d.ts +0 -3
- package/dist/quicktype-core/rewrites/ReplaceObjectType.js +0 -60
- package/dist/quicktype-core/rewrites/ResolveIntersections.d.ts +0 -3
- package/dist/quicktype-core/rewrites/ResolveIntersections.js +0 -244
- package/dist/quicktype-core/support/Acronyms.d.ts +0 -10
- package/dist/quicktype-core/support/Acronyms.js +0 -1128
- package/dist/quicktype-core/support/Chance.d.ts +0 -38
- package/dist/quicktype-core/support/Chance.js +0 -2146
- package/dist/quicktype-core/support/Converters.d.ts +0 -6
- package/dist/quicktype-core/support/Converters.js +0 -16
- package/dist/quicktype-core/support/Strings.d.ts +0 -44
- package/dist/quicktype-core/support/Strings.js +0 -525
- package/dist/quicktype-core/support/Support.d.ts +0 -29
- package/dist/quicktype-core/support/Support.js +0 -162
- package/dist/quicktype-graphql-input/GraphQLSchema.d.ts +0 -645
- package/dist/quicktype-graphql-input/GraphQLSchema.js +0 -39
- package/dist/quicktype-graphql-input/index.d.ts +0 -17
- package/dist/quicktype-graphql-input/index.js +0 -407
- package/dist/quicktype-typescript-input/index.d.ts +0 -2
- package/dist/quicktype-typescript-input/index.js +0 -98
|
@@ -1,969 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.JSONPythonRenderer = exports.PythonRenderer = exports.PythonTargetLanguage = exports.pythonOptions = void 0;
|
|
4
|
-
const TargetLanguage_1 = require("../TargetLanguage");
|
|
5
|
-
const Type_1 = require("../Type");
|
|
6
|
-
const RendererOptions_1 = require("../RendererOptions");
|
|
7
|
-
const ConvenienceRenderer_1 = require("../ConvenienceRenderer");
|
|
8
|
-
const Naming_1 = require("../Naming");
|
|
9
|
-
const Strings_1 = require("../support/Strings");
|
|
10
|
-
const Support_1 = require("../support/Support");
|
|
11
|
-
const Source_1 = require("../Source");
|
|
12
|
-
const TypeUtils_1 = require("../TypeUtils");
|
|
13
|
-
const Transformers_1 = require("../Transformers");
|
|
14
|
-
const collection_utils_1 = require("collection-utils");
|
|
15
|
-
const unicode = require("unicode-properties");
|
|
16
|
-
const forbiddenTypeNames = [
|
|
17
|
-
"Any",
|
|
18
|
-
"True",
|
|
19
|
-
"False",
|
|
20
|
-
"None",
|
|
21
|
-
"Enum",
|
|
22
|
-
"List",
|
|
23
|
-
"Dict",
|
|
24
|
-
"Optional",
|
|
25
|
-
"Union",
|
|
26
|
-
"Iterable",
|
|
27
|
-
"Type",
|
|
28
|
-
"TypeVar",
|
|
29
|
-
"T",
|
|
30
|
-
"EnumT"
|
|
31
|
-
];
|
|
32
|
-
const forbiddenPropertyNames = [
|
|
33
|
-
"and",
|
|
34
|
-
"as",
|
|
35
|
-
"assert",
|
|
36
|
-
"async",
|
|
37
|
-
"await",
|
|
38
|
-
"bool",
|
|
39
|
-
"break",
|
|
40
|
-
"class",
|
|
41
|
-
"continue",
|
|
42
|
-
"datetime",
|
|
43
|
-
"def",
|
|
44
|
-
"del",
|
|
45
|
-
"dict",
|
|
46
|
-
"elif",
|
|
47
|
-
"else",
|
|
48
|
-
"except",
|
|
49
|
-
"finally",
|
|
50
|
-
"float",
|
|
51
|
-
"for",
|
|
52
|
-
"from",
|
|
53
|
-
"global",
|
|
54
|
-
"if",
|
|
55
|
-
"import",
|
|
56
|
-
"in",
|
|
57
|
-
"int",
|
|
58
|
-
"is",
|
|
59
|
-
"lambda",
|
|
60
|
-
"nonlocal",
|
|
61
|
-
"not",
|
|
62
|
-
"or",
|
|
63
|
-
"pass",
|
|
64
|
-
"print",
|
|
65
|
-
"raise",
|
|
66
|
-
"return",
|
|
67
|
-
"self",
|
|
68
|
-
"str",
|
|
69
|
-
"try",
|
|
70
|
-
"while",
|
|
71
|
-
"with",
|
|
72
|
-
"yield"
|
|
73
|
-
];
|
|
74
|
-
exports.pythonOptions = {
|
|
75
|
-
features: new RendererOptions_1.EnumOption("python-version", "Python version", [
|
|
76
|
-
["3.5", { typeHints: false, dataClasses: false }],
|
|
77
|
-
["3.6", { typeHints: true, dataClasses: false }],
|
|
78
|
-
["3.7", { typeHints: true, dataClasses: true }]
|
|
79
|
-
], "3.6"),
|
|
80
|
-
justTypes: new RendererOptions_1.BooleanOption("just-types", "Classes only", false),
|
|
81
|
-
nicePropertyNames: new RendererOptions_1.BooleanOption("nice-property-names", "Transform property names to be Pythonic", true)
|
|
82
|
-
};
|
|
83
|
-
class PythonTargetLanguage extends TargetLanguage_1.TargetLanguage {
|
|
84
|
-
getOptions() {
|
|
85
|
-
return [exports.pythonOptions.features, exports.pythonOptions.justTypes, exports.pythonOptions.nicePropertyNames];
|
|
86
|
-
}
|
|
87
|
-
get stringTypeMapping() {
|
|
88
|
-
const mapping = new Map();
|
|
89
|
-
const dateTimeType = "date-time";
|
|
90
|
-
mapping.set("date", dateTimeType);
|
|
91
|
-
mapping.set("time", dateTimeType);
|
|
92
|
-
mapping.set("date-time", dateTimeType);
|
|
93
|
-
mapping.set("uuid", "uuid");
|
|
94
|
-
mapping.set("integer-string", "integer-string");
|
|
95
|
-
mapping.set("bool-string", "bool-string");
|
|
96
|
-
return mapping;
|
|
97
|
-
}
|
|
98
|
-
get supportsUnionsWithBothNumberTypes() {
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
get supportsOptionalClassProperties() {
|
|
102
|
-
return false;
|
|
103
|
-
}
|
|
104
|
-
needsTransformerForType(t) {
|
|
105
|
-
if (t instanceof Type_1.UnionType) {
|
|
106
|
-
return (0, collection_utils_1.iterableSome)(t.members, m => this.needsTransformerForType(m));
|
|
107
|
-
}
|
|
108
|
-
return t.kind === "integer-string" || t.kind === "bool-string";
|
|
109
|
-
}
|
|
110
|
-
makeRenderer(renderContext, untypedOptionValues) {
|
|
111
|
-
const options = (0, RendererOptions_1.getOptionValues)(exports.pythonOptions, untypedOptionValues);
|
|
112
|
-
if (options.justTypes) {
|
|
113
|
-
return new PythonRenderer(this, renderContext, options);
|
|
114
|
-
}
|
|
115
|
-
else {
|
|
116
|
-
return new JSONPythonRenderer(this, renderContext, options);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
exports.PythonTargetLanguage = PythonTargetLanguage;
|
|
121
|
-
function isNormalizedStartCharacter3(utf16Unit) {
|
|
122
|
-
// FIXME: add Other_ID_Start - https://docs.python.org/3/reference/lexical_analysis.html#identifiers
|
|
123
|
-
const category = unicode.getCategory(utf16Unit);
|
|
124
|
-
return ["Lu", "Ll", "Lt", "Lm", "Lo", "Nl"].indexOf(category) >= 0;
|
|
125
|
-
}
|
|
126
|
-
function isNormalizedPartCharacter3(utf16Unit) {
|
|
127
|
-
// FIXME: add Other_ID_Continue - https://docs.python.org/3/reference/lexical_analysis.html#identifiers
|
|
128
|
-
if (isNormalizedStartCharacter3(utf16Unit))
|
|
129
|
-
return true;
|
|
130
|
-
const category = unicode.getCategory(utf16Unit);
|
|
131
|
-
return ["Mn", "Mc", "Nd", "Pc"].indexOf(category) >= 0;
|
|
132
|
-
}
|
|
133
|
-
function isStartCharacter3(utf16Unit) {
|
|
134
|
-
const s = String.fromCharCode(utf16Unit).normalize("NFKC");
|
|
135
|
-
const l = s.length;
|
|
136
|
-
if (l === 0 || !isNormalizedStartCharacter3(s.charCodeAt(0)))
|
|
137
|
-
return false;
|
|
138
|
-
for (let i = 1; i < l; i++) {
|
|
139
|
-
if (!isNormalizedPartCharacter3(s.charCodeAt(i)))
|
|
140
|
-
return false;
|
|
141
|
-
}
|
|
142
|
-
return true;
|
|
143
|
-
}
|
|
144
|
-
function isPartCharacter3(utf16Unit) {
|
|
145
|
-
const s = String.fromCharCode(utf16Unit).normalize("NFKC");
|
|
146
|
-
const l = s.length;
|
|
147
|
-
for (let i = 0; i < l; i++) {
|
|
148
|
-
if (!isNormalizedPartCharacter3(s.charCodeAt(i)))
|
|
149
|
-
return false;
|
|
150
|
-
}
|
|
151
|
-
return true;
|
|
152
|
-
}
|
|
153
|
-
const legalizeName3 = (0, Strings_1.utf16LegalizeCharacters)(isPartCharacter3);
|
|
154
|
-
function classNameStyle(original) {
|
|
155
|
-
const words = (0, Strings_1.splitIntoWords)(original);
|
|
156
|
-
return (0, Strings_1.combineWords)(words, legalizeName3, Strings_1.firstUpperWordStyle, Strings_1.firstUpperWordStyle, Strings_1.allUpperWordStyle, Strings_1.allUpperWordStyle, "", isStartCharacter3);
|
|
157
|
-
}
|
|
158
|
-
function getWordStyle(uppercase, forceSnakeNameStyle) {
|
|
159
|
-
if (!forceSnakeNameStyle) {
|
|
160
|
-
return Strings_1.originalWord;
|
|
161
|
-
}
|
|
162
|
-
return uppercase ? Strings_1.allUpperWordStyle : Strings_1.allLowerWordStyle;
|
|
163
|
-
}
|
|
164
|
-
function snakeNameStyle(original, uppercase, forceSnakeNameStyle) {
|
|
165
|
-
const wordStyle = getWordStyle(uppercase, forceSnakeNameStyle);
|
|
166
|
-
const separator = forceSnakeNameStyle ? "_" : "";
|
|
167
|
-
const words = (0, Strings_1.splitIntoWords)(original);
|
|
168
|
-
return (0, Strings_1.combineWords)(words, legalizeName3, wordStyle, wordStyle, wordStyle, wordStyle, separator, isStartCharacter3);
|
|
169
|
-
}
|
|
170
|
-
class PythonRenderer extends ConvenienceRenderer_1.ConvenienceRenderer {
|
|
171
|
-
pyOptions;
|
|
172
|
-
imports = new Map();
|
|
173
|
-
declaredTypes = new Set();
|
|
174
|
-
constructor(targetLanguage, renderContext, pyOptions) {
|
|
175
|
-
super(targetLanguage, renderContext);
|
|
176
|
-
this.pyOptions = pyOptions;
|
|
177
|
-
}
|
|
178
|
-
forbiddenNamesForGlobalNamespace() {
|
|
179
|
-
return forbiddenTypeNames;
|
|
180
|
-
}
|
|
181
|
-
forbiddenForObjectProperties(_, _classNamed) {
|
|
182
|
-
return { names: forbiddenPropertyNames, includeGlobalForbidden: false };
|
|
183
|
-
}
|
|
184
|
-
makeNamedTypeNamer() {
|
|
185
|
-
return (0, Naming_1.funPrefixNamer)("type", classNameStyle);
|
|
186
|
-
}
|
|
187
|
-
namerForObjectProperty() {
|
|
188
|
-
return (0, Naming_1.funPrefixNamer)("property", s => snakeNameStyle(s, false, this.pyOptions.nicePropertyNames));
|
|
189
|
-
}
|
|
190
|
-
makeUnionMemberNamer() {
|
|
191
|
-
return null;
|
|
192
|
-
}
|
|
193
|
-
makeEnumCaseNamer() {
|
|
194
|
-
return (0, Naming_1.funPrefixNamer)("enum-case", s => snakeNameStyle(s, true, this.pyOptions.nicePropertyNames));
|
|
195
|
-
}
|
|
196
|
-
get commentLineStart() {
|
|
197
|
-
return "# ";
|
|
198
|
-
}
|
|
199
|
-
emitDescriptionBlock(lines) {
|
|
200
|
-
if (lines.length === 1) {
|
|
201
|
-
this.emitLine('"""', lines[0], '"""');
|
|
202
|
-
}
|
|
203
|
-
else {
|
|
204
|
-
this.emitCommentLines(lines, "", undefined, '"""', '"""');
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
get needsTypeDeclarationBeforeUse() {
|
|
208
|
-
return true;
|
|
209
|
-
}
|
|
210
|
-
canBeForwardDeclared(t) {
|
|
211
|
-
const kind = t.kind;
|
|
212
|
-
return kind === "class" || kind === "enum";
|
|
213
|
-
}
|
|
214
|
-
emitBlock(line, f) {
|
|
215
|
-
this.emitLine(line);
|
|
216
|
-
this.indent(f);
|
|
217
|
-
}
|
|
218
|
-
string(s) {
|
|
219
|
-
const openQuote = '"';
|
|
220
|
-
return [openQuote, (0, Strings_1.stringEscape)(s), '"'];
|
|
221
|
-
}
|
|
222
|
-
withImport(module, name) {
|
|
223
|
-
if (this.pyOptions.features.typeHints || module !== "typing") {
|
|
224
|
-
// FIXME: This is ugly. We should rather not generate that import in the first
|
|
225
|
-
// place, but right now we just make the type source and then throw it away. It's
|
|
226
|
-
// not a performance issue, so it's fine, I just bemoan this special case, and
|
|
227
|
-
// potential others down the road.
|
|
228
|
-
(0, collection_utils_1.mapUpdateInto)(this.imports, module, s => (s ? (0, collection_utils_1.setUnionInto)(s, [name]) : new Set([name])));
|
|
229
|
-
}
|
|
230
|
-
return name;
|
|
231
|
-
}
|
|
232
|
-
withTyping(name) {
|
|
233
|
-
return this.withImport("typing", name);
|
|
234
|
-
}
|
|
235
|
-
namedType(t) {
|
|
236
|
-
const name = this.nameForNamedType(t);
|
|
237
|
-
if (this.declaredTypes.has(t))
|
|
238
|
-
return name;
|
|
239
|
-
return ["'", name, "'"];
|
|
240
|
-
}
|
|
241
|
-
pythonType(t) {
|
|
242
|
-
const actualType = (0, Transformers_1.followTargetType)(t);
|
|
243
|
-
return (0, TypeUtils_1.matchType)(actualType, _anyType => this.withTyping("Any"), _nullType => "None", _boolType => "bool", _integerType => "int", _doubletype => "float", _stringType => "str", arrayType => [this.withTyping("List"), "[", this.pythonType(arrayType.items), "]"], classType => this.namedType(classType), mapType => [this.withTyping("Dict"), "[str, ", this.pythonType(mapType.values), "]"], enumType => this.namedType(enumType), unionType => {
|
|
244
|
-
const [hasNull, nonNulls] = (0, TypeUtils_1.removeNullFromUnion)(unionType);
|
|
245
|
-
const memberTypes = Array.from(nonNulls).map(m => this.pythonType(m));
|
|
246
|
-
if (hasNull !== null) {
|
|
247
|
-
let rest = [];
|
|
248
|
-
if (!this.getAlphabetizeProperties() && this.pyOptions.features.dataClasses)
|
|
249
|
-
rest.push(" = None");
|
|
250
|
-
if (nonNulls.size > 1) {
|
|
251
|
-
this.withImport("typing", "Union");
|
|
252
|
-
return [
|
|
253
|
-
this.withTyping("Optional"),
|
|
254
|
-
"[Union[",
|
|
255
|
-
(0, collection_utils_1.arrayIntercalate)(", ", memberTypes),
|
|
256
|
-
"]]",
|
|
257
|
-
...rest
|
|
258
|
-
];
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
261
|
-
return [this.withTyping("Optional"), "[", (0, Support_1.defined)((0, collection_utils_1.iterableFirst)(memberTypes)), "]", ...rest];
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
else {
|
|
265
|
-
return [this.withTyping("Union"), "[", (0, collection_utils_1.arrayIntercalate)(", ", memberTypes), "]"];
|
|
266
|
-
}
|
|
267
|
-
}, transformedStringType => {
|
|
268
|
-
if (transformedStringType.kind === "date-time") {
|
|
269
|
-
return this.withImport("datetime", "datetime");
|
|
270
|
-
}
|
|
271
|
-
if (transformedStringType.kind === "uuid") {
|
|
272
|
-
return this.withImport("uuid", "UUID");
|
|
273
|
-
}
|
|
274
|
-
return (0, Support_1.panic)(`Transformed type ${transformedStringType.kind} not supported`);
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
declarationLine(t) {
|
|
278
|
-
if (t instanceof Type_1.ClassType) {
|
|
279
|
-
return ["class ", this.nameForNamedType(t), ":"];
|
|
280
|
-
}
|
|
281
|
-
if (t instanceof Type_1.EnumType) {
|
|
282
|
-
return ["class ", this.nameForNamedType(t), "(", this.withImport("enum", "Enum"), "):"];
|
|
283
|
-
}
|
|
284
|
-
return (0, Support_1.panic)(`Can't declare type ${t.kind}`);
|
|
285
|
-
}
|
|
286
|
-
declareType(t, emitter) {
|
|
287
|
-
this.emitBlock(this.declarationLine(t), () => {
|
|
288
|
-
this.emitDescription(this.descriptionForType(t));
|
|
289
|
-
emitter();
|
|
290
|
-
});
|
|
291
|
-
this.declaredTypes.add(t);
|
|
292
|
-
}
|
|
293
|
-
emitClassMembers(t) {
|
|
294
|
-
if (this.pyOptions.features.dataClasses)
|
|
295
|
-
return;
|
|
296
|
-
const args = [];
|
|
297
|
-
this.forEachClassProperty(t, "none", (name, _, cp) => {
|
|
298
|
-
args.push([name, this.typeHint(": ", this.pythonType(cp.type))]);
|
|
299
|
-
});
|
|
300
|
-
this.emitBlock(["def __init__(self, ", (0, collection_utils_1.arrayIntercalate)(", ", args), ")", this.typeHint(" -> None"), ":"], () => {
|
|
301
|
-
if (args.length === 0) {
|
|
302
|
-
this.emitLine("pass");
|
|
303
|
-
}
|
|
304
|
-
else {
|
|
305
|
-
this.forEachClassProperty(t, "none", name => {
|
|
306
|
-
this.emitLine("self.", name, " = ", name);
|
|
307
|
-
});
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
}
|
|
311
|
-
typeHint(...sl) {
|
|
312
|
-
if (this.pyOptions.features.typeHints) {
|
|
313
|
-
return sl;
|
|
314
|
-
}
|
|
315
|
-
return [];
|
|
316
|
-
}
|
|
317
|
-
typingDecl(name, type) {
|
|
318
|
-
return [name, this.typeHint(": ", this.withTyping(type))];
|
|
319
|
-
}
|
|
320
|
-
typingReturn(type) {
|
|
321
|
-
return this.typeHint(" -> ", this.withTyping(type));
|
|
322
|
-
}
|
|
323
|
-
sortClassProperties(properties, propertyNames) {
|
|
324
|
-
if (this.pyOptions.features.dataClasses) {
|
|
325
|
-
return (0, collection_utils_1.mapSortBy)(properties, (p) => {
|
|
326
|
-
return p.type instanceof Type_1.UnionType && (0, TypeUtils_1.nullableFromUnion)(p.type) != null ? 1 : 0;
|
|
327
|
-
});
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
return super.sortClassProperties(properties, propertyNames);
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
emitClass(t) {
|
|
334
|
-
if (this.pyOptions.features.dataClasses) {
|
|
335
|
-
this.emitLine("@", this.withImport("dataclasses", "dataclass"));
|
|
336
|
-
}
|
|
337
|
-
this.declareType(t, () => {
|
|
338
|
-
if (this.pyOptions.features.typeHints) {
|
|
339
|
-
if (t.getProperties().size === 0) {
|
|
340
|
-
this.emitLine("pass");
|
|
341
|
-
}
|
|
342
|
-
else {
|
|
343
|
-
this.forEachClassProperty(t, "none", (name, jsonName, cp) => {
|
|
344
|
-
this.emitDescription(this.descriptionForClassProperty(t, jsonName));
|
|
345
|
-
this.emitLine(name, this.typeHint(": ", this.pythonType(cp.type)));
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
this.ensureBlankLine();
|
|
349
|
-
}
|
|
350
|
-
this.emitClassMembers(t);
|
|
351
|
-
});
|
|
352
|
-
}
|
|
353
|
-
emitEnum(t) {
|
|
354
|
-
this.declareType(t, () => {
|
|
355
|
-
this.forEachEnumCase(t, "none", (name, jsonName) => {
|
|
356
|
-
this.emitLine([name, " = ", this.string(jsonName)]);
|
|
357
|
-
});
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
|
-
emitImports() {
|
|
361
|
-
this.imports.forEach((names, module) => {
|
|
362
|
-
this.emitLine("from ", module, " import ", Array.from(names).join(", "));
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
emitSupportCode() {
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
emitClosingCode() {
|
|
369
|
-
return;
|
|
370
|
-
}
|
|
371
|
-
emitSourceStructure(_givenOutputFilename) {
|
|
372
|
-
const declarationLines = this.gatherSource(() => {
|
|
373
|
-
this.forEachNamedType(["interposing", 2], (c) => this.emitClass(c), e => this.emitEnum(e), _u => {
|
|
374
|
-
return;
|
|
375
|
-
});
|
|
376
|
-
});
|
|
377
|
-
const closingLines = this.gatherSource(() => this.emitClosingCode());
|
|
378
|
-
const supportLines = this.gatherSource(() => this.emitSupportCode());
|
|
379
|
-
if (this.leadingComments !== undefined) {
|
|
380
|
-
this.emitCommentLines(this.leadingComments);
|
|
381
|
-
}
|
|
382
|
-
this.ensureBlankLine();
|
|
383
|
-
this.emitImports();
|
|
384
|
-
this.ensureBlankLine(2);
|
|
385
|
-
this.emitGatheredSource(supportLines);
|
|
386
|
-
this.ensureBlankLine(2);
|
|
387
|
-
this.emitGatheredSource(declarationLines);
|
|
388
|
-
this.ensureBlankLine(2);
|
|
389
|
-
this.emitGatheredSource(closingLines);
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
exports.PythonRenderer = PythonRenderer;
|
|
393
|
-
function compose(input, f) {
|
|
394
|
-
if (typeof f === "function") {
|
|
395
|
-
if (input.value !== undefined) {
|
|
396
|
-
// `input` is a value, so just apply `f` to its source form.
|
|
397
|
-
return { value: f(makeValue(input)) };
|
|
398
|
-
}
|
|
399
|
-
if (input.lambda !== undefined) {
|
|
400
|
-
// `input` is a lambda, so build `lambda x: f(input(x))`.
|
|
401
|
-
return { lambda: (0, Source_1.multiWord)(" ", "lambda x:", f([(0, Source_1.parenIfNeeded)(input.lambda), "(x)"])), value: undefined };
|
|
402
|
-
}
|
|
403
|
-
// `input` is the identify function, so the composition is `lambda x: f(x)`.
|
|
404
|
-
return { lambda: (0, Source_1.multiWord)(" ", "lambda x:", f("x")), value: undefined };
|
|
405
|
-
}
|
|
406
|
-
if (f.value !== undefined) {
|
|
407
|
-
return (0, Support_1.panic)("Cannot compose into a value");
|
|
408
|
-
}
|
|
409
|
-
if (f.lambda === undefined) {
|
|
410
|
-
// `f` is the identity function, so the result is just `input`.
|
|
411
|
-
return input;
|
|
412
|
-
}
|
|
413
|
-
if (input.value === undefined) {
|
|
414
|
-
// `input` is a lambda
|
|
415
|
-
if (input.lambda === undefined) {
|
|
416
|
-
// `input` is the identity function, so the result is just `f`.
|
|
417
|
-
return f;
|
|
418
|
-
}
|
|
419
|
-
// `input` is a lambda, so the result is `lambda x: f(input(x))`.
|
|
420
|
-
return {
|
|
421
|
-
lambda: (0, Source_1.multiWord)("", "lambda x: ", (0, Source_1.parenIfNeeded)(f.lambda), "(", (0, Source_1.parenIfNeeded)(input.lambda), "(x))"),
|
|
422
|
-
value: undefined
|
|
423
|
-
};
|
|
424
|
-
}
|
|
425
|
-
// `input` is a value, so return `f(input)`.
|
|
426
|
-
return { lambda: f.lambda, value: makeValue(input) };
|
|
427
|
-
}
|
|
428
|
-
const identity = { value: undefined };
|
|
429
|
-
// If `vol` is a lambda, return it in its source form. If it's
|
|
430
|
-
// a value, return a `lambda` that returns the value.
|
|
431
|
-
function makeLambda(vol) {
|
|
432
|
-
if (vol.lambda !== undefined) {
|
|
433
|
-
if (vol.value === undefined) {
|
|
434
|
-
return vol.lambda;
|
|
435
|
-
}
|
|
436
|
-
return (0, Source_1.multiWord)("", "lambda x: ", (0, Source_1.parenIfNeeded)(vol.lambda), "(", vol.value, ")");
|
|
437
|
-
}
|
|
438
|
-
else if (vol.value !== undefined) {
|
|
439
|
-
return (0, Source_1.multiWord)(" ", "lambda x:", vol.value);
|
|
440
|
-
}
|
|
441
|
-
return (0, Source_1.multiWord)(" ", "lambda x:", "x");
|
|
442
|
-
}
|
|
443
|
-
// If `vol` is a value, return the value in its source form.
|
|
444
|
-
// Calling this with `vol` being a lambda is not allowed.
|
|
445
|
-
function makeValue(vol) {
|
|
446
|
-
if (vol.value === undefined) {
|
|
447
|
-
return (0, Support_1.panic)("Cannot make value from lambda without value");
|
|
448
|
-
}
|
|
449
|
-
if (vol.lambda !== undefined) {
|
|
450
|
-
return [(0, Source_1.parenIfNeeded)(vol.lambda), "(", vol.value, ")"];
|
|
451
|
-
}
|
|
452
|
-
return vol.value;
|
|
453
|
-
}
|
|
454
|
-
class JSONPythonRenderer extends PythonRenderer {
|
|
455
|
-
_deserializerFunctions = new Set();
|
|
456
|
-
_converterNamer = (0, Naming_1.funPrefixNamer)("converter", s => snakeNameStyle(s, false, this.pyOptions.nicePropertyNames));
|
|
457
|
-
_topLevelConverterNames = new Map();
|
|
458
|
-
_haveTypeVar = false;
|
|
459
|
-
_haveEnumTypeVar = false;
|
|
460
|
-
_haveDateutil = false;
|
|
461
|
-
emitTypeVar(tvar, constraints) {
|
|
462
|
-
if (!this.pyOptions.features.typeHints) {
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
this.emitLine(tvar, " = ", this.withTyping("TypeVar"), "(", this.string(tvar), constraints, ")");
|
|
466
|
-
}
|
|
467
|
-
typeVar() {
|
|
468
|
-
this._haveTypeVar = true;
|
|
469
|
-
// FIXME: This is ugly, but the code that requires the type variables, in
|
|
470
|
-
// `emitImports` actually runs after imports have been imported. The proper
|
|
471
|
-
// solution would be to either allow more complex dependencies, or to
|
|
472
|
-
// gather-emit the type variable declarations, too. Unfortunately the
|
|
473
|
-
// gather-emit is a bit buggy with blank lines, and I can't be bothered to
|
|
474
|
-
// fix it now.
|
|
475
|
-
this.withTyping("TypeVar");
|
|
476
|
-
return "T";
|
|
477
|
-
}
|
|
478
|
-
enumTypeVar() {
|
|
479
|
-
this._haveEnumTypeVar = true;
|
|
480
|
-
// See the comment above.
|
|
481
|
-
this.withTyping("TypeVar");
|
|
482
|
-
this.withImport("enum", "Enum");
|
|
483
|
-
return "EnumT";
|
|
484
|
-
}
|
|
485
|
-
cast(type, v) {
|
|
486
|
-
if (!this.pyOptions.features.typeHints) {
|
|
487
|
-
return v;
|
|
488
|
-
}
|
|
489
|
-
return [this.withTyping("cast"), "(", type, ", ", v, ")"];
|
|
490
|
-
}
|
|
491
|
-
emitNoneConverter() {
|
|
492
|
-
// FIXME: We can't return the None type here because mypy thinks that means
|
|
493
|
-
// We're not returning any value, when we're actually returning `None`.
|
|
494
|
-
this.emitBlock(["def from_none(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> ", this.withTyping("Any")), ":"], () => {
|
|
495
|
-
this.emitLine("assert x is None");
|
|
496
|
-
this.emitLine("return x");
|
|
497
|
-
});
|
|
498
|
-
}
|
|
499
|
-
emitBoolConverter() {
|
|
500
|
-
this.emitBlock(["def from_bool(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> bool"), ":"], () => {
|
|
501
|
-
this.emitLine("assert isinstance(x, bool)");
|
|
502
|
-
this.emitLine("return x");
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
emitIntConverter() {
|
|
506
|
-
this.emitBlock(["def from_int(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> int"), ":"], () => {
|
|
507
|
-
this.emitLine("assert isinstance(x, int) and not isinstance(x, bool)");
|
|
508
|
-
this.emitLine("return x");
|
|
509
|
-
});
|
|
510
|
-
}
|
|
511
|
-
emitFromFloatConverter() {
|
|
512
|
-
this.emitBlock(["def from_float(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> float"), ":"], () => {
|
|
513
|
-
this.emitLine("assert isinstance(x, (float, int)) and not isinstance(x, bool)");
|
|
514
|
-
this.emitLine("return float(x)");
|
|
515
|
-
});
|
|
516
|
-
}
|
|
517
|
-
emitToFloatConverter() {
|
|
518
|
-
this.emitBlock(["def to_float(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> float"), ":"], () => {
|
|
519
|
-
this.emitLine("assert isinstance(x, float)");
|
|
520
|
-
this.emitLine("return x");
|
|
521
|
-
});
|
|
522
|
-
}
|
|
523
|
-
emitStrConverter() {
|
|
524
|
-
this.emitBlock(["def from_str(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> str"), ":"], () => {
|
|
525
|
-
const strType = "str";
|
|
526
|
-
this.emitLine("assert isinstance(x, ", strType, ")");
|
|
527
|
-
this.emitLine("return x");
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
emitToEnumConverter() {
|
|
531
|
-
const tvar = this.enumTypeVar();
|
|
532
|
-
this.emitBlock([
|
|
533
|
-
"def to_enum(c",
|
|
534
|
-
this.typeHint(": ", this.withTyping("Type"), "[", tvar, "]"),
|
|
535
|
-
", ",
|
|
536
|
-
this.typingDecl("x", "Any"),
|
|
537
|
-
")",
|
|
538
|
-
this.typeHint(" -> ", tvar),
|
|
539
|
-
":"
|
|
540
|
-
], () => {
|
|
541
|
-
this.emitLine("assert isinstance(x, c)");
|
|
542
|
-
this.emitLine("return x.value");
|
|
543
|
-
});
|
|
544
|
-
}
|
|
545
|
-
emitListConverter() {
|
|
546
|
-
const tvar = this.typeVar();
|
|
547
|
-
this.emitBlock([
|
|
548
|
-
"def from_list(f",
|
|
549
|
-
this.typeHint(": ", this.withTyping("Callable"), "[[", this.withTyping("Any"), "], ", tvar, "]"),
|
|
550
|
-
", ",
|
|
551
|
-
this.typingDecl("x", "Any"),
|
|
552
|
-
")",
|
|
553
|
-
this.typeHint(" -> ", this.withTyping("List"), "[", tvar, "]"),
|
|
554
|
-
":"
|
|
555
|
-
], () => {
|
|
556
|
-
this.emitLine("assert isinstance(x, list)");
|
|
557
|
-
this.emitLine("return [f(y) for y in x]");
|
|
558
|
-
});
|
|
559
|
-
}
|
|
560
|
-
emitToClassConverter() {
|
|
561
|
-
const tvar = this.typeVar();
|
|
562
|
-
this.emitBlock([
|
|
563
|
-
"def to_class(c",
|
|
564
|
-
this.typeHint(": ", this.withTyping("Type"), "[", tvar, "]"),
|
|
565
|
-
", ",
|
|
566
|
-
this.typingDecl("x", "Any"),
|
|
567
|
-
")",
|
|
568
|
-
this.typeHint(" -> dict"),
|
|
569
|
-
":"
|
|
570
|
-
], () => {
|
|
571
|
-
this.emitLine("assert isinstance(x, c)");
|
|
572
|
-
this.emitLine("return ", this.cast(this.withTyping("Any"), "x"), ".to_dict()");
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
|
-
emitDictConverter() {
|
|
576
|
-
const tvar = this.typeVar();
|
|
577
|
-
this.emitBlock([
|
|
578
|
-
"def from_dict(f",
|
|
579
|
-
this.typeHint(": ", this.withTyping("Callable"), "[[", this.withTyping("Any"), "], ", tvar, "]"),
|
|
580
|
-
", ",
|
|
581
|
-
this.typingDecl("x", "Any"),
|
|
582
|
-
")",
|
|
583
|
-
this.typeHint(" -> ", this.withTyping("Dict"), "[str, ", tvar, "]"),
|
|
584
|
-
":"
|
|
585
|
-
], () => {
|
|
586
|
-
this.emitLine("assert isinstance(x, dict)");
|
|
587
|
-
this.emitLine("return { k: f(v) for (k, v) in x.items() }");
|
|
588
|
-
});
|
|
589
|
-
}
|
|
590
|
-
// This is not easily idiomatically typeable in Python. See
|
|
591
|
-
// https://stackoverflow.com/questions/51066468/computed-types-in-mypy/51084497
|
|
592
|
-
emitUnionConverter() {
|
|
593
|
-
this.emitMultiline(`def from_union(fs, x):
|
|
594
|
-
for f in fs:
|
|
595
|
-
try:
|
|
596
|
-
return f(x)
|
|
597
|
-
except:
|
|
598
|
-
pass
|
|
599
|
-
assert False`);
|
|
600
|
-
}
|
|
601
|
-
emitFromDatetimeConverter() {
|
|
602
|
-
this.emitBlock([
|
|
603
|
-
"def from_datetime(",
|
|
604
|
-
this.typingDecl("x", "Any"),
|
|
605
|
-
")",
|
|
606
|
-
this.typeHint(" -> ", this.withImport("datetime", "datetime")),
|
|
607
|
-
":"
|
|
608
|
-
], () => {
|
|
609
|
-
this._haveDateutil = true;
|
|
610
|
-
this.emitLine("return dateutil.parser.parse(x)");
|
|
611
|
-
});
|
|
612
|
-
}
|
|
613
|
-
emitFromStringifiedBoolConverter() {
|
|
614
|
-
this.emitBlock(["def from_stringified_bool(x", this.typeHint(": str"), ")", this.typeHint(" -> bool"), ":"], () => {
|
|
615
|
-
this.emitBlock('if x == "true":', () => this.emitLine("return True"));
|
|
616
|
-
this.emitBlock('if x == "false":', () => this.emitLine("return False"));
|
|
617
|
-
this.emitLine("assert False");
|
|
618
|
-
});
|
|
619
|
-
}
|
|
620
|
-
emitIsTypeConverter() {
|
|
621
|
-
const tvar = this.typeVar();
|
|
622
|
-
this.emitBlock([
|
|
623
|
-
"def is_type(t",
|
|
624
|
-
this.typeHint(": ", this.withTyping("Type"), "[", tvar, "]"),
|
|
625
|
-
", ",
|
|
626
|
-
this.typingDecl("x", "Any"),
|
|
627
|
-
")",
|
|
628
|
-
this.typeHint(" -> ", tvar),
|
|
629
|
-
":"
|
|
630
|
-
], () => {
|
|
631
|
-
this.emitLine("assert isinstance(x, t)");
|
|
632
|
-
this.emitLine("return x");
|
|
633
|
-
});
|
|
634
|
-
}
|
|
635
|
-
emitConverter(cf) {
|
|
636
|
-
switch (cf) {
|
|
637
|
-
case "none":
|
|
638
|
-
return this.emitNoneConverter();
|
|
639
|
-
case "bool":
|
|
640
|
-
return this.emitBoolConverter();
|
|
641
|
-
case "int":
|
|
642
|
-
return this.emitIntConverter();
|
|
643
|
-
case "from-float":
|
|
644
|
-
return this.emitFromFloatConverter();
|
|
645
|
-
case "to-float":
|
|
646
|
-
return this.emitToFloatConverter();
|
|
647
|
-
case "str":
|
|
648
|
-
return this.emitStrConverter();
|
|
649
|
-
case "to-enum":
|
|
650
|
-
return this.emitToEnumConverter();
|
|
651
|
-
case "list":
|
|
652
|
-
return this.emitListConverter();
|
|
653
|
-
case "to-class":
|
|
654
|
-
return this.emitToClassConverter();
|
|
655
|
-
case "dict":
|
|
656
|
-
return this.emitDictConverter();
|
|
657
|
-
case "union":
|
|
658
|
-
return this.emitUnionConverter();
|
|
659
|
-
case "from-datetime":
|
|
660
|
-
return this.emitFromDatetimeConverter();
|
|
661
|
-
case "from-stringified-bool":
|
|
662
|
-
return this.emitFromStringifiedBoolConverter();
|
|
663
|
-
case "is-type":
|
|
664
|
-
return this.emitIsTypeConverter();
|
|
665
|
-
default:
|
|
666
|
-
return (0, Support_1.assertNever)(cf);
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
// Return the name of the Python converter function `cf`.
|
|
670
|
-
conv(cf) {
|
|
671
|
-
this._deserializerFunctions.add(cf);
|
|
672
|
-
const name = cf.replace(/-/g, "_");
|
|
673
|
-
if (cf.startsWith("from-") || cf.startsWith("to-") || cf.startsWith("is-"))
|
|
674
|
-
return name;
|
|
675
|
-
return ["from_", name];
|
|
676
|
-
}
|
|
677
|
-
// Applies the converter function to `arg`
|
|
678
|
-
convFn(cf, arg) {
|
|
679
|
-
return compose(arg, { lambda: (0, Source_1.singleWord)(this.conv(cf)), value: undefined });
|
|
680
|
-
}
|
|
681
|
-
typeObject(t) {
|
|
682
|
-
const s = (0, TypeUtils_1.matchType)(t, _anyType => undefined, _nullType => "type(None)", _boolType => "bool", _integerType => "int", _doubleType => "float", _stringType => "str", _arrayType => "List", classType => this.nameForNamedType(classType), _mapType => "dict", enumType => this.nameForNamedType(enumType), _unionType => undefined, transformedStringType => {
|
|
683
|
-
if (transformedStringType.kind === "date-time") {
|
|
684
|
-
return this.withImport("datetime", "datetime");
|
|
685
|
-
}
|
|
686
|
-
if (transformedStringType.kind === "uuid") {
|
|
687
|
-
return this.withImport("uuid", "UUID");
|
|
688
|
-
}
|
|
689
|
-
return undefined;
|
|
690
|
-
});
|
|
691
|
-
if (s === undefined) {
|
|
692
|
-
return (0, Support_1.panic)(`No type object for ${t.kind}`);
|
|
693
|
-
}
|
|
694
|
-
return s;
|
|
695
|
-
}
|
|
696
|
-
transformer(inputTransformer, xfer, targetType) {
|
|
697
|
-
const consume = (consumer, vol) => {
|
|
698
|
-
if (consumer === undefined) {
|
|
699
|
-
return vol;
|
|
700
|
-
}
|
|
701
|
-
return this.transformer(vol, consumer, targetType);
|
|
702
|
-
};
|
|
703
|
-
const isType = (t, valueToCheck) => {
|
|
704
|
-
return compose(valueToCheck, v => [this.conv("is-type"), "(", this.typeObject(t), ", ", v, ")"]);
|
|
705
|
-
};
|
|
706
|
-
if (xfer instanceof Transformers_1.DecodingChoiceTransformer || xfer instanceof Transformers_1.ChoiceTransformer) {
|
|
707
|
-
const lambdas = xfer.transformers.map(x => makeLambda(this.transformer(identity, x, targetType)).source);
|
|
708
|
-
return compose(inputTransformer, v => [
|
|
709
|
-
this.conv("union"),
|
|
710
|
-
"([",
|
|
711
|
-
(0, collection_utils_1.arrayIntercalate)(", ", lambdas),
|
|
712
|
-
"], ",
|
|
713
|
-
v,
|
|
714
|
-
")"
|
|
715
|
-
]);
|
|
716
|
-
}
|
|
717
|
-
else if (xfer instanceof Transformers_1.DecodingTransformer) {
|
|
718
|
-
const consumer = xfer.consumer;
|
|
719
|
-
const vol = this.deserializer(inputTransformer, xfer.sourceType);
|
|
720
|
-
return consume(consumer, vol);
|
|
721
|
-
}
|
|
722
|
-
else if (xfer instanceof Transformers_1.EncodingTransformer) {
|
|
723
|
-
return this.serializer(inputTransformer, xfer.sourceType);
|
|
724
|
-
}
|
|
725
|
-
else if (xfer instanceof Transformers_1.UnionInstantiationTransformer) {
|
|
726
|
-
return inputTransformer;
|
|
727
|
-
}
|
|
728
|
-
else if (xfer instanceof Transformers_1.UnionMemberMatchTransformer) {
|
|
729
|
-
const consumer = xfer.transformer;
|
|
730
|
-
const vol = isType(xfer.memberType, inputTransformer);
|
|
731
|
-
return consume(consumer, vol);
|
|
732
|
-
}
|
|
733
|
-
else if (xfer instanceof Transformers_1.ParseStringTransformer) {
|
|
734
|
-
const consumer = xfer.consumer;
|
|
735
|
-
const immediateTargetType = consumer === undefined ? targetType : consumer.sourceType;
|
|
736
|
-
let vol;
|
|
737
|
-
switch (immediateTargetType.kind) {
|
|
738
|
-
case "integer":
|
|
739
|
-
vol = compose(inputTransformer, v => ["int(", v, ")"]);
|
|
740
|
-
break;
|
|
741
|
-
case "bool":
|
|
742
|
-
vol = this.convFn("from-stringified-bool", inputTransformer);
|
|
743
|
-
break;
|
|
744
|
-
case "enum":
|
|
745
|
-
vol = this.deserializer(inputTransformer, immediateTargetType);
|
|
746
|
-
break;
|
|
747
|
-
case "date-time":
|
|
748
|
-
vol = this.convFn("from-datetime", inputTransformer);
|
|
749
|
-
break;
|
|
750
|
-
case "uuid":
|
|
751
|
-
vol = compose(inputTransformer, v => [this.withImport("uuid", "UUID"), "(", v, ")"]);
|
|
752
|
-
break;
|
|
753
|
-
default:
|
|
754
|
-
return (0, Support_1.panic)(`Parsing of ${immediateTargetType.kind} in a transformer is not supported`);
|
|
755
|
-
}
|
|
756
|
-
return consume(consumer, vol);
|
|
757
|
-
}
|
|
758
|
-
else if (xfer instanceof Transformers_1.StringifyTransformer) {
|
|
759
|
-
const consumer = xfer.consumer;
|
|
760
|
-
let vol;
|
|
761
|
-
switch (xfer.sourceType.kind) {
|
|
762
|
-
case "integer":
|
|
763
|
-
vol = compose(inputTransformer, v => ["str(", v, ")"]);
|
|
764
|
-
break;
|
|
765
|
-
case "bool":
|
|
766
|
-
vol = compose(inputTransformer, v => ["str(", v, ").lower()"]);
|
|
767
|
-
break;
|
|
768
|
-
case "enum":
|
|
769
|
-
vol = this.serializer(inputTransformer, xfer.sourceType);
|
|
770
|
-
break;
|
|
771
|
-
case "date-time":
|
|
772
|
-
vol = compose(inputTransformer, v => [v, ".isoformat()"]);
|
|
773
|
-
break;
|
|
774
|
-
case "uuid":
|
|
775
|
-
vol = compose(inputTransformer, v => ["str(", v, ")"]);
|
|
776
|
-
break;
|
|
777
|
-
default:
|
|
778
|
-
return (0, Support_1.panic)(`Parsing of ${xfer.sourceType.kind} in a transformer is not supported`);
|
|
779
|
-
}
|
|
780
|
-
return consume(consumer, vol);
|
|
781
|
-
}
|
|
782
|
-
else {
|
|
783
|
-
return (0, Support_1.panic)(`Transformer ${xfer.kind} is not supported`);
|
|
784
|
-
}
|
|
785
|
-
}
|
|
786
|
-
// Returns the code to deserialize `value` as type `t`. If `t` has
|
|
787
|
-
// an associated transformer, the code for that transformer is
|
|
788
|
-
// returned.
|
|
789
|
-
deserializer(value, t) {
|
|
790
|
-
const xf = (0, Transformers_1.transformationForType)(t);
|
|
791
|
-
if (xf !== undefined) {
|
|
792
|
-
return this.transformer(value, xf.transformer, xf.targetType);
|
|
793
|
-
}
|
|
794
|
-
return (0, TypeUtils_1.matchType)(t, _anyType => value, _nullType => this.convFn("none", value), _boolType => this.convFn("bool", value), _integerType => this.convFn("int", value), _doubleType => this.convFn("from-float", value), _stringType => this.convFn("str", value), arrayType => compose(value, v => [
|
|
795
|
-
this.conv("list"),
|
|
796
|
-
"(",
|
|
797
|
-
makeLambda(this.deserializer(identity, arrayType.items)).source,
|
|
798
|
-
", ",
|
|
799
|
-
v,
|
|
800
|
-
")"
|
|
801
|
-
]), classType => compose(value, {
|
|
802
|
-
lambda: (0, Source_1.singleWord)(this.nameForNamedType(classType), ".from_dict"),
|
|
803
|
-
value: undefined
|
|
804
|
-
}), mapType => compose(value, v => [
|
|
805
|
-
this.conv("dict"),
|
|
806
|
-
"(",
|
|
807
|
-
makeLambda(this.deserializer(identity, mapType.values)).source,
|
|
808
|
-
", ",
|
|
809
|
-
v,
|
|
810
|
-
")"
|
|
811
|
-
]), enumType => compose(value, { lambda: (0, Source_1.singleWord)(this.nameForNamedType(enumType)), value: undefined }), unionType => {
|
|
812
|
-
// FIXME: handle via transformers
|
|
813
|
-
const deserializers = Array.from(unionType.members).map(m => makeLambda(this.deserializer(identity, m)).source);
|
|
814
|
-
return compose(value, v => [
|
|
815
|
-
this.conv("union"),
|
|
816
|
-
"([",
|
|
817
|
-
(0, collection_utils_1.arrayIntercalate)(", ", deserializers),
|
|
818
|
-
"], ",
|
|
819
|
-
v,
|
|
820
|
-
")"
|
|
821
|
-
]);
|
|
822
|
-
}, transformedStringType => {
|
|
823
|
-
// FIXME: handle via transformers
|
|
824
|
-
if (transformedStringType.kind === "date-time") {
|
|
825
|
-
return this.convFn("from-datetime", value);
|
|
826
|
-
}
|
|
827
|
-
if (transformedStringType.kind === "uuid") {
|
|
828
|
-
return compose(value, v => [this.withImport("uuid", "UUID"), "(", v, ")"]);
|
|
829
|
-
}
|
|
830
|
-
return (0, Support_1.panic)(`Transformed type ${transformedStringType.kind} not supported`);
|
|
831
|
-
});
|
|
832
|
-
}
|
|
833
|
-
serializer(value, t) {
|
|
834
|
-
const xf = (0, Transformers_1.transformationForType)(t);
|
|
835
|
-
if (xf !== undefined) {
|
|
836
|
-
const reverse = xf.reverse;
|
|
837
|
-
return this.transformer(value, reverse.transformer, reverse.targetType);
|
|
838
|
-
}
|
|
839
|
-
return (0, TypeUtils_1.matchType)(t, _anyType => value, _nullType => this.convFn("none", value), _boolType => this.convFn("bool", value), _integerType => this.convFn("int", value), _doubleType => this.convFn("to-float", value), _stringType => this.convFn("str", value), arrayType => compose(value, v => [
|
|
840
|
-
this.conv("list"),
|
|
841
|
-
"(",
|
|
842
|
-
makeLambda(this.serializer(identity, arrayType.items)).source,
|
|
843
|
-
", ",
|
|
844
|
-
v,
|
|
845
|
-
")"
|
|
846
|
-
]), classType => compose(value, v => [this.conv("to-class"), "(", this.nameForNamedType(classType), ", ", v, ")"]), mapType => compose(value, v => [
|
|
847
|
-
this.conv("dict"),
|
|
848
|
-
"(",
|
|
849
|
-
makeLambda(this.serializer(identity, mapType.values)).source,
|
|
850
|
-
", ",
|
|
851
|
-
v,
|
|
852
|
-
")"
|
|
853
|
-
]), enumType => compose(value, v => [this.conv("to-enum"), "(", this.nameForNamedType(enumType), ", ", v, ")"]), unionType => {
|
|
854
|
-
const serializers = Array.from(unionType.members).map(m => makeLambda(this.serializer(identity, m)).source);
|
|
855
|
-
return compose(value, v => [
|
|
856
|
-
this.conv("union"),
|
|
857
|
-
"([",
|
|
858
|
-
(0, collection_utils_1.arrayIntercalate)(", ", serializers),
|
|
859
|
-
"], ",
|
|
860
|
-
v,
|
|
861
|
-
")"
|
|
862
|
-
]);
|
|
863
|
-
}, transformedStringType => {
|
|
864
|
-
if (transformedStringType.kind === "date-time") {
|
|
865
|
-
return compose(value, v => [v, ".isoformat()"]);
|
|
866
|
-
}
|
|
867
|
-
if (transformedStringType.kind === "uuid") {
|
|
868
|
-
return compose(value, v => ["str(", v, ")"]);
|
|
869
|
-
}
|
|
870
|
-
return (0, Support_1.panic)(`Transformed type ${transformedStringType.kind} not supported`);
|
|
871
|
-
});
|
|
872
|
-
}
|
|
873
|
-
emitClassMembers(t) {
|
|
874
|
-
super.emitClassMembers(t);
|
|
875
|
-
this.ensureBlankLine();
|
|
876
|
-
const className = this.nameForNamedType(t);
|
|
877
|
-
this.emitLine("@staticmethod");
|
|
878
|
-
this.emitBlock(["def from_dict(", this.typingDecl("obj", "Any"), ")", this.typeHint(" -> ", this.namedType(t)), ":"], () => {
|
|
879
|
-
const args = [];
|
|
880
|
-
this.emitLine("assert isinstance(obj, dict)");
|
|
881
|
-
this.forEachClassProperty(t, "none", (name, jsonName, cp) => {
|
|
882
|
-
const property = { value: ["obj.get(", this.string(jsonName), ")"] };
|
|
883
|
-
this.emitLine(name, " = ", makeValue(this.deserializer(property, cp.type)));
|
|
884
|
-
args.push(name);
|
|
885
|
-
});
|
|
886
|
-
this.emitLine("return ", className, "(", (0, collection_utils_1.arrayIntercalate)(", ", args), ")");
|
|
887
|
-
});
|
|
888
|
-
this.ensureBlankLine();
|
|
889
|
-
this.emitBlock(["def to_dict(self)", this.typeHint(" -> dict"), ":"], () => {
|
|
890
|
-
this.emitLine("result", this.typeHint(": dict"), " = {}");
|
|
891
|
-
this.forEachClassProperty(t, "none", (name, jsonName, cp) => {
|
|
892
|
-
const property = { value: ["self.", name] };
|
|
893
|
-
if (cp.isOptional) {
|
|
894
|
-
this.emitBlock(["if self.", name, " is not None:"], () => {
|
|
895
|
-
this.emitLine("result[", this.string(jsonName), "] = ", makeValue(this.serializer(property, cp.type)));
|
|
896
|
-
});
|
|
897
|
-
}
|
|
898
|
-
else {
|
|
899
|
-
this.emitLine("result[", this.string(jsonName), "] = ", makeValue(this.serializer(property, cp.type)));
|
|
900
|
-
}
|
|
901
|
-
});
|
|
902
|
-
this.emitLine("return result");
|
|
903
|
-
});
|
|
904
|
-
}
|
|
905
|
-
emitImports() {
|
|
906
|
-
super.emitImports();
|
|
907
|
-
if (this._haveDateutil) {
|
|
908
|
-
this.emitLine("import dateutil.parser");
|
|
909
|
-
}
|
|
910
|
-
if (!this._haveTypeVar && !this._haveEnumTypeVar)
|
|
911
|
-
return;
|
|
912
|
-
this.ensureBlankLine(2);
|
|
913
|
-
if (this._haveTypeVar) {
|
|
914
|
-
this.emitTypeVar(this.typeVar(), []);
|
|
915
|
-
}
|
|
916
|
-
if (this._haveEnumTypeVar) {
|
|
917
|
-
this.emitTypeVar(this.enumTypeVar(), [", bound=", this.withImport("enum", "Enum")]);
|
|
918
|
-
}
|
|
919
|
-
}
|
|
920
|
-
emitSupportCode() {
|
|
921
|
-
const map = Array.from(this._deserializerFunctions).map(f => [f, f]);
|
|
922
|
-
this.forEachWithBlankLines(map, ["interposing", 2], cf => {
|
|
923
|
-
this.emitConverter(cf);
|
|
924
|
-
});
|
|
925
|
-
}
|
|
926
|
-
makeTopLevelDependencyNames(_t, topLevelName) {
|
|
927
|
-
const fromDict = new Naming_1.DependencyName(this._converterNamer, ConvenienceRenderer_1.topLevelNameOrder, l => `${l(topLevelName)}_from_dict`);
|
|
928
|
-
const toDict = new Naming_1.DependencyName(this._converterNamer, ConvenienceRenderer_1.topLevelNameOrder, l => `${l(topLevelName)}_to_dict`);
|
|
929
|
-
this._topLevelConverterNames.set(topLevelName, { fromDict, toDict });
|
|
930
|
-
return [fromDict, toDict];
|
|
931
|
-
}
|
|
932
|
-
emitDefaultLeadingComments() {
|
|
933
|
-
this.ensureBlankLine();
|
|
934
|
-
if (this._haveDateutil) {
|
|
935
|
-
this.emitCommentLines([
|
|
936
|
-
"This code parses date/times, so please",
|
|
937
|
-
"",
|
|
938
|
-
" pip install python-dateutil",
|
|
939
|
-
""
|
|
940
|
-
]);
|
|
941
|
-
}
|
|
942
|
-
this.emitCommentLines([
|
|
943
|
-
"To use this code, make sure you",
|
|
944
|
-
"",
|
|
945
|
-
" import json",
|
|
946
|
-
"",
|
|
947
|
-
"and then, to convert JSON from a string, do",
|
|
948
|
-
""
|
|
949
|
-
]);
|
|
950
|
-
this.forEachTopLevel("none", (_, name) => {
|
|
951
|
-
const { fromDict } = (0, Support_1.defined)(this._topLevelConverterNames.get(name));
|
|
952
|
-
this.emitLine(this.commentLineStart, " result = ", fromDict, "(json.loads(json_string))");
|
|
953
|
-
});
|
|
954
|
-
}
|
|
955
|
-
emitClosingCode() {
|
|
956
|
-
this.forEachTopLevel(["interposing", 2], (t, name) => {
|
|
957
|
-
const { fromDict, toDict } = (0, Support_1.defined)(this._topLevelConverterNames.get(name));
|
|
958
|
-
const pythonType = this.pythonType(t);
|
|
959
|
-
this.emitBlock(["def ", fromDict, "(", this.typingDecl("s", "Any"), ")", this.typeHint(" -> ", pythonType), ":"], () => {
|
|
960
|
-
this.emitLine("return ", makeValue(this.deserializer({ value: "s" }, t)));
|
|
961
|
-
});
|
|
962
|
-
this.ensureBlankLine(2);
|
|
963
|
-
this.emitBlock(["def ", toDict, "(x", this.typeHint(": ", pythonType), ")", this.typingReturn("Any"), ":"], () => {
|
|
964
|
-
this.emitLine("return ", makeValue(this.serializer({ value: "x" }, t)));
|
|
965
|
-
});
|
|
966
|
-
});
|
|
967
|
-
}
|
|
968
|
-
}
|
|
969
|
-
exports.JSONPythonRenderer = JSONPythonRenderer;
|