# HG changeset patch # User Sebastien Jodogne # Date 1719916216 -7200 # Node ID ddf3e987827f01470f5b0cf790f28c1d54c7f7f9 # Parent f49864df6f1f45cc832b4a5c67b24e1bdd05d652 created Python documentation for the Orthanc interface diff -r f49864df6f1f -r ddf3e987827f CMakeLists.txt --- a/CMakeLists.txt Thu Jun 27 21:53:03 2024 +0200 +++ b/CMakeLists.txt Tue Jul 02 12:30:16 2024 +0200 @@ -215,6 +215,11 @@ SOVERSION ${PLUGIN_VERSION} ) +configure_file( + Sources/Autogenerated/orthanc.pyi + ${CMAKE_CURRENT_BINARY_DIR}/orthanc.pyi + COPYONLY) + install( TARGETS OrthancPython RUNTIME DESTINATION lib # Destination for Windows diff -r f49864df6f1f -r ddf3e987827f CodeAnalysis/GenerateOrthancSDK.py --- a/CodeAnalysis/GenerateOrthancSDK.py Thu Jun 27 21:53:03 2024 +0200 +++ b/CodeAnalysis/GenerateOrthancSDK.py Tue Jul 02 12:30:16 2024 +0200 @@ -59,9 +59,17 @@ 'args' : [ { 'name' : 'arg0', + 'sdk_name' : 'size', 'sdk_type' : 'uint32_t', } ], + 'documentation' : { + 'args' : { + 'size' : 'Size of the memory buffer to be created', + }, + 'return' : 'The newly allocated memory buffer', + 'description' : [ 'Create a new memory buffer managed by the Orthanc core' ], + }, 'return_sdk_type' : 'OrthancPluginMemoryBuffer *', } ] @@ -138,6 +146,16 @@ return s +def ToLowerCase(name): + s = '' + for i in range(len(name)): + if (name[i].isupper() and + len(s) != 0): + s += '_' + s += name[i].lower() + return s + + def GetShortName(name): if not name.startswith('OrthancPlugin'): raise Exception() @@ -279,6 +297,66 @@ answer['tuple_format'] = ', '.join([ '"' + tuple_format + '"' ] + tuple_target) answer['allow_threads'] = allow_threads + if 'documentation' in f: + documentation = {} + description = f['documentation'].get('description', []) + if len(description) > 0: + documentation['short_description'] = description[0].split('.') [0] + documentation['description'] = map(lambda x: { 'text' : x }, description) + + args_declaration = [] + args_documentation = [] + for a in f['args']: + arg_name = ToLowerCase(a['sdk_name']) + if a['sdk_type'] == 'const char *': + arg_type = 'str' + elif a['sdk_type'] == 'float': + arg_type = 'float' + elif a['sdk_type'] in [ 'const_void_pointer_with_size', 'const void *' ]: + arg_type = 'bytes' + elif a['sdk_type'] == 'enumeration': + arg_type = GetShortName(a['sdk_enumeration']) + elif a['sdk_type'] == 'const_object': + arg_type = GetShortName(a['sdk_class']) + elif a['sdk_type'] in [ 'int32_t', 'uint32_t', 'uint8_t', 'uint16_t', 'uint64_t' ]: + arg_type = 'int' + else: + raise Exception('Argument type not implemented: %s' % a['sdk_type']) + args_declaration.append('%s: %s' % (arg_name, arg_type)) + args_documentation.append({ + 'name' : arg_name, + 'type' : arg_type, + 'text' : f['documentation']['args'] [a['sdk_name']], + }) + + documentation['args_declaration'] = ', '.join(args_declaration) + documentation['args'] = args_documentation + documentation['has_args'] = len(args_documentation) > 0 + documentation['has_return'] = True + documentation['return_text'] = f['documentation'].get('return', None) + + if f['return_sdk_type'] == 'enumeration': + if f['return_sdk_enumeration'] == 'OrthancPluginErrorCode': + documentation['has_return'] = False + documentation['return_type'] = 'None' + else: + documentation['return_type'] = GetShortName(f['return_sdk_enumeration']) + elif f['return_sdk_type'] == 'object': + documentation['return_type'] = GetShortName(f['return_sdk_class']) + elif f['return_sdk_type'] == 'void': + documentation['has_return'] = False + documentation['return_type'] = 'None' + elif f['return_sdk_type'] == 'OrthancPluginMemoryBuffer *': + documentation['return_type'] = 'bytes' + elif f['return_sdk_type'] in [ 'char *', 'const char *' ]: + documentation['return_type'] = 'str' + elif f['return_sdk_type'] in [ 'int32_t', 'uint32_t', 'int64_t' ]: + documentation['return_type'] = 'int' + else: + raise Exception('Return type not implemented: %s' % f['return_sdk_type']) + + answer['documentation'] = documentation + if len(call_args) > 0: answer['call_args'] = ', ' + ', '.join(call_args) @@ -313,12 +391,15 @@ values.append({ 'key' : ToUpperCase(value['key']), 'value' : value['value'], + 'documentation' : value['documentation'], }) enumerations.append({ 'name' : e['name'], + 'short_name' : GetShortName(e['name']), 'path' : 'sdk_%s.impl.h' % e['name'], 'values' : values, + 'documentation' : e['documentation'], }) path = 'sdk_%s.impl.h' % e['name'] @@ -392,3 +473,11 @@ h.write(renderer.render(f.read(), { 'classes' : sortedClasses, })) + +with open(os.path.join(ROOT, 'PythonDocumentation.mustache'), 'r') as f: + with open(os.path.join(TARGET, 'orthanc.pyi'), 'w') as h: + h.write(renderer.render(f.read(), { + 'classes' : sortedClasses, + 'enumerations' : sortedEnumerations, + 'global_functions' : sortedGlobalFunctions, + })) diff -r f49864df6f1f -r ddf3e987827f CodeAnalysis/PythonDocumentation.mustache --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CodeAnalysis/PythonDocumentation.mustache Tue Jul 02 12:30:16 2024 +0200 @@ -0,0 +1,95 @@ +## +## Python plugin for Orthanc +## Copyright (C) 2020-2023 Osimis S.A., Belgium +## Copyright (C) 2024-2024 Orthanc Team SRL, Belgium +## Copyright (C) 2021-2024 Sebastien Jodogne, ICTEAM UCLouvain, Belgium +## +## This program is free software: you can redistribute it and/or +## modify it under the terms of the GNU Affero General Public License +## as published by the Free Software Foundation, either version 3 of +## the License, or (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## Affero General Public License for more details. +## +## You should have received a copy of the GNU Affero General Public License +## along with this program. If not, see . +## + +import enum + +{{#enumerations}} + +class {{short_name}}(enum.Enum): + """ + {{documentation}} + """ +{{#values}} + + """ + {{documentation}} + """ + {{key}}: int = {{value}}, +{{/values}} +{{/enumerations}} + + +{{#global_functions}} + +{{#documentation.short_description}} +# {{documentation.short_description}} +{{/documentation.short_description}} +def {{short_name}}({{documentation.args_declaration}}) -> {{documentation.return_type}}: + """ +{{#documentation.description}} + {{text}} +{{/documentation.description}} +{{#documentation.has_args}} + + Args: + {{#documentation.args}} + {{name}} ({{type}}): {{text}} + {{/documentation.args}} +{{/documentation.has_args}} +{{#documentation.has_return}} + + Returns: + {{documentation.return_type}}: {{documentation.return_text}} +{{/documentation.has_return}} + """ + ... +{{/global_functions}} + + +{{#classes}} +class {{short_name}}: + ... + +{{#methods}} +{{#documentation.short_description}} + # {{documentation.short_description}} +{{/documentation.short_description}} + def {{short_name}}(self{{#documentation.has_args}}, {{/documentation.has_args}}{{documentation.args_declaration}}) -> {{documentation.return_type}}: + """ +{{#documentation.description}} + {{text}} +{{/documentation.description}} +{{#documentation.has_args}} + + Args: + {{#documentation.args}} + {{name}} ({{type}}): {{text}} + {{/documentation.args}} +{{/documentation.has_args}} +{{#documentation.has_return}} + + Returns: + {{documentation.return_type}}: {{documentation.return_text}} +{{/documentation.has_return}} + """ + ... + +{{/methods}} +{{/classes}} diff -r f49864df6f1f -r ddf3e987827f NEWS --- a/NEWS Thu Jun 27 21:53:03 2024 +0200 +++ b/NEWS Tue Jul 02 12:30:16 2024 +0200 @@ -1,6 +1,7 @@ Pending changes in the mainline =============================== +* Created Python documentation for the Orthanc interface, check out "orthanc.pyi" * Added Windows builder for Python 3.12