plain 0.42.0__tar.gz → 0.42.2__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.
Files changed (165) hide show
  1. {plain-0.42.0 → plain-0.42.2}/PKG-INFO +1 -1
  2. {plain-0.42.0 → plain-0.42.2}/plain/logs/configure.py +9 -4
  3. {plain-0.42.0 → plain-0.42.2}/plain/urls/resolvers.py +0 -17
  4. plain-0.42.2/plain/urls/utils.py +43 -0
  5. {plain-0.42.0 → plain-0.42.2}/pyproject.toml +1 -1
  6. plain-0.42.0/plain/urls/utils.py +0 -62
  7. {plain-0.42.0 → plain-0.42.2}/.gitignore +0 -0
  8. {plain-0.42.0 → plain-0.42.2}/LICENSE +0 -0
  9. {plain-0.42.0 → plain-0.42.2}/README.md +0 -0
  10. {plain-0.42.0 → plain-0.42.2}/plain/README.md +0 -0
  11. {plain-0.42.0 → plain-0.42.2}/plain/__main__.py +0 -0
  12. {plain-0.42.0 → plain-0.42.2}/plain/assets/README.md +0 -0
  13. {plain-0.42.0 → plain-0.42.2}/plain/assets/__init__.py +0 -0
  14. {plain-0.42.0 → plain-0.42.2}/plain/assets/compile.py +0 -0
  15. {plain-0.42.0 → plain-0.42.2}/plain/assets/finders.py +0 -0
  16. {plain-0.42.0 → plain-0.42.2}/plain/assets/fingerprints.py +0 -0
  17. {plain-0.42.0 → plain-0.42.2}/plain/assets/urls.py +0 -0
  18. {plain-0.42.0 → plain-0.42.2}/plain/assets/views.py +0 -0
  19. {plain-0.42.0 → plain-0.42.2}/plain/chores/README.md +0 -0
  20. {plain-0.42.0 → plain-0.42.2}/plain/chores/__init__.py +0 -0
  21. {plain-0.42.0 → plain-0.42.2}/plain/chores/registry.py +0 -0
  22. {plain-0.42.0 → plain-0.42.2}/plain/cli/README.md +0 -0
  23. {plain-0.42.0 → plain-0.42.2}/plain/cli/__init__.py +0 -0
  24. {plain-0.42.0 → plain-0.42.2}/plain/cli/build.py +0 -0
  25. {plain-0.42.0 → plain-0.42.2}/plain/cli/chores.py +0 -0
  26. {plain-0.42.0 → plain-0.42.2}/plain/cli/core.py +0 -0
  27. {plain-0.42.0 → plain-0.42.2}/plain/cli/docs.py +0 -0
  28. {plain-0.42.0 → plain-0.42.2}/plain/cli/formatting.py +0 -0
  29. {plain-0.42.0 → plain-0.42.2}/plain/cli/preflight.py +0 -0
  30. {plain-0.42.0 → plain-0.42.2}/plain/cli/print.py +0 -0
  31. {plain-0.42.0 → plain-0.42.2}/plain/cli/registry.py +0 -0
  32. {plain-0.42.0 → plain-0.42.2}/plain/cli/scaffold.py +0 -0
  33. {plain-0.42.0 → plain-0.42.2}/plain/cli/settings.py +0 -0
  34. {plain-0.42.0 → plain-0.42.2}/plain/cli/shell.py +0 -0
  35. {plain-0.42.0 → plain-0.42.2}/plain/cli/startup.py +0 -0
  36. {plain-0.42.0 → plain-0.42.2}/plain/cli/urls.py +0 -0
  37. {plain-0.42.0 → plain-0.42.2}/plain/cli/utils.py +0 -0
  38. {plain-0.42.0 → plain-0.42.2}/plain/csrf/README.md +0 -0
  39. {plain-0.42.0 → plain-0.42.2}/plain/csrf/middleware.py +0 -0
  40. {plain-0.42.0 → plain-0.42.2}/plain/csrf/views.py +0 -0
  41. {plain-0.42.0 → plain-0.42.2}/plain/debug.py +0 -0
  42. {plain-0.42.0 → plain-0.42.2}/plain/exceptions.py +0 -0
  43. {plain-0.42.0 → plain-0.42.2}/plain/forms/README.md +0 -0
  44. {plain-0.42.0 → plain-0.42.2}/plain/forms/__init__.py +0 -0
  45. {plain-0.42.0 → plain-0.42.2}/plain/forms/boundfield.py +0 -0
  46. {plain-0.42.0 → plain-0.42.2}/plain/forms/exceptions.py +0 -0
  47. {plain-0.42.0 → plain-0.42.2}/plain/forms/fields.py +0 -0
  48. {plain-0.42.0 → plain-0.42.2}/plain/forms/forms.py +0 -0
  49. {plain-0.42.0 → plain-0.42.2}/plain/http/README.md +0 -0
  50. {plain-0.42.0 → plain-0.42.2}/plain/http/__init__.py +0 -0
  51. {plain-0.42.0 → plain-0.42.2}/plain/http/cookie.py +0 -0
  52. {plain-0.42.0 → plain-0.42.2}/plain/http/multipartparser.py +0 -0
  53. {plain-0.42.0 → plain-0.42.2}/plain/http/request.py +0 -0
  54. {plain-0.42.0 → plain-0.42.2}/plain/http/response.py +0 -0
  55. {plain-0.42.0 → plain-0.42.2}/plain/internal/__init__.py +0 -0
  56. {plain-0.42.0 → plain-0.42.2}/plain/internal/files/__init__.py +0 -0
  57. {plain-0.42.0 → plain-0.42.2}/plain/internal/files/base.py +0 -0
  58. {plain-0.42.0 → plain-0.42.2}/plain/internal/files/locks.py +0 -0
  59. {plain-0.42.0 → plain-0.42.2}/plain/internal/files/move.py +0 -0
  60. {plain-0.42.0 → plain-0.42.2}/plain/internal/files/temp.py +0 -0
  61. {plain-0.42.0 → plain-0.42.2}/plain/internal/files/uploadedfile.py +0 -0
  62. {plain-0.42.0 → plain-0.42.2}/plain/internal/files/uploadhandler.py +0 -0
  63. {plain-0.42.0 → plain-0.42.2}/plain/internal/files/utils.py +0 -0
  64. {plain-0.42.0 → plain-0.42.2}/plain/internal/handlers/__init__.py +0 -0
  65. {plain-0.42.0 → plain-0.42.2}/plain/internal/handlers/base.py +0 -0
  66. {plain-0.42.0 → plain-0.42.2}/plain/internal/handlers/exception.py +0 -0
  67. {plain-0.42.0 → plain-0.42.2}/plain/internal/handlers/wsgi.py +0 -0
  68. {plain-0.42.0 → plain-0.42.2}/plain/internal/middleware/__init__.py +0 -0
  69. {plain-0.42.0 → plain-0.42.2}/plain/internal/middleware/headers.py +0 -0
  70. {plain-0.42.0 → plain-0.42.2}/plain/internal/middleware/https.py +0 -0
  71. {plain-0.42.0 → plain-0.42.2}/plain/internal/middleware/slash.py +0 -0
  72. {plain-0.42.0 → plain-0.42.2}/plain/json.py +0 -0
  73. {plain-0.42.0 → plain-0.42.2}/plain/logs/README.md +0 -0
  74. {plain-0.42.0 → plain-0.42.2}/plain/logs/__init__.py +0 -0
  75. {plain-0.42.0 → plain-0.42.2}/plain/logs/loggers.py +0 -0
  76. {plain-0.42.0 → plain-0.42.2}/plain/logs/utils.py +0 -0
  77. {plain-0.42.0 → plain-0.42.2}/plain/packages/README.md +0 -0
  78. {plain-0.42.0 → plain-0.42.2}/plain/packages/__init__.py +0 -0
  79. {plain-0.42.0 → plain-0.42.2}/plain/packages/config.py +0 -0
  80. {plain-0.42.0 → plain-0.42.2}/plain/packages/registry.py +0 -0
  81. {plain-0.42.0 → plain-0.42.2}/plain/paginator.py +0 -0
  82. {plain-0.42.0 → plain-0.42.2}/plain/preflight/README.md +0 -0
  83. {plain-0.42.0 → plain-0.42.2}/plain/preflight/__init__.py +0 -0
  84. {plain-0.42.0 → plain-0.42.2}/plain/preflight/files.py +0 -0
  85. {plain-0.42.0 → plain-0.42.2}/plain/preflight/messages.py +0 -0
  86. {plain-0.42.0 → plain-0.42.2}/plain/preflight/registry.py +0 -0
  87. {plain-0.42.0 → plain-0.42.2}/plain/preflight/security.py +0 -0
  88. {plain-0.42.0 → plain-0.42.2}/plain/preflight/urls.py +0 -0
  89. {plain-0.42.0 → plain-0.42.2}/plain/runtime/README.md +0 -0
  90. {plain-0.42.0 → plain-0.42.2}/plain/runtime/__init__.py +0 -0
  91. {plain-0.42.0 → plain-0.42.2}/plain/runtime/global_settings.py +0 -0
  92. {plain-0.42.0 → plain-0.42.2}/plain/runtime/user_settings.py +0 -0
  93. {plain-0.42.0 → plain-0.42.2}/plain/signals/README.md +0 -0
  94. {plain-0.42.0 → plain-0.42.2}/plain/signals/__init__.py +0 -0
  95. {plain-0.42.0 → plain-0.42.2}/plain/signals/dispatch/__init__.py +0 -0
  96. {plain-0.42.0 → plain-0.42.2}/plain/signals/dispatch/dispatcher.py +0 -0
  97. {plain-0.42.0 → plain-0.42.2}/plain/signals/dispatch/license.txt +0 -0
  98. {plain-0.42.0 → plain-0.42.2}/plain/signing.py +0 -0
  99. {plain-0.42.0 → plain-0.42.2}/plain/templates/README.md +0 -0
  100. {plain-0.42.0 → plain-0.42.2}/plain/templates/__init__.py +0 -0
  101. {plain-0.42.0 → plain-0.42.2}/plain/templates/core.py +0 -0
  102. {plain-0.42.0 → plain-0.42.2}/plain/templates/jinja/__init__.py +0 -0
  103. {plain-0.42.0 → plain-0.42.2}/plain/templates/jinja/environments.py +0 -0
  104. {plain-0.42.0 → plain-0.42.2}/plain/templates/jinja/extensions.py +0 -0
  105. {plain-0.42.0 → plain-0.42.2}/plain/templates/jinja/filters.py +0 -0
  106. {plain-0.42.0 → plain-0.42.2}/plain/templates/jinja/globals.py +0 -0
  107. {plain-0.42.0 → plain-0.42.2}/plain/test/README.md +0 -0
  108. {plain-0.42.0 → plain-0.42.2}/plain/test/__init__.py +0 -0
  109. {plain-0.42.0 → plain-0.42.2}/plain/test/client.py +0 -0
  110. {plain-0.42.0 → plain-0.42.2}/plain/test/encoding.py +0 -0
  111. {plain-0.42.0 → plain-0.42.2}/plain/test/exceptions.py +0 -0
  112. {plain-0.42.0 → plain-0.42.2}/plain/urls/README.md +0 -0
  113. {plain-0.42.0 → plain-0.42.2}/plain/urls/__init__.py +0 -0
  114. {plain-0.42.0 → plain-0.42.2}/plain/urls/converters.py +0 -0
  115. {plain-0.42.0 → plain-0.42.2}/plain/urls/exceptions.py +0 -0
  116. {plain-0.42.0 → plain-0.42.2}/plain/urls/patterns.py +0 -0
  117. {plain-0.42.0 → plain-0.42.2}/plain/urls/routers.py +0 -0
  118. {plain-0.42.0 → plain-0.42.2}/plain/utils/README.md +0 -0
  119. {plain-0.42.0 → plain-0.42.2}/plain/utils/__init__.py +0 -0
  120. {plain-0.42.0 → plain-0.42.2}/plain/utils/cache.py +0 -0
  121. {plain-0.42.0 → plain-0.42.2}/plain/utils/connection.py +0 -0
  122. {plain-0.42.0 → plain-0.42.2}/plain/utils/crypto.py +0 -0
  123. {plain-0.42.0 → plain-0.42.2}/plain/utils/datastructures.py +0 -0
  124. {plain-0.42.0 → plain-0.42.2}/plain/utils/dateparse.py +0 -0
  125. {plain-0.42.0 → plain-0.42.2}/plain/utils/deconstruct.py +0 -0
  126. {plain-0.42.0 → plain-0.42.2}/plain/utils/decorators.py +0 -0
  127. {plain-0.42.0 → plain-0.42.2}/plain/utils/duration.py +0 -0
  128. {plain-0.42.0 → plain-0.42.2}/plain/utils/encoding.py +0 -0
  129. {plain-0.42.0 → plain-0.42.2}/plain/utils/functional.py +0 -0
  130. {plain-0.42.0 → plain-0.42.2}/plain/utils/hashable.py +0 -0
  131. {plain-0.42.0 → plain-0.42.2}/plain/utils/html.py +0 -0
  132. {plain-0.42.0 → plain-0.42.2}/plain/utils/http.py +0 -0
  133. {plain-0.42.0 → plain-0.42.2}/plain/utils/inspect.py +0 -0
  134. {plain-0.42.0 → plain-0.42.2}/plain/utils/ipv6.py +0 -0
  135. {plain-0.42.0 → plain-0.42.2}/plain/utils/itercompat.py +0 -0
  136. {plain-0.42.0 → plain-0.42.2}/plain/utils/module_loading.py +0 -0
  137. {plain-0.42.0 → plain-0.42.2}/plain/utils/regex_helper.py +0 -0
  138. {plain-0.42.0 → plain-0.42.2}/plain/utils/safestring.py +0 -0
  139. {plain-0.42.0 → plain-0.42.2}/plain/utils/text.py +0 -0
  140. {plain-0.42.0 → plain-0.42.2}/plain/utils/timesince.py +0 -0
  141. {plain-0.42.0 → plain-0.42.2}/plain/utils/timezone.py +0 -0
  142. {plain-0.42.0 → plain-0.42.2}/plain/utils/tree.py +0 -0
  143. {plain-0.42.0 → plain-0.42.2}/plain/validators.py +0 -0
  144. {plain-0.42.0 → plain-0.42.2}/plain/views/README.md +0 -0
  145. {plain-0.42.0 → plain-0.42.2}/plain/views/__init__.py +0 -0
  146. {plain-0.42.0 → plain-0.42.2}/plain/views/base.py +0 -0
  147. {plain-0.42.0 → plain-0.42.2}/plain/views/csrf.py +0 -0
  148. {plain-0.42.0 → plain-0.42.2}/plain/views/errors.py +0 -0
  149. {plain-0.42.0 → plain-0.42.2}/plain/views/exceptions.py +0 -0
  150. {plain-0.42.0 → plain-0.42.2}/plain/views/forms.py +0 -0
  151. {plain-0.42.0 → plain-0.42.2}/plain/views/objects.py +0 -0
  152. {plain-0.42.0 → plain-0.42.2}/plain/views/redirect.py +0 -0
  153. {plain-0.42.0 → plain-0.42.2}/plain/views/templates.py +0 -0
  154. {plain-0.42.0 → plain-0.42.2}/plain/wsgi.py +0 -0
  155. {plain-0.42.0 → plain-0.42.2}/tests/.bolt/assets_collected/assets.json +0 -0
  156. {plain-0.42.0 → plain-0.42.2}/tests/.gitignore +0 -0
  157. {plain-0.42.0 → plain-0.42.2}/tests/app/.gitignore +0 -0
  158. {plain-0.42.0 → plain-0.42.2}/tests/app/settings.py +0 -0
  159. {plain-0.42.0 → plain-0.42.2}/tests/app/test/__init__.py +0 -0
  160. {plain-0.42.0 → plain-0.42.2}/tests/app/test/default_settings.py +0 -0
  161. {plain-0.42.0 → plain-0.42.2}/tests/app/urls.py +0 -0
  162. {plain-0.42.0 → plain-0.42.2}/tests/conftest.py +0 -0
  163. {plain-0.42.0 → plain-0.42.2}/tests/test_cli.py +0 -0
  164. {plain-0.42.0 → plain-0.42.2}/tests/test_runtime.py +0 -0
  165. {plain-0.42.0 → plain-0.42.2}/tests/test_wsgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain
