Skip to content

Commit

Permalink
chore: revert "update implementation to handle forward references"
Browse files Browse the repository at this point in the history
This reverts commit bf6415e.
  • Loading branch information
jonaslagoni committed Mar 14, 2024
1 parent bf6415e commit e7aacdf
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 170 deletions.
90 changes: 9 additions & 81 deletions src/generators/python/renderers/ClassRenderer.ts
@@ -1,13 +1,8 @@
import { PythonRenderer } from '../PythonRenderer';
import {
ConstrainedArrayModel,
ConstrainedDictionaryModel,
ConstrainedMetaModel,
ConstrainedObjectModel,
ConstrainedObjectPropertyModel,
ConstrainedReferenceModel,
ConstrainedTupleModel,
ConstrainedUnionModel
ConstrainedReferenceModel
} from '../../../models';
import { PythonOptions } from '../PythonGenerator';
import { ClassPresetType } from '../PythonPreset';
Expand Down Expand Up @@ -77,62 +72,6 @@ ${this.indent(this.renderBlock(content, 2))}
runSetterPreset(property: ConstrainedObjectPropertyModel): Promise<string> {
return this.runPreset('setter', { property });
}

/**
* Return forward reference types (`Address` becomes `'Address'`) when it resolves around self-references that are
* either a direct dependency or part of another model such as array, union, dictionary and tuple.
*
* Otherwise just return the provided propertyType as is.
*/
returnPropertyType({
model,
property,
propertyType
}: {
model: ConstrainedMetaModel;
property: ConstrainedMetaModel;
propertyType: string;
}): string {
const isSelfReference =
property instanceof ConstrainedReferenceModel && property.ref === model;
if (isSelfReference) {
// Use forward references for getters and setters
return propertyType.replace(property.ref.type, `'${property.ref.type}'`);
} else if (property instanceof ConstrainedArrayModel) {
return this.returnPropertyType({
model,
property: property.valueModel,
propertyType
});
} else if (property instanceof ConstrainedTupleModel) {
let newPropType = propertyType;
for (const tupl of property.tuple) {
newPropType = this.returnPropertyType({
model,
property: tupl.value,
propertyType
});
}
return newPropType;
} else if (property instanceof ConstrainedUnionModel) {
let newPropType = propertyType;
for (const unionModel of property.union) {
newPropType = this.returnPropertyType({
model,
property: unionModel,
propertyType
});
}
return newPropType;
} else if (property instanceof ConstrainedDictionaryModel) {
return this.returnPropertyType({
model,
property: property.value,
propertyType
});
}
return propertyType;
}
}

