Browse code

replace 'install-miniver' script with 'miniver' with command 'install' (#19)

Joseph Weston authored on 17/10/2019 19:21:51 • GitHub committed on 17/10/2019 19:21:51
Showing 1 changed files
1 1
deleted file mode 100755
... ...
@@ -1,190 +0,0 @@
1
-#!/usr/bin/env python3
2
-# This file is part of 'miniver': https://github.com/jbweston/miniver
3
-
4
-import sys
5
-import os
6
-import os.path
7
-import argparse
8
-import tempfile
9
-import shutil
10
-import textwrap
11
-from zipfile import ZipFile
12
-from importlib.util import find_spec
13
-from urllib.request import urlretrieve
14
-
15
-if sys.version_info < (3, 5):
16
-    print("Miniver needs at least Python 3.5")
17
-    sys.exit(1)
18
-
19
-try:
20
-    import miniver
21
-
22
-    _miniver_version = miniver.__version__
23
-    del miniver
24
-    _miniver_is_installed = True
25
-except ImportError:
26
-    _miniver_version = "unknown"
27
-    _miniver_is_installed = False
28
-
29
-# When we fetch miniver from local files
30
-_miniver_modules = ("_version",)
31
-
32
-
33
-# When we fetch miniver from GitHub
34
-_miniver_zip_url = "https://github.com/jbweston/miniver/archive/master.zip"
35
-_zipfile_root = "miniver-master"  # tied to the fact that we fetch master.zip
36
-
37
-# File templates
38
-_setup_template = textwrap.dedent(
39
-    '''
40
-    def get_version_and_cmdclass(package_path):
41
-        """Load version.py module without importing the whole package.
42
-
43
-        Template code from miniver
44
-        """
45
-        import os
46
-        from importlib.util import module_from_spec, spec_from_file_location
47
-        spec = spec_from_file_location('version',
48
-                                       os.path.join(package_path, '_version.py'))
49
-        module = module_from_spec(spec)
50
-        spec.loader.exec_module(module)
51
-        return module.__version__, module.cmdclass
52
-
53
-
54
-    version, cmdclass = get_version_and_cmdclass('{package_dir}')
55
-
56
-    setup(
57
-        ...,
58
-        version=version,
59
-        cmdclass=cmdclass,
60
-    )
61
-'''
62
-)
63
-
64
-_static_version_template = textwrap.dedent(
65
-    """\
66
-    # -*- coding: utf-8 -*-
67
-    # This file is part of 'miniver': https://github.com/jbweston/miniver
68
-    #
69
-    # This file will be overwritten by setup.py when a source or binary
70
-    # distribution is made.  The magic value "__use_git__" is interpreted by
71
-    # version.py.
72
-
73
-    version = "__use_git__"
74
-
75
-    # These values are only set if the distribution was created with 'git archive'
76
-    refnames = "$Format:%D$"
77
-    git_hash = "$Format:%h$"
78
-"""
79
-)
80
-
81
-_init_template = "from ._version import __version__"
82
-_gitattribute_template = "{package_dir}/_static_version.py export-subst"
83
-
84
-
85
-def _line_in_file(to_find, filename):
86
-    """Return True if the specified line exists in the named file."""
87
-    assert "\n" not in to_find
88
-    try:
89
-        with open(filename) as f:
90
-            for line in f:
91
-                if to_find in line:
92
-                    return True
93
-            return False
94
-    except FileNotFoundError:
95
-        return False
96
-
97
-
98
-def _write_line(content, filename):
99
-    assert "\n" not in content
100
-    if not _line_in_file(content, filename):
101
-        with open(filename, "a") as f:
102
-            f.write(content)
103
-
104
-
105
-def _write_content(content, filename):
106
-    with open(filename, "w") as f:
107
-        f.write(content)
108
-
109
-
110
-def _fail(msg):
111
-    print(msg, file=sys.stderr)
112
-    print("Miniver was not installed", file=sys.stderr)
113
-    sys.exit(1)
114
-
115
-
116
-def extract_miniver_from_github():
117
-    filename, _ = urlretrieve(_miniver_zip_url)
118
-    z = ZipFile(filename)
119
-    tmpdir = tempfile.mkdtemp()
120
-    input_paths = [
121
-        "/".join((_zipfile_root, "miniver", module + ".py"))
122
-        for module in _miniver_modules
123
-    ]
124
-    for p in input_paths:
125
-        z.extract(p, path=tmpdir)
126
-    return [os.path.join(tmpdir, *p.split()) for p in input_paths]
127
-
128
-
129
-def extract_miniver_from_local():
130
-    return [
131
-        find_spec("." + module, package="miniver").origin for module in _miniver_modules
132
-    ]
133
-
134
-
135
-def get_args():
136
-    parser = argparse.ArgumentParser(
137
-        description="Install 'miniver' into the current Python package"
138
-    )
139
-    parser.add_argument("-v", "--version", action="version", version=_miniver_version)
140
-    parser.add_argument(
141
-        "package_directory", help="Directory to install 'miniver' into."
142
-    )
143
-    return parser.parse_args().package_directory
144
-
145
-
146
-def main():
147
-    package_dir = get_args()
148
-    if not os.path.isdir(package_dir):
149
-        _fail("Directory '{}' does not exist".format(package_dir))
150
-    if package_dir != os.path.relpath(package_dir):
151
-        _fail("'{}' is not a relative directory".format(package_dir))
152
-
153
-    # Get miniver files
154
-    if _miniver_is_installed:
155
-        miniver_paths = extract_miniver_from_local()
156
-    else:
157
-        miniver_paths = extract_miniver_from_github()
158
-    output_paths = [
159
-        os.path.join(package_dir, os.path.basename(path)) for path in miniver_paths
160
-    ]
161
-
162
-    for path in output_paths:
163
-        if os.path.exists(path):
164
-            _fail("'{}' already exists".format(path))
165
-
166
-    # Write content to local package directory
167
-    for path, output_path in zip(miniver_paths, output_paths):
168
-        shutil.copy(path, output_path)
169
-    _write_content(
170
-        _static_version_template, os.path.join(package_dir, "_static_version.py")
171
-    )
172
-    _write_line(
173
-        _gitattribute_template.format(package_dir=package_dir), ".gitattributes"
174
-    )
175
-    _write_line(
176
-        _init_template.format(package_dir=package_dir),
177
-        os.path.join(package_dir, "__init__.py"),
178
-    )
179
-
180
-    msg = "\n".join(
181
-        textwrap.wrap(
182
-            "Miniver is installed into '{package_dir}/'. "
183
-            "You still have to copy the following snippet into your 'setup.py':"
184
-        )
185
-    )
186
-    print("\n".join((msg, _setup_template)).format(package_dir=package_dir))
187
-
188
-
189
-if __name__ == "__main__":
190
-    main()
Browse code

run black code formatter on the "install-miniver" script

Joseph Weston authored on 17/10/2019 18:07:05
Showing 1 changed files
... ...
@@ -13,28 +13,30 @@ from importlib.util import find_spec
13 13
 from urllib.request import urlretrieve
14 14
 
15 15
 if sys.version_info < (3, 5):
16
-    print('Miniver needs at least Python 3.5')
16
+    print("Miniver needs at least Python 3.5")
17 17
     sys.exit(1)
18 18
 
19 19
 try:
20 20
     import miniver
21
+
21 22
     _miniver_version = miniver.__version__
22 23
     del miniver
23 24
     _miniver_is_installed = True
24 25
 except ImportError:
25
-    _miniver_version = 'unknown'
26
+    _miniver_version = "unknown"
26 27
     _miniver_is_installed = False
27 28
 
28 29
 # When we fetch miniver from local files
29
-_miniver_modules = ('_version',)
30
+_miniver_modules = ("_version",)
30 31
 
31 32
 
32 33
 # When we fetch miniver from GitHub
33
-_miniver_zip_url = 'https://github.com/jbweston/miniver/archive/master.zip'
34
-_zipfile_root = 'miniver-master'  # tied to the fact that we fetch master.zip
34
+_miniver_zip_url = "https://github.com/jbweston/miniver/archive/master.zip"
35
+_zipfile_root = "miniver-master"  # tied to the fact that we fetch master.zip
35 36
 
36 37
 # File templates
37
-_setup_template = textwrap.dedent('''
38
+_setup_template = textwrap.dedent(
39
+    '''
38 40
     def get_version_and_cmdclass(package_path):
39 41
         """Load version.py module without importing the whole package.
40 42
 
... ...
@@ -56,9 +58,11 @@ _setup_template = textwrap.dedent('''
56 58
         version=version,
57 59
         cmdclass=cmdclass,
58 60
     )
59
-''')
61
+'''
62
+)
60 63
 
61
-_static_version_template = textwrap.dedent('''\
64
+_static_version_template = textwrap.dedent(
65
+    """\
62 66
     # -*- coding: utf-8 -*-
63 67
     # This file is part of 'miniver': https://github.com/jbweston/miniver
64 68
     #
... ...
@@ -71,15 +75,16 @@ _static_version_template = textwrap.dedent('''\
71 75
     # These values are only set if the distribution was created with 'git archive'
72 76
     refnames = "$Format:%D$"
73 77
     git_hash = "$Format:%h$"
74
-''')
78
+"""
79
+)
75 80
 
76
-_init_template = 'from ._version import __version__'
77
-_gitattribute_template = '{package_dir}/_static_version.py export-subst'
81
+_init_template = "from ._version import __version__"
82
+_gitattribute_template = "{package_dir}/_static_version.py export-subst"
78 83
 
79 84
 
80 85
 def _line_in_file(to_find, filename):
81 86
     """Return True if the specified line exists in the named file."""
82
-    assert '\n' not in to_find
87
+    assert "\n" not in to_find
83 88
     try:
84 89
         with open(filename) as f:
85 90
             for line in f:
... ...
@@ -91,20 +96,20 @@ def _line_in_file(to_find, filename):
91 96
 
92 97
 
93 98
 def _write_line(content, filename):
94
-    assert '\n' not in content
99
+    assert "\n" not in content
95 100
     if not _line_in_file(content, filename):
96
-        with open(filename, 'a') as f:
101
+        with open(filename, "a") as f:
97 102
             f.write(content)
98 103
 
99 104
 
100 105
 def _write_content(content, filename):
101
-    with open(filename, 'w') as f:
106
+    with open(filename, "w") as f:
102 107
         f.write(content)
103 108
 
104 109
 
105 110
 def _fail(msg):
106 111
     print(msg, file=sys.stderr)
107
-    print('Miniver was not installed', file=sys.stderr)
112
+    print("Miniver was not installed", file=sys.stderr)
108 113
     sys.exit(1)
109 114
 
110 115
 
... ...
@@ -112,25 +117,29 @@ def extract_miniver_from_github():
112 117
     filename, _ = urlretrieve(_miniver_zip_url)
113 118
     z = ZipFile(filename)
114 119
     tmpdir = tempfile.mkdtemp()
115
-    input_paths = ['/'.join((_zipfile_root, 'miniver', module+'.py'))
116
-                   for module in _miniver_modules]
120
+    input_paths = [
121
+        "/".join((_zipfile_root, "miniver", module + ".py"))
122
+        for module in _miniver_modules
123
+    ]
117 124
     for p in input_paths:
118 125
         z.extract(p, path=tmpdir)
119 126
     return [os.path.join(tmpdir, *p.split()) for p in input_paths]
120 127
 
121 128
 
122 129
 def extract_miniver_from_local():
123
-    return [find_spec('.' + module, package='miniver').origin
124
-            for module in _miniver_modules]
130
+    return [
131
+        find_spec("." + module, package="miniver").origin for module in _miniver_modules
132
+    ]
125 133
 
126 134
 
127 135
 def get_args():
128 136
     parser = argparse.ArgumentParser(
129
-        description="Install 'miniver' into the current Python package")
130
-    parser.add_argument("-v", "--version", action="version",
131
-                        version=_miniver_version)
132
-    parser.add_argument('package_directory',
133
-                        help="Directory to install 'miniver' into.")
137
+        description="Install 'miniver' into the current Python package"
138
+    )
139
+    parser.add_argument("-v", "--version", action="version", version=_miniver_version)
140
+    parser.add_argument(
141
+        "package_directory", help="Directory to install 'miniver' into."
142
+    )
134 143
     return parser.parse_args().package_directory
135 144
 
136 145
 
... ...
@@ -146,8 +155,9 @@ def main():
146 155
         miniver_paths = extract_miniver_from_local()
147 156
     else:
148 157
         miniver_paths = extract_miniver_from_github()
149
-    output_paths = [os.path.join(package_dir, os.path.basename(path))
150
-                    for path in miniver_paths]
158
+    output_paths = [
159
+        os.path.join(package_dir, os.path.basename(path)) for path in miniver_paths
160
+    ]
151 161
 
152 162
     for path in output_paths:
153 163
         if os.path.exists(path):
... ...
@@ -156,19 +166,25 @@ def main():
156 166
     # Write content to local package directory
157 167
     for path, output_path in zip(miniver_paths, output_paths):
158 168
         shutil.copy(path, output_path)
159
-    _write_content(_static_version_template,
160
-                   os.path.join(package_dir, '_static_version.py'))
161
-    _write_line(_gitattribute_template.format(package_dir=package_dir),
162
-                '.gitattributes')
163
-    _write_line(_init_template.format(package_dir=package_dir),
164
-                os.path.join(package_dir, '__init__.py'))
169
+    _write_content(
170
+        _static_version_template, os.path.join(package_dir, "_static_version.py")
171
+    )
172
+    _write_line(
173
+        _gitattribute_template.format(package_dir=package_dir), ".gitattributes"
174
+    )
175
+    _write_line(
176
+        _init_template.format(package_dir=package_dir),
177
+        os.path.join(package_dir, "__init__.py"),
178
+    )
165 179
 
166
-    msg = '\n'.join(textwrap.wrap(
167
-        "Miniver is installed into '{package_dir}/'. "
168
-        "You still have to copy the following snippet into your 'setup.py':"
169
-    ))
170
-    print('\n'.join((msg, _setup_template)).format(package_dir=package_dir))
180
+    msg = "\n".join(
181
+        textwrap.wrap(
182
+            "Miniver is installed into '{package_dir}/'. "
183
+            "You still have to copy the following snippet into your 'setup.py':"
184
+        )
185
+    )
186
+    print("\n".join((msg, _setup_template)).format(package_dir=package_dir))
171 187
 
172 188
 
173
-if __name__ == '__main__':
189
+if __name__ == "__main__":
174 190
     main()
Browse code

use textwrap.dedent to make code copy pastable.

Mark Harfouche authored on 16/02/2019 17:45:31
Showing 1 changed files
... ...
@@ -34,9 +34,12 @@ _miniver_zip_url = 'https://github.com/jbweston/miniver/archive/master.zip'
34 34
 _zipfile_root = 'miniver-master'  # tied to the fact that we fetch master.zip
35 35
 
36 36
 # File templates
37
-_setup_template = '''
38
-    # Loads version.py module without importing the whole package.
37
+_setup_template = textwrap.dedent('''
39 38
     def get_version_and_cmdclass(package_path):
39
+        """Load version.py module without importing the whole package.
40
+
41
+        Template code from miniver
42
+        """
40 43
         import os
41 44
         from importlib.util import module_from_spec, spec_from_file_location
42 45
         spec = spec_from_file_location('version',
... ...
@@ -53,7 +56,7 @@ _setup_template = '''
53 56
         version=version,
54 57
         cmdclass=cmdclass,
55 58
     )
56
-'''
59
+''')
57 60
 
58 61
 _static_version_template = textwrap.dedent('''\
59 62
     # -*- coding: utf-8 -*-
Browse code

define _miniver_version even when it is not installed

Fixes #8.

Joseph Weston authored on 06/08/2018 09:53:22
Showing 1 changed files
... ...
@@ -22,6 +22,7 @@ try:
22 22
     del miniver
23 23
     _miniver_is_installed = True
24 24
 except ImportError:
25
+    _miniver_version = 'unknown'
25 26
     _miniver_is_installed = False
26 27
 
27 28
 # When we fetch miniver from local files
Browse code

add --version flag to the install-miniver script

Joseph Weston authored on 21/06/2018 22:30:14
Showing 1 changed files
... ...
@@ -18,6 +18,7 @@ if sys.version_info < (3, 5):
18 18
 
19 19
 try:
20 20
     import miniver
21
+    _miniver_version = miniver.__version__
21 22
     del miniver
22 23
     _miniver_is_installed = True
23 24
 except ImportError:
... ...
@@ -122,6 +123,8 @@ def extract_miniver_from_local():
122 123
 def get_args():
123 124
     parser = argparse.ArgumentParser(
124 125
         description="Install 'miniver' into the current Python package")
126
+    parser.add_argument("-v", "--version", action="version",
127
+                        version=_miniver_version)
125 128
     parser.add_argument('package_directory',
126 129
                         help="Directory to install 'miniver' into.")
127 130
     return parser.parse_args().package_directory
Browse code

add template for _static_version.py to install-miniver script

This is necessary, as when miniver is installed locally, the
installed _static_version.py has its version string set to the
miniver version.

Closes #4.

Joseph Weston authored on 21/06/2018 22:21:35
Showing 1 changed files
... ...
@@ -24,7 +24,7 @@ except ImportError:
24 24
     _miniver_is_installed = False
25 25
 
26 26
 # When we fetch miniver from local files
27
-_miniver_modules = ('_version', '_static_version')
27
+_miniver_modules = ('_version',)
28 28
 
29 29
 
30 30
 # When we fetch miniver from GitHub
... ...
@@ -53,6 +53,21 @@ _setup_template = '''
53 53
     )
54 54
 '''
55 55
 
56
+_static_version_template = textwrap.dedent('''\
57
+    # -*- coding: utf-8 -*-
58
+    # This file is part of 'miniver': https://github.com/jbweston/miniver
59
+    #
60
+    # This file will be overwritten by setup.py when a source or binary
61
+    # distribution is made.  The magic value "__use_git__" is interpreted by
62
+    # version.py.
63
+
64
+    version = "__use_git__"
65
+
66
+    # These values are only set if the distribution was created with 'git archive'
67
+    refnames = "$Format:%D$"
68
+    git_hash = "$Format:%h$"
69
+''')
70
+
56 71
 _init_template = 'from ._version import __version__'
57 72
 _gitattribute_template = '{package_dir}/_static_version.py export-subst'
58 73
 
... ...
@@ -77,6 +92,11 @@ def _write_line(content, filename):
77 92
             f.write(content)
78 93
 
79 94
 
95
+def _write_content(content, filename):
96
+    with open(filename, 'w') as f:
97
+        f.write(content)
98
+
99
+
80 100
 def _fail(msg):
81 101
     print(msg, file=sys.stderr)
82 102
     print('Miniver was not installed', file=sys.stderr)
... ...
@@ -129,6 +149,8 @@ def main():
129 149
     # Write content to local package directory
130 150
     for path, output_path in zip(miniver_paths, output_paths):
131 151
         shutil.copy(path, output_path)
152
+    _write_content(_static_version_template,
153
+                   os.path.join(package_dir, '_static_version.py'))
132 154
     _write_line(_gitattribute_template.format(package_dir=package_dir),
133 155
                 '.gitattributes')
134 156
     _write_line(_init_template.format(package_dir=package_dir),
Browse code

clarify stance on Python 2 support

Joseph Weston authored on 07/03/2018 15:01:23
Showing 1 changed files
... ...
@@ -12,6 +12,10 @@ from zipfile import ZipFile
12 12
 from importlib.util import find_spec
13 13
 from urllib.request import urlretrieve
14 14
 
15
+if sys.version_info < (3, 5):
16
+    print('Miniver needs at least Python 3.5')
17
+    sys.exit(1)
18
+
15 19
 try:
16 20
     import miniver
17 21
     del miniver
Browse code

add 'install-miniver' script

Also update README and setup.py to accomodate it.

Joseph Weston authored on 26/02/2018 23:54:00
Showing 1 changed files
1 1
new file mode 100755
... ...
@@ -0,0 +1,141 @@
1
+#!/usr/bin/env python3
2
+# This file is part of 'miniver': https://github.com/jbweston/miniver
3
+
4
+import sys
5
+import os
6
+import os.path
7
+import argparse
8
+import tempfile
9
+import shutil
10
+import textwrap
11
+from zipfile import ZipFile
12
+from importlib.util import find_spec
13
+from urllib.request import urlretrieve
14
+
15
+try:
16
+    import miniver
17
+    del miniver
18
+    _miniver_is_installed = True
19
+except ImportError:
20
+    _miniver_is_installed = False
21
+
22
+# When we fetch miniver from local files
23
+_miniver_modules = ('_version', '_static_version')
24
+
25
+
26
+# When we fetch miniver from GitHub
27
+_miniver_zip_url = 'https://github.com/jbweston/miniver/archive/master.zip'
28
+_zipfile_root = 'miniver-master'  # tied to the fact that we fetch master.zip
29
+
30
+# File templates
31
+_setup_template = '''
32
+    # Loads version.py module without importing the whole package.
33
+    def get_version_and_cmdclass(package_path):
34
+        import os
35
+        from importlib.util import module_from_spec, spec_from_file_location
36
+        spec = spec_from_file_location('version',
37
+                                       os.path.join(package_path, '_version.py'))
38
+        module = module_from_spec(spec)
39
+        spec.loader.exec_module(module)
40
+        return module.__version__, module.cmdclass
41
+
42
+
43
+    version, cmdclass = get_version_and_cmdclass('{package_dir}')
44
+
45
+    setup(
46
+        ...,
47
+        version=version,
48
+        cmdclass=cmdclass,
49
+    )
50
+'''
51
+
52
+_init_template = 'from ._version import __version__'
53
+_gitattribute_template = '{package_dir}/_static_version.py export-subst'
54
+
55
+
56
+def _line_in_file(to_find, filename):
57
+    """Return True if the specified line exists in the named file."""
58
+    assert '\n' not in to_find
59
+    try:
60
+        with open(filename) as f:
61
+            for line in f:
62
+                if to_find in line:
63
+                    return True
64
+            return False
65
+    except FileNotFoundError:
66
+        return False
67
+
68
+
69
+def _write_line(content, filename):
70
+    assert '\n' not in content
71
+    if not _line_in_file(content, filename):
72
+        with open(filename, 'a') as f:
73
+            f.write(content)
74
+
75
+
76
+def _fail(msg):
77
+    print(msg, file=sys.stderr)
78
+    print('Miniver was not installed', file=sys.stderr)
79
+    sys.exit(1)
80
+
81
+
82
+def extract_miniver_from_github():
83
+    filename, _ = urlretrieve(_miniver_zip_url)
84
+    z = ZipFile(filename)
85
+    tmpdir = tempfile.mkdtemp()
86
+    input_paths = ['/'.join((_zipfile_root, 'miniver', module+'.py'))
87
+                   for module in _miniver_modules]
88
+    for p in input_paths:
89
+        z.extract(p, path=tmpdir)
90
+    return [os.path.join(tmpdir, *p.split()) for p in input_paths]
91
+
92
+
93
+def extract_miniver_from_local():
94
+    return [find_spec('.' + module, package='miniver').origin
95
+            for module in _miniver_modules]
96
+
97
+
98
+def get_args():
99
+    parser = argparse.ArgumentParser(
100
+        description="Install 'miniver' into the current Python package")
101
+    parser.add_argument('package_directory',
102
+                        help="Directory to install 'miniver' into.")
103
+    return parser.parse_args().package_directory
104
+
105
+
106
+def main():
107
+    package_dir = get_args()
108
+    if not os.path.isdir(package_dir):
109
+        _fail("Directory '{}' does not exist".format(package_dir))
110
+    if package_dir != os.path.relpath(package_dir):
111
+        _fail("'{}' is not a relative directory".format(package_dir))
112
+
113
+    # Get miniver files
114
+    if _miniver_is_installed:
115
+        miniver_paths = extract_miniver_from_local()
116
+    else:
117
+        miniver_paths = extract_miniver_from_github()
118
+    output_paths = [os.path.join(package_dir, os.path.basename(path))
119
+                    for path in miniver_paths]
120
+
121
+    for path in output_paths:
122
+        if os.path.exists(path):
123
+            _fail("'{}' already exists".format(path))
124
+
125
+    # Write content to local package directory
126
+    for path, output_path in zip(miniver_paths, output_paths):
127
+        shutil.copy(path, output_path)
128
+    _write_line(_gitattribute_template.format(package_dir=package_dir),
129
+                '.gitattributes')
130
+    _write_line(_init_template.format(package_dir=package_dir),
131
+                os.path.join(package_dir, '__init__.py'))
132
+
133
+    msg = '\n'.join(textwrap.wrap(
134
+        "Miniver is installed into '{package_dir}/'. "
135
+        "You still have to copy the following snippet into your 'setup.py':"
136
+    ))
137
+    print('\n'.join((msg, _setup_template)).format(package_dir=package_dir))
138
+
139
+
140
+if __name__ == '__main__':
141
+    main()