plain 0.2.0__tar.gz → 0.2.1__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 (159) hide show
  1. {plain-0.2.0 → plain-0.2.1}/PKG-INFO +1 -1
  2. plain-0.2.1/plain/assets/README.md +94 -0
  3. {plain-0.2.0 → plain-0.2.1}/plain/assets/compile.py +10 -0
  4. {plain-0.2.0 → plain-0.2.1}/plain/cli/cli.py +8 -9
  5. {plain-0.2.0 → plain-0.2.1}/plain/runtime/global_settings.py +0 -4
  6. {plain-0.2.0 → plain-0.2.1}/pyproject.toml +1 -1
  7. plain-0.2.0/plain/assets/README.md +0 -37
  8. {plain-0.2.0 → plain-0.2.1}/LICENSE +0 -0
  9. {plain-0.2.0 → plain-0.2.1}/README.md +0 -0
  10. {plain-0.2.0 → plain-0.2.1}/plain/README.md +0 -0
  11. {plain-0.2.0 → plain-0.2.1}/plain/__main__.py +0 -0
  12. {plain-0.2.0 → plain-0.2.1}/plain/assets/__init__.py +0 -0
  13. {plain-0.2.0 → plain-0.2.1}/plain/assets/finders.py +0 -0
  14. {plain-0.2.0 → plain-0.2.1}/plain/assets/fingerprints.py +0 -0
  15. {plain-0.2.0 → plain-0.2.1}/plain/assets/urls.py +0 -0
  16. {plain-0.2.0 → plain-0.2.1}/plain/assets/views.py +0 -0
  17. {plain-0.2.0 → plain-0.2.1}/plain/cli/README.md +0 -0
  18. {plain-0.2.0 → plain-0.2.1}/plain/cli/__init__.py +0 -0
  19. {plain-0.2.0 → plain-0.2.1}/plain/cli/formatting.py +0 -0
  20. {plain-0.2.0 → plain-0.2.1}/plain/cli/packages.py +0 -0
  21. {plain-0.2.0 → plain-0.2.1}/plain/cli/print.py +0 -0
  22. {plain-0.2.0 → plain-0.2.1}/plain/cli/startup.py +0 -0
  23. {plain-0.2.0 → plain-0.2.1}/plain/csrf/README.md +0 -0
  24. {plain-0.2.0 → plain-0.2.1}/plain/csrf/middleware.py +0 -0
  25. {plain-0.2.0 → plain-0.2.1}/plain/csrf/views.py +0 -0
  26. {plain-0.2.0 → plain-0.2.1}/plain/debug.py +0 -0
  27. {plain-0.2.0 → plain-0.2.1}/plain/exceptions.py +0 -0
  28. {plain-0.2.0 → plain-0.2.1}/plain/forms/README.md +0 -0
  29. {plain-0.2.0 → plain-0.2.1}/plain/forms/__init__.py +0 -0
  30. {plain-0.2.0 → plain-0.2.1}/plain/forms/boundfield.py +0 -0
  31. {plain-0.2.0 → plain-0.2.1}/plain/forms/exceptions.py +0 -0
  32. {plain-0.2.0 → plain-0.2.1}/plain/forms/fields.py +0 -0
  33. {plain-0.2.0 → plain-0.2.1}/plain/forms/forms.py +0 -0
  34. {plain-0.2.0 → plain-0.2.1}/plain/http/README.md +0 -0
  35. {plain-0.2.0 → plain-0.2.1}/plain/http/__init__.py +0 -0
  36. {plain-0.2.0 → plain-0.2.1}/plain/http/cookie.py +0 -0
  37. {plain-0.2.0 → plain-0.2.1}/plain/http/multipartparser.py +0 -0
  38. {plain-0.2.0 → plain-0.2.1}/plain/http/request.py +0 -0
  39. {plain-0.2.0 → plain-0.2.1}/plain/http/response.py +0 -0
  40. {plain-0.2.0 → plain-0.2.1}/plain/internal/__init__.py +0 -0
  41. {plain-0.2.0 → plain-0.2.1}/plain/internal/files/README.md +0 -0
  42. {plain-0.2.0 → plain-0.2.1}/plain/internal/files/__init__.py +0 -0
  43. {plain-0.2.0 → plain-0.2.1}/plain/internal/files/base.py +0 -0
  44. {plain-0.2.0 → plain-0.2.1}/plain/internal/files/locks.py +0 -0
  45. {plain-0.2.0 → plain-0.2.1}/plain/internal/files/move.py +0 -0
  46. {plain-0.2.0 → plain-0.2.1}/plain/internal/files/temp.py +0 -0
  47. {plain-0.2.0 → plain-0.2.1}/plain/internal/files/uploadedfile.py +0 -0
  48. {plain-0.2.0 → plain-0.2.1}/plain/internal/files/uploadhandler.py +0 -0
  49. {plain-0.2.0 → plain-0.2.1}/plain/internal/files/utils.py +0 -0
  50. {plain-0.2.0 → plain-0.2.1}/plain/internal/handlers/__init__.py +0 -0
  51. {plain-0.2.0 → plain-0.2.1}/plain/internal/handlers/base.py +0 -0
  52. {plain-0.2.0 → plain-0.2.1}/plain/internal/handlers/exception.py +0 -0
  53. {plain-0.2.0 → plain-0.2.1}/plain/internal/handlers/wsgi.py +0 -0
  54. {plain-0.2.0 → plain-0.2.1}/plain/internal/legacy/__init__.py +0 -0
  55. {plain-0.2.0 → plain-0.2.1}/plain/internal/legacy/__main__.py +0 -0
  56. {plain-0.2.0 → plain-0.2.1}/plain/internal/legacy/management/__init__.py +0 -0
  57. {plain-0.2.0 → plain-0.2.1}/plain/internal/legacy/management/base.py +0 -0
  58. {plain-0.2.0 → plain-0.2.1}/plain/internal/legacy/management/color.py +0 -0
  59. {plain-0.2.0 → plain-0.2.1}/plain/internal/legacy/management/sql.py +0 -0
  60. {plain-0.2.0 → plain-0.2.1}/plain/internal/legacy/management/utils.py +0 -0
  61. {plain-0.2.0 → plain-0.2.1}/plain/json.py +0 -0
  62. {plain-0.2.0 → plain-0.2.1}/plain/logs/README.md +0 -0
  63. {plain-0.2.0 → plain-0.2.1}/plain/logs/__init__.py +0 -0
  64. {plain-0.2.0 → plain-0.2.1}/plain/logs/configure.py +0 -0
  65. {plain-0.2.0 → plain-0.2.1}/plain/logs/loggers.py +0 -0
  66. {plain-0.2.0 → plain-0.2.1}/plain/logs/utils.py +0 -0
  67. {plain-0.2.0 → plain-0.2.1}/plain/middleware/README.md +0 -0
  68. {plain-0.2.0 → plain-0.2.1}/plain/middleware/__init__.py +0 -0
  69. {plain-0.2.0 → plain-0.2.1}/plain/middleware/clickjacking.py +0 -0
  70. {plain-0.2.0 → plain-0.2.1}/plain/middleware/common.py +0 -0
  71. {plain-0.2.0 → plain-0.2.1}/plain/middleware/gzip.py +0 -0
  72. {plain-0.2.0 → plain-0.2.1}/plain/middleware/security.py +0 -0
  73. {plain-0.2.0 → plain-0.2.1}/plain/packages/README.md +0 -0
  74. {plain-0.2.0 → plain-0.2.1}/plain/packages/__init__.py +0 -0
  75. {plain-0.2.0 → plain-0.2.1}/plain/packages/config.py +0 -0
  76. {plain-0.2.0 → plain-0.2.1}/plain/packages/registry.py +0 -0
  77. {plain-0.2.0 → plain-0.2.1}/plain/paginator.py +0 -0
  78. {plain-0.2.0 → plain-0.2.1}/plain/preflight/README.md +0 -0
  79. {plain-0.2.0 → plain-0.2.1}/plain/preflight/__init__.py +0 -0
  80. {plain-0.2.0 → plain-0.2.1}/plain/preflight/compatibility/__init__.py +0 -0
  81. {plain-0.2.0 → plain-0.2.1}/plain/preflight/compatibility/django_4_0.py +0 -0
  82. {plain-0.2.0 → plain-0.2.1}/plain/preflight/files.py +0 -0
  83. {plain-0.2.0 → plain-0.2.1}/plain/preflight/messages.py +0 -0
  84. {plain-0.2.0 → plain-0.2.1}/plain/preflight/registry.py +0 -0
  85. {plain-0.2.0 → plain-0.2.1}/plain/preflight/security/__init__.py +0 -0
  86. {plain-0.2.0 → plain-0.2.1}/plain/preflight/security/base.py +0 -0
  87. {plain-0.2.0 → plain-0.2.1}/plain/preflight/security/csrf.py +0 -0
  88. {plain-0.2.0 → plain-0.2.1}/plain/preflight/urls.py +0 -0
  89. {plain-0.2.0 → plain-0.2.1}/plain/runtime/README.md +0 -0
  90. {plain-0.2.0 → plain-0.2.1}/plain/runtime/__init__.py +0 -0
  91. {plain-0.2.0 → plain-0.2.1}/plain/runtime/user_settings.py +0 -0
  92. {plain-0.2.0 → plain-0.2.1}/plain/signals/README.md +0 -0
  93. {plain-0.2.0 → plain-0.2.1}/plain/signals/__init__.py +0 -0
  94. {plain-0.2.0 → plain-0.2.1}/plain/signals/dispatch/__init__.py +0 -0
  95. {plain-0.2.0 → plain-0.2.1}/plain/signals/dispatch/dispatcher.py +0 -0
  96. {plain-0.2.0 → plain-0.2.1}/plain/signals/dispatch/license.txt +0 -0
  97. {plain-0.2.0 → plain-0.2.1}/plain/signing.py +0 -0
  98. {plain-0.2.0 → plain-0.2.1}/plain/templates/README.md +0 -0
  99. {plain-0.2.0 → plain-0.2.1}/plain/templates/__init__.py +0 -0
  100. {plain-0.2.0 → plain-0.2.1}/plain/templates/core.py +0 -0
  101. {plain-0.2.0 → plain-0.2.1}/plain/templates/jinja/README.md +0 -0
  102. {plain-0.2.0 → plain-0.2.1}/plain/templates/jinja/__init__.py +0 -0
  103. {plain-0.2.0 → plain-0.2.1}/plain/templates/jinja/defaults.py +0 -0
  104. {plain-0.2.0 → plain-0.2.1}/plain/templates/jinja/extensions.py +0 -0
  105. {plain-0.2.0 → plain-0.2.1}/plain/templates/jinja/filters.py +0 -0
  106. {plain-0.2.0 → plain-0.2.1}/plain/templates/jinja/globals.py +0 -0
  107. {plain-0.2.0 → plain-0.2.1}/plain/test/README.md +0 -0
  108. {plain-0.2.0 → plain-0.2.1}/plain/test/__init__.py +0 -0
  109. {plain-0.2.0 → plain-0.2.1}/plain/test/client.py +0 -0
  110. {plain-0.2.0 → plain-0.2.1}/plain/urls/README.md +0 -0
  111. {plain-0.2.0 → plain-0.2.1}/plain/urls/__init__.py +0 -0
  112. {plain-0.2.0 → plain-0.2.1}/plain/urls/base.py +0 -0
  113. {plain-0.2.0 → plain-0.2.1}/plain/urls/conf.py +0 -0
  114. {plain-0.2.0 → plain-0.2.1}/plain/urls/converters.py +0 -0
  115. {plain-0.2.0 → plain-0.2.1}/plain/urls/exceptions.py +0 -0
  116. {plain-0.2.0 → plain-0.2.1}/plain/urls/resolvers.py +0 -0
  117. {plain-0.2.0 → plain-0.2.1}/plain/utils/README.md +0 -0
  118. {plain-0.2.0 → plain-0.2.1}/plain/utils/__init__.py +0 -0
  119. {plain-0.2.0 → plain-0.2.1}/plain/utils/_os.py +0 -0
  120. {plain-0.2.0 → plain-0.2.1}/plain/utils/cache.py +0 -0
  121. {plain-0.2.0 → plain-0.2.1}/plain/utils/connection.py +0 -0
  122. {plain-0.2.0 → plain-0.2.1}/plain/utils/crypto.py +0 -0
  123. {plain-0.2.0 → plain-0.2.1}/plain/utils/datastructures.py +0 -0
  124. {plain-0.2.0 → plain-0.2.1}/plain/utils/dateformat.py +0 -0
  125. {plain-0.2.0 → plain-0.2.1}/plain/utils/dateparse.py +0 -0
  126. {plain-0.2.0 → plain-0.2.1}/plain/utils/dates.py +0 -0
  127. {plain-0.2.0 → plain-0.2.1}/plain/utils/deconstruct.py +0 -0
  128. {plain-0.2.0 → plain-0.2.1}/plain/utils/decorators.py +0 -0
  129. {plain-0.2.0 → plain-0.2.1}/plain/utils/deprecation.py +0 -0
  130. {plain-0.2.0 → plain-0.2.1}/plain/utils/duration.py +0 -0
  131. {plain-0.2.0 → plain-0.2.1}/plain/utils/email.py +0 -0
  132. {plain-0.2.0 → plain-0.2.1}/plain/utils/encoding.py +0 -0
  133. {plain-0.2.0 → plain-0.2.1}/plain/utils/functional.py +0 -0
  134. {plain-0.2.0 → plain-0.2.1}/plain/utils/hashable.py +0 -0
  135. {plain-0.2.0 → plain-0.2.1}/plain/utils/html.py +0 -0
  136. {plain-0.2.0 → plain-0.2.1}/plain/utils/http.py +0 -0
  137. {plain-0.2.0 → plain-0.2.1}/plain/utils/inspect.py +0 -0
  138. {plain-0.2.0 → plain-0.2.1}/plain/utils/ipv6.py +0 -0
  139. {plain-0.2.0 → plain-0.2.1}/plain/utils/itercompat.py +0 -0
  140. {plain-0.2.0 → plain-0.2.1}/plain/utils/module_loading.py +0 -0
  141. {plain-0.2.0 → plain-0.2.1}/plain/utils/regex_helper.py +0 -0
  142. {plain-0.2.0 → plain-0.2.1}/plain/utils/safestring.py +0 -0
  143. {plain-0.2.0 → plain-0.2.1}/plain/utils/termcolors.py +0 -0
  144. {plain-0.2.0 → plain-0.2.1}/plain/utils/text.py +0 -0
  145. {plain-0.2.0 → plain-0.2.1}/plain/utils/timesince.py +0 -0
  146. {plain-0.2.0 → plain-0.2.1}/plain/utils/timezone.py +0 -0
  147. {plain-0.2.0 → plain-0.2.1}/plain/utils/tree.py +0 -0
  148. {plain-0.2.0 → plain-0.2.1}/plain/validators.py +0 -0
  149. {plain-0.2.0 → plain-0.2.1}/plain/views/README.md +0 -0
  150. {plain-0.2.0 → plain-0.2.1}/plain/views/__init__.py +0 -0
  151. {plain-0.2.0 → plain-0.2.1}/plain/views/base.py +0 -0
  152. {plain-0.2.0 → plain-0.2.1}/plain/views/csrf.py +0 -0
  153. {plain-0.2.0 → plain-0.2.1}/plain/views/errors.py +0 -0
  154. {plain-0.2.0 → plain-0.2.1}/plain/views/exceptions.py +0 -0
  155. {plain-0.2.0 → plain-0.2.1}/plain/views/forms.py +0 -0
  156. {plain-0.2.0 → plain-0.2.1}/plain/views/objects.py +0 -0
  157. {plain-0.2.0 → plain-0.2.1}/plain/views/redirect.py +0 -0
  158. {plain-0.2.0 → plain-0.2.1}/plain/views/templates.py +0 -0
  159. {plain-0.2.0 → plain-0.2.1}/plain/wsgi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: plain
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: A web framework for building products with Python.
5
5
  Author: Dave Gaeddert
