plain 0.68.1__tar.gz → 0.69.0__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 (182) hide show
  1. {plain-0.68.1 → plain-0.69.0}/.gitignore +1 -0
  2. {plain-0.68.1 → plain-0.69.0}/PKG-INFO +1 -1
  3. {plain-0.68.1 → plain-0.69.0}/plain/CHANGELOG.md +12 -0
  4. {plain-0.68.1 → plain-0.69.0}/plain/exceptions.py +1 -43
  5. {plain-0.68.1 → plain-0.69.0}/plain/views/objects.py +13 -3
  6. {plain-0.68.1 → plain-0.69.0}/pyproject.toml +1 -1
  7. {plain-0.68.1 → plain-0.69.0}/LICENSE +0 -0
  8. {plain-0.68.1 → plain-0.69.0}/README.md +0 -0
  9. {plain-0.68.1 → plain-0.69.0}/plain/AGENTS.md +0 -0
  10. {plain-0.68.1 → plain-0.69.0}/plain/README.md +0 -0
  11. {plain-0.68.1 → plain-0.69.0}/plain/__main__.py +0 -0
  12. {plain-0.68.1 → plain-0.69.0}/plain/assets/README.md +0 -0
  13. {plain-0.68.1 → plain-0.69.0}/plain/assets/__init__.py +0 -0
  14. {plain-0.68.1 → plain-0.69.0}/plain/assets/compile.py +0 -0
  15. {plain-0.68.1 → plain-0.69.0}/plain/assets/finders.py +0 -0
  16. {plain-0.68.1 → plain-0.69.0}/plain/assets/fingerprints.py +0 -0
  17. {plain-0.68.1 → plain-0.69.0}/plain/assets/urls.py +0 -0
  18. {plain-0.68.1 → plain-0.69.0}/plain/assets/views.py +0 -0
  19. {plain-0.68.1 → plain-0.69.0}/plain/chores/README.md +0 -0
  20. {plain-0.68.1 → plain-0.69.0}/plain/chores/__init__.py +0 -0
  21. {plain-0.68.1 → plain-0.69.0}/plain/chores/registry.py +0 -0
  22. {plain-0.68.1 → plain-0.69.0}/plain/cli/README.md +0 -0
  23. {plain-0.68.1 → plain-0.69.0}/plain/cli/__init__.py +0 -0
  24. {plain-0.68.1 → plain-0.69.0}/plain/cli/agent/__init__.py +0 -0
  25. {plain-0.68.1 → plain-0.69.0}/plain/cli/agent/docs.py +0 -0
  26. {plain-0.68.1 → plain-0.69.0}/plain/cli/agent/llmdocs.py +0 -0
  27. {plain-0.68.1 → plain-0.69.0}/plain/cli/agent/md.py +0 -0
  28. {plain-0.68.1 → plain-0.69.0}/plain/cli/agent/prompt.py +0 -0
  29. {plain-0.68.1 → plain-0.69.0}/plain/cli/agent/request.py +0 -0
  30. {plain-0.68.1 → plain-0.69.0}/plain/cli/build.py +0 -0
  31. {plain-0.68.1 → plain-0.69.0}/plain/cli/changelog.py +0 -0
  32. {plain-0.68.1 → plain-0.69.0}/plain/cli/chores.py +0 -0
  33. {plain-0.68.1 → plain-0.69.0}/plain/cli/core.py +0 -0
  34. {plain-0.68.1 → plain-0.69.0}/plain/cli/docs.py +0 -0
  35. {plain-0.68.1 → plain-0.69.0}/plain/cli/formatting.py +0 -0
  36. {plain-0.68.1 → plain-0.69.0}/plain/cli/install.py +0 -0
  37. {plain-0.68.1 → plain-0.69.0}/plain/cli/output.py +0 -0
  38. {plain-0.68.1 → plain-0.69.0}/plain/cli/preflight.py +0 -0
  39. {plain-0.68.1 → plain-0.69.0}/plain/cli/print.py +0 -0
  40. {plain-0.68.1 → plain-0.69.0}/plain/cli/registry.py +0 -0
  41. {plain-0.68.1 → plain-0.69.0}/plain/cli/scaffold.py +0 -0
  42. {plain-0.68.1 → plain-0.69.0}/plain/cli/settings.py +0 -0
  43. {plain-0.68.1 → plain-0.69.0}/plain/cli/shell.py +0 -0
  44. {plain-0.68.1 → plain-0.69.0}/plain/cli/startup.py +0 -0
  45. {plain-0.68.1 → plain-0.69.0}/plain/cli/upgrade.py +0 -0
  46. {plain-0.68.1 → plain-0.69.0}/plain/cli/urls.py +0 -0
  47. {plain-0.68.1 → plain-0.69.0}/plain/cli/utils.py +0 -0
  48. {plain-0.68.1 → plain-0.69.0}/plain/csrf/README.md +0 -0
  49. {plain-0.68.1 → plain-0.69.0}/plain/csrf/middleware.py +0 -0
  50. {plain-0.68.1 → plain-0.69.0}/plain/csrf/views.py +0 -0
  51. {plain-0.68.1 → plain-0.69.0}/plain/debug.py +0 -0
  52. {plain-0.68.1 → plain-0.69.0}/plain/forms/README.md +0 -0
  53. {plain-0.68.1 → plain-0.69.0}/plain/forms/__init__.py +0 -0
  54. {plain-0.68.1 → plain-0.69.0}/plain/forms/boundfield.py +0 -0
  55. {plain-0.68.1 → plain-0.69.0}/plain/forms/exceptions.py +0 -0
  56. {plain-0.68.1 → plain-0.69.0}/plain/forms/fields.py +0 -0
  57. {plain-0.68.1 → plain-0.69.0}/plain/forms/forms.py +0 -0
  58. {plain-0.68.1 → plain-0.69.0}/plain/http/README.md +0 -0
  59. {plain-0.68.1 → plain-0.69.0}/plain/http/__init__.py +0 -0
  60. {plain-0.68.1 → plain-0.69.0}/plain/http/cookie.py +0 -0
  61. {plain-0.68.1 → plain-0.69.0}/plain/http/multipartparser.py +0 -0
  62. {plain-0.68.1 → plain-0.69.0}/plain/http/request.py +0 -0
  63. {plain-0.68.1 → plain-0.69.0}/plain/http/response.py +0 -0
  64. {plain-0.68.1 → plain-0.69.0}/plain/internal/__init__.py +0 -0
  65. {plain-0.68.1 → plain-0.69.0}/plain/internal/files/__init__.py +0 -0
  66. {plain-0.68.1 → plain-0.69.0}/plain/internal/files/base.py +0 -0
  67. {plain-0.68.1 → plain-0.69.0}/plain/internal/files/locks.py +0 -0
  68. {plain-0.68.1 → plain-0.69.0}/plain/internal/files/move.py +0 -0
  69. {plain-0.68.1 → plain-0.69.0}/plain/internal/files/temp.py +0 -0
  70. {plain-0.68.1 → plain-0.69.0}/plain/internal/files/uploadedfile.py +0 -0
  71. {plain-0.68.1 → plain-0.69.0}/plain/internal/files/uploadhandler.py +0 -0
  72. {plain-0.68.1 → plain-0.69.0}/plain/internal/files/utils.py +0 -0
  73. {plain-0.68.1 → plain-0.69.0}/plain/internal/handlers/__init__.py +0 -0
  74. {plain-0.68.1 → plain-0.69.0}/plain/internal/handlers/base.py +0 -0
  75. {plain-0.68.1 → plain-0.69.0}/plain/internal/handlers/exception.py +0 -0
  76. {plain-0.68.1 → plain-0.69.0}/plain/internal/handlers/wsgi.py +0 -0
  77. {plain-0.68.1 → plain-0.69.0}/plain/internal/middleware/__init__.py +0 -0
  78. {plain-0.68.1 → plain-0.69.0}/plain/internal/middleware/headers.py +0 -0
  79. {plain-0.68.1 → plain-0.69.0}/plain/internal/middleware/hosts.py +0 -0
  80. {plain-0.68.1 → plain-0.69.0}/plain/internal/middleware/https.py +0 -0
  81. {plain-0.68.1 → plain-0.69.0}/plain/internal/middleware/slash.py +0 -0
  82. {plain-0.68.1 → plain-0.69.0}/plain/json.py +0 -0
  83. {plain-0.68.1 → plain-0.69.0}/plain/logs/README.md +0 -0
  84. {plain-0.68.1 → plain-0.69.0}/plain/logs/__init__.py +0 -0
  85. {plain-0.68.1 → plain-0.69.0}/plain/logs/configure.py +0 -0
  86. {plain-0.68.1 → plain-0.69.0}/plain/logs/debug.py +0 -0
  87. {plain-0.68.1 → plain-0.69.0}/plain/logs/formatters.py +0 -0
  88. {plain-0.68.1 → plain-0.69.0}/plain/logs/loggers.py +0 -0
  89. {plain-0.68.1 → plain-0.69.0}/plain/logs/utils.py +0 -0
  90. {plain-0.68.1 → plain-0.69.0}/plain/packages/README.md +0 -0
  91. {plain-0.68.1 → plain-0.69.0}/plain/packages/__init__.py +0 -0
  92. {plain-0.68.1 → plain-0.69.0}/plain/packages/config.py +0 -0
  93. {plain-0.68.1 → plain-0.69.0}/plain/packages/registry.py +0 -0
  94. {plain-0.68.1 → plain-0.69.0}/plain/paginator.py +0 -0
  95. {plain-0.68.1 → plain-0.69.0}/plain/preflight/README.md +0 -0
  96. {plain-0.68.1 → plain-0.69.0}/plain/preflight/__init__.py +0 -0
  97. {plain-0.68.1 → plain-0.69.0}/plain/preflight/checks.py +0 -0
  98. {plain-0.68.1 → plain-0.69.0}/plain/preflight/files.py +0 -0
  99. {plain-0.68.1 → plain-0.69.0}/plain/preflight/registry.py +0 -0
  100. {plain-0.68.1 → plain-0.69.0}/plain/preflight/results.py +0 -0
  101. {plain-0.68.1 → plain-0.69.0}/plain/preflight/security.py +0 -0
  102. {plain-0.68.1 → plain-0.69.0}/plain/preflight/urls.py +0 -0
  103. {plain-0.68.1 → plain-0.69.0}/plain/runtime/README.md +0 -0
  104. {plain-0.68.1 → plain-0.69.0}/plain/runtime/__init__.py +0 -0
  105. {plain-0.68.1 → plain-0.69.0}/plain/runtime/global_settings.py +0 -0
  106. {plain-0.68.1 → plain-0.69.0}/plain/runtime/user_settings.py +0 -0
  107. {plain-0.68.1 → plain-0.69.0}/plain/runtime/utils.py +0 -0
  108. {plain-0.68.1 → plain-0.69.0}/plain/signals/README.md +0 -0
  109. {plain-0.68.1 → plain-0.69.0}/plain/signals/__init__.py +0 -0
  110. {plain-0.68.1 → plain-0.69.0}/plain/signals/dispatch/__init__.py +0 -0
  111. {plain-0.68.1 → plain-0.69.0}/plain/signals/dispatch/dispatcher.py +0 -0
  112. {plain-0.68.1 → plain-0.69.0}/plain/signals/dispatch/license.txt +0 -0
  113. {plain-0.68.1 → plain-0.69.0}/plain/signing.py +0 -0
  114. {plain-0.68.1 → plain-0.69.0}/plain/templates/AGENTS.md +0 -0
  115. {plain-0.68.1 → plain-0.69.0}/plain/templates/README.md +0 -0
  116. {plain-0.68.1 → plain-0.69.0}/plain/templates/__init__.py +0 -0
  117. {plain-0.68.1 → plain-0.69.0}/plain/templates/core.py +0 -0
  118. {plain-0.68.1 → plain-0.69.0}/plain/templates/jinja/__init__.py +0 -0
  119. {plain-0.68.1 → plain-0.69.0}/plain/templates/jinja/environments.py +0 -0
  120. {plain-0.68.1 → plain-0.69.0}/plain/templates/jinja/extensions.py +0 -0
  121. {plain-0.68.1 → plain-0.69.0}/plain/templates/jinja/filters.py +0 -0
  122. {plain-0.68.1 → plain-0.69.0}/plain/templates/jinja/globals.py +0 -0
  123. {plain-0.68.1 → plain-0.69.0}/plain/test/README.md +0 -0
  124. {plain-0.68.1 → plain-0.69.0}/plain/test/__init__.py +0 -0
  125. {plain-0.68.1 → plain-0.69.0}/plain/test/client.py +0 -0
  126. {plain-0.68.1 → plain-0.69.0}/plain/test/encoding.py +0 -0
  127. {plain-0.68.1 → plain-0.69.0}/plain/test/exceptions.py +0 -0
  128. {plain-0.68.1 → plain-0.69.0}/plain/urls/README.md +0 -0
  129. {plain-0.68.1 → plain-0.69.0}/plain/urls/__init__.py +0 -0
  130. {plain-0.68.1 → plain-0.69.0}/plain/urls/converters.py +0 -0
  131. {plain-0.68.1 → plain-0.69.0}/plain/urls/exceptions.py +0 -0
  132. {plain-0.68.1 → plain-0.69.0}/plain/urls/patterns.py +0 -0
  133. {plain-0.68.1 → plain-0.69.0}/plain/urls/resolvers.py +0 -0
  134. {plain-0.68.1 → plain-0.69.0}/plain/urls/routers.py +0 -0
  135. {plain-0.68.1 → plain-0.69.0}/plain/urls/utils.py +0 -0
  136. {plain-0.68.1 → plain-0.69.0}/plain/utils/README.md +0 -0
  137. {plain-0.68.1 → plain-0.69.0}/plain/utils/__init__.py +0 -0
  138. {plain-0.68.1 → plain-0.69.0}/plain/utils/cache.py +0 -0
  139. {plain-0.68.1 → plain-0.69.0}/plain/utils/crypto.py +0 -0
  140. {plain-0.68.1 → plain-0.69.0}/plain/utils/datastructures.py +0 -0
  141. {plain-0.68.1 → plain-0.69.0}/plain/utils/dateparse.py +0 -0
  142. {plain-0.68.1 → plain-0.69.0}/plain/utils/deconstruct.py +0 -0
  143. {plain-0.68.1 → plain-0.69.0}/plain/utils/decorators.py +0 -0
  144. {plain-0.68.1 → plain-0.69.0}/plain/utils/duration.py +0 -0
  145. {plain-0.68.1 → plain-0.69.0}/plain/utils/encoding.py +0 -0
  146. {plain-0.68.1 → plain-0.69.0}/plain/utils/functional.py +0 -0
  147. {plain-0.68.1 → plain-0.69.0}/plain/utils/hashable.py +0 -0
  148. {plain-0.68.1 → plain-0.69.0}/plain/utils/html.py +0 -0
  149. {plain-0.68.1 → plain-0.69.0}/plain/utils/http.py +0 -0
  150. {plain-0.68.1 → plain-0.69.0}/plain/utils/inspect.py +0 -0
  151. {plain-0.68.1 → plain-0.69.0}/plain/utils/ipv6.py +0 -0
  152. {plain-0.68.1 → plain-0.69.0}/plain/utils/itercompat.py +0 -0
  153. {plain-0.68.1 → plain-0.69.0}/plain/utils/module_loading.py +0 -0
  154. {plain-0.68.1 → plain-0.69.0}/plain/utils/regex_helper.py +0 -0
  155. {plain-0.68.1 → plain-0.69.0}/plain/utils/safestring.py +0 -0
  156. {plain-0.68.1 → plain-0.69.0}/plain/utils/text.py +0 -0
  157. {plain-0.68.1 → plain-0.69.0}/plain/utils/timesince.py +0 -0
  158. {plain-0.68.1 → plain-0.69.0}/plain/utils/timezone.py +0 -0
  159. {plain-0.68.1 → plain-0.69.0}/plain/utils/tree.py +0 -0
  160. {plain-0.68.1 → plain-0.69.0}/plain/validators.py +0 -0
  161. {plain-0.68.1 → plain-0.69.0}/plain/views/README.md +0 -0
  162. {plain-0.68.1 → plain-0.69.0}/plain/views/__init__.py +0 -0
  163. {plain-0.68.1 → plain-0.69.0}/plain/views/base.py +0 -0
  164. {plain-0.68.1 → plain-0.69.0}/plain/views/errors.py +0 -0
  165. {plain-0.68.1 → plain-0.69.0}/plain/views/exceptions.py +0 -0
  166. {plain-0.68.1 → plain-0.69.0}/plain/views/forms.py +0 -0
  167. {plain-0.68.1 → plain-0.69.0}/plain/views/redirect.py +0 -0
  168. {plain-0.68.1 → plain-0.69.0}/plain/views/templates.py +0 -0
  169. {plain-0.68.1 → plain-0.69.0}/plain/wsgi.py +0 -0
  170. {plain-0.68.1 → plain-0.69.0}/tests/.gitignore +0 -0
  171. {plain-0.68.1 → plain-0.69.0}/tests/app/.gitignore +0 -0
  172. {plain-0.68.1 → plain-0.69.0}/tests/app/settings.py +0 -0
  173. {plain-0.68.1 → plain-0.69.0}/tests/app/test/__init__.py +0 -0
  174. {plain-0.68.1 → plain-0.69.0}/tests/app/test/default_settings.py +0 -0
  175. {plain-0.68.1 → plain-0.69.0}/tests/app/urls.py +0 -0
  176. {plain-0.68.1 → plain-0.69.0}/tests/conftest.py +0 -0
  177. {plain-0.68.1 → plain-0.69.0}/tests/test_cli.py +0 -0
  178. {plain-0.68.1 → plain-0.69.0}/tests/test_csrf.py +0 -0
  179. {plain-0.68.1 → plain-0.69.0}/tests/test_http_hosts.py +0 -0
  180. {plain-0.68.1 → plain-0.69.0}/tests/test_logs.py +0 -0
  181. {plain-0.68.1 → plain-0.69.0}/tests/test_runtime.py +0 -0
  182. {plain-0.68.1 → plain-0.69.0}/tests/test_wsgi.py +0 -0
