Skip to content

Commit

Permalink
fix: Updated Python types generation to be more PEP8 compliant
Browse files Browse the repository at this point in the history
  • Loading branch information
beneboy committed Jul 23, 2019
1 parent e6919f1 commit 1e7a6c0
Showing 1 changed file with 70 additions and 7 deletions.
77 changes: 70 additions & 7 deletions src/python.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import path from 'path'
import fs from 'fs-extra'
import { read, types, props, Schema, unions } from './bindings'

const MAX_LINE_LENGTH = 75 // Desired max length - 4 to allow for indent

/**
* Run `build()` when this file is run as a Node script
*/
Expand All @@ -18,6 +20,11 @@ if (module.parent === null) build()
*/
let globals: string[] = []

/**
* Mapping between an enum signature (MD5 unique ID) and index
*/
const enumSignatures: Record<string, number> = {}

/**
* Generate `python/types.py` from schemas.
*/
Expand All @@ -33,8 +40,7 @@ async function build(): Promise<void> {
.join('')
const globalsCode = globals.join('\n')

const code = `
from typing import Any, Dict, List as Array, Optional, Union
const code = `from typing import Any, Dict, List as Array, Optional, Union
from enum import Enum
${globalsCode}
Expand All @@ -47,6 +53,36 @@ ${unionsCode}
await fs.writeFile(path.join(__dirname, '..', 'python', 'types.py'), code)
}

/**
* Split a description into lines < MAX_LINE_LENGTH for PEP8 compliance.
* @param description
*/
function formatDocstring(description: string): string {
const lines: string[] = []
description = description.replace('\n', ' ').trim()

while (description.length > MAX_LINE_LENGTH) {
let splitIndex = MAX_LINE_LENGTH
for (; splitIndex > 0; --splitIndex) {
if (description.substr(splitIndex, 1) === ' ') {
lines.push(description.substring(0, splitIndex))
description = description.substring(splitIndex + 1)
break
}
}
if (splitIndex === 0) {
// reached the end without finding a space, split in the middle of word if we have to
description = description.substring(0, MAX_LINE_LENGTH)
if (description.length > MAX_LINE_LENGTH) {
// not at the end so push here and continue trimming
lines.push(description)
}
}
}
lines.push(description)
return lines.join('\n ')
}

/**
* Generate a `class`.
*/
Expand All @@ -55,7 +91,18 @@ export function classGenerator(schema: Schema): string {
const { inherited, own, required, optional } = props(schema)

const base = parent !== undefined ? '(' + parent + ')' : ''
const clas = `class ${title}${base}:\n """\n ${description}\n """\n\n`
let docString = ''

if (description !== undefined) {
const formattedDescription = formatDocstring(description)
if (formattedDescription.length <= MAX_LINE_LENGTH - 6) {
docString = ` """${formattedDescription}"""\n\n` // docstring should fit on one line if it can
} else {
docString = ` """\n ${formattedDescription}\n """\n\n`
}
}

const clas = `class ${title}${base}:\n${docString}`

const attrs = own
.map(({ name, schema, optional }) => {
Expand Down Expand Up @@ -86,7 +133,10 @@ export function classGenerator(schema: Schema): string {
const superCall = ` super().__init__(${superArgs})`

const initSetters = own
.map(({ name }) => ` if ${name} is not None: self.${name} = ${name}`)
.map(
({ name }) =>
` if ${name} is not None:\n self.${name} = ${name}`
)
.join('\n')

const init = ` def __init__(${initPars}) -> None:\n${superCall}\n${initSetters}\n\n`
Expand Down Expand Up @@ -181,10 +231,23 @@ export function enumToType(enu: (string | number)[]): string {
.update(values)
.digest('hex')

const name = `Enum${signature}`
const defn = `${name} = Enum("${signature}", [${values}])`
let enumIndex = Object.keys(enumSignatures).length
let enumExists = false

if (enumSignatures[signature] !== undefined) {
enumIndex = enumSignatures[signature]
enumExists = true
} else {
enumSignatures[signature] = enumIndex
}

const name = `Enum${enumIndex}`

if (!enumExists) {
const defn = `${name} = Enum("${enumIndex}", [${values}])\n`

if (!globals.includes(defn)) globals.push(defn)
if (!globals.includes(defn)) globals.push(defn)
}

return `"${name}"`
}

0 comments on commit 1e7a6c0

Please sign in to comment.