more structure
This commit is contained in:
parent
1a2bd4507b
commit
f2ef8bf393
28
autocmake/http.py
Normal file
28
autocmake/http.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
def fetch_url(src, dst):
|
||||||
|
"""
|
||||||
|
Fetch file from URL src and save it to dst.
|
||||||
|
"""
|
||||||
|
# we do not use the nicer sys.version_info.major
|
||||||
|
# for compatibility with Python < 2.7
|
||||||
|
if sys.version_info[0] > 2:
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
class URLopener(urllib.request.FancyURLopener):
|
||||||
|
def http_error_default(self, url, fp, errcode, errmsg, headers):
|
||||||
|
sys.stderr.write("ERROR: could not fetch {0}\n".format(url))
|
||||||
|
sys.exit(-1)
|
||||||
|
else:
|
||||||
|
import urllib
|
||||||
|
|
||||||
|
class URLopener(urllib.FancyURLopener):
|
||||||
|
def http_error_default(self, url, fp, errcode, errmsg, headers):
|
||||||
|
sys.stderr.write("ERROR: could not fetch {0}\n".format(url))
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
dirname = os.path.dirname(dst)
|
||||||
|
if dirname != '':
|
||||||
|
if not os.path.isdir(dirname):
|
||||||
|
os.makedirs(dirname)
|
||||||
|
|
||||||
|
opener = URLopener()
|
||||||
|
opener.retrieve(src, dst)
|
47
autocmake/interpolate.py
Normal file
47
autocmake/interpolate.py
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
def replace(s, d):
|
||||||
|
from re import findall
|
||||||
|
if isinstance(s, str):
|
||||||
|
for var in findall(r"%\(([A-Za-z0-9_]*)\)", s):
|
||||||
|
s = s.replace("%({})".format(var), str(d[var]))
|
||||||
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def test_replace():
|
||||||
|
assert replace('hey %(foo) ho %(bar)',
|
||||||
|
{'foo': 'hey', 'bar': 'ho'}) == 'hey hey ho ho'
|
||||||
|
|
||||||
|
|
||||||
|
def interpolate(d, d_map):
|
||||||
|
from collections import Mapping, Iterable
|
||||||
|
from copy import copy
|
||||||
|
for k, v in d.items():
|
||||||
|
if isinstance(v, Mapping):
|
||||||
|
d[k] = interpolate(d[k], d_map)
|
||||||
|
elif isinstance(v, Iterable) and not isinstance(v, str):
|
||||||
|
l = []
|
||||||
|
for x in v:
|
||||||
|
if isinstance(x, Mapping):
|
||||||
|
l.append(interpolate(x, d_map))
|
||||||
|
else:
|
||||||
|
l.append(replace(x, d_map))
|
||||||
|
d[k] = copy(l)
|
||||||
|
else:
|
||||||
|
d[k] = replace(d[k], d_map)
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def test_interpolate():
|
||||||
|
d = {'foo': 'hey',
|
||||||
|
'bar': 'ho',
|
||||||
|
'one': 'hey %(foo) ho %(bar)',
|
||||||
|
'two': {'one': 'hey %(foo) ho %(bar)',
|
||||||
|
'two': 'raboof'}}
|
||||||
|
d_interpolated = {'foo': 'hey',
|
||||||
|
'bar': 'ho',
|
||||||
|
'one': 'hey hey ho ho',
|
||||||
|
'two': {'one': 'hey hey ho ho',
|
||||||
|
'two': 'raboof'}}
|
||||||
|
assert interpolate(d, d) == d_interpolated
|
||||||
|
d2 = {'modules': [{'fc': [{'source': '%(url_root)fc_optional.cmake'}]}], 'url_root': 'downloaded/downloaded_'}
|
||||||
|
d2_interpolated = {'modules': [{'fc': [{'source': 'downloaded/downloaded_fc_optional.cmake'}]}], 'url_root': 'downloaded/downloaded_'}
|
||||||
|
assert interpolate(d2, d2) == d2_interpolated
|
133
autocmake/parse_rst.py
Normal file
133
autocmake/parse_rst.py
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
def parse_cmake_module(s_in, override={}):
|
||||||
|
import sys
|
||||||
|
from collections import Mapping, Iterable, defaultdict
|
||||||
|
from autocmake.parse_yaml import parse_yaml
|
||||||
|
|
||||||
|
# we do not use the nicer sys.version_info.major
|
||||||
|
# for compatibility with Python < 2.7
|
||||||
|
if sys.version_info[0] > 2:
|
||||||
|
from io import StringIO
|
||||||
|
else:
|
||||||
|
from StringIO import StringIO
|
||||||
|
|
||||||
|
parsed_config = defaultdict(lambda: None)
|
||||||
|
|
||||||
|
if 'autocmake.yml configuration::' not in s_in:
|
||||||
|
return parsed_config
|
||||||
|
|
||||||
|
s_out = []
|
||||||
|
is_rst_line = False
|
||||||
|
for line in s_in.split('\n'):
|
||||||
|
if is_rst_line:
|
||||||
|
if len(line) > 0:
|
||||||
|
if line[0] != '#':
|
||||||
|
is_rst_line = False
|
||||||
|
else:
|
||||||
|
is_rst_line = False
|
||||||
|
if is_rst_line:
|
||||||
|
s_out.append(line[2:])
|
||||||
|
if '#.rst:' in line:
|
||||||
|
is_rst_line = True
|
||||||
|
|
||||||
|
autocmake_entry = '\n'.join(s_out).split('autocmake.yml configuration::')[1]
|
||||||
|
autocmake_entry = autocmake_entry.replace('\n ', '\n')
|
||||||
|
|
||||||
|
buf = StringIO(autocmake_entry)
|
||||||
|
config = parse_yaml(buf, override)
|
||||||
|
|
||||||
|
for k, v in config.items():
|
||||||
|
if isinstance(v, Iterable) and not isinstance(v, str):
|
||||||
|
parsed_config[k] = [x for x in config[k]]
|
||||||
|
else:
|
||||||
|
parsed_config[k] = [config[k]]
|
||||||
|
|
||||||
|
return parsed_config
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse_cmake_module():
|
||||||
|
|
||||||
|
s = r'''#.rst:
|
||||||
|
#
|
||||||
|
# Foo ...
|
||||||
|
#
|
||||||
|
# autocmake.yml configuration::
|
||||||
|
#
|
||||||
|
# docopt:
|
||||||
|
# - "--cxx=<CXX> C++ compiler [default: g++]."
|
||||||
|
# - "--extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: '']."
|
||||||
|
# export: "'CXX={0}'.format(arguments['--cxx'])"
|
||||||
|
# define: "'-DEXTRA_CXXFLAGS=\"{0}\"'.format(arguments['--extra-cxx-flags'])"
|
||||||
|
|
||||||
|
enable_language(CXX)
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_C_COMPILER_ID)
|
||||||
|
message(FATAL_ERROR "CMAKE_C_COMPILER_ID variable is not defined!")
|
||||||
|
endif()'''
|
||||||
|
|
||||||
|
parsed_config = parse_cmake_module(s)
|
||||||
|
assert parsed_config['docopt'] == ["--cxx=<CXX> C++ compiler [default: g++].", "--extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: '']."]
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse_cmake_module_no_key():
|
||||||
|
|
||||||
|
s = '''#.rst:
|
||||||
|
#
|
||||||
|
# Foo ...
|
||||||
|
#
|
||||||
|
# Bar ...
|
||||||
|
|
||||||
|
enable_language(CXX)
|
||||||
|
|
||||||
|
if(NOT DEFINED CMAKE_C_COMPILER_ID)
|
||||||
|
message(FATAL_ERROR "CMAKE_C_COMPILER_ID variable is not defined!")
|
||||||
|
endif()'''
|
||||||
|
|
||||||
|
parsed_config = parse_cmake_module(s)
|
||||||
|
assert parsed_config['docopt'] is None
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse_cmake_module_interpolate():
|
||||||
|
|
||||||
|
s = r'''#.rst:
|
||||||
|
#
|
||||||
|
# Foo ...
|
||||||
|
#
|
||||||
|
# autocmake.yml configuration::
|
||||||
|
#
|
||||||
|
# major: 1
|
||||||
|
# minor: 2
|
||||||
|
# patch: 3
|
||||||
|
# a: v%(major)
|
||||||
|
# b: v%(minor)
|
||||||
|
# c: v%(patch)
|
||||||
|
|
||||||
|
enable_language(CXX)'''
|
||||||
|
|
||||||
|
parsed_config = parse_cmake_module(s)
|
||||||
|
assert parsed_config['a'] == ['v1']
|
||||||
|
assert parsed_config['b'] == ['v2']
|
||||||
|
assert parsed_config['c'] == ['v3']
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse_cmake_module_override():
|
||||||
|
|
||||||
|
s = r'''#.rst:
|
||||||
|
#
|
||||||
|
# Foo ...
|
||||||
|
#
|
||||||
|
# autocmake.yml configuration::
|
||||||
|
#
|
||||||
|
# major: 1
|
||||||
|
# minor: 2
|
||||||
|
# patch: 3
|
||||||
|
# a: v%(major)
|
||||||
|
# b: v%(minor)
|
||||||
|
# c: v%(patch)
|
||||||
|
|
||||||
|
enable_language(CXX)'''
|
||||||
|
|
||||||
|
d = {'minor': 4}
|
||||||
|
parsed_config = parse_cmake_module(s, d)
|
||||||
|
assert parsed_config['a'] == ['v1']
|
||||||
|
assert parsed_config['b'] == ['v4']
|
||||||
|
assert parsed_config['c'] == ['v3']
|
16
autocmake/parse_yaml.py
Normal file
16
autocmake/parse_yaml.py
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
def parse_yaml(stream, override={}):
|
||||||
|
import yaml
|
||||||
|
from autocmake.interpolate import interpolate
|
||||||
|
|
||||||
|
try:
|
||||||
|
config = yaml.load(stream, yaml.SafeLoader)
|
||||||
|
except yaml.YAMLError as exc:
|
||||||
|
print(exc)
|
||||||
|
sys.exit(-1)
|
||||||
|
|
||||||
|
for k in config:
|
||||||
|
if k in override:
|
||||||
|
config[k] = override[k]
|
||||||
|
|
||||||
|
config = interpolate(config, config)
|
||||||
|
return config
|
242
update.py
242
update.py
@ -8,119 +8,12 @@ import collections
|
|||||||
|
|
||||||
__version__ = 'X.Y.Z'
|
__version__ = 'X.Y.Z'
|
||||||
|
|
||||||
# we do not use the nicer sys.version_info.major
|
|
||||||
# for compatibility with Python < 2.7
|
|
||||||
if sys.version_info[0] > 2:
|
|
||||||
from io import StringIO
|
|
||||||
import urllib.request
|
|
||||||
|
|
||||||
class URLopener(urllib.request.FancyURLopener):
|
|
||||||
def http_error_default(self, url, fp, errcode, errmsg, headers):
|
|
||||||
sys.stderr.write("ERROR: could not fetch {0}\n".format(url))
|
|
||||||
sys.exit(-1)
|
|
||||||
else:
|
|
||||||
from StringIO import StringIO
|
|
||||||
import urllib
|
|
||||||
|
|
||||||
class URLopener(urllib.FancyURLopener):
|
|
||||||
def http_error_default(self, url, fp, errcode, errmsg, headers):
|
|
||||||
sys.stderr.write("ERROR: could not fetch {0}\n".format(url))
|
|
||||||
sys.exit(-1)
|
|
||||||
|
|
||||||
|
|
||||||
AUTOCMAKE_GITHUB_URL = 'https://github.com/coderefinery/autocmake/raw/yaml/'
|
AUTOCMAKE_GITHUB_URL = 'https://github.com/coderefinery/autocmake/raw/yaml/'
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
def replace(s, d):
|
|
||||||
from re import findall
|
|
||||||
if isinstance(s, str):
|
|
||||||
for var in findall(r"%\(([A-Za-z0-9_]*)\)", s):
|
|
||||||
s = s.replace("%({})".format(var), str(d[var]))
|
|
||||||
return s
|
|
||||||
|
|
||||||
|
|
||||||
def test_replace():
|
|
||||||
assert replace('hey %(foo) ho %(bar)',
|
|
||||||
{'foo': 'hey', 'bar': 'ho'}) == 'hey hey ho ho'
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
def interpolate(d, d_map):
|
|
||||||
from collections import Mapping, Iterable
|
|
||||||
from copy import copy
|
|
||||||
for k, v in d.items():
|
|
||||||
if isinstance(v, Mapping):
|
|
||||||
d[k] = interpolate(d[k], d_map)
|
|
||||||
elif isinstance(v, Iterable) and not isinstance(v, str):
|
|
||||||
l = []
|
|
||||||
for x in v:
|
|
||||||
if isinstance(x, Mapping):
|
|
||||||
l.append(interpolate(x, d_map))
|
|
||||||
else:
|
|
||||||
l.append(replace(x, d_map))
|
|
||||||
d[k] = copy(l)
|
|
||||||
else:
|
|
||||||
d[k] = replace(d[k], d_map)
|
|
||||||
return d
|
|
||||||
|
|
||||||
|
|
||||||
def test_interpolate():
|
|
||||||
d = {'foo': 'hey',
|
|
||||||
'bar': 'ho',
|
|
||||||
'one': 'hey %(foo) ho %(bar)',
|
|
||||||
'two': {'one': 'hey %(foo) ho %(bar)',
|
|
||||||
'two': 'raboof'}}
|
|
||||||
d_interpolated = {'foo': 'hey',
|
|
||||||
'bar': 'ho',
|
|
||||||
'one': 'hey hey ho ho',
|
|
||||||
'two': {'one': 'hey hey ho ho',
|
|
||||||
'two': 'raboof'}}
|
|
||||||
assert interpolate(d, d) == d_interpolated
|
|
||||||
d2 = {'modules': [{'fc': [{'source': '%(url_root)fc_optional.cmake'}]}], 'url_root': 'downloaded/downloaded_'}
|
|
||||||
d2_interpolated = {'modules': [{'fc': [{'source': 'downloaded/downloaded_fc_optional.cmake'}]}], 'url_root': 'downloaded/downloaded_'}
|
|
||||||
assert interpolate(d2, d2) == d2_interpolated
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
def fetch_url(src, dst):
|
|
||||||
"""
|
|
||||||
Fetch file from URL src and save it to dst.
|
|
||||||
"""
|
|
||||||
dirname = os.path.dirname(dst)
|
|
||||||
if dirname != '':
|
|
||||||
if not os.path.isdir(dirname):
|
|
||||||
os.makedirs(dirname)
|
|
||||||
|
|
||||||
opener = URLopener()
|
|
||||||
opener.retrieve(src, dst)
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
def parse_yaml(stream, override={}):
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
try:
|
|
||||||
config = yaml.load(stream, yaml.SafeLoader)
|
|
||||||
except yaml.YAMLError as exc:
|
|
||||||
print(exc)
|
|
||||||
sys.exit(-1)
|
|
||||||
|
|
||||||
for k in config:
|
|
||||||
if k in override:
|
|
||||||
config[k] = override[k]
|
|
||||||
|
|
||||||
config = interpolate(config, config)
|
|
||||||
return config
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
def print_progress_bar(text, done, total, width):
|
def print_progress_bar(text, done, total, width):
|
||||||
"""
|
"""
|
||||||
Print progress bar.
|
Print progress bar.
|
||||||
@ -349,6 +242,7 @@ def fetch_modules(config, relative_path):
|
|||||||
be included in CMakeLists.txt.
|
be included in CMakeLists.txt.
|
||||||
"""
|
"""
|
||||||
from collections import Iterable
|
from collections import Iterable
|
||||||
|
from autocmake.http import fetch_url
|
||||||
|
|
||||||
download_directory = 'downloaded'
|
download_directory = 'downloaded'
|
||||||
if not os.path.exists(download_directory):
|
if not os.path.exists(download_directory):
|
||||||
@ -431,6 +325,9 @@ def main(argv):
|
|||||||
"""
|
"""
|
||||||
Main function.
|
Main function.
|
||||||
"""
|
"""
|
||||||
|
from autocmake.parse_yaml import parse_yaml
|
||||||
|
from autocmake.http import fetch_url
|
||||||
|
|
||||||
if len(argv) != 2:
|
if len(argv) != 2:
|
||||||
sys.stderr.write("\nYou can update a project in two steps.\n\n")
|
sys.stderr.write("\nYou can update a project in two steps.\n\n")
|
||||||
sys.stderr.write("Step 1: Update or create infrastructure files\n")
|
sys.stderr.write("Step 1: Update or create infrastructure files\n")
|
||||||
@ -464,6 +361,7 @@ def main(argv):
|
|||||||
for f in ['autocmake/configure.py',
|
for f in ['autocmake/configure.py',
|
||||||
'autocmake/external/docopt.py',
|
'autocmake/external/docopt.py',
|
||||||
'autocmake/__init__.py',
|
'autocmake/__init__.py',
|
||||||
|
'autocmake/interpolate.py',
|
||||||
'update.py']:
|
'update.py']:
|
||||||
print('- fetching {0}'.format(f))
|
print('- fetching {0}'.format(f))
|
||||||
fetch_url(
|
fetch_url(
|
||||||
@ -535,135 +433,5 @@ def make_executable(path):
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
def parse_cmake_module(s_in, override={}):
|
|
||||||
from collections import Mapping, Iterable
|
|
||||||
|
|
||||||
parsed_config = collections.defaultdict(lambda: None)
|
|
||||||
|
|
||||||
if 'autocmake.yml configuration::' not in s_in:
|
|
||||||
return parsed_config
|
|
||||||
|
|
||||||
s_out = []
|
|
||||||
is_rst_line = False
|
|
||||||
for line in s_in.split('\n'):
|
|
||||||
if is_rst_line:
|
|
||||||
if len(line) > 0:
|
|
||||||
if line[0] != '#':
|
|
||||||
is_rst_line = False
|
|
||||||
else:
|
|
||||||
is_rst_line = False
|
|
||||||
if is_rst_line:
|
|
||||||
s_out.append(line[2:])
|
|
||||||
if '#.rst:' in line:
|
|
||||||
is_rst_line = True
|
|
||||||
|
|
||||||
autocmake_entry = '\n'.join(s_out).split('autocmake.yml configuration::')[1]
|
|
||||||
autocmake_entry = autocmake_entry.replace('\n ', '\n')
|
|
||||||
|
|
||||||
buf = StringIO(autocmake_entry)
|
|
||||||
config = parse_yaml(buf, override)
|
|
||||||
|
|
||||||
for k, v in config.items():
|
|
||||||
if isinstance(v, Iterable) and not isinstance(v, str):
|
|
||||||
parsed_config[k] = [x for x in config[k]]
|
|
||||||
else:
|
|
||||||
parsed_config[k] = [config[k]]
|
|
||||||
|
|
||||||
return parsed_config
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
def test_parse_cmake_module():
|
|
||||||
|
|
||||||
s = r'''#.rst:
|
|
||||||
#
|
|
||||||
# Foo ...
|
|
||||||
#
|
|
||||||
# autocmake.yml configuration::
|
|
||||||
#
|
|
||||||
# docopt:
|
|
||||||
# - "--cxx=<CXX> C++ compiler [default: g++]."
|
|
||||||
# - "--extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: '']."
|
|
||||||
# export: "'CXX={0}'.format(arguments['--cxx'])"
|
|
||||||
# define: "'-DEXTRA_CXXFLAGS=\"{0}\"'.format(arguments['--extra-cxx-flags'])"
|
|
||||||
|
|
||||||
enable_language(CXX)
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_C_COMPILER_ID)
|
|
||||||
message(FATAL_ERROR "CMAKE_C_COMPILER_ID variable is not defined!")
|
|
||||||
endif()'''
|
|
||||||
|
|
||||||
parsed_config = parse_cmake_module(s)
|
|
||||||
assert parsed_config['docopt'] == ["--cxx=<CXX> C++ compiler [default: g++].", "--extra-cxx-flags=<EXTRA_CXXFLAGS> Extra C++ compiler flags [default: '']."]
|
|
||||||
|
|
||||||
|
|
||||||
def test_parse_cmake_module_no_key():
|
|
||||||
|
|
||||||
s = '''#.rst:
|
|
||||||
#
|
|
||||||
# Foo ...
|
|
||||||
#
|
|
||||||
# Bar ...
|
|
||||||
|
|
||||||
enable_language(CXX)
|
|
||||||
|
|
||||||
if(NOT DEFINED CMAKE_C_COMPILER_ID)
|
|
||||||
message(FATAL_ERROR "CMAKE_C_COMPILER_ID variable is not defined!")
|
|
||||||
endif()'''
|
|
||||||
|
|
||||||
parsed_config = parse_cmake_module(s)
|
|
||||||
assert parsed_config['docopt'] is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_parse_cmake_module_interpolate():
|
|
||||||
|
|
||||||
s = r'''#.rst:
|
|
||||||
#
|
|
||||||
# Foo ...
|
|
||||||
#
|
|
||||||
# autocmake.yml configuration::
|
|
||||||
#
|
|
||||||
# major: 1
|
|
||||||
# minor: 2
|
|
||||||
# patch: 3
|
|
||||||
# a: v%(major)
|
|
||||||
# b: v%(minor)
|
|
||||||
# c: v%(patch)
|
|
||||||
|
|
||||||
enable_language(CXX)'''
|
|
||||||
|
|
||||||
parsed_config = parse_cmake_module(s)
|
|
||||||
assert parsed_config['a'] == ['v1']
|
|
||||||
assert parsed_config['b'] == ['v2']
|
|
||||||
assert parsed_config['c'] == ['v3']
|
|
||||||
|
|
||||||
|
|
||||||
def test_parse_cmake_module_override():
|
|
||||||
|
|
||||||
s = r'''#.rst:
|
|
||||||
#
|
|
||||||
# Foo ...
|
|
||||||
#
|
|
||||||
# autocmake.yml configuration::
|
|
||||||
#
|
|
||||||
# major: 1
|
|
||||||
# minor: 2
|
|
||||||
# patch: 3
|
|
||||||
# a: v%(major)
|
|
||||||
# b: v%(minor)
|
|
||||||
# c: v%(patch)
|
|
||||||
|
|
||||||
enable_language(CXX)'''
|
|
||||||
|
|
||||||
d = {'minor': 4}
|
|
||||||
parsed_config = parse_cmake_module(s, d)
|
|
||||||
assert parsed_config['a'] == ['v1']
|
|
||||||
assert parsed_config['b'] == ['v4']
|
|
||||||
assert parsed_config['c'] == ['v3']
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main(sys.argv)
|
main(sys.argv)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user