6
6
  Author-email: dave.gaeddert@dropseed.dev
@@ -0,0 +1,94 @@
1
+ # Assets
2
+
3
+ Serve static assets (CSS, JS, images, etc.) directly from your app.
4
+
5
+
6
+ ## Usage
7
+
8
+ To serve assets, put them in `app/assets` or `app/{package}/assets`.
9
+
10
+ Then include the `plain.assets.urls` in your `urls.py`:
11
+
12
+ ```python
13
+ # app/urls.py
14
+ from plain.urls import include, path
15
+ import plain.assets.urls
16
+
17
+
18
+ urlpatterns = [
19
+ path("assets/", include(plain.assets.urls)),
20
+ # ...
21
+ ]
22
+ ```
23
+
24
+ Now in your template you can use the `asset()` function to get the URL:
25
+
26
+ ```html
27
+ <link rel="stylesheet" href="{{ asset('css/style.css') }}">
28
+ ```
29
+
30
+
31
+ ## Local development
32
+
33
+ When you're working with `settings.DEBUG = True`, the assets will be served directly from their original location. You don't need to run `plain compile` or configure anything else.
34
+
35
+
36
+ ## Production deployment
37
+
38
+ In production, one of your deployment steps should be to compile the assets.
39
+
40
+ ```bash
41
+ plain compile
42
+ ```
43
+
44
+ By default, this generates "fingerprinted" and compressed versions of the assets, which are then served by your app. This means that a file like `main.css` will result in two new files, like `main.d0db67b.css` and `main.d0db67b.css.gz`.
45
+
46
+ The purpose of fingerprinting the assets is to allow the browser to cache them indefinitely. When the content of the file changes, the fingerprint will change, and the browser will use the newer file. This cuts down on the number of requests that your app has to handle related to assets.
47
+
48
+
49
+ ## FAQs
50
+
51
+ ### How do you reference assets in Python code?
52
+
53
+ ```python
54
+ from plain.assets.urls import get_asset_url
55
+
56
+ url = get_asset_url("css/style.css")
57
+ ```
58
+
59
+ ### What if I need the files in a different location?
60
+
61
+ The generated/copied files are stored in `{repo}/.plain/assets/compiled`. If you need them to be somewhere else, try simply moving them after compilation.
62
+
63
+ ```bash
64
+ plain compile
65
+ mv .plain/assets/compiled /path/to/your/static
66
+ ```
67
+
68
+ ### How do I upload the assets to a CDN?
69
+
70
+ The steps for this will vary, but the general idea is to compile them, and then upload the compiled assets.
71
+
72
+ ```bash
73
+ plain compile
74
+ ./example-upload-to-cdn-script
75
+ ```
76
+
77
+ Use the `ASSETS_BASE_URL` setting to tell the `{{ asset() }}` template function where to point.
78
+
79
+ ```python
80
+ # app/settings.py
81
+ ASSETS_BASE_URL = "https://cdn.example.com/"
82
+ ```
83
+
84
+
85
+ ### Why aren't the originals copied to the compiled directory?
86
+
87
+ The default behavior is to fingerprint assets, which is an exact copy of the original file but with a different filename. The originals aren't copied over because you should generally always use this fingerprinted path (that automatically uses longer-lived caching).
88
+
89
+ If you need the originals for any reason, you can use `plain compile --keep-original`, though this will typically be combined with `--no-fingerprint` otherwise the fingerprinted files will still get priority in `{{ asset() }}` template calls.
90
+
91
+
92
+ ### What about source maps or imported css files?
93
+
94
+ TODO
@@ -3,6 +3,8 @@ import hashlib
3
3
  import os
