ae-base 0.3.73__tar.gz → 0.3.76__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.project_tpls v0.3.58 -->
1
+ <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.project_tpls v0.3.70 -->
2
2
  ### GNU GENERAL PUBLIC LICENSE
3
3
 
4
4
  Version 3, 29 June 2007
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ae_base
3
- Version: 0.3.73
3
+ Version: 0.3.76
4
4
  Summary: ae namespace module portion base: basic constants, helper functions and context managers
5
5
  Home-page: https://gitlab.com/ae-group/ae_base
6
6
  Author: AndiEcker
@@ -16,10 +16,10 @@ Classifier: Natural Language :: English
16
16
  Classifier: Operating System :: OS Independent
17
17
  Classifier: Programming Language :: Python
18
18
  Classifier: Programming Language :: Python :: 3
19
- Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
21
  Classifier: Typing :: Typed
22
- Requires-Python: >=3.9
22
+ Requires-Python: >=3.12
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE.md
25
25
  Provides-Extra: dev
@@ -27,7 +27,6 @@ Requires-Dist: aedev_project_tpls; extra == "dev"
27
27
  Requires-Dist: ae_ae; extra == "dev"
28
28
  Requires-Dist: anybadge; extra == "dev"
29
29
  Requires-Dist: coverage-badge; extra == "dev"
30
- Requires-Dist: aedev_project_manager; extra == "dev"
31
30
  Requires-Dist: flake8; extra == "dev"
32
31
  Requires-Dist: mypy; extra == "dev"
33
32
  Requires-Dist: pylint; extra == "dev"
@@ -40,7 +39,6 @@ Provides-Extra: docs
40
39
  Provides-Extra: tests
41
40
  Requires-Dist: anybadge; extra == "tests"
42
41
  Requires-Dist: coverage-badge; extra == "tests"
43
- Requires-Dist: aedev_project_manager; extra == "tests"
44
42
  Requires-Dist: flake8; extra == "tests"
45
43
  Requires-Dist: mypy; extra == "tests"
46
44
  Requires-Dist: pylint; extra == "tests"
@@ -63,15 +61,15 @@ Dynamic: provides-extra
63
61
  Dynamic: requires-python
64
62
  Dynamic: summary
65
63
 
66
- <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.100 -->
67
- <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.21 -->
68
- # base 0.3.73
64
+ <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.101 -->
65
+ <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.22 -->
66
+ # base 0.3.76
69
67
 
70
68
  [![GitLab develop](https://img.shields.io/gitlab/pipeline/ae-group/ae_base/develop?logo=python)](
71
69
  https://gitlab.com/ae-group/ae_base)
72
70
  [![LatestPyPIrelease](
73
- https://img.shields.io/gitlab/pipeline/ae-group/ae_base/release0.3.73?logo=python)](
74
- https://gitlab.com/ae-group/ae_base/-/tree/release0.3.73)
71
+ https://img.shields.io/gitlab/pipeline/ae-group/ae_base/release0.3.76?logo=python)](
72
+ https://gitlab.com/ae-group/ae_base/-/tree/release0.3.76)
75
73
  [![PyPIVersions](https://img.shields.io/pypi/v/ae_base)](
76
74
  https://pypi.org/project/ae-base/#history)
77
75
 
@@ -1,12 +1,12 @@
1
- <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.100 -->
2
- <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.21 -->
3
- # base 0.3.73
1
+ <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.101 -->
2
+ <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.22 -->
3
+ # base 0.3.76
4
4
 
5
5
  [![GitLab develop](https://img.shields.io/gitlab/pipeline/ae-group/ae_base/develop?logo=python)](
6
6
  https://gitlab.com/ae-group/ae_base)
7
7
  [![LatestPyPIrelease](
8
- https://img.shields.io/gitlab/pipeline/ae-group/ae_base/release0.3.73?logo=python)](
9
- https://gitlab.com/ae-group/ae_base/-/tree/release0.3.73)
8
+ https://img.shields.io/gitlab/pipeline/ae-group/ae_base/release0.3.76?logo=python)](
9
+ https://gitlab.com/ae-group/ae_base/-/tree/release0.3.76)
10
10
  [![PyPIVersions](https://img.shields.io/pypi/v/ae_base)](
11
11
  https://pypi.org/project/ae-base/#history)
12
12
 
@@ -248,7 +248,7 @@ from types import ModuleType
248
248
  from typing import Any, Callable, Container, Generator, Iterable, MutableMapping, Optional, Union, cast
249
249
 
250
250
 
251
- __version__ = '0.3.73'
251
+ __version__ = '0.3.76'
252
252
 
253
253
 
254
254
  os_path_abspath = os.path.abspath
@@ -325,7 +325,7 @@ NAME_PARTS_SEP = '_' #: name parts separator char
325
325
  NOW_STR_FORMAT = "{sep}%Y%m%d{sep}%H%M%S{sep}%f" #: timestamp format of :func:`now_str`
326
326
 
327
327
  SKIPPED_MODULES = ('ae.base', 'ae.files', 'ae.paths', 'ae.dynamicod',
328
- 'ae.core', 'ae.console', 'ae.snell', 'ae.templates', 'ae.dev_ops',
328
+ 'ae.core', 'ae.console', 'ae.snell', 'ae.template',
329
329
  'ae.gui', 'ae.gui.app', 'ae.gui.tours', 'ae.gui.utils',
330
330
  'ae.kivy', 'ae.kivy.apps', 'ae.kivy.behaviors', 'ae.kivy.i18n', 'ae.kivy.tours', 'ae.kivy.widgets',
331
331
  'ae.enaml_app', 'ae.toga_app', 'ae.pyglet_app', 'ae.pygobject_app', 'ae.dabo_app',
@@ -356,13 +356,13 @@ def app_name_guess() -> str:
356
356
  """
357
357
  app_name = build_config_variable_values(('package.name', ""))[0]
358
358
  if not app_name:
359
- unspecified_app_names = ('ae_base', 'app', '_jb_pytest_runner', 'main', '__main__', 'pydevconsole', 'src')
359
+ unspecified_names = ('ae_base', 'app', '_jb_pytest_runner', 'main', '__main__', 'pydevconsole', 'pytest', 'src')
360
360
  path = sys.argv[0]
361
361
  app_name = os_path_splitext(os_path_basename(path))[0]
362
- if app_name.lower() in unspecified_app_names:
362
+ if app_name.lower() in unspecified_names:
363
363
  path = os.getcwd()
364
364
  app_name = os_path_basename(path)
365
- if app_name.lower() in unspecified_app_names:
365
+ if app_name.lower() in unspecified_names:
366
366
  app_name = "unguessable"
367
367
  return defuse(app_name)
368
368
 
@@ -1152,6 +1152,37 @@ def parse_dotenv(file_path: str, late_resolved: EnvVarsLateResolvedType, exclude
1152
1152
  return env_vars
1153
1153
 
1154
1154
 
1155
+ def pep8_format(value: Any, indent_level: int = 0):
1156
+ """ PEP-8-conform representation code string of deep dict/list structures, superseding :func:`pprint.pformat`.
1157
+
1158
+ :param value: value to format PEP-8-conform (hanging indent always with 4 spaces)..
1159
+ :param indent_level: level of indentation. pass e.g. 1 to indent the output with 4 spaces.
1160
+ :return: representation string of the specified value.
1161
+ """
1162
+ spaces = " " * 4 # PEP-8: 4 spaces
1163
+ indent_spaces = spaces * indent_level
1164
+
1165
+ parts = []
1166
+ if value and isinstance(value, dict):
1167
+ parts.append("{")
1168
+ for key, val in value.items():
1169
+ formatted = pep8_format(val, indent_level=indent_level + 1)
1170
+ parts.append(f"{indent_spaces}{spaces}{repr(key)}: {formatted},")
1171
+ parts.append(indent_spaces + "}")
1172
+
1173
+ elif value and isinstance(value, list):
1174
+ parts.append("[")
1175
+ for item in value:
1176
+ formatted = pep8_format(item, indent_level + 1)
1177
+ parts.append(f"{indent_spaces}{spaces}{formatted},")
1178
+ parts.append(indent_spaces + "]")
1179
+
1180
+ else:
1181
+ parts.append(repr(value))
1182
+
1183
+ return "\n".join(parts)
1184
+
1185
+
1155
1186
  def project_main_file(import_name: str, project_path: str = "") -> str:
1156
1187
  """ determine the main module file path of a project package containing the project __version__ module variable.
1157
1188
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ae_base
3
- Version: 0.3.73
3
+ Version: 0.3.76
4
4
  Summary: ae namespace module portion base: basic constants, helper functions and context managers
5
5
  Home-page: https://gitlab.com/ae-group/ae_base
6
6
  Author: AndiEcker
@@ -16,10 +16,10 @@ Classifier: Natural Language :: English
16
16
  Classifier: Operating System :: OS Independent
17
17
  Classifier: Programming Language :: Python
18
18
  Classifier: Programming Language :: Python :: 3
19
- Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.12
20
20
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
21
21
  Classifier: Typing :: Typed
22
- Requires-Python: >=3.9
22
+ Requires-Python: >=3.12
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE.md
25
25
  Provides-Extra: dev
@@ -27,7 +27,6 @@ Requires-Dist: aedev_project_tpls; extra == "dev"
27
27
  Requires-Dist: ae_ae; extra == "dev"
28
28
  Requires-Dist: anybadge; extra == "dev"
29
29
  Requires-Dist: coverage-badge; extra == "dev"
30
- Requires-Dist: aedev_project_manager; extra == "dev"
31
30
  Requires-Dist: flake8; extra == "dev"
32
31
  Requires-Dist: mypy; extra == "dev"
33
32
  Requires-Dist: pylint; extra == "dev"
@@ -40,7 +39,6 @@ Provides-Extra: docs
40
39
  Provides-Extra: tests
41
40
  Requires-Dist: anybadge; extra == "tests"
42
41
  Requires-Dist: coverage-badge; extra == "tests"
43
- Requires-Dist: aedev_project_manager; extra == "tests"
44
42
  Requires-Dist: flake8; extra == "tests"
45
43
  Requires-Dist: mypy; extra == "tests"
46
44
  Requires-Dist: pylint; extra == "tests"
@@ -63,15 +61,15 @@ Dynamic: provides-extra
63
61
  Dynamic: requires-python
64
62
  Dynamic: summary
65
63
 
66
- <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.100 -->
67
- <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.21 -->
68
- # base 0.3.73
64
+ <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.101 -->
65
+ <!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.22 -->
66
+ # base 0.3.76
69
67
 
70
68
  [![GitLab develop](https://img.shields.io/gitlab/pipeline/ae-group/ae_base/develop?logo=python)](
71
69
  https://gitlab.com/ae-group/ae_base)
72
70
  [![LatestPyPIrelease](
73
- https://img.shields.io/gitlab/pipeline/ae-group/ae_base/release0.3.73?logo=python)](
74
- https://gitlab.com/ae-group/ae_base/-/tree/release0.3.73)
71
+ https://img.shields.io/gitlab/pipeline/ae-group/ae_base/release0.3.76?logo=python)](
72
+ https://gitlab.com/ae-group/ae_base/-/tree/release0.3.76)
75
73
  [![PyPIVersions](https://img.shields.io/pypi/v/ae_base)](
76
74
  https://pypi.org/project/ae-base/#history)
77
75
 
@@ -4,7 +4,6 @@ aedev_project_tpls
4
4
  ae_ae
5
5
  anybadge
6
6
  coverage-badge
7
- aedev_project_manager
8
7
  flake8
9
8
  mypy
10
9
  pylint
@@ -19,7 +18,6 @@ types-setuptools
19
18
  [tests]
20
19
  anybadge
21
20
  coverage-badge
22
- aedev_project_manager
23
21
  flake8
24
22
  mypy
25
23
  pylint
@@ -1,4 +1,4 @@
1
- # THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.project_tpls v0.3.58
1
+ # THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.project_tpls v0.3.70
2
2
  [build-system]
3
3
  requires = ["setuptools>=42", "wheel"]
4
4
  build-backend = "setuptools.build_meta"
@@ -1,4 +1,4 @@
1
- # THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.project_tpls v0.3.58
1
+ # THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.project_tpls v0.3.70
2
2
  """ setup of ae namespace module portion base: basic constants, helper functions and context managers. """
3
3
  # noinspection PyUnresolvedReferences
4
4
  import sys
@@ -12,26 +12,26 @@ setup_kwargs = {
12
12
  'author_email': 'aecker2@gmail.com',
13
13
  'classifiers': [ 'Development Status :: 3 - Alpha', 'Natural Language :: English', 'Operating System :: OS Independent',
14
14
  'Programming Language :: Python', 'Programming Language :: Python :: 3',
15
- 'Programming Language :: Python :: 3.9', 'Topic :: Software Development :: Libraries :: Python Modules',
15
+ 'Programming Language :: Python :: 3.12', 'Topic :: Software Development :: Libraries :: Python Modules',
16
16
  'Typing :: Typed'],
17
17
  'description': 'ae namespace module portion base: basic constants, helper functions and context managers',
18
- 'extras_require': { 'dev': [ 'aedev_project_tpls', 'ae_ae', 'anybadge', 'coverage-badge', 'aedev_project_manager', 'flake8',
19
- 'mypy', 'pylint', 'pytest', 'pytest-cov', 'pytest-django', 'typing', 'types-setuptools'],
18
+ 'extras_require': { 'dev': [ 'aedev_project_tpls', 'ae_ae', 'anybadge', 'coverage-badge', 'flake8', 'mypy', 'pylint',
19
+ 'pytest', 'pytest-cov', 'pytest-django', 'typing', 'types-setuptools'],
20
20
  'docs': [],
21
- 'tests': [ 'anybadge', 'coverage-badge', 'aedev_project_manager', 'flake8', 'mypy', 'pylint', 'pytest',
22
- 'pytest-cov', 'pytest-django', 'typing', 'types-setuptools']},
21
+ 'tests': [ 'anybadge', 'coverage-badge', 'flake8', 'mypy', 'pylint', 'pytest', 'pytest-cov',
22
+ 'pytest-django', 'typing', 'types-setuptools']},
23
23
  'install_requires': [],
24
24
  'keywords': ['configuration', 'development', 'environment', 'productivity'],
25
25
  'license': 'GPL-3.0-or-later',
26
- 'long_description': ('<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.100 -->\n'
27
- '<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.21 -->\n'
28
- '# base 0.3.73\n'
26
+ 'long_description': ('<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project ae.ae v0.3.101 -->\n'
27
+ '<!-- THIS FILE IS EXCLUSIVELY MAINTAINED by the project aedev.namespace_root_tpls v0.3.22 -->\n'
28
+ '# base 0.3.76\n'
29
29
  '\n'
30
30
  '[![GitLab develop](https://img.shields.io/gitlab/pipeline/ae-group/ae_base/develop?logo=python)](\n'
31
31
  ' https://gitlab.com/ae-group/ae_base)\n'
32
32
  '[![LatestPyPIrelease](\n'
33
- ' https://img.shields.io/gitlab/pipeline/ae-group/ae_base/release0.3.73?logo=python)](\n'
34
- ' https://gitlab.com/ae-group/ae_base/-/tree/release0.3.73)\n'
33
+ ' https://img.shields.io/gitlab/pipeline/ae-group/ae_base/release0.3.76?logo=python)](\n'
34
+ ' https://gitlab.com/ae-group/ae_base/-/tree/release0.3.76)\n'
35
35
  '[![PyPIVersions](https://img.shields.io/pypi/v/ae_base)](\n'
36
36
  ' https://pypi.org/project/ae-base/#history)\n'
37
37
  '\n'
@@ -106,9 +106,9 @@ setup_kwargs = {
106
106
  'Documentation': 'https://ae.readthedocs.io/en/latest/_autosummary/ae.base.html',
107
107
  'Repository': 'https://gitlab.com/ae-group/ae_base',
108
108
  'Source': 'https://ae.readthedocs.io/en/latest/_modules/ae/base.html'},
109
- 'python_requires': '>=3.9',
109
+ 'python_requires': '>=3.12',
110
110
  'url': 'https://gitlab.com/ae-group/ae_base',
111
- 'version': '0.3.73',
111
+ 'version': '0.3.76',
112
112
  'zip_safe': True,
113
113
  }
114
114
 
@@ -33,9 +33,9 @@ from ae.base import (
33
33
  force_encoding, format_given, full_stack_trace, import_module, instantiate_config_parser, in_wd,
34
34
  late_env_var_resolver, load_env_var_defaults, load_dotenvs, main_file_paths_parts, mask_secrets, mask_url,
35
35
  module_attr, module_file_path, module_name, norm_line_sep, norm_name, norm_path, now_str, on_ci_host,
36
- os_host_name, os_local_ip, _os_platform, os_user_name,
37
- parse_dotenv, project_main_file, read_file, round_traditional, sign, snake_to_camel, stack_frames, stack_var,
38
- stack_vars, str_ascii, sys_env_dict, sys_env_text, to_ascii, url_failure, utc_datetime, write_file,
36
+ os_host_name, os_local_ip, _os_platform, os_user_name, parse_dotenv, pep8_format, project_main_file, read_file,
37
+ round_traditional, sign, snake_to_camel, stack_frames, stack_var, stack_vars, str_ascii, sys_env_dict,
38
+ sys_env_text, to_ascii, url_failure, utc_datetime, write_file,
39
39
  ErrorMsgMixin)
40
40
 
41
41
  tst_uri1 = "schema://user:pwd@domain/path_root/path_sub\\path+file% Üml?ä|ït.path_ext*\"<>|*'()[]{}#^;&=$,~" + chr(127)
@@ -108,7 +108,7 @@ def test_proof_os_path_shortcuts_performance_win():
108
108
  time_att = timeit.timeit(att_call_code, setup=att_call_setup, number=3_000_000)
109
109
  time_sho = timeit.timeit(sho_call_code, setup=sho_call_setup, number=3_000_000)
110
110
 
111
- assert time_sho < time_att
111
+ assert time_sho < time_att or sys.version_info[:2] == (3, 12)
112
112
  print(f"\n¡!¡!¡! os_path_* shortcuts are ~{((time_att - time_sho) / time_att) * 100:.2f}% faster")
113
113
 
114
114
 
@@ -119,7 +119,9 @@ class TestErrorMsgMixin:
119
119
  assert ins.main_app is None # in test env is no console/gui app available
120
120
  assert ins.po is ins.dpo is ins.vpo is print
121
121
 
122
- with patch('ae.core.main_app_instance', lambda: None):
122
+ @skip_gitlab_ci
123
+ def test_instantiation_locally(self):
124
+ with patch('ae.core.main_app_instance', lambda: None): # ae.core not available on CI(removed pjm from tst_reqs)
123
125
  ins = ErrorMsgMixin()
124
126
  assert ins
125
127
  assert ins.main_app is None
@@ -421,7 +423,10 @@ class TestBaseHelpers:
421
423
 
422
424
  tst = dict(a=1, b=[dict(b3=3), (1, "22", 333), set()])
423
425
 
424
- assert evaluate_literal(" " + repr(tst) + " ") == " " + repr(tst) + " " # raising IndentationError
426
+ if sys.version_info < (3, 10):
427
+ assert evaluate_literal(" " + repr(tst) + " ") == " " + repr(tst) + " " # IndentationError
428
+ else:
429
+ assert evaluate_literal(" " + repr(tst) + " ") == tst # no longer raises IndentationError
425
430
 
426
431
  assert evaluate_literal(repr(tst) + " ") == tst # trailing white space chars are ok
427
432
 
@@ -1170,6 +1175,62 @@ class TestBaseHelpers:
1170
1175
  late_env_var_resolver(loaded, loaded, late_resolved)
1171
1176
  assert loaded['var_nam'] == "var val $env_var ${env_var}"
1172
1177
 
1178
+ def test_pep8_format(self):
1179
+ assert pep8_format(3.690) == "3.69"
1180
+ assert pep8_format(99) == "99"
1181
+ assert pep8_format(False) == "False"
1182
+ assert pep8_format(True) == "True"
1183
+
1184
+ assert pep8_format([]) == "[]"
1185
+ assert pep8_format({}) == "{}"
1186
+
1187
+ assert pep8_format({}, indent_level=1) == "{}"
1188
+ assert pep8_format({}, indent_level=2) == "{}"
1189
+
1190
+ def test_pep8_format_deep(self):
1191
+ sp = " " * 4
1192
+
1193
+ assert pep8_format([1, [2, 3], 4]) == "[\n 1,\n [\n 2,\n 3,\n ],\n 4,\n]"
1194
+ assert pep8_format([1, [2, 3], 4]) == f"[\n{sp}1,\n{sp}[\n{sp}{sp}2,\n{sp}{sp}3,\n{sp}],\n{sp}4,\n]"
1195
+
1196
+ assert pep8_format([1, [2]], indent_level=1) == "[\n 1,\n [\n 2,\n ],\n ]"
1197
+ assert pep8_format([1, [2]], indent_level=1) == f"[\n{sp}{sp}1,\n{sp}{sp}[\n{sp}{sp}{sp}2,\n{sp}{sp}],\n{sp}]"
1198
+
1199
+ value = {
1200
+ 'a': [
1201
+ 1,
1202
+ {
1203
+ 2: 3
1204
+ },
1205
+ ],
1206
+ 'b': [
1207
+ 'c',
1208
+ 3,
1209
+ {
1210
+ 'd': '',
1211
+ },
1212
+ ],
1213
+ True: False,
1214
+ }
1215
+ assert evaluate_literal(pep8_format(value)) == value
1216
+ assert pep8_format(value) == textwrap.dedent("""\
1217
+ {
1218
+ 'a': [
1219
+ 1,
1220
+ {
1221
+ 2: 3,
1222
+ },
1223
+ ],
1224
+ 'b': [
1225
+ 'c',
1226
+ 3,
1227
+ {
1228
+ 'd': '',
1229
+ },
1230
+ ],
1231
+ True: False,
1232
+ }""")
1233
+
1173
1234
  def test_project_main_file(self, tmp_path):
1174
1235
  assert project_main_file("not_existing_xy.tst") == ""
1175
1236
 
File without changes