@@ -15,3 +15,4 @@ plain*/tests/.plain
15
15
  .plain
16
16
 
17
17
  .vscode
18
+ /.claude
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plain
3
- Version: 0.68.1
3
+ Version: 0.69.0
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
@@ -1,5 +1,17 @@
1
1
  # plain changelog
2
2
 
3
+ ## [0.69.0](https://github.com/dropseed/plain/releases/plain@0.69.0) (2025-09-29)
4
+
5
+ ### What's changed
6
+
7
+ - Model-related exceptions (`FieldDoesNotExist`, `FieldError`, `ObjectDoesNotExist`, `MultipleObjectsReturned`, `EmptyResultSet`, `FullResultSet`) moved from `plain.exceptions` to `plain.models.exceptions` ([1c02564](https://github.com/dropseed/plain/commit/1c02564561))
8
+ - Added `plain dev` alias prompt that suggests adding `p` as a shell alias for convenience ([d913b44](https://github.com/dropseed/plain/commit/d913b44fab))
9
+
10
+ ### Upgrade instructions
11
+
12
+ - Replace imports of `FieldDoesNotExist`, `FieldError`, `ObjectDoesNotExist`, `MultipleObjectsReturned`, `EmptyResultSet`, or `FullResultSet` from `plain.exceptions` to `plain.models.exceptions`
13
+ - If you're using `ObjectDoesNotExist` in views, update your import from `plain.exceptions.ObjectDoesNotExist` to `plain.models.exceptions.ObjectDoesNotExist`
14
+
3
15
  ## [0.68.1](https://github.com/dropseed/plain/releases/plain@0.68.1) (2025-09-25)
4
16
 
5
17
  ### What's changed
@@ -6,7 +6,7 @@ import operator
6
6
 
7
7
  from plain.utils.hashable import make_hashable
8
8
 
9
- # MARK: Configuration and Registry
9
+ # MARK: Configuration and Package Registry
10
10
 
11
11
 
12
12
  class PackageRegistryNotReady(Exception):
@@ -21,33 +21,6 @@ class ImproperlyConfigured(Exception):
21
21
  pass
22
22
 
23
23
 
24
- # MARK: Model and Field Errors
25
-
26
-
27
- class FieldDoesNotExist(Exception):
28
- """The requested model field does not exist"""
29
-
30
- pass
31
-
32
-
33
- class FieldError(Exception):
34
- """Some kind of problem with a model field."""
35
-
36
- pass
37
-
38
-
39
- class ObjectDoesNotExist(Exception):
40
- """The requested object does not exist"""
41
-
42
- pass
43
-
44
-
45
- class MultipleObjectsReturned(Exception):
46
- """The query returned multiple objects when only one was expected."""
47
-
48
- pass
49
-
50
-
51
24
  # MARK: Security and Suspicious Operations
52
25
 
53
26
 
@@ -210,18 +183,3 @@ class ValidationError(Exception):
210
183
  if hasattr(self, "error_dict"):
211
184
  return hash(make_hashable(self.error_dict))
212
185
  return hash(tuple(sorted(self.error_list, key=operator.attrgetter("message"))))
213
-
214
-
215
- # MARK: Database
216
-
217
-
218
- class EmptyResultSet(Exception):
219
- """A database query predicate is impossible."""
220
-
221
- pass
222
-
223
-
224
- class FullResultSet(Exception):
225
- """A database query predicate is matches everything."""
226
-
227
- pass
@@ -1,7 +1,13 @@
1
1
  from functools import cached_property
2
2
  from typing import Any
3
3
 
4
- from plain.exceptions import ImproperlyConfigured, ObjectDoesNotExist
4
+ from plain.exceptions import ImproperlyConfigured
5
+
6
+ try:
7
+ from plain.models.exceptions import ObjectDoesNotExist
8
+ except ImportError:
9
+ ObjectDoesNotExist = None
10
+
5
11
  from plain.forms import Form
6
12
  from plain.http import Http404
7
13
 
@@ -42,8 +48,12 @@ class ObjectTemplateViewMixin:
42
48
  def object(self) -> Any:
43
49
  try:
44
50
  obj = self.get_object()
45
- except ObjectDoesNotExist:
46
- raise Http404
51
+ except Exception as e:
52
+ # If ObjectDoesNotExist is available and this is that exception, raise 404
53
+ if ObjectDoesNotExist and isinstance(e, ObjectDoesNotExist):
54
+ raise Http404
55
+ # Otherwise, let other exceptions bubble up
56
+ raise
47
57
 
48
58
  # Also raise 404 if get_object() returns None
49
59
  if not obj:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "plain"
3
- version = "0.68.1"
3
+ version = "0.69.0"
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"
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
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