quicktype 18.0.6 → 19.0.5

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.
Files changed (174) hide show
  1. package/README.md +1 -1
  2. package/dist/{cli/CompressedJSONFromStream.d.ts → CompressedJSONFromStream.d.ts} +1 -1
  3. package/dist/{cli/CompressedJSONFromStream.js → CompressedJSONFromStream.js} +2 -2
  4. package/dist/{cli/GraphQLIntrospection.d.ts → GraphQLIntrospection.d.ts} +0 -0
  5. package/dist/{cli/GraphQLIntrospection.js → GraphQLIntrospection.js} +1 -1
  6. package/dist/{cli/TypeSource.d.ts → TypeSource.d.ts} +2 -2
  7. package/dist/{cli/TypeSource.js → TypeSource.js} +0 -0
  8. package/dist/{cli/URLGrammar.d.ts → URLGrammar.d.ts} +0 -0
  9. package/dist/{cli/URLGrammar.js → URLGrammar.js} +1 -1
  10. package/dist/{cli/index.d.ts → index.d.ts} +2 -1
  11. package/dist/{cli/index.js → index.js} +4 -4
  12. package/package.json +61 -77
  13. package/dist/quicktype-core/Annotation.d.ts +0 -8
  14. package/dist/quicktype-core/Annotation.js +0 -16
  15. package/dist/quicktype-core/ConvenienceRenderer.d.ts +0 -138
  16. package/dist/quicktype-core/ConvenienceRenderer.js +0 -668
  17. package/dist/quicktype-core/DateTime.d.ts +0 -10
  18. package/dist/quicktype-core/DateTime.js +0 -57
  19. package/dist/quicktype-core/DeclarationIR.d.ts +0 -14
  20. package/dist/quicktype-core/DeclarationIR.js +0 -167
  21. package/dist/quicktype-core/EncodedMarkovChain.d.ts +0 -1
  22. package/dist/quicktype-core/EncodedMarkovChain.js +0 -4
  23. package/dist/quicktype-core/GatherNames.d.ts +0 -2
  24. package/dist/quicktype-core/GatherNames.js +0 -333
  25. package/dist/quicktype-core/Graph.d.ts +0 -12
  26. package/dist/quicktype-core/Graph.js +0 -220
  27. package/dist/quicktype-core/GraphRewriting.d.ts +0 -87
  28. package/dist/quicktype-core/GraphRewriting.js +0 -421
  29. package/dist/quicktype-core/MakeTransformations.d.ts +0 -4
  30. package/dist/quicktype-core/MakeTransformations.js +0 -193
  31. package/dist/quicktype-core/MarkovChain.d.ts +0 -15
  32. package/dist/quicktype-core/MarkovChain.js +0 -154
  33. package/dist/quicktype-core/Messages.d.ts +0 -294
  34. package/dist/quicktype-core/Messages.js +0 -105
  35. package/dist/quicktype-core/Naming.d.ts +0 -64
  36. package/dist/quicktype-core/Naming.js +0 -356
  37. package/dist/quicktype-core/Renderer.d.ts +0 -50
  38. package/dist/quicktype-core/Renderer.js +0 -274
  39. package/dist/quicktype-core/RendererOptions.d.ts +0 -71
  40. package/dist/quicktype-core/RendererOptions.js +0 -141
  41. package/dist/quicktype-core/Run.d.ts +0 -174
  42. package/dist/quicktype-core/Run.js +0 -393
  43. package/dist/quicktype-core/Source.d.ts +0 -65
  44. package/dist/quicktype-core/Source.js +0 -204
  45. package/dist/quicktype-core/TargetLanguage.d.ts +0 -34
  46. package/dist/quicktype-core/TargetLanguage.js +0 -66
  47. package/dist/quicktype-core/Transformers.d.ts +0 -209
  48. package/dist/quicktype-core/Transformers.js +0 -836
  49. package/dist/quicktype-core/Type.d.ts +0 -206
  50. package/dist/quicktype-core/Type.js +0 -716
  51. package/dist/quicktype-core/TypeBuilder.d.ts +0 -61
  52. package/dist/quicktype-core/TypeBuilder.js +0 -324
  53. package/dist/quicktype-core/TypeGraph.d.ts +0 -75
  54. package/dist/quicktype-core/TypeGraph.js +0 -420
  55. package/dist/quicktype-core/TypeUtils.d.ts +0 -33
  56. package/dist/quicktype-core/TypeUtils.js +0 -230
  57. package/dist/quicktype-core/UnifyClasses.d.ts +0 -16
  58. package/dist/quicktype-core/UnifyClasses.js +0 -159
  59. package/dist/quicktype-core/UnionBuilder.d.ts +0 -49
  60. package/dist/quicktype-core/UnionBuilder.js +0 -282
  61. package/dist/quicktype-core/attributes/AccessorNames.d.ts +0 -18
  62. package/dist/quicktype-core/attributes/AccessorNames.js +0 -182
  63. package/dist/quicktype-core/attributes/Constraints.d.ts +0 -38
  64. package/dist/quicktype-core/attributes/Constraints.js +0 -172
  65. package/dist/quicktype-core/attributes/Description.d.ts +0 -9
  66. package/dist/quicktype-core/attributes/Description.js +0 -97
  67. package/dist/quicktype-core/attributes/EnumValues.d.ts +0 -8
  68. package/dist/quicktype-core/attributes/EnumValues.js +0 -31
  69. package/dist/quicktype-core/attributes/StringTypes.d.ts +0 -28
  70. package/dist/quicktype-core/attributes/StringTypes.js +0 -189
  71. package/dist/quicktype-core/attributes/TypeAttributes.d.ts +0 -34
  72. package/dist/quicktype-core/attributes/TypeAttributes.js +0 -119
  73. package/dist/quicktype-core/attributes/TypeNames.d.ts +0 -46
  74. package/dist/quicktype-core/attributes/TypeNames.js +0 -274
  75. package/dist/quicktype-core/attributes/URIAttributes.d.ts +0 -8
  76. package/dist/quicktype-core/attributes/URIAttributes.js +0 -85
  77. package/dist/quicktype-core/index.d.ts +0 -48
  78. package/dist/quicktype-core/index.js +0 -180
  79. package/dist/quicktype-core/input/CompressedJSON.d.ts +0 -69
  80. package/dist/quicktype-core/input/CompressedJSON.js +0 -276
  81. package/dist/quicktype-core/input/FetchingJSONSchemaStore.d.ts +0 -6
  82. package/dist/quicktype-core/input/FetchingJSONSchemaStore.js +0 -18
  83. package/dist/quicktype-core/input/Inference.d.ts +0 -22
  84. package/dist/quicktype-core/input/Inference.js +0 -240
  85. package/dist/quicktype-core/input/Inputs.d.ts +0 -48
  86. package/dist/quicktype-core/input/Inputs.js +0 -145
  87. package/dist/quicktype-core/input/JSONSchemaInput.d.ts +0 -91
  88. package/dist/quicktype-core/input/JSONSchemaInput.js +0 -1041
  89. package/dist/quicktype-core/input/JSONSchemaStore.d.ts +0 -8
  90. package/dist/quicktype-core/input/JSONSchemaStore.js +0 -36
  91. package/dist/quicktype-core/input/PostmanCollection.d.ts +0 -5
  92. package/dist/quicktype-core/input/PostmanCollection.js +0 -60
  93. package/dist/quicktype-core/input/io/NodeIO.d.ts +0 -3
  94. package/dist/quicktype-core/input/io/NodeIO.js +0 -87
  95. package/dist/quicktype-core/input/io/get-stream/buffer-stream.d.ts +0 -2
  96. package/dist/quicktype-core/input/io/get-stream/buffer-stream.js +0 -45
  97. package/dist/quicktype-core/input/io/get-stream/index.d.ts +0 -9
  98. package/dist/quicktype-core/input/io/get-stream/index.js +0 -52
  99. package/dist/quicktype-core/language/All.d.ts +0 -3
  100. package/dist/quicktype-core/language/All.js +0 -57
  101. package/dist/quicktype-core/language/CPlusPlus.d.ts +0 -241
  102. package/dist/quicktype-core/language/CPlusPlus.js +0 -1847
  103. package/dist/quicktype-core/language/CSharp.d.ts +0 -201
  104. package/dist/quicktype-core/language/CSharp.js +0 -1850
  105. package/dist/quicktype-core/language/Crystal.d.ts +0 -37
  106. package/dist/quicktype-core/language/Crystal.js +0 -337
  107. package/dist/quicktype-core/language/Dart.d.ts +0 -66
  108. package/dist/quicktype-core/language/Dart.js +0 -576
  109. package/dist/quicktype-core/language/Elm.d.ts +0 -58
  110. package/dist/quicktype-core/language/Elm.js +0 -522
  111. package/dist/quicktype-core/language/Golang.d.ts +0 -51
  112. package/dist/quicktype-core/language/Golang.js +0 -460
  113. package/dist/quicktype-core/language/Haskell.d.ts +0 -56
  114. package/dist/quicktype-core/language/Haskell.js +0 -411
  115. package/dist/quicktype-core/language/JSONSchema.d.ts +0 -31
  116. package/dist/quicktype-core/language/JSONSchema.js +0 -169
  117. package/dist/quicktype-core/language/Java.d.ts +0 -125
  118. package/dist/quicktype-core/language/Java.js +0 -1081
  119. package/dist/quicktype-core/language/JavaScript.d.ts +0 -68
  120. package/dist/quicktype-core/language/JavaScript.js +0 -435
  121. package/dist/quicktype-core/language/JavaScriptPropTypes.d.ts +0 -40
  122. package/dist/quicktype-core/language/JavaScriptPropTypes.js +0 -213
  123. package/dist/quicktype-core/language/JavaScriptUnicodeMaps.d.ts +0 -2
  124. package/dist/quicktype-core/language/JavaScriptUnicodeMaps.js +0 -134
  125. package/dist/quicktype-core/language/Kotlin.d.ts +0 -109
  126. package/dist/quicktype-core/language/Kotlin.js +0 -832
  127. package/dist/quicktype-core/language/Objective-C.d.ts +0 -79
  128. package/dist/quicktype-core/language/Objective-C.js +0 -777
  129. package/dist/quicktype-core/language/Php.d.ts +0 -80
  130. package/dist/quicktype-core/language/Php.js +0 -702
  131. package/dist/quicktype-core/language/Pike.d.ts +0 -37
  132. package/dist/quicktype-core/language/Pike.js +0 -276
  133. package/dist/quicktype-core/language/Python.d.ts +0 -107
  134. package/dist/quicktype-core/language/Python.js +0 -969
  135. package/dist/quicktype-core/language/Rust.d.ts +0 -56
  136. package/dist/quicktype-core/language/Rust.js +0 -309
  137. package/dist/quicktype-core/language/Swift.d.ts +0 -96
  138. package/dist/quicktype-core/language/Swift.js +0 -1211
  139. package/dist/quicktype-core/language/TypeScriptFlow.d.ts +0 -77
  140. package/dist/quicktype-core/language/TypeScriptFlow.js +0 -286
  141. package/dist/quicktype-core/language/ruby/index.d.ts +0 -52
  142. package/dist/quicktype-core/language/ruby/index.js +0 -557
  143. package/dist/quicktype-core/language/ruby/keywords.d.ts +0 -3
  144. package/dist/quicktype-core/language/ruby/keywords.js +0 -358
  145. package/dist/quicktype-core/rewrites/CombineClasses.d.ts +0 -3
  146. package/dist/quicktype-core/rewrites/CombineClasses.js +0 -125
  147. package/dist/quicktype-core/rewrites/ExpandStrings.d.ts +0 -4
  148. package/dist/quicktype-core/rewrites/ExpandStrings.js +0 -143
  149. package/dist/quicktype-core/rewrites/FlattenStrings.d.ts +0 -3
  150. package/dist/quicktype-core/rewrites/FlattenStrings.js +0 -45
  151. package/dist/quicktype-core/rewrites/FlattenUnions.d.ts +0 -3
  152. package/dist/quicktype-core/rewrites/FlattenUnions.js +0 -47
  153. package/dist/quicktype-core/rewrites/InferMaps.d.ts +0 -3
  154. package/dist/quicktype-core/rewrites/InferMaps.js +0 -117
  155. package/dist/quicktype-core/rewrites/ReplaceObjectType.d.ts +0 -3
  156. package/dist/quicktype-core/rewrites/ReplaceObjectType.js +0 -60
  157. package/dist/quicktype-core/rewrites/ResolveIntersections.d.ts +0 -3
  158. package/dist/quicktype-core/rewrites/ResolveIntersections.js +0 -244
  159. package/dist/quicktype-core/support/Acronyms.d.ts +0 -10
  160. package/dist/quicktype-core/support/Acronyms.js +0 -1128
  161. package/dist/quicktype-core/support/Chance.d.ts +0 -38
  162. package/dist/quicktype-core/support/Chance.js +0 -2146
  163. package/dist/quicktype-core/support/Converters.d.ts +0 -6
  164. package/dist/quicktype-core/support/Converters.js +0 -16
  165. package/dist/quicktype-core/support/Strings.d.ts +0 -44
  166. package/dist/quicktype-core/support/Strings.js +0 -525
  167. package/dist/quicktype-core/support/Support.d.ts +0 -29
  168. package/dist/quicktype-core/support/Support.js +0 -162
  169. package/dist/quicktype-graphql-input/GraphQLSchema.d.ts +0 -645
  170. package/dist/quicktype-graphql-input/GraphQLSchema.js +0 -39
  171. package/dist/quicktype-graphql-input/index.d.ts +0 -17
  172. package/dist/quicktype-graphql-input/index.js +0 -407
  173. package/dist/quicktype-typescript-input/index.d.ts +0 -2
  174. 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;