4
4
  import shutil
5
5
 
6
+ from plain.runtime import settings
7
+
6
8
  from .finders import find_assets
7
9
  from .fingerprints import AssetsFingerprintsManifest
8
10
 
@@ -41,6 +43,14 @@ SKIP_COMPRESS_EXTENSIONS = (
41
43
  )
42
44
 
43
45
 
46
+ def get_compiled_path():
47
+ """
48
+ Get the path at runtime to the compiled assets directory.
49
+ There's no reason currently for this to be a user-facing setting.
50
+ """
51
+ return settings.PLAIN_TEMP_PATH / "assets" / "compiled"
52
+
53
+
44
54
  def compile_assets(*, target_dir, keep_original, fingerprint, compress):
45
55
  manifest = AssetsFingerprintsManifest()
46
56
 
@@ -13,9 +13,8 @@ from click.core import Command, Context
13
13
 
14
14
  import plain.runtime
15
15
  from plain import preflight
16
- from plain.assets.compile import compile_assets
16
+ from plain.assets.compile import compile_assets, get_compiled_path
17
17
  from plain.packages import packages
18
- from plain.runtime import settings
19
18
 
20
19
  from .formatting import PlainContext
21
20
  from .packages import EntryPointGroup, InstalledPackagesGroup
@@ -336,18 +335,18 @@ def compile(keep_original, fingerprint, compress):
336
335
  sys.exit(result.returncode)
