mirror of
https://git.rtems.org/rtems-source-builder
synced 2024-10-09 07:15:10 +08:00
sb: Align the version processing with rtems-tools.
- Use the same VERSION file format as rtems-tools so a common release generation can be used. - The version.py is almost the same as rtems-tools. There are some minor differences, one is the RTEMS version is present in this file while rtems-tool uses config/rtems-release.ini. Updates #3822
This commit is contained in:
@@ -244,7 +244,7 @@ def run(args):
|
|||||||
del os.environ['ACLOCAL_PATH']
|
del os.environ['ACLOCAL_PATH']
|
||||||
optargs = { '--rtems': 'The RTEMS source directory',
|
optargs = { '--rtems': 'The RTEMS source directory',
|
||||||
'--preinstall': 'Preinstall AM generation' }
|
'--preinstall': 'Preinstall AM generation' }
|
||||||
log.notice('RTEMS Source Builder - RTEMS Bootstrap, %s' % (version.str()))
|
log.notice('RTEMS Source Builder - RTEMS Bootstrap, %s' % (version.string()))
|
||||||
opts = options.load(sys.argv, optargs, logfile = False)
|
opts = options.load(sys.argv, optargs, logfile = False)
|
||||||
if opts.get_arg('--rtems'):
|
if opts.get_arg('--rtems'):
|
||||||
topdir = opts.get_arg('--rtems')
|
topdir = opts.get_arg('--rtems')
|
||||||
|
@@ -672,7 +672,7 @@ def run(args):
|
|||||||
try:
|
try:
|
||||||
optargs = { '--list-configs': 'List available configurations' }
|
optargs = { '--list-configs': 'List available configurations' }
|
||||||
opts = options.load(args, optargs)
|
opts = options.load(args, optargs)
|
||||||
log.notice('RTEMS Source Builder, Package Builder, %s' % (version.str()))
|
log.notice('RTEMS Source Builder, Package Builder, %s' % (version.string()))
|
||||||
opts.log_info()
|
opts.log_info()
|
||||||
if not check.host_setup(opts):
|
if not check.host_setup(opts):
|
||||||
if not opts.force():
|
if not opts.force():
|
||||||
|
@@ -264,7 +264,7 @@ def run():
|
|||||||
import sys
|
import sys
|
||||||
try:
|
try:
|
||||||
_opts = options.load(args = sys.argv, logfile = False)
|
_opts = options.load(args = sys.argv, logfile = False)
|
||||||
log.notice('RTEMS Source Builder - Check, %s' % (version.str()))
|
log.notice('RTEMS Source Builder - Check, %s' % (version.string()))
|
||||||
|
|
||||||
orphans = _opts.parse_args('--check-orphans', error = False, extra = False)
|
orphans = _opts.parse_args('--check-orphans', error = False, extra = False)
|
||||||
if orphans:
|
if orphans:
|
||||||
|
@@ -625,7 +625,7 @@ def run(args = sys.argv):
|
|||||||
argopts = argsp.parse_args(args[2:])
|
argopts = argsp.parse_args(args[2:])
|
||||||
|
|
||||||
load_log(argopts.log)
|
load_log(argopts.log)
|
||||||
log.notice('RTEMS Source Builder - Get Sources, %s' % (version.str()))
|
log.notice('RTEMS Source Builder - Get Sources, %s' % (version.string()))
|
||||||
log.tracing = argopts.trace
|
log.tracing = argopts.trace
|
||||||
|
|
||||||
opts = load_options(args, argopts)
|
opts = load_options(args, argopts)
|
||||||
|
@@ -30,12 +30,14 @@ import re
|
|||||||
import os
|
import os
|
||||||
import string
|
import string
|
||||||
|
|
||||||
|
import download
|
||||||
import error
|
import error
|
||||||
import execute
|
import execute
|
||||||
import git
|
import git
|
||||||
import log
|
import log
|
||||||
import macros
|
import macros
|
||||||
import path
|
import path
|
||||||
|
import sources
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import version
|
import version
|
||||||
@@ -361,7 +363,7 @@ class command_line:
|
|||||||
def sb_released(self):
|
def sb_released(self):
|
||||||
if version.released():
|
if version.released():
|
||||||
self.defaults['rsb_released'] = '1'
|
self.defaults['rsb_released'] = '1'
|
||||||
self.defaults['rsb_version'] = version.str()
|
self.defaults['rsb_version'] = version.string()
|
||||||
|
|
||||||
def sb_git(self):
|
def sb_git(self):
|
||||||
repo = git.repo(self.defaults.expand('%{_sbdir}'), self)
|
repo = git.repo(self.defaults.expand('%{_sbdir}'), self)
|
||||||
@@ -599,7 +601,7 @@ class command_line:
|
|||||||
self.args.append('--with-tools=%s' % (rtems_tools[1]))
|
self.args.append('--with-tools=%s' % (rtems_tools[1]))
|
||||||
rtems_version = self.parse_args('--rtems-version')
|
rtems_version = self.parse_args('--rtems-version')
|
||||||
if rtems_version is None:
|
if rtems_version is None:
|
||||||
rtems_version = version.version()
|
rtems_version = str(version.version())
|
||||||
else:
|
else:
|
||||||
rtems_version = rtems_version[1]
|
rtems_version = rtems_version[1]
|
||||||
self.defaults['rtems_version'] = rtems_version
|
self.defaults['rtems_version'] = rtems_version
|
||||||
@@ -701,14 +703,28 @@ def load(args, optargs = None, defaults = '%{_sbdir}/defaults.mc', logfile = Tru
|
|||||||
#
|
#
|
||||||
# Load the release settings
|
# Load the release settings
|
||||||
#
|
#
|
||||||
version.load_release_settings(o.defaults)
|
def setting_error(msg):
|
||||||
|
raise error.general(msg)
|
||||||
|
hashes = version.load_release_settings('hashes', error = setting_error)
|
||||||
|
for hash in hashes:
|
||||||
|
hs = hash[1].split()
|
||||||
|
if len(hs) != 2:
|
||||||
|
raise error.general('invalid release hash in VERSION')
|
||||||
|
sources.hash((hs[0], hash[0], hs[1]), o.defaults, setting_error)
|
||||||
|
release_path = version.load_release_setting('version', 'release_path',
|
||||||
|
raw = True, error = setting_error)
|
||||||
|
if release_path is not None:
|
||||||
|
try:
|
||||||
|
release_path = ','.join([rp.strip() for rp in release_path.split(',')])
|
||||||
|
except:
|
||||||
|
raise error.general('invalid release path in VERSION')
|
||||||
|
download.set_release_path(release_path, o.defaults)
|
||||||
return o
|
return o
|
||||||
|
|
||||||
def run(args):
|
def run(args):
|
||||||
try:
|
try:
|
||||||
_opts = load(args = args, defaults = 'defaults.mc')
|
_opts = load(args = args, defaults = 'defaults.mc')
|
||||||
log.notice('RTEMS Source Builder - Defaults, %s' % (version.str()))
|
log.notice('RTEMS Source Builder - Defaults, %s' % (version.string()))
|
||||||
_opts.log_info()
|
_opts.log_info()
|
||||||
log.notice('Options:')
|
log.notice('Options:')
|
||||||
log.notice(str(_opts))
|
log.notice(str(_opts))
|
||||||
|
@@ -645,7 +645,7 @@ class report:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def release_status(self):
|
def release_status(self):
|
||||||
self.formatter.release_status(version.str())
|
self.formatter.release_status(version.string())
|
||||||
|
|
||||||
def git_status(self):
|
def git_status(self):
|
||||||
r = git.repo('.', self.opts, self.macros)
|
r = git.repo('.', self.opts, self.macros)
|
||||||
@@ -896,7 +896,7 @@ def run(args):
|
|||||||
opts = options.load(args, optargs, logfile = False)
|
opts = options.load(args, optargs, logfile = False)
|
||||||
if opts.get_arg('--output') and len(opts.params()) > 1:
|
if opts.get_arg('--output') and len(opts.params()) > 1:
|
||||||
raise error.general('--output can only be used with a single config')
|
raise error.general('--output can only be used with a single config')
|
||||||
print('RTEMS Source Builder, Reporter, %s' % (version.str()))
|
print('RTEMS Source Builder, Reporter, %s' % (version.string()))
|
||||||
opts.log_info()
|
opts.log_info()
|
||||||
if not check.host_setup(opts):
|
if not check.host_setup(opts):
|
||||||
log.warning('forcing build with known host setup problems')
|
log.warning('forcing build with known host setup problems')
|
||||||
|
@@ -193,7 +193,7 @@ def run(args):
|
|||||||
bsp = bsp_config(opts, prefix, opts.get_arg('--rtems-bsp')[1])
|
bsp = bsp_config(opts, prefix, opts.get_arg('--rtems-bsp')[1])
|
||||||
|
|
||||||
if opts.get_arg('--list'):
|
if opts.get_arg('--list'):
|
||||||
log.notice('RTEMS Source Builder - RTEMS Configuration, %s' % (version.str()))
|
log.notice('RTEMS Source Builder - RTEMS Configuration, %s' % (version.string()))
|
||||||
opts.log_info()
|
opts.log_info()
|
||||||
configs = list(bsp.keys())
|
configs = list(bsp.keys())
|
||||||
for c in sorted(configs.keys()):
|
for c in sorted(configs.keys()):
|
||||||
|
@@ -698,7 +698,7 @@ def run():
|
|||||||
else:
|
else:
|
||||||
mail['to'] = macro_expand(opts.defaults, '%{_mail_tools_to}')
|
mail['to'] = macro_expand(opts.defaults, '%{_mail_tools_to}')
|
||||||
mail['from'] = mail['mail'].from_address()
|
mail['from'] = mail['mail'].from_address()
|
||||||
log.notice('RTEMS Source Builder - Set Builder, %s' % (version.str()))
|
log.notice('RTEMS Source Builder - Set Builder, %s' % (version.string()))
|
||||||
opts.log_info()
|
opts.log_info()
|
||||||
if not check.host_setup(opts):
|
if not check.host_setup(opts):
|
||||||
raise error.general('host build environment is not set up correctly')
|
raise error.general('host build environment is not set up correctly')
|
||||||
|
@@ -1,36 +1,84 @@
|
|||||||
#
|
#
|
||||||
# RTEMS Tools Project (http://www.rtems.org/)
|
# RTEMS Tools Project (http://www.rtems.org/)
|
||||||
# Copyright 2010-2016 Chris Johns (chrisj@rtems.org)
|
# Copyright 2010-2018 Chris Johns (chrisj@rtems.org)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
# This file is part of the RTEMS Tools package in 'rtems-tools'.
|
# This file is part of the RTEMS Tools package in 'rtems-tools'.
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for any
|
# Redistribution and use in source and binary forms, with or without
|
||||||
# purpose with or without fee is hereby granted, provided that the above
|
# modification, are permitted provided that the following conditions are met:
|
||||||
# copyright notice and this permission notice appear in all copies.
|
#
|
||||||
|
# 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer.
|
||||||
|
#
|
||||||
|
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
# this list of conditions and the following disclaimer in the documentation
|
||||||
|
# and/or other materials provided with the distribution.
|
||||||
|
#
|
||||||
|
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
# POSSIBILITY OF SUCH DAMAGE.
|
||||||
#
|
#
|
||||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
||||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
||||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
||||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
||||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
||||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
||||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# To release the RSB create a git archive and then add a suitable VERSION file
|
# Releasing RTEMS Tools
|
||||||
# to the top directory.
|
# ---------------------
|
||||||
|
#
|
||||||
|
# Format:
|
||||||
|
#
|
||||||
|
# The format is INI. The file requires a `[version`] section and a `revision`
|
||||||
|
# option:
|
||||||
|
#
|
||||||
|
# [version]
|
||||||
|
# revision = <version-string>
|
||||||
|
#
|
||||||
|
# The `<version-string>` has the `version` and `revision` delimited by a
|
||||||
|
# single `.`. An example file is:
|
||||||
|
#
|
||||||
|
# [version]
|
||||||
|
# revision = 5.0.not_released
|
||||||
|
#
|
||||||
|
# where the `version` is `5` and the revision is `0` and the package is not
|
||||||
|
# released. The label `not_released` is reversed to mean the package is not
|
||||||
|
# released. A revision string can contain extra characters after the
|
||||||
|
# `revision` number for example `5.0-rc1` or is deploying a package
|
||||||
|
# `5.0-nasa-cfs`
|
||||||
|
#
|
||||||
|
# Packages can optionally add specialised sections to a version configuration
|
||||||
|
# files. These can be accessed via the:
|
||||||
|
#
|
||||||
|
# load_release_settings: Return the items in a section
|
||||||
|
# load_release_setting: Return an item from a section
|
||||||
|
#
|
||||||
|
# User deployment:
|
||||||
|
#
|
||||||
|
# Create a git archive and then add a suitable VERSION file to the top
|
||||||
|
# directory of the package. The package assumes your python executable is
|
||||||
|
# location in `bin` directory which is one below the top of the package's
|
||||||
|
# install prefix.
|
||||||
|
#
|
||||||
|
# Notes:
|
||||||
|
#
|
||||||
|
# This module uses os.apth for paths and assumes all paths are in the host
|
||||||
|
# format.
|
||||||
#
|
#
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
import download
|
|
||||||
import error
|
import error
|
||||||
import git
|
import git
|
||||||
import path
|
import path
|
||||||
import sources
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Default to an internal string.
|
# Default to an internal string.
|
||||||
@@ -40,6 +88,7 @@ _revision = 'not_released'
|
|||||||
_version_str = '%s.%s' % (_version, _revision)
|
_version_str = '%s.%s' % (_version, _revision)
|
||||||
_released = False
|
_released = False
|
||||||
_git = False
|
_git = False
|
||||||
|
_is_loaded = False
|
||||||
|
|
||||||
def _top():
|
def _top():
|
||||||
top = path.dirname(sys.argv[0])
|
top = path.dirname(sys.argv[0])
|
||||||
@@ -48,84 +97,147 @@ def _top():
|
|||||||
return top
|
return top
|
||||||
|
|
||||||
def _load_released_version_config():
|
def _load_released_version_config():
|
||||||
|
'''Local worker to load a configuration file.'''
|
||||||
top = _top()
|
top = _top()
|
||||||
for ver in [top, '..']:
|
for ver in [path.join(top, 'VERSION'),
|
||||||
if path.exists(path.join(ver, 'VERSION')):
|
path.join('..', 'VERSION')]:
|
||||||
|
if path.exists(path.join(ver)):
|
||||||
try:
|
try:
|
||||||
import configparser
|
import configparser
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import ConfigParser as configparser
|
import ConfigParser as configparser
|
||||||
v = configparser.SafeConfigParser()
|
v = configparser.SafeConfigParser()
|
||||||
try:
|
try:
|
||||||
v.read(path.join(ver, 'VERSION'))
|
v.read(path.host(ver))
|
||||||
except:
|
except Exception as e:
|
||||||
raise error.general('Invalid VERSION file')
|
raise error.general('Invalid version config format: %s: %s' % (ver,
|
||||||
return v
|
e))
|
||||||
return None
|
return ver, v
|
||||||
|
return None, None
|
||||||
|
|
||||||
def _load_released_version():
|
def _load_released_version():
|
||||||
|
'''Load the release data if present. If not found the package is not released.
|
||||||
|
|
||||||
|
A release can be made by adding a file called `VERSION` to the top level
|
||||||
|
directory of a package. This is useful for user deploying a package and
|
||||||
|
making custom releases.
|
||||||
|
|
||||||
|
The RTEMS project reserves the `rtems-version.ini` file for it's
|
||||||
|
releases. This is the base release and should not be touched by users
|
||||||
|
deploying a package.
|
||||||
|
|
||||||
|
'''
|
||||||
|
global _version
|
||||||
|
global _revision
|
||||||
global _released
|
global _released
|
||||||
global _version_str
|
global _version_str
|
||||||
v = _load_released_version_config()
|
global _is_loaded
|
||||||
if v is not None:
|
|
||||||
try:
|
if not _is_loaded:
|
||||||
_version_str = v.get('version', 'release')
|
vc, v = _load_released_version_config()
|
||||||
except:
|
if v is not None:
|
||||||
raise error.general('Invalid VERSION file')
|
try:
|
||||||
_released = True
|
ver_str = v.get('version', 'revision')
|
||||||
|
except Exception as e:
|
||||||
|
raise error.general('Invalid version file: %s: %s' % (vc, e))
|
||||||
|
ver_split = ver_str.split('.', 1)
|
||||||
|
if len(ver_split) < 2:
|
||||||
|
raise error.general('Invalid version release value: %s: %s' % (vc,
|
||||||
|
ver_str))
|
||||||
|
ver = ver_split[0]
|
||||||
|
rev = ver_split[1]
|
||||||
|
try:
|
||||||
|
_version = int(ver)
|
||||||
|
except:
|
||||||
|
raise error.general('Invalid version config value: %s: %s' % (vc,
|
||||||
|
ver))
|
||||||
|
_revision = rev
|
||||||
|
if 'not_released' not in ver:
|
||||||
|
_released = True
|
||||||
|
_version_str = ver_str
|
||||||
|
_is_loaded = True
|
||||||
return _released
|
return _released
|
||||||
|
|
||||||
def _load_git_version():
|
def _load_git_version():
|
||||||
|
global _version
|
||||||
|
global _revision
|
||||||
global _git
|
global _git
|
||||||
global _version_str
|
global _version_str
|
||||||
repo = git.repo(_top())
|
global _is_loaded
|
||||||
if repo.valid():
|
|
||||||
head = repo.head()
|
if not _is_loaded:
|
||||||
if repo.dirty():
|
repo = git.repo(_top())
|
||||||
modified = ' modified'
|
if repo.valid():
|
||||||
else:
|
head = repo.head()
|
||||||
modified = ''
|
if repo.dirty():
|
||||||
_version_str = '%s (%s%s)' % (_version, head[0:12], modified)
|
modified = 'modified'
|
||||||
_git = True
|
revision_sep = '-'
|
||||||
|
sep = ' '
|
||||||
|
else:
|
||||||
|
modified = ''
|
||||||
|
revision_sep = ''
|
||||||
|
sep = ''
|
||||||
|
_revision = '%s%s%s' % (head[0:12], revision_sep, modified)
|
||||||
|
_version_str = '%s (%s%s%s)' % (_version, head[0:12], sep, modified)
|
||||||
|
_git = True
|
||||||
|
_is_loaded = True
|
||||||
return _git
|
return _git
|
||||||
|
|
||||||
|
def load_release_settings(section, error = False):
|
||||||
|
vc, v = _load_released_version_config()
|
||||||
|
items = []
|
||||||
|
if v is not None:
|
||||||
|
try:
|
||||||
|
items = v.items(section)
|
||||||
|
except Exception as e:
|
||||||
|
if not isinstance(error, bool):
|
||||||
|
error(e)
|
||||||
|
elif error:
|
||||||
|
raise error.general('Invalid config section: %s: %s: %s' % (vc,
|
||||||
|
section,
|
||||||
|
e))
|
||||||
|
return items
|
||||||
|
|
||||||
|
def load_release_setting(section, option, raw = False, error = False):
|
||||||
|
vc, v = _load_released_version_config()
|
||||||
|
value = None
|
||||||
|
if v is not None:
|
||||||
|
try:
|
||||||
|
value = v.get(section, option, raw = raw)
|
||||||
|
except Exception as e:
|
||||||
|
if not isinstance(error, bool):
|
||||||
|
error(e)
|
||||||
|
elif error:
|
||||||
|
raise error.general('Invalid config section: %s: %s: %s.%s' % (vc,
|
||||||
|
section,
|
||||||
|
option,
|
||||||
|
e))
|
||||||
|
return value
|
||||||
|
|
||||||
def released():
|
def released():
|
||||||
return _load_released_version()
|
return _load_released_version()
|
||||||
|
|
||||||
def version_control():
|
def version_control():
|
||||||
return _load_git_version()
|
return _load_git_version()
|
||||||
|
|
||||||
def str():
|
def string():
|
||||||
if not _released and not _git:
|
_load_released_version()
|
||||||
if not _load_released_version():
|
_load_git_version()
|
||||||
_load_git_version()
|
|
||||||
return _version_str
|
return _version_str
|
||||||
|
|
||||||
def load_release_settings(macros):
|
|
||||||
def setting_error(msg):
|
|
||||||
raise error.general(msg)
|
|
||||||
|
|
||||||
if released():
|
|
||||||
v = _load_released_version_config()
|
|
||||||
if v is not None:
|
|
||||||
try:
|
|
||||||
hashes = v.items('hashes')
|
|
||||||
except:
|
|
||||||
hashes = []
|
|
||||||
for hash in hashes:
|
|
||||||
hs = hash[1].split()
|
|
||||||
if len(hs) != 2:
|
|
||||||
raise error.general('invalid release hash in VERSION')
|
|
||||||
sources.hash((hs[0], hash[0], hs[1]), macros, setting_error)
|
|
||||||
try:
|
|
||||||
release_path = v.get('version', 'release_path', raw = True)
|
|
||||||
release_path = ','.join([rp.strip() for rp in release_path.split(',')])
|
|
||||||
except:
|
|
||||||
release_path = None
|
|
||||||
download.set_release_path(release_path, macros)
|
|
||||||
|
|
||||||
def version():
|
def version():
|
||||||
|
_load_released_version()
|
||||||
|
_load_git_version()
|
||||||
return _version
|
return _version
|
||||||
|
|
||||||
|
def revision():
|
||||||
|
_load_released_version()
|
||||||
|
_load_git_version()
|
||||||
|
return _revision
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print('Version: %s' % (str()))
|
print('Version: %s' % (str(version())))
|
||||||
|
print('Revision: %s' % (str(revision())))
|
||||||
|
print('String: %s' % (string()))
|
||||||
|
if version() == 'undefined':
|
||||||
|
raise Exception('version is undefined')
|
||||||
|
Reference in New Issue
Block a user