232 lines
9.3 KiB
Python
232 lines
9.3 KiB
Python
#!/usr/bin/env python
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
from __future__ import unicode_literals
|
|
|
|
import getopt
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
|
|
import onnx
|
|
|
|
import tensorflow as tf
|
|
|
|
from onnx_tf import opset_version, __version__
|
|
|
|
|
|
def main(docs_dir):
|
|
base_dir = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
|
|
docs_dir = os.path.join(base_dir, 'doc')
|
|
onnx_version = onnx.__version__
|
|
onnx_tf_release_build = False
|
|
|
|
try:
|
|
opts, args = getopt.getopt(sys.argv[1:], 'h:mr',
|
|
['onnx_master', 'onnx_tf_release_build'])
|
|
except getopt.GetoptError:
|
|
print('Usage:')
|
|
print(' gen_status.py [-m -r]')
|
|
print(' gen_status.py -h')
|
|
print('Description:')
|
|
print(' -m, --onnx_master installed ONNX is the latest master code')
|
|
print(' if omitted, ONNX version is onnx.__version__')
|
|
print(' -r, --onnx_tf_release_build create report for ONNX-TF release with version')
|
|
print(' stated in the VERSION_NUMBER file')
|
|
print(' if omitted, the report is for ONNX-TF master')
|
|
print(' -h show this help message and exit')
|
|
print('eg. 1. generate support_status.md for ONNX-TF master and ONNX onnx.__version__')
|
|
print(' gen_status.py')
|
|
print(' 2. generate support_status.md for ONNX-TF master and ONNX master')
|
|
print(' gen_status.py -m')
|
|
print(' 3. generate support_status_<onnx_tf_version>.md for ONNX-TF version')
|
|
print(' stated in the VERSION_NUMBER file and ONNX onnx.__version__ ')
|
|
print(' gen_status.py -r')
|
|
sys.exit(2)
|
|
for opt, arg in opts:
|
|
if opt == '-h':
|
|
print('Usage:')
|
|
print(' gen_status.py [-m -r]')
|
|
print(' gen_status.py -h')
|
|
print('Description:')
|
|
print(' -m, --onnx_master installed ONNX is the latest master code')
|
|
print(' if omitted, ONNX version is onnx.__version__')
|
|
print(' -r, --onnx_tf_release_build create report for ONNX-TF release with version')
|
|
print(' stated in the VERSION_NUMBER file')
|
|
print(' if omitted, the report is for ONNX-TF master')
|
|
print(' -h show this help message and exit')
|
|
print('eg. 1. generate support_status.md for ONNX-TF master and ONNX onnx.__version__')
|
|
print(' gen_status.py')
|
|
print(' 2. generate support_status.md for ONNX-TF master and ONNX master')
|
|
print(' gen_status.py -m')
|
|
print(' 3. generate support_status_<onnx_tf_version>.md for ONNX-TF version')
|
|
print(' stated in the VERSION_NUMBER file and ONNX onnx.__version__ ')
|
|
print(' gen_status.py -r')
|
|
sys.exit()
|
|
elif opt in ('-m', '--onnx_master'):
|
|
onnx_version = 'master'
|
|
elif opt in ('-r', '--onnx_tf_release_build'):
|
|
onnx_tf_release_build = True
|
|
|
|
gen_support_status(docs_dir, onnx_version, onnx_tf_release_build)
|
|
|
|
|
|
def gen_support_status(docs_dir, onnx_version, onnx_tf_release_build):
|
|
|
|
# set filename
|
|
if onnx_tf_release_build:
|
|
onnx_tf_version = 'v' + __version__
|
|
filename = 'support_status_' + onnx_tf_version.replace('.', '_') + '.md'
|
|
else: # onnx-tf = master
|
|
# get onnx-tf commit id
|
|
onnx_tf_commit_id = subprocess.check_output('git rev-parse HEAD',
|
|
shell=True)
|
|
onnx_tf_commit_id = onnx_tf_commit_id.decode().strip('\n')
|
|
onnx_tf_version = 'Master ( commit id: {} )'.format(onnx_tf_commit_id)
|
|
filename = 'support_status.md'
|
|
|
|
with open(os.path.join(docs_dir, filename), 'w') as status_file:
|
|
status_file.write('# ONNX-Tensorflow Support Status\n')
|
|
status_file.write('|||\n')
|
|
status_file.write('|-:|:-|\n')
|
|
status_file.write('|ONNX-Tensorflow Version|{}|\n'.format(onnx_tf_version))
|
|
|
|
# get onnx commit id
|
|
if onnx_version == 'master':
|
|
onnx_commit_id = onnx.version.git_version
|
|
status_file.write(
|
|
'|ONNX Version|Master ( commit id: {} )|\n'.format(onnx_commit_id))
|
|
else:
|
|
status_file.write('|ONNX Version|v{}|\n'.format(onnx_version))
|
|
|
|
# get tf_version
|
|
status_file.write('|Tensorflow Version|v{}|\n\n'.format(tf.__version__))
|
|
|
|
# display the table legend
|
|
status_file.write('Notes:\n')
|
|
status_file.write('* Values that are new or updated from a ')
|
|
status_file.write('previous opset version are in bold.\n')
|
|
status_file.write('* -: not defined in corresponding ONNX ')
|
|
status_file.write('opset version\n')
|
|
status_file.write('* \*: the operator is deprecated\n')
|
|
status_file.write('* :small_red_triangle:: not supported yet\n')
|
|
status_file.write('* :small_orange_diamond:: partially supported\n')
|
|
status_file.write('* the rest are all supported\n\n')
|
|
|
|
# get oll onnx ops
|
|
onnx_ops = {}
|
|
for schema in onnx.defs.get_all_schemas():
|
|
if schema.domain == '': # only get onnx ops
|
|
onnx_ops[schema.name] = {
|
|
'versions': [],
|
|
'deprecated': schema.since_version if schema.deprecated else -1
|
|
}
|
|
for schema in onnx.defs.get_all_schemas_with_history():
|
|
if schema.domain == '': # only get onnx ops
|
|
op = onnx_ops[schema.name]
|
|
if schema.deprecated:
|
|
if schema.since_version <= op['deprecated']:
|
|
op['versions'].append(schema.since_version)
|
|
op['deprecated'] = schema.since_version
|
|
else:
|
|
op['versions'].append(schema.since_version)
|
|
|
|
# get all onnx-tf supported ops
|
|
onnx_tf_ops = opset_version.backend_opset_version
|
|
onnx_tf_ops_ps = opset_version.backend_partial_support
|
|
|
|
# get the cureent opset version
|
|
current_opset = onnx.defs.onnx_opset_version()
|
|
|
|
# setup table header
|
|
status_file.write('|||')
|
|
for i in range(current_opset):
|
|
status_file.write('|')
|
|
status_file.write('\n|:-:|:-:|')
|
|
for i in range(current_opset):
|
|
status_file.write(':-:|')
|
|
status_file.write('\n|**ONNX Operator**|')
|
|
for opset in range(1, current_opset + 1):
|
|
status_file.write('**Opset {}**|'.format(opset))
|
|
status_file.write('**ONNX Operator**|')
|
|
|
|
ops_count = len(onnx_ops)
|
|
# fill in data for the table
|
|
for key, val in sorted(onnx_ops.items()):
|
|
try:
|
|
status_file.write('\n|{}|'.format(key))
|
|
i = 0
|
|
vers = val['versions']
|
|
deprecated = val['deprecated']
|
|
for opset in range(1, current_opset + 1):
|
|
if i <= len(vers) - 1:
|
|
lb = vers[i]
|
|
ub = vers[i + 1] if i < len(vers) - 1 else vers[i]
|
|
if opset < lb:
|
|
if i == 0:
|
|
status_file.write('-')
|
|
elif opset == lb:
|
|
status_file.write('**{}**'.format(lb))
|
|
if lb >= deprecated and deprecated > 0:
|
|
status_file.write('\*')
|
|
elif lb not in onnx_tf_ops[key]:
|
|
status_file.write(':small_red_triangle:')
|
|
if opset == current_opset:
|
|
ops_count -= 1
|
|
elif key in onnx_tf_ops_ps:
|
|
status_file.write(':small_orange_diamond:')
|
|
else: # opset > lb
|
|
if opset < ub:
|
|
status_file.write('{}'.format(lb))
|
|
if lb >= deprecated and deprecated > 0:
|
|
status_file.write('\*')
|
|
elif lb not in onnx_tf_ops[key]:
|
|
status_file.write(':small_red_triangle:')
|
|
if opset == current_opset:
|
|
ops_count -= 1
|
|
elif key in onnx_tf_ops_ps:
|
|
status_file.write(':small_orange_diamond:')
|
|
elif opset == ub:
|
|
status_file.write('**{}**'.format(ub))
|
|
if ub >= deprecated and deprecated > 0:
|
|
status_file.write('\*')
|
|
elif ub not in onnx_tf_ops[key]:
|
|
status_file.write(':small_red_triangle:')
|
|
if opset == current_opset:
|
|
ops_count -= 1
|
|
elif key in onnx_tf_ops_ps:
|
|
status_file.write(':small_orange_diamond:')
|
|
i += 1
|
|
else: #opset > ub
|
|
status_file.write('{}'.format(ub))
|
|
if ub >= deprecated and deprecated > 0:
|
|
status_file.write('\*')
|
|
elif ub not in onnx_tf_ops[key]:
|
|
status_file.write(':small_red_triangle:')
|
|
if opset == current_opset:
|
|
ops_count -= 1
|
|
elif key in onnx_tf_ops_ps:
|
|
status_file.write(':small_orange_diamond:')
|
|
status_file.write('|')
|
|
status_file.write('{}|'.format(key))
|
|
except:
|
|
# ops defined in onnx but not in opset_version.backend_opset_versionn
|
|
status_file.write(':small_red_triangle:|')
|
|
|
|
status_file.write(
|
|
'\n\nONNX-TF Supported Operators / ONNX Operators: {} / {}'.format(
|
|
ops_count, len(onnx_ops)))
|
|
|
|
# display partial support footnote
|
|
status_file.write('\n\nNotes:\n')
|
|
index = 1
|
|
for key in onnx_tf_ops_ps:
|
|
status_file.write(
|
|
str(index) + '. ' + key + ': ' + onnx_tf_ops_ps[key] + '\n')
|
|
index += 1
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main(sys.argv[1:])
|