@alloy-js/python 0.3.0-dev.5 → 0.3.0
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/CHANGELOG.md +15 -0
- package/dist/src/components/FutureStatement.d.ts +35 -0
- package/dist/src/components/FutureStatement.d.ts.map +1 -0
- package/dist/src/components/FutureStatement.js +31 -0
- package/dist/src/components/FutureStatement.js.map +1 -0
- package/dist/src/components/SourceFile.d.ts +8 -2
- package/dist/src/components/SourceFile.d.ts.map +1 -1
- package/dist/src/components/SourceFile.js +124 -8
- package/dist/src/components/SourceFile.js.map +1 -1
- package/dist/src/components/index.d.ts +1 -0
- package/dist/src/components/index.d.ts.map +1 -1
- package/dist/src/components/index.js +1 -0
- package/dist/src/components/index.js.map +1 -1
- package/dist/test/classdeclarations.test.js +2 -0
- package/dist/test/classdeclarations.test.js.map +1 -1
- package/dist/test/dataclassdeclarations.test.js +13 -0
- package/dist/test/dataclassdeclarations.test.js.map +1 -1
- package/dist/test/enums.test.js +7 -0
- package/dist/test/enums.test.js.map +1 -1
- package/dist/test/externals.test.js +2 -0
- package/dist/test/externals.test.js.map +1 -1
- package/dist/test/functiondeclaration.test.js +2 -0
- package/dist/test/functiondeclaration.test.js.map +1 -1
- package/dist/test/methoddeclaration.test.js +1 -0
- package/dist/test/methoddeclaration.test.js.map +1 -1
- package/dist/test/namepolicies.test.js +1 -0
- package/dist/test/namepolicies.test.js.map +1 -1
- package/dist/test/propertydeclaration.test.js +1 -0
- package/dist/test/propertydeclaration.test.js.map +1 -1
- package/dist/test/pydocs.test.js +1 -1
- package/dist/test/pydocs.test.js.map +1 -1
- package/dist/test/sourcefiles.test.js +921 -39
- package/dist/test/sourcefiles.test.js.map +1 -1
- package/dist/test/utils.d.ts +2 -2
- package/dist/test/utils.d.ts.map +1 -1
- package/dist/test/utils.js +9 -9
- package/dist/test/utils.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/src/components/FutureStatement.tsx +38 -0
- package/src/components/SourceFile.tsx +128 -8
- package/src/components/index.ts +1 -0
- package/temp/api.json +122 -2
- package/test/classdeclarations.test.tsx +2 -0
- package/test/dataclassdeclarations.test.tsx +13 -0
- package/test/enums.test.tsx +7 -0
- package/test/externals.test.tsx +2 -0
- package/test/functiondeclaration.test.tsx +2 -0
- package/test/methoddeclaration.test.tsx +1 -0
- package/test/namepolicies.test.tsx +1 -0
- package/test/propertydeclaration.test.tsx +1 -0
- package/test/pydocs.test.tsx +1 -1
- package/test/sourcefiles.test.tsx +754 -48
- package/test/utils.tsx +10 -5
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type Children } from "@alloy-js/core";
|
|
2
|
+
|
|
3
|
+
export interface FutureStatementProps {
|
|
4
|
+
/**
|
|
5
|
+
* The name of the feature to import from __future__.
|
|
6
|
+
*/
|
|
7
|
+
feature: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A future statement that imports features from __future__.
|
|
12
|
+
*
|
|
13
|
+
* Future statements are directives to the compiler that a particular module
|
|
14
|
+
* should be compiled using syntax or semantics from a future Python release.
|
|
15
|
+
* They must appear near the top of the module, after the module docstring (if any).
|
|
16
|
+
*
|
|
17
|
+
* Use this in the `futureImports` prop of SourceFile to ensure proper placement.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* <SourceFile path="models.py" futureImports={<FutureStatement feature="annotations" />}>
|
|
22
|
+
* <ClassDeclaration name="User">
|
|
23
|
+
* <PropertyDeclaration name="manager" type="User" />
|
|
24
|
+
* </ClassDeclaration>
|
|
25
|
+
* </SourceFile>
|
|
26
|
+
* ```
|
|
27
|
+
* renders to
|
|
28
|
+
* ```py
|
|
29
|
+
* from __future__ import annotations
|
|
30
|
+
*
|
|
31
|
+
*
|
|
32
|
+
* class User:
|
|
33
|
+
* manager: User
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export function FutureStatement(props: FutureStatementProps): Children {
|
|
37
|
+
return <>from __future__ import {props.feature}</>;
|
|
38
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
+
childrenArray,
|
|
2
3
|
ComponentContext,
|
|
3
4
|
SourceFile as CoreSourceFile,
|
|
4
5
|
createNamedContext,
|
|
6
|
+
isComponentCreator,
|
|
5
7
|
List,
|
|
6
8
|
Scope,
|
|
7
9
|
Show,
|
|
@@ -12,8 +14,51 @@ import {
|
|
|
12
14
|
import { join } from "pathe";
|
|
13
15
|
import { PythonModuleScope } from "../symbols/index.js";
|
|
14
16
|
import { ImportStatements } from "./ImportStatement.js";
|
|
17
|
+
import { SimpleCommentBlock } from "./PyDoc.js";
|
|
15
18
|
import { Reference } from "./Reference.js";
|
|
16
19
|
|
|
20
|
+
// Non top-level definitions
|
|
21
|
+
const NON_DEFINITION_NAMES = new Set([
|
|
22
|
+
"VariableDeclaration",
|
|
23
|
+
"MemberExpression",
|
|
24
|
+
"FunctionCallExpression",
|
|
25
|
+
"ClassInstantiation",
|
|
26
|
+
"Reference",
|
|
27
|
+
]);
|
|
28
|
+
|
|
29
|
+
// Wrapper components that we should look inside to find the actual first child
|
|
30
|
+
const WRAPPER_COMPONENT_NAMES = new Set(["StatementList"]);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Checks if the first child is a top-level definition (function or class).
|
|
34
|
+
* PEP 8 requires 2 blank lines before top-level function and class definitions,
|
|
35
|
+
* but not before other statements like variable assignments.
|
|
36
|
+
*
|
|
37
|
+
* Returns true only if there are children and the first child is a definition.
|
|
38
|
+
*/
|
|
39
|
+
function firstChildIsDefinition(children: Children | undefined): boolean {
|
|
40
|
+
if (!children) return false;
|
|
41
|
+
const arr = childrenArray(() => children);
|
|
42
|
+
if (arr.length === 0) return false;
|
|
43
|
+
const first = arr[0];
|
|
44
|
+
|
|
45
|
+
// Non-component children (strings, numbers, refkeys, etc.) are not definitions
|
|
46
|
+
if (!isComponentCreator(first)) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const name = first.component.name;
|
|
51
|
+
if (NON_DEFINITION_NAMES.has(name)) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
// Look inside wrapper components
|
|
55
|
+
if (WRAPPER_COMPONENT_NAMES.has(name) && first.props?.children) {
|
|
56
|
+
return firstChildIsDefinition(first.props.children as Children);
|
|
57
|
+
}
|
|
58
|
+
// If we get here, it's likely a definition (FunctionDeclaration, ClassDeclaration, etc.)
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
|
|
17
62
|
export interface PythonSourceFileContext {
|
|
18
63
|
scope: PythonModuleScope;
|
|
19
64
|
/** The module name for this file, e.g. 'test' for test.py */
|
|
@@ -37,17 +82,23 @@ export interface SourceFileProps {
|
|
|
37
82
|
*/
|
|
38
83
|
children?: Children;
|
|
39
84
|
/**
|
|
40
|
-
*
|
|
85
|
+
* Content to render at the very top of the file, before everything else.
|
|
86
|
+
* Use this for shebang lines, encoding declarations, or license headers.
|
|
41
87
|
*/
|
|
42
88
|
header?: Children;
|
|
43
89
|
/**
|
|
44
|
-
* Comment to add
|
|
90
|
+
* Comment to add at the top of the file, rendered as a Python comment block.
|
|
91
|
+
* This is a convenience prop for adding copyright notices or other comments.
|
|
45
92
|
*/
|
|
46
93
|
headerComment?: string;
|
|
47
94
|
/**
|
|
48
95
|
* Documentation for this module, which will be rendered as a module-level docstring.
|
|
49
96
|
*/
|
|
50
97
|
doc?: Children;
|
|
98
|
+
/**
|
|
99
|
+
* __future__ imports to render after the docstring but before regular imports.
|
|
100
|
+
*/
|
|
101
|
+
futureImports?: Children;
|
|
51
102
|
}
|
|
52
103
|
|
|
53
104
|
/**
|
|
@@ -100,21 +151,90 @@ export function SourceFile(props: SourceFileProps) {
|
|
|
100
151
|
module: path,
|
|
101
152
|
};
|
|
102
153
|
|
|
154
|
+
// Check if there are any children
|
|
155
|
+
const hasChildren =
|
|
156
|
+
props.children !== undefined &&
|
|
157
|
+
childrenArray(() => props.children).length > 0;
|
|
158
|
+
|
|
159
|
+
// PEP 8 requires 2 blank lines before top-level function/class definitions
|
|
160
|
+
const needsExtraSpacing = firstChildIsDefinition(props.children);
|
|
161
|
+
|
|
162
|
+
// Check if there's any preamble content (header, doc, imports, etc.)
|
|
163
|
+
const hasPreamble =
|
|
164
|
+
props.header !== undefined ||
|
|
165
|
+
props.headerComment !== undefined ||
|
|
166
|
+
props.doc !== undefined ||
|
|
167
|
+
props.futureImports !== undefined;
|
|
168
|
+
|
|
103
169
|
return (
|
|
104
|
-
<CoreSourceFile
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
170
|
+
<CoreSourceFile
|
|
171
|
+
path={props.path}
|
|
172
|
+
filetype="py"
|
|
173
|
+
reference={Reference}
|
|
174
|
+
header={props.header}
|
|
175
|
+
>
|
|
176
|
+
{/* Extra blank line after header when followed by doc/futureImports/children (not headerComment) */}
|
|
177
|
+
<Show
|
|
178
|
+
when={
|
|
179
|
+
props.header !== undefined &&
|
|
180
|
+
props.headerComment === undefined &&
|
|
181
|
+
(props.doc !== undefined ||
|
|
182
|
+
props.futureImports !== undefined ||
|
|
183
|
+
hasChildren)
|
|
184
|
+
}
|
|
185
|
+
>
|
|
108
186
|
<hbr />
|
|
109
187
|
</Show>
|
|
188
|
+
<Show when={props.headerComment !== undefined}>
|
|
189
|
+
<SimpleCommentBlock>{props.headerComment}</SimpleCommentBlock>
|
|
190
|
+
{/* When followed by doc: just newline (no blank line) */}
|
|
191
|
+
<Show when={props.doc !== undefined}>
|
|
192
|
+
<hbr />
|
|
193
|
+
</Show>
|
|
194
|
+
{/* When followed by futureImports or children directly (no doc): blank line */}
|
|
195
|
+
<Show
|
|
196
|
+
when={
|
|
197
|
+
props.doc === undefined &&
|
|
198
|
+
(props.futureImports !== undefined || hasChildren)
|
|
199
|
+
}
|
|
200
|
+
>
|
|
201
|
+
<hbr />
|
|
202
|
+
<hbr />
|
|
203
|
+
</Show>
|
|
204
|
+
</Show>
|
|
110
205
|
<Show when={props.doc !== undefined}>
|
|
111
206
|
{props.doc}
|
|
112
|
-
<
|
|
207
|
+
<Show when={props.futureImports !== undefined || hasChildren}>
|
|
208
|
+
<hbr />
|
|
209
|
+
</Show>
|
|
210
|
+
</Show>
|
|
211
|
+
<Show when={props.futureImports !== undefined}>
|
|
212
|
+
{props.futureImports}
|
|
213
|
+
<Show when={hasChildren}>
|
|
214
|
+
<hbr />
|
|
215
|
+
<hbr />
|
|
216
|
+
</Show>
|
|
217
|
+
</Show>
|
|
218
|
+
<Show when={scope.importedModules.size > 0}>
|
|
219
|
+
<ImportStatements records={scope.importedModules} />
|
|
220
|
+
<Show when={hasChildren}>
|
|
221
|
+
<hbr />
|
|
222
|
+
<hbr />
|
|
223
|
+
</Show>
|
|
224
|
+
</Show>
|
|
225
|
+
{/* Extra blank line before top-level definitions */}
|
|
226
|
+
<Show
|
|
227
|
+
when={
|
|
228
|
+
needsExtraSpacing && (hasPreamble || scope.importedModules.size > 0)
|
|
229
|
+
}
|
|
230
|
+
>
|
|
113
231
|
<hbr />
|
|
114
232
|
</Show>
|
|
115
233
|
<PythonSourceFileContext.Provider value={sfContext}>
|
|
116
234
|
<Scope value={scope}>
|
|
117
|
-
<
|
|
235
|
+
<Show when={hasChildren}>
|
|
236
|
+
<List doubleHardline>{props.children}</List>
|
|
237
|
+
</Show>
|
|
118
238
|
</Scope>
|
|
119
239
|
</PythonSourceFileContext.Provider>
|
|
120
240
|
</CoreSourceFile>
|
package/src/components/index.ts
CHANGED
|
@@ -12,6 +12,7 @@ export * from "./EnumMember.js";
|
|
|
12
12
|
export type { CommonFunctionProps } from "./FunctionBase.js";
|
|
13
13
|
export * from "./FunctionCallExpression.js";
|
|
14
14
|
export * from "./FunctionDeclaration.js";
|
|
15
|
+
export * from "./FutureStatement.js";
|
|
15
16
|
export * from "./ImportStatement.js";
|
|
16
17
|
export * from "./LexicalScope.js";
|
|
17
18
|
export * from "./MemberExpression.js";
|
package/temp/api.json
CHANGED
|
@@ -4350,6 +4350,98 @@
|
|
|
4350
4350
|
],
|
|
4351
4351
|
"extendsTokenRanges": []
|
|
4352
4352
|
},
|
|
4353
|
+
{
|
|
4354
|
+
"kind": "Function",
|
|
4355
|
+
"canonicalReference": "@alloy-js/python!FutureStatement:function(1)",
|
|
4356
|
+
"docComment": "/**\n * A future statement that imports features from __future__.\n *\n * Future statements are directives to the compiler that a particular module\n * should be compiled using syntax or semantics from a future Python release.\n * They must appear near the top of the module, after the module docstring (if any).\n *\n * Use this in the `futureImports` prop of SourceFile to ensure proper placement.\n *\n * @example\n * ```tsx\n * <SourceFile path=\"models.py\" futureImports={<FutureStatement feature=\"annotations\" />}>\n * <ClassDeclaration name=\"User\">\n * <PropertyDeclaration name=\"manager\" type=\"User\" />\n * </ClassDeclaration>\n * </SourceFile>\n * ```\n *\n * renders to\n * ```py\n * from __future__ import annotations\n *\n *\n * class User:\n * manager: User\n * ```\n *\n */\n",
|
|
4357
|
+
"excerptTokens": [
|
|
4358
|
+
{
|
|
4359
|
+
"kind": "Content",
|
|
4360
|
+
"text": "export declare function FutureStatement(props: "
|
|
4361
|
+
},
|
|
4362
|
+
{
|
|
4363
|
+
"kind": "Reference",
|
|
4364
|
+
"text": "FutureStatementProps",
|
|
4365
|
+
"canonicalReference": "@alloy-js/python!FutureStatementProps:interface"
|
|
4366
|
+
},
|
|
4367
|
+
{
|
|
4368
|
+
"kind": "Content",
|
|
4369
|
+
"text": "): "
|
|
4370
|
+
},
|
|
4371
|
+
{
|
|
4372
|
+
"kind": "Reference",
|
|
4373
|
+
"text": "Children",
|
|
4374
|
+
"canonicalReference": "@alloy-js/core!Children:type"
|
|
4375
|
+
},
|
|
4376
|
+
{
|
|
4377
|
+
"kind": "Content",
|
|
4378
|
+
"text": ";"
|
|
4379
|
+
}
|
|
4380
|
+
],
|
|
4381
|
+
"fileUrlPath": "src/components/FutureStatement.tsx",
|
|
4382
|
+
"returnTypeTokenRange": {
|
|
4383
|
+
"startIndex": 3,
|
|
4384
|
+
"endIndex": 4
|
|
4385
|
+
},
|
|
4386
|
+
"releaseTag": "Public",
|
|
4387
|
+
"overloadIndex": 1,
|
|
4388
|
+
"parameters": [
|
|
4389
|
+
{
|
|
4390
|
+
"parameterName": "props",
|
|
4391
|
+
"parameterTypeTokenRange": {
|
|
4392
|
+
"startIndex": 1,
|
|
4393
|
+
"endIndex": 2
|
|
4394
|
+
},
|
|
4395
|
+
"isOptional": false
|
|
4396
|
+
}
|
|
4397
|
+
],
|
|
4398
|
+
"name": "FutureStatement"
|
|
4399
|
+
},
|
|
4400
|
+
{
|
|
4401
|
+
"kind": "Interface",
|
|
4402
|
+
"canonicalReference": "@alloy-js/python!FutureStatementProps:interface",
|
|
4403
|
+
"docComment": "",
|
|
4404
|
+
"excerptTokens": [
|
|
4405
|
+
{
|
|
4406
|
+
"kind": "Content",
|
|
4407
|
+
"text": "export interface FutureStatementProps "
|
|
4408
|
+
}
|
|
4409
|
+
],
|
|
4410
|
+
"fileUrlPath": "src/components/FutureStatement.tsx",
|
|
4411
|
+
"releaseTag": "Public",
|
|
4412
|
+
"name": "FutureStatementProps",
|
|
4413
|
+
"preserveMemberOrder": false,
|
|
4414
|
+
"members": [
|
|
4415
|
+
{
|
|
4416
|
+
"kind": "PropertySignature",
|
|
4417
|
+
"canonicalReference": "@alloy-js/python!FutureStatementProps#feature:member",
|
|
4418
|
+
"docComment": "/**\n * The name of the feature to import from __future__.\n */\n",
|
|
4419
|
+
"excerptTokens": [
|
|
4420
|
+
{
|
|
4421
|
+
"kind": "Content",
|
|
4422
|
+
"text": "feature: "
|
|
4423
|
+
},
|
|
4424
|
+
{
|
|
4425
|
+
"kind": "Content",
|
|
4426
|
+
"text": "string"
|
|
4427
|
+
},
|
|
4428
|
+
{
|
|
4429
|
+
"kind": "Content",
|
|
4430
|
+
"text": ";"
|
|
4431
|
+
}
|
|
4432
|
+
],
|
|
4433
|
+
"isReadonly": false,
|
|
4434
|
+
"isOptional": false,
|
|
4435
|
+
"releaseTag": "Public",
|
|
4436
|
+
"name": "feature",
|
|
4437
|
+
"propertyTypeTokenRange": {
|
|
4438
|
+
"startIndex": 1,
|
|
4439
|
+
"endIndex": 2
|
|
4440
|
+
}
|
|
4441
|
+
}
|
|
4442
|
+
],
|
|
4443
|
+
"extendsTokenRanges": []
|
|
4444
|
+
},
|
|
4353
4445
|
{
|
|
4354
4446
|
"kind": "Function",
|
|
4355
4447
|
"canonicalReference": "@alloy-js/python!GeneratorDoc:function(1)",
|
|
@@ -9986,10 +10078,38 @@
|
|
|
9986
10078
|
"endIndex": 2
|
|
9987
10079
|
}
|
|
9988
10080
|
},
|
|
10081
|
+
{
|
|
10082
|
+
"kind": "PropertySignature",
|
|
10083
|
+
"canonicalReference": "@alloy-js/python!SourceFileProps#futureImports:member",
|
|
10084
|
+
"docComment": "/**\n * __future__ imports to render after the docstring but before regular imports.\n */\n",
|
|
10085
|
+
"excerptTokens": [
|
|
10086
|
+
{
|
|
10087
|
+
"kind": "Content",
|
|
10088
|
+
"text": "futureImports?: "
|
|
10089
|
+
},
|
|
10090
|
+
{
|
|
10091
|
+
"kind": "Reference",
|
|
10092
|
+
"text": "Children",
|
|
10093
|
+
"canonicalReference": "@alloy-js/core!Children:type"
|
|
10094
|
+
},
|
|
10095
|
+
{
|
|
10096
|
+
"kind": "Content",
|
|
10097
|
+
"text": ";"
|
|
10098
|
+
}
|
|
10099
|
+
],
|
|
10100
|
+
"isReadonly": false,
|
|
10101
|
+
"isOptional": true,
|
|
10102
|
+
"releaseTag": "Public",
|
|
10103
|
+
"name": "futureImports",
|
|
10104
|
+
"propertyTypeTokenRange": {
|
|
10105
|
+
"startIndex": 1,
|
|
10106
|
+
"endIndex": 2
|
|
10107
|
+
}
|
|
10108
|
+
},
|
|
9989
10109
|
{
|
|
9990
10110
|
"kind": "PropertySignature",
|
|
9991
10111
|
"canonicalReference": "@alloy-js/python!SourceFileProps#header:member",
|
|
9992
|
-
"docComment": "/**\n *
|
|
10112
|
+
"docComment": "/**\n * Content to render at the very top of the file, before everything else.\n * Use this for shebang lines, encoding declarations, or license headers.\n */\n",
|
|
9993
10113
|
"excerptTokens": [
|
|
9994
10114
|
{
|
|
9995
10115
|
"kind": "Content",
|
|
@@ -10017,7 +10137,7 @@
|
|
|
10017
10137
|
{
|
|
10018
10138
|
"kind": "PropertySignature",
|
|
10019
10139
|
"canonicalReference": "@alloy-js/python!SourceFileProps#headerComment:member",
|
|
10020
|
-
"docComment": "/**\n * Comment to add
|
|
10140
|
+
"docComment": "/**\n * Comment to add at the top of the file, rendered as a Python comment block.\n * This is a convenience prop for adding copyright notices or other comments.\n */\n",
|
|
10021
10141
|
"excerptTokens": [
|
|
10022
10142
|
{
|
|
10023
10143
|
"kind": "Content",
|
|
@@ -108,6 +108,7 @@ describe("Python Class", () => {
|
|
|
108
108
|
const mod2Expected = d`
|
|
109
109
|
from mod1 import A
|
|
110
110
|
|
|
111
|
+
|
|
111
112
|
class B(A):
|
|
112
113
|
pass
|
|
113
114
|
|
|
@@ -116,6 +117,7 @@ describe("Python Class", () => {
|
|
|
116
117
|
const mod3Expected = d`
|
|
117
118
|
from folder.mod2 import B
|
|
118
119
|
|
|
120
|
+
|
|
119
121
|
class C(B):
|
|
120
122
|
pass
|
|
121
123
|
|
|
@@ -27,6 +27,7 @@ describe("DataclassDeclaration", () => {
|
|
|
27
27
|
d`
|
|
28
28
|
from dataclasses import dataclass
|
|
29
29
|
|
|
30
|
+
|
|
30
31
|
@dataclass
|
|
31
32
|
class User:
|
|
32
33
|
"""
|
|
@@ -74,6 +75,7 @@ describe("DataclassDeclaration", () => {
|
|
|
74
75
|
from dataclasses import dataclass
|
|
75
76
|
from dataclasses import KW_ONLY
|
|
76
77
|
|
|
78
|
+
|
|
77
79
|
@dataclass
|
|
78
80
|
class User:
|
|
79
81
|
id: int
|
|
@@ -106,6 +108,7 @@ describe("DataclassDeclaration", () => {
|
|
|
106
108
|
d`
|
|
107
109
|
from dataclasses import dataclass
|
|
108
110
|
|
|
111
|
+
|
|
109
112
|
@dataclass(frozen=True, slots=True, kw_only=True)
|
|
110
113
|
class User:
|
|
111
114
|
id: int
|
|
@@ -141,6 +144,7 @@ describe("DataclassDeclaration", () => {
|
|
|
141
144
|
d`
|
|
142
145
|
from dataclasses import dataclass
|
|
143
146
|
|
|
147
|
+
|
|
144
148
|
@dataclass(init=True, repr=False, eq=True, order=False, unsafe_hash=True, frozen=True, match_args=False, kw_only=True, slots=True, weakref_slot=False)
|
|
145
149
|
class User:
|
|
146
150
|
pass
|
|
@@ -178,6 +182,7 @@ describe("DataclassDeclaration", () => {
|
|
|
178
182
|
d`
|
|
179
183
|
from dataclasses import dataclass
|
|
180
184
|
|
|
185
|
+
|
|
181
186
|
@dataclass(slots=True, weakref_slot=True)
|
|
182
187
|
class User:
|
|
183
188
|
pass
|
|
@@ -213,6 +218,7 @@ describe("DataclassDeclaration", () => {
|
|
|
213
218
|
d`
|
|
214
219
|
from dataclasses import dataclass
|
|
215
220
|
|
|
221
|
+
|
|
216
222
|
@dataclass(order=True)
|
|
217
223
|
class User:
|
|
218
224
|
pass
|
|
@@ -398,6 +404,7 @@ describe("DataclassDeclaration", () => {
|
|
|
398
404
|
d`
|
|
399
405
|
from dataclasses import dataclass
|
|
400
406
|
|
|
407
|
+
|
|
401
408
|
@dataclass(kw_only=True)
|
|
402
409
|
class User:
|
|
403
410
|
id: int
|
|
@@ -421,6 +428,7 @@ describe("DataclassDeclaration", () => {
|
|
|
421
428
|
d`
|
|
422
429
|
from dataclasses import dataclass
|
|
423
430
|
|
|
431
|
+
|
|
424
432
|
@dataclass
|
|
425
433
|
class User(Base):
|
|
426
434
|
pass
|
|
@@ -503,6 +511,7 @@ describe("DataclassDeclaration", () => {
|
|
|
503
511
|
d`
|
|
504
512
|
from dataclasses import dataclass
|
|
505
513
|
|
|
514
|
+
|
|
506
515
|
@dataclass(unsafe_hash=True)
|
|
507
516
|
class User:
|
|
508
517
|
pass
|
|
@@ -556,6 +565,7 @@ describe("DataclassDeclaration", () => {
|
|
|
556
565
|
d`
|
|
557
566
|
from dataclasses import dataclass
|
|
558
567
|
|
|
568
|
+
|
|
559
569
|
@dataclass(frozen=True)
|
|
560
570
|
class User:
|
|
561
571
|
pass
|
|
@@ -578,6 +588,7 @@ describe("DataclassDeclaration", () => {
|
|
|
578
588
|
d`
|
|
579
589
|
from dataclasses import dataclass
|
|
580
590
|
|
|
591
|
+
|
|
581
592
|
@dataclass(slots=True)
|
|
582
593
|
class User:
|
|
583
594
|
pass
|
|
@@ -627,6 +638,7 @@ describe("DataclassDeclaration", () => {
|
|
|
627
638
|
"models.py": `
|
|
628
639
|
from dataclasses import dataclass
|
|
629
640
|
|
|
641
|
+
|
|
630
642
|
@dataclass
|
|
631
643
|
class User:
|
|
632
644
|
id: int
|
|
@@ -636,6 +648,7 @@ describe("DataclassDeclaration", () => {
|
|
|
636
648
|
"services.py": `
|
|
637
649
|
from models import User
|
|
638
650
|
|
|
651
|
+
|
|
639
652
|
def get_user() -> User:
|
|
640
653
|
user: User = User(1, "Alice")
|
|
641
654
|
return user
|
package/test/enums.test.tsx
CHANGED
|
@@ -24,6 +24,7 @@ describe("Python Enum", () => {
|
|
|
24
24
|
const expected = d`
|
|
25
25
|
from enum import IntEnum
|
|
26
26
|
|
|
27
|
+
|
|
27
28
|
class Color(IntEnum):
|
|
28
29
|
RED = 1
|
|
29
30
|
GREEN = 2
|
|
@@ -52,6 +53,7 @@ describe("Python Enum", () => {
|
|
|
52
53
|
const expected = d`
|
|
53
54
|
from enum import IntEnum
|
|
54
55
|
|
|
56
|
+
|
|
55
57
|
class Color(IntEnum):
|
|
56
58
|
RED = "1"
|
|
57
59
|
GREEN = 2
|
|
@@ -83,6 +85,7 @@ describe("Python Enum", () => {
|
|
|
83
85
|
const expected = d`
|
|
84
86
|
from enum import Enum
|
|
85
87
|
|
|
88
|
+
|
|
86
89
|
class Dog:
|
|
87
90
|
pass
|
|
88
91
|
|
|
@@ -113,6 +116,7 @@ describe("Python Enum", () => {
|
|
|
113
116
|
from enum import auto
|
|
114
117
|
from enum import Enum
|
|
115
118
|
|
|
119
|
+
|
|
116
120
|
class Animal(Enum):
|
|
117
121
|
DOG = auto()
|
|
118
122
|
CAT = auto()
|
|
@@ -144,6 +148,7 @@ describe("Python Enum", () => {
|
|
|
144
148
|
from enum import auto
|
|
145
149
|
from enum import Flag
|
|
146
150
|
|
|
151
|
+
|
|
147
152
|
class Permission(Flag):
|
|
148
153
|
READ = 1
|
|
149
154
|
WRITE = auto()
|
|
@@ -172,6 +177,7 @@ describe("Python Enum", () => {
|
|
|
172
177
|
const expected = d`
|
|
173
178
|
from enum import Enum
|
|
174
179
|
|
|
180
|
+
|
|
175
181
|
Direction = Enum('Direction', ['NORTH', 'SOUTH', 'EAST', 'WEST'])
|
|
176
182
|
`;
|
|
177
183
|
expect(result).toRenderTo(expected);
|
|
@@ -194,6 +200,7 @@ describe("Python Enum", () => {
|
|
|
194
200
|
const expected = d`
|
|
195
201
|
from enum import Enum
|
|
196
202
|
|
|
203
|
+
|
|
197
204
|
Priority = Enum('Priority', {'HIGH' : 1, 'MEDIUM' : 2, 'LOW' : 3})
|
|
198
205
|
`;
|
|
199
206
|
expect(result).toRenderTo(expected);
|
package/test/externals.test.tsx
CHANGED
|
@@ -94,6 +94,7 @@ it("uses import from external library in multiple functions", () => {
|
|
|
94
94
|
from requests import post
|
|
95
95
|
from requests.models import Response
|
|
96
96
|
|
|
97
|
+
|
|
97
98
|
def get_user(user_id: int) -> Response:
|
|
98
99
|
response = get(1)
|
|
99
100
|
return response.json()
|
|
@@ -170,6 +171,7 @@ it("uses import from external library in multiple class methods", () => {
|
|
|
170
171
|
from requests import post
|
|
171
172
|
from requests.models import Response
|
|
172
173
|
|
|
174
|
+
|
|
173
175
|
class UserClient:
|
|
174
176
|
some_var = 12
|
|
175
177
|
def get_user(self, user_id: int) -> Response:
|
|
@@ -289,6 +289,7 @@ describe("Function Declaration", () => {
|
|
|
289
289
|
expect(toSourceText([decl], { externals: [abcModule] })).toBe(d`
|
|
290
290
|
from abc import abstractmethod
|
|
291
291
|
|
|
292
|
+
|
|
292
293
|
class MyClass:
|
|
293
294
|
@abstractmethod
|
|
294
295
|
def methoddef(self, x: int):
|
|
@@ -453,6 +454,7 @@ describe("Function Declaration", () => {
|
|
|
453
454
|
from mod2 import A
|
|
454
455
|
from mod2 import B
|
|
455
456
|
|
|
457
|
+
|
|
456
458
|
async def foo(x: A, y: B, *args, **kwargs) -> Foo:
|
|
457
459
|
pass
|
|
458
460
|
|
package/test/pydocs.test.tsx
CHANGED
|
@@ -1138,6 +1138,7 @@ describe("Full example", () => {
|
|
|
1138
1138
|
const expected = d`
|
|
1139
1139
|
from enum import IntEnum
|
|
1140
1140
|
|
|
1141
|
+
|
|
1141
1142
|
class Color(IntEnum):
|
|
1142
1143
|
"""
|
|
1143
1144
|
An enum representing colors.
|
|
@@ -1219,7 +1220,6 @@ describe("Full example", () => {
|
|
|
1219
1220
|
* Improve error messages
|
|
1220
1221
|
"""
|
|
1221
1222
|
|
|
1222
|
-
|
|
1223
1223
|
default_timeout = 30
|
|
1224
1224
|
|
|
1225
1225
|
max_retries = 3
|