Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
1e3b83c
feat: add first version of python generator (with not fully working h…
Jan 17, 2026
c346863
fix: remove generated code
Jan 17, 2026
64af218
fix: remove some unused imports and queries from templates
Jan 17, 2026
a71c556
fix: add missing copyright comments to python files
Jan 17, 2026
98a3531
fix: some imports in python templates
Mar 8, 2026
e7fb1df
fix: annotation mismatches
Mar 8, 2026
37a2f3c
fix: identation generation error to make first working version of aut…
Mar 8, 2026
b006e62
feat: flas some templates/queries for refactor to common packages
Mar 21, 2026
879a19f
feat: little template naming changes
Mar 21, 2026
a4b4f89
feat: change python generated code structure from nested directories …
Mar 21, 2026
4442d39
feat: add add methods to resource classes
Mar 21, 2026
6b3cfb7
fix: oslc value type annotations
Mar 22, 2026
9f19800
fix: add missing oslc title decorator
Mar 22, 2026
893830a
fix: add missing member property annotation
Mar 22, 2026
cd947b3
feat: add mising allowedValuesAnnotation and rdfCollectionTypeAnnotation
Mar 22, 2026
731b760
feat: refactor resource getter and setter generation to more mirror j…
Mar 22, 2026
fdb1aa7
fix: inheritance in python generated classes
Mar 22, 2026
31e67bb
fix: import generation in python template to more match style of java…
Mar 30, 2026
4a6ff12
feat: update standalone python codegenerator templates
May 10, 2026
ddd0ae6
fix: manifest.mf in codegenerator
May 10, 2026
306b757
fix: make standalone python templates self-contained
May 10, 2026
c807cb9
fix: keep python template branch scoped to python package
May 10, 2026
781ffbc
Revert "fix: keep python template branch scoped to python package"
May 10, 2026
e24bd90
feat: cleanup manifest.mf a bit
May 10, 2026
48775a5
fix: include standalone python definition lookup services
May 10, 2026
33f1763
fix: manifest.mf in code generator
May 10, 2026
378681d
feat: add other python templates subpackages to manifest
May 10, 2026
5c7b0f4
fix: codegenerator manifest syntax error
May 10, 2026
0a5f703
fix: vocabulary constants generation
May 13, 2026
7368a07
fix: vocabulary constants path resolving
May 13, 2026
a702880
fix: package init generations
May 13, 2026
28a2f30
fix: remove trailing import
May 13, 2026
06960f4
fix: remove old unused parameters
May 17, 2026
57c3c70
feat: move domainSpecificationImplicitVocabularyNamespaceConstantName…
May 17, 2026
1c8bf9e
fix: move mid-file imports to tops
May 17, 2026
1d052a7
fix: remove unused python queries/templates
May 17, 2026
e700b75
fix: remove unused resourceConstantName query from python package
May 17, 2026
b389c3d
fix: sort queries in service files
May 17, 2026
9819645
Merge branch 'master' into feat/python-templates
May 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion org.eclipse.lyo.oslc4j.codegenerator/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,12 @@ Export-Package: org.eclipse.lyo.oslc4j.codegenerator.files,
org.eclipse.lyo.oslc4j.codegenerator.jsp,
org.eclipse.lyo.oslc4j.codegenerator.staticFiles,
org.eclipse.lyo.oslc4j.codegenerator.main,
org.eclipse.lyo.oslc4j.codegenerator.services
org.eclipse.lyo.oslc4j.codegenerator.services,
org.eclipse.lyo.oslc4j.codegenerator.python.files,
org.eclipse.lyo.oslc4j.codegenerator.python.config,
org.eclipse.lyo.oslc4j.codegenerator.python.staticFiles,
org.eclipse.lyo.oslc4j.codegenerator.python.main,
org.eclipse.lyo.oslc4j.codegenerator.python.services
Bundle-ClassPath: bin/,
.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[comment encoding = UTF-8 /]
[comment
/*
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
* which is available at http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
*/
/]
[module generateConfigFiles('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary', 'http://www.eclipse.org/emf/2002/Ecore')/]


[template public generateConfigFiles(aSpecification : Specification)]
[file ('requirements.txt', false, 'UTF-8')]
oslc4py-client
rdflib
[/file]
[/template]
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
[comment encoding = UTF-8 /]
[comment
/*
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
* which is available at http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
*/
/]
[module generateAdaptorPackageInfo('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary')/]
[import org::eclipse::lyo::oslc4j::codegenerator::python::services::resourceServices/]
[import org::eclipse::lyo::oslc4j::codegenerator::python::services::services/]

[template public generateAdaptorPackageInfo(resources : Set(Resource), defaultFilesPath : String, defaultPackageName : String)]
[let generatedResources : Set(Resource) = resources->select(r : Resource | r.generate())]
[if (resources->size() > 0)]
[comment This can be any resource because it's only used for constructing correct path /]
[let aResource : Resource = resources->any(true)]
[file (aResource.pythonClassFullFolderName(null, defaultFilesPath, defaultPackageName).concatenatePaths('__init__.py'), false, 'UTF-8')]
[for (r : Resource | generatedResources->sortedBy(name))]
from .[r.pythonClassName()/] import [r.pythonClassName()/]
[/for]
# [protected ('imports')]
# [/protected]
[/file]
[/let]
[/if]
[/let]
[/template]

[template public generateAdaptorPackageInfo(resourcesOnSameFolderPath: Set(Resource), contextAdaptorInterface : AdaptorInterface, defaultFilesPath : String, defaultPackageName : String)]
[generateAdaptorPackageInfo(resourcesOnSameFolderPath, contextAdaptorInterface.filesBasePath(defaultFilesPath), contextAdaptorInterface.pythonBasePackageName(defaultPackageName))/]
[/template]
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
[comment encoding = UTF-8 /]
[comment
/*
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
* which is available at http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
*/
/]
[module generateDomainSpecificationConstants('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary')/]

[import org::eclipse::lyo::oslc4j::codegenerator::python::services::fileServices/]
[import org::eclipse::lyo::oslc4j::codegenerator::python::services::services/]
[import org::eclipse::lyo::oslc4j::codegenerator::python::services::adaptorInterfaceServices/]
[import org::eclipse::lyo::oslc4j::codegenerator::python::services::domainSpecificationServices/]

[template public generateDomainSpecificationConstants(aDomainSpecification : DomainSpecification, defaultFilesPath : String, defaultPackageName : String)]
[let rootInitFileName : String = aDomainSpecification.pythonFilesBasePath(null, defaultFilesPath).concatenatePaths('__init__.py')]
[file (rootInitFileName, false, 'UTF-8')]
# [protected ('imports')]
# [/protected]
[/file]
[/let]
[let packageInitFileName : String = aDomainSpecification.pythonFullFolderNameForConstants(null, defaultFilesPath, defaultPackageName).concatenatePaths('__init__.py')]
[file (packageInitFileName, false, 'UTF-8')]
# [protected ('imports')]
# [/protected]
[/file]
[/let]
[file (aDomainSpecification.pythonFullFileNameForConstants(null, defaultFilesPath, defaultPackageName), false, 'UTF-8')]
import rdflib

# [protected ('imports')]
# [/protected]

[aDomainSpecification.domainSpecificationImplicitVocabularyNamespaceConstantName()/] = rdflib.Namespace("[aDomainSpecification.namespaceURI/]")

# [protected ('constants')]
# [/protected]
[/file]
[/template]

[template public generateDomainSpecificationConstants(aDomainSpecification : DomainSpecification, anAdaptorInterface : AdaptorInterface, defaultFilesPath : String, defaultPackageName : String)]
[aDomainSpecification.generateDomainSpecificationConstants(aDomainSpecification.filesBasePath(anAdaptorInterface, defaultFilesPath), aDomainSpecification.pythonPackageNameForConstants(anAdaptorInterface, defaultPackageName))/]
[/template]
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
[comment encoding = UTF-8 /]
[comment
/*
* Copyright (c) 2020 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the Eclipse Distribution License 1.0
* which is available at http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Simple
*/
/]
[module generateResource('http://org.eclipse.lyo/oslc4j/adaptorInterface', 'http://org.eclipse.lyo/oslc4j/vocabulary')/]
[import org::eclipse::lyo::oslc4j::codegenerator::python::services::vocabularyServices/]
[import org::eclipse::lyo::oslc4j::codegenerator::python::services::adaptorInterfaceServices/]
[import org::eclipse::lyo::oslc4j::codegenerator::python::services::domainSpecificationServices/]
[import org::eclipse::lyo::oslc4j::codegenerator::python::services::resourceServices/]

[import org::eclipse::lyo::oslc4j::codegenerator::python::services::resourcePropertyServices/]
[import org::eclipse::lyo::oslc4j::codegenerator::python::services::services/]

[template public generateClassHeader(aResource : Resource, contextAdaptorInterface : AdaptorInterface)]
# [protected ('Copyright')]
#
# Copyright (c) 2020 Contributors to the Eclipse Foundation
#
# See the NOTICE file(s) distributed with this work for additional
# information regarding copyright ownership.
#
# This program and the accompanying materials are made available under the
# terms of the Eclipse Distribution License 1.0 which is available at
# http://www.eclipse.org/org/documents/edl-v10.php.
#
# SPDX-License-Identifier: BSD-3-Simple
#
# This file is generated by Lyo Designer (https://www.eclipse.org/lyo/)
#
# [/protected]
[/template]

[template public generateImports(aResource : Resource, contextAdaptorInterface : AdaptorInterface, defaultPackageName : String)]
[if (hasDateTimeProperty(aResource))]from datetime import datetime[/if]
[if (hasSetProperty(aResource))]from typing import Set[/if]
from oslc4py_client.annotation_types.Occurs import Occurs
from oslc4py_client.annotation_types.ValueType import ValueType
from oslc4py_client.annotation_types.Representation import Representation
from oslc4py_client.OSLCResource import OSLCResource
[if (hasLinkProperty(aResource))]from oslc4py_client.Link import Link[/if]
from oslc4py_client.decorators import oslc_description, oslc_name, oslc_namespace, oslc_rdf_collection_type, oslc_occurs, oslc_property_definition, oslc_resource_shape, oslc_value_type, oslc_representation, oslc_range, oslc_read_only, oslc_title, oslc_member_property, oslc_allowed_values

from [aResource.definingDomainSpecification().pythonPackageNameForConstants(contextAdaptorInterface, defaultPackageName)/].[aResource.definingDomainSpecification().pythonNameForConstants()/] import [aResource.definingDomainSpecification().domainSpecificationImplicitVocabularyNamespaceConstantName()/]
[if (not aResource.directParentResource().oclIsUndefined() and aResource.directParentResource() <> aResource)]from [aResource.directParentResource().pythonClassPackageName(contextAdaptorInterface, defaultPackageName)/].[aResource.directParentResource().pythonClassName()/] import [aResource.directParentResource().pythonClassName()/][/if]
[for (aDomainSpecification: DomainSpecification | (aResource.resourceProperties->union(aResource.interfaceProperties()->asSet())->collect(p: ResourceProperty | Set{p.definingDomainSpecification()}->union(p.range.definingDomainSpecification()->asSet())))->flatten()->asSet()->sortedBy(name))]from [aDomainSpecification.pythonPackageNameForConstants(contextAdaptorInterface, defaultPackageName)/].[aDomainSpecification.pythonNameForConstants()/] import [aDomainSpecification.domainSpecificationImplicitVocabularyNamespaceConstantName()/]
[/for]
[for (aVocabulary: Vocabulary | ((aResource.resourceProperties->asSequence())->union(interfaceProperties(aResource)))->asSet()
->select(p: ResourceProperty | not (p.propertyDefinition.oclIsUndefined()))
->collect(p: ResourceProperty | p.propertyDefinition.definingVocabulary())
->flatten()->asSet()->sortedBy(label))]from [aVocabulary.pythonPackageNameForConstants(contextAdaptorInterface, defaultPackageName)/].[aVocabulary.pythonNameForConstants()/] import [aVocabulary.vocabularyNamespaceConstantName()/]
[/for]
[for (r: Resource | ((aResource.resourceProperties->asSequence())->union(interfaceProperties(aResource)))
->select(p: ResourceProperty |
(p.valueType.toString() = 'LocalResource' and p.range->size() = 1) or
(p.valueType.toString() = 'Resource' and not p.representation.oclIsUndefined() and p.representation.toString().equalsIgnoreCase('inline') and p.range->size() = 1)
)
->collect(p: ResourceProperty | p.range)->flatten()->asSet()
->sortedBy(name))]
[if (r <> aResource)]
from [r.pythonClassPackageName(contextAdaptorInterface, defaultPackageName)/].[r.pythonClassName()/] import [r.pythonClassName()/]
[/if]
[/for]
# [protected ('imports')]
# [/protected]
[/template]

[template public generatePreClassCode(aResource : Resource, contextAdaptorInterface : AdaptorInterface)]
# [protected ('preClassCode')]
# [/protected]
[/template]

[template public generateClassAnnotations(aResource : Resource)]
# [protected ('classAnnotations')]
# [/protected]
[pythonNamespaceAnnotation(aResource)/]
[pythonNameAnnotation(aResource)/]
[pythonResourceShapeAnnotation(aResource)/]
[/template]

[template public generateClassDeclaration(aResource : Resource)]
class [aResource.pythonClassName()/]([if (aResource.directParentResource().oclIsUndefined())]OSLCResource[else][pythonClassName(aResource.directParentResource())/][/if]):
[/template]

[template public generateInstanceAttributes(aResource : Resource)]
[for (aProperty: ResourceProperty | ((aResource.resourceProperties->asSequence())->union(interfaceProperties(aResource))))]
# [protected ('attributeAnnotation:'.concat(pythonAttributeName(aProperty, aResource)))]
# [/protected]
self._[aProperty.pythonAttributeName(aResource)/] = [aProperty.pythonAttributeInitialConstruction()/]
[/for]
[/template]

[template public generateClassAttributes(aResource : Resource)]
# [protected ('classAttributes')]
# [/protected]
[/template]

[template public generateClassMethods(aResource : Resource)]
# [protected ('classMethods')]
# [/protected]
[/template]

[template public generateConstructor(aResource : Resource)]
def __init__(self, **kwargs):
super().__init__(**kwargs)
# [protected ('constructor')]
# [/protected]
[generateInstanceAttributes(aResource)/]
[/template]

[template public generateAddToAttributeMethods(aResource : Resource)]
[for (aProperty: ResourceProperty | ((aResource.resourceProperties->asSequence())->union(interfaceProperties(aResource))))]
[if (Sequence{'zeroOrMany', 'oneOrMany'}->includes(aProperty.occurs.toString()))]
def add_[pythonAttributeName(aProperty, aResource)/](self, value: [pythonAttributeBaseType(aProperty) /]):
self.[pythonAttributeName(aProperty, aResource) /].add(value)

[/if]
[/for]
[/template]

[template public generateGetter(aProperty: ResourceProperty, aResource : Resource, contextAdaptorInterface : AdaptorInterface)]
@property
# [protected ('getterAnnotation:'.concat(pythonAttributeName(aProperty, aResource)))]
# [/protected]
[if (not (nameAnnotation(aProperty) = ''))]
[nameAnnotation(aProperty)/]
[/if]
[if (not (propertyDefinitionAnnotation(aProperty, aResource, contextAdaptorInterface) = ''))]
[propertyDefinitionAnnotation(aProperty, aResource, contextAdaptorInterface)/]
[/if]
[if (not (descriptionAnnotation(aProperty) = ''))]
[descriptionAnnotation(aProperty)/]
[/if]
[if (not (rdfCollectionTypeAnnotation(aProperty) = ''))]
[rdfCollectionTypeAnnotation(aProperty)/]
[/if]
[if (not (occursAnnotation(aProperty) = ''))]
[occursAnnotation(aProperty)/]
[/if]
[if (not (valueTypeAnnotation(aProperty) = ''))]
[valueTypeAnnotation(aProperty)/]
[/if]
[if (not (representationAnnotation(aProperty) = ''))]
[representationAnnotation(aProperty)/]
[/if]
[if (not (rangeAnnotation(aProperty, aResource, contextAdaptorInterface)= ''))]
[rangeAnnotation(aProperty, aResource, contextAdaptorInterface)/]
[/if]
[if (not (readOnlyAnnotation(aProperty) = ''))]
[readOnlyAnnotation(aProperty)/]
[/if]
[if (not (titleAnnotation(aProperty)= ''))]
[titleAnnotation(aProperty)/]
[/if]
[if (not (isMemberPropertyAnnotation(aProperty)= ''))]
[isMemberPropertyAnnotation(aProperty)/]
[/if]
[if (not (allowedValuesAnnotation(aProperty) = ''))]
[allowedValuesAnnotation(aProperty)/]
[/if]
def [aProperty.pythonAttributeGetterMethodName(aResource)/](self):
# [protected ('getterInit:'.concat(pythonAttributeName(aProperty, aResource)))]
# [/protected]
return self._[aProperty.pythonAttributeName(aResource)/]
[/template]

[template public generateSetter(aProperty: ResourceProperty, aResource : Resource)]
@[aProperty.pythonAttributeSetterMethodName(aResource)/].setter
def [aProperty.pythonAttributeSetterMethodName(aResource)/](self, value: [aProperty.pythonAttributeTypeDeclaration()/]):
# [protected ('setterInit:'.concat(pythonAttributeName(aProperty, aResource)))]
# [/protected]
self._[aProperty.pythonAttributeName(aResource)/] = value
# [protected ('setterFinalize:'.concat(pythonAttributeName(aProperty, aResource)))]
# [/protected]
[/template]


[template public generateResource(aResource : Resource, contextAdaptorInterface : AdaptorInterface, defaultFilesPath : String, defaultPackageName : String)]
[if (aResource.generate())]
[file (aResource.pythonClassFullFileName(contextAdaptorInterface, defaultFilesPath, defaultPackageName), false, 'UTF-8')]
[generateClassHeader(aResource, contextAdaptorInterface)/]

[generateImports(aResource, contextAdaptorInterface, defaultPackageName)/]

[generatePreClassCode(aResource, contextAdaptorInterface)/]

[generateClassAnnotations(aResource)/]
[generateClassDeclaration(aResource)/]
[generateClassAttributes(aResource)/]
[generateClassMethods(aResource)/]
[generateConstructor(aResource)/]
[generateAddToAttributeMethods(aResource)/]
[for (aProperty: ResourceProperty | ((aResource.resourceProperties->asSequence())->union(interfaceProperties(aResource))))]
[generateGetter(aProperty, aResource, contextAdaptorInterface)/]

[/for]
[for (aProperty: ResourceProperty | ((aResource.resourceProperties->asSequence())->union(interfaceProperties(aResource))))]
[generateSetter(aProperty, aResource)/]

[/for]
[/file]
[/if]
[/template]
Loading