337
336
 
338
337
  # Compile our assets
339
- compiled_target_dir = settings.ASSETS_COMPILED_PATH
340
- click.secho(f"Compiling assets to {compiled_target_dir}", bold=True)
341
- if compiled_target_dir.exists():
338
+ target_dir = get_compiled_path()
339
+ click.secho(f"Compiling assets to {target_dir}", bold=True)
340
+ if target_dir.exists():
342
341
  click.secho("(clearing previously compiled assets)")
343
- shutil.rmtree(compiled_target_dir)
344
- compiled_target_dir.mkdir(parents=True, exist_ok=True)
342
+ shutil.rmtree(target_dir)
343
+ target_dir.mkdir(parents=True, exist_ok=True)
345
344
 
346
345
  total_files = 0
347
346
  total_compiled = 0
348
347
 
349
348
  for url_path, resolved_url_path, compiled_paths in compile_assets(
350
- target_dir=compiled_target_dir,
349
+ target_dir=target_dir,
351
350
  keep_original=keep_original,
352
351
  fingerprint=fingerprint,
353
352
  compress=compress,
@@ -365,7 +364,7 @@ def compile(keep_original, fingerprint, compress):
365
364
  total_compiled += len(compiled_paths)
366
365
 
367
366
  click.secho(
368
- f"Compiled {total_files} assets into {total_compiled} files", fg="green"
367
+ f"\nCompiled {total_files} assets into {total_compiled} files", fg="green"
369
368
  )
370
369
 
371
370
 
@@ -150,10 +150,6 @@ LOGGING = {}
150
150
  # ASSETS #
151
151
  ###############
152
152
 
153
- # Absolute path to the directory assets files should be collected to.
154
- # Example: "/var/www/example.com/assets/"
155
- ASSETS_COMPILED_PATH = PLAIN_TEMP_PATH / "assets" / "compiled"
156
-
157
153
  # Whether to redirect the original asset path to the fingerprinted path.
158
154
  ASSETS_REDIRECT_ORIGINAL = True
159
155
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "plain"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "A web framework for building products with Python."
5
5
  authors = ["Dave Gaeddert <dave.gaeddert@dropseed.dev>"]
6
6
  readme = "README.md"
@@ -1,37 +0,0 @@
1
- # Assets
2
-
3
- Serve static assets (CSS, JS, images, etc.) directly from your app.
4
-
5
- The default behavior is for Plain to serve its own assets through a view. This behaves in a way similar to [Whitenoise](https://whitenoise.readthedocs.io/en/latest/).
6
-
7
- ## Usage
8
-
9
- To include assests in your app, put them either in `app/assets` or `app/<package>/assets`.
10
-
11
- Then include the `plain.assets.urls` in your `urls.py`:
12
-
13
- ```python
14
- # app/urls.py
15
- from plain.urls import include, path
16
- import plain.assets.urls
17
-
18
-
19
- urlpatterns = [
20
- path("assets/", include(plain.assets.urls)),
21
- # ...
22
- ]
23
- ```
24
-
25
- Then in your template you can use the `asset()` function to get the URL.
26
-
27
- ```html
28
- <link rel="stylesheet" href="{{ asset('css/style.css') }}">
29
- ```
30
-
31
- If you ever need to reference an asset directly in Python code, you can use the `get_asset_url()` function.
32
-
33
- ```python
34
- from plain.assets.urls import get_asset_url
35
-
36
- print(get_asset_url("css/style.css"))
37
- ```
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