export const PYTHON_DEFAULT_CLASS_PRESET: ClassPresetType<PythonOptions> = {
Expand All @@ -144,18 +83,17 @@ export const PYTHON_DEFAULT_CLASS_PRESET: ClassPresetType<PythonOptions> = {
let body = '';
if (Object.keys(properties).length > 0) {
const assignments = Object.values(properties).map((property) => {
const propertyType = property.property.type;
if (property.property.options.const) {
return `self._${property.propertyName}: ${propertyType} = ${property.property.options.const.value}`;
return `self._${property.propertyName}: ${property.property.type} = ${property.property.options.const.value}`;
}
let assignment: string;
if (property.property instanceof ConstrainedReferenceModel) {
assignment = `self._${property.propertyName}: ${propertyType} = ${propertyType}(input['${property.propertyName}'])`;
assignment = `self._${property.propertyName}: ${property.property.type} = ${property.property.type}(input['${property.propertyName}'])`;
} else {
assignment = `self._${property.propertyName}: ${propertyType} = input['${property.propertyName}']`;
assignment = `self._${property.propertyName}: ${property.property.type} = input['${property.propertyName}']`;
}
if (!property.required) {
return `if '${property.propertyName}' in input:
return `if hasattr(input, '${property.propertyName}'):
${renderer.indent(assignment, 2)}`;
}
return assignment;
Expand All @@ -170,30 +108,20 @@ No properties
return `def __init__(self, input: Dict):
${renderer.indent(body, 2)}`;
},
getter({ property, renderer, model }) {
const propertyType = renderer.returnPropertyType({
model,
property: property.property,
propertyType: property.property.type
});
getter({ property, renderer }) {
const propAssignment = `return self._${property.propertyName}`;
return `@property
def ${property.propertyName}(self) -> ${propertyType}:
def ${property.propertyName}(self) -> ${property.property.type}:
${renderer.indent(propAssignment, 2)}`;
},
setter({ property, renderer, model }) {
setter({ property, renderer }) {
// if const value exists we should not render a setter
if (property.property.options.const?.value) {
return '';
}
const propertyType = renderer.returnPropertyType({
model,
property: property.property,
propertyType: property.property.type
});

const propAssignment = `self._${property.propertyName} = ${property.propertyName}`;
const propArgument = `${property.propertyName}: ${propertyType}`;
const propArgument = `${property.propertyName}: ${property.property.type}`;

return `@${property.propertyName}.setter
def ${property.propertyName}(self, ${propArgument}):
Expand Down
29 changes: 0 additions & 29 deletions test/generators/python/PythonGenerator.spec.ts
Expand Up @@ -81,35 +81,6 @@ describe('PythonGenerator', () => {
expect(models).toHaveLength(1);
expect(models[0].result).toMatchSnapshot();
});
test('should handle self reference models', async () => {
const doc = {
$id: 'Address',
type: 'object',
properties: {
test: { type: 'string' },
self_model: { $ref: '#' },
array_model: { type: 'array', items: { $ref: '#' } },
tuple_model: {
type: 'array',
items: [{ $ref: '#' }],
additionalItems: false
},
map_model: {
type: 'object',
additionalProperties: {
$ref: '#'
}
},
union_model: {
oneOf: [{ $ref: '#' }]
}
},
additionalProperties: false
};
const models = await generator.generate(doc);
expect(models).toHaveLength(1);
expect(models[0].result).toMatchSnapshot();
});
test('should render `class` type', async () => {
const doc = {
$id: 'Address',
Expand Down
60 changes: 0 additions & 60 deletions test/generators/python/__snapshots__/PythonGenerator.spec.ts.snap
@@ -1,65 +1,5 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`PythonGenerator Class should handle self reference models 1`] = `
"class Address:
def __init__(self, input: Dict):
if 'test' in input:
self._test: str = input['test']
if 'self_model' in input:
self._self_model: Address = Address(input['self_model'])
if 'array_model' in input:
self._array_model: List[Address] = input['array_model']
if 'tuple_model' in input:
self._tuple_model: tuple[Address] = input['tuple_model']
if 'map_model' in input:
self._map_model: dict[str, Address] = input['map_model']
if 'union_model' in input:
self._union_model: Address = input['union_model']
@property
def test(self) -> str:
return self._test
@test.setter
def test(self, test: str):
self._test = test
@property
def self_model(self) -> 'Address':
return self._self_model
@self_model.setter
def self_model(self, self_model: 'Address'):
self._self_model = self_model
@property
def array_model(self) -> List['Address']:
return self._array_model
@array_model.setter
def array_model(self, array_model: List['Address']):
self._array_model = array_model
@property
def tuple_model(self) -> tuple['Address']:
return self._tuple_model
@tuple_model.setter
def tuple_model(self, tuple_model: tuple['Address']):
self._tuple_model = tuple_model
@property
def map_model(self) -> dict[str, 'Address']:
return self._map_model
@map_model.setter
def map_model(self, map_model: dict[str, 'Address']):
self._map_model = map_model
@property
def union_model(self) -> 'Address':
return self._union_model
@union_model.setter
def union_model(self, union_model: 'Address'):
self._union_model = union_model
"
`;

exports[`PythonGenerator Class should not render reserved keyword 1`] = `
"class Address:
def __init__(self, input: Dict):
Expand Down

0 comments on commit e7aacdf

Please sign in to comment.