diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index d57714f..55037fa 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -1,3 +1,5 @@ +name: Publish + on: release: types: [created] diff --git a/src/parseTypeDefinition.ts b/src/parseTypeDefinition.ts index f60e023..c1d124d 100644 --- a/src/parseTypeDefinition.ts +++ b/src/parseTypeDefinition.ts @@ -45,17 +45,20 @@ export const parseTypeDefinition = ( } else { const properties = type .getProperties() + // empty strings are not allowed for keys in TypedDicts + .filter(v => v.getName() !== ""); + + const parsedProperties = properties .map((v) => parsePropertyForDict(state, v)); - const propertyDocumentation = type - .getProperties() + const propertyDocumentation = properties .map((v) => getDocumentationStringForDict(state, v)) .filter(v => v !== undefined) .join("\n"); const innerDocstring = documentation?.replaceAll("\n", " \n") + (propertyDocumentation.length > 0 ? "\n## Entries\n" + propertyDocumentation : ""); const docstring = innerDocstring.length > 0 ? `\n"""\n${innerDocstring}\n"""` : ""; - const definition = `${name} = TypedDict(${JSON.stringify(name)}, {\n ${properties.join(",\n ")}\n})${docstring}`; + const definition = `${name} = TypedDict(${JSON.stringify(name)}, {\n ${parsedProperties.join(",\n ")}\n})${docstring}`; state.statements.push(definition); } diff --git a/src/testing/dicts.test.ts b/src/testing/dicts.test.ts index 0729825..77691b0 100644 --- a/src/testing/dicts.test.ts +++ b/src/testing/dicts.test.ts @@ -100,6 +100,18 @@ class A(TypedDict): ); }); + it("ignores empty string property names in functional dicts", async () => { + const result = await transpileString(`export type A = { + "": string, + "foo.bar"?: string, + }`); + expect(result).toContain( + `A = TypedDict("A", { + "foo.bar": NotRequired[str] +})`, + ); + }); + it("moves the key/value docstrings to the object docstring in the functional syntax", async () => { const result = await transpileString(` /** This is A */