3
- Version: 0.42.0
3
+ Version: 0.42.2
4
4
  Summary: A web framework for building products with Python.
5
5
  Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
6
6
  License-File: LICENSE
@@ -14,19 +14,24 @@ def configure_logging(logging_settings):
14
14
  },
15
15
  },
16
16
  "handlers": {
17
- "console": {
18
- "level": "INFO",
17
+ "plain_console": {
18
+ "level": environ.get("PLAIN_LOG_LEVEL", "INFO"),
19
+ "class": "logging.StreamHandler",
20
+ "formatter": "simple",
21
+ },
22
+ "app_console": {
23
+ "level": environ.get("APP_LOG_LEVEL", "INFO"),
19
24
  "class": "logging.StreamHandler",
20
25
  "formatter": "simple",
21
26
  },
22
27
  },
23
28
  "loggers": {
24
29
  "plain": {
25
- "handlers": ["console"],
30
+ "handlers": ["plain_console"],
26
31
  "level": environ.get("PLAIN_LOG_LEVEL", "INFO"),
27
32
  },
28
33
  "app": {
29
- "handlers": ["console"],
34
+ "handlers": ["app_console"],
30
35
  "level": environ.get("APP_LOG_LEVEL", "INFO"),
31
36
  "propagate": False,
32
37
  },
@@ -103,7 +103,6 @@ class URLResolver:
103
103
  self.router = router
104
104
  self._reverse_dict = {}
105
105
  self._namespace_dict = {}
106
- self._app_dict = {}
107
106
  self._populated = False
108
107
  self._local = local()
109
108
 
@@ -132,7 +131,6 @@ class URLResolver:
132
131
  self._local.populating = True
133
132
  lookups = MultiValueDict()
134
133
  namespaces = {}
135
- packages = {}
136
134
  for url_pattern in reversed(self.url_patterns):
137
135
  p_pattern = url_pattern.pattern.regex.pattern
138
136
  p_pattern = p_pattern.removeprefix("^")
@@ -158,9 +156,6 @@ class URLResolver:
158
156
  else: # url_pattern is a URLResolver.
159
157
  url_pattern._populate()
160
158
  if url_pattern.namespace:
161
- packages.setdefault(url_pattern.namespace, []).append(
162
- url_pattern.namespace
163
- )
164
159
  namespaces[url_pattern.namespace] = (p_pattern, url_pattern)
165
160
  else:
166
161
  for name in url_pattern.reverse_dict:
@@ -189,13 +184,7 @@ class URLResolver:
189
184
  current_converters = url_pattern.pattern.converters
190
185
  sub_pattern.pattern.converters.update(current_converters)
191
186
  namespaces[namespace] = (p_pattern + prefix, sub_pattern)
192
- for (
193
- namespace,
194
- namespace_list,
195
- ) in url_pattern.app_dict.items():
196
- packages.setdefault(namespace, []).extend(namespace_list)
197
187
  self._namespace_dict = namespaces
198
- self._app_dict = packages
199
188
  self._reverse_dict = lookups
200
189
  self._populated = True
201
190
  finally:
@@ -213,12 +202,6 @@ class URLResolver:
213
202
  self._populate()
214
203
  return self._namespace_dict
215
204
 
216
- @property
217
- def app_dict(self):
218
- if not self._app_dict:
219
- self._populate()
220
- return self._app_dict
221
-
222
205
  @staticmethod
223
206
  def _join_route(route1, route2):
224
207
  """Join two routes, without the starting ^ in the second route."""
@@ -0,0 +1,43 @@
1
+ from plain.utils.functional import lazy
2
+
3
+ from .exceptions import NoReverseMatch
4
+ from .resolvers import get_ns_resolver, get_resolver
5
+
6
+
7
+ def reverse(url_name: str, *args, **kwargs):
8
+ resolver = get_resolver()
9
+
10
+ *path, view = url_name.split(":")
11
+
12
+ current_path = None
13
+
14
+ resolved_path = []
15
+ ns_pattern = ""
16
+ ns_converters = {}
17
+ for ns in path:
18
+ current_ns = current_path.pop() if current_path else None
19
+
20
+ if ns != current_ns:
21
+ current_path = None
22
+
23
+ try:
24
+ extra, resolver = resolver.namespace_dict[ns]
25
+ resolved_path.append(ns)
26
+ ns_pattern += extra
27
+ ns_converters.update(resolver.pattern.converters)
28
+ except KeyError as key:
29
+ if resolved_path:
30
+ raise NoReverseMatch(
31
+ "{} is not a registered namespace inside '{}'".format(
32
+ key, ":".join(resolved_path)
33
+ )
34
+ )
35
+ else:
36
+ raise NoReverseMatch(f"{key} is not a registered namespace")
37
+ if ns_pattern:
38
+ resolver = get_ns_resolver(ns_pattern, resolver, tuple(ns_converters.items()))
39
+
40
+ return resolver.reverse(view, *args, **kwargs)
41
+
42
+
43
+ reverse_lazy = lazy(reverse, str)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "plain"
3
- version = "0.42.0"
3
+ version = "0.42.2"
4
4
  description = "A web framework for building products with Python."
5
5
  authors = [{name = "Dave Gaeddert", email = "dave.gaeddert@dropseed.dev"}]
6
6
  readme = "README.md"
@@ -1,62 +0,0 @@
1
- from plain.utils.functional import lazy
2
-
3
- from .exceptions import NoReverseMatch
4
- from .resolvers import get_ns_resolver, get_resolver
5
-
6
-
7
- def reverse(viewname, *args, **kwargs):
8
- resolver = get_resolver()
9
-
10
- if not isinstance(viewname, str):
11
- view = viewname
12
- else:
13
- *path, view = viewname.split(":")
14
-
15
- current_path = None
16
-
17
- resolved_path = []
18
- ns_pattern = ""
19
- ns_converters = {}
20
- for ns in path:
21
- current_ns = current_path.pop() if current_path else None
22
- # Lookup the name to see if it could be an app identifier.
23
- try:
24
- app_list = resolver.app_dict[ns]
25
- # Yes! Path part matches an app in the current Resolver.
26
- if current_ns and current_ns in app_list:
27
- # If we are reversing for a particular app, use that
28
- # namespace.
29
- ns = current_ns
30
- elif ns not in app_list:
31
- # The name isn't shared by one of the instances (i.e.,
32
- # the default) so pick the first instance as the default.
33
- ns = app_list[0]
34
- except KeyError:
35
- pass
36
-
37
- if ns != current_ns:
38
- current_path = None
39
-
40
- try:
41
- extra, resolver = resolver.namespace_dict[ns]
42
- resolved_path.append(ns)
43
- ns_pattern += extra
44
- ns_converters.update(resolver.pattern.converters)
45
- except KeyError as key:
46
- if resolved_path:
47
- raise NoReverseMatch(
48
- "{} is not a registered namespace inside '{}'".format(
49
- key, ":".join(resolved_path)
50
- )
51
- )
52
- else:
53
- raise NoReverseMatch(f"{key} is not a registered namespace")
54
- if ns_pattern:
55
- resolver = get_ns_resolver(
56
- ns_pattern, resolver, tuple(ns_converters.items())
57
- )
58
-
59
- return resolver.reverse(view, *args, **kwargs)
60
-
61
-
62
- reverse_lazy = lazy(reverse, str)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes