Ver Fonte

falsk rofms

TelenkovDmitry há 1 ano atrás
pai
commit
a502db9750
100 ficheiros alterados com 6237 adições e 0 exclusões
  1. BIN
      courses/flask/microblog/__pycache__/config.cpython-310.pyc
  2. BIN
      courses/flask/microblog/__pycache__/microblog.cpython-310.pyc
  3. 2 0
      courses/flask/microblog/app/__init__.py
  4. BIN
      courses/flask/microblog/app/__pycache__/__init__.cpython-310.pyc
  5. 10 0
      courses/flask/microblog/app/forms.py
  6. 0 0
      courses/flask/microblog/app/templates/login.html
  7. 6 0
      courses/flask/microblog/config.py
  8. 1 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf-1.2.1.dist-info/INSTALLER
  9. 72 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf-1.2.1.dist-info/METADATA
  10. 26 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf-1.2.1.dist-info/RECORD
  11. 0 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf-1.2.1.dist-info/REQUESTED
  12. 4 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf-1.2.1.dist-info/WHEEL
  13. 28 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf-1.2.1.dist-info/licenses/LICENSE.rst
  14. 8 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/__init__.py
  15. BIN
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/__pycache__/__init__.cpython-310.pyc
  16. BIN
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/__pycache__/_compat.cpython-310.pyc
  17. BIN
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/__pycache__/csrf.cpython-310.pyc
  18. BIN
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/__pycache__/file.cpython-310.pyc
  19. BIN
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/__pycache__/form.cpython-310.pyc
  20. BIN
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/__pycache__/i18n.cpython-310.pyc
  21. 11 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/_compat.py
  22. 329 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/csrf.py
  23. 147 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/file.py
  24. 127 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/form.py
  25. 47 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/i18n.py
  26. 3 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/__init__.py
  27. BIN
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/__pycache__/__init__.cpython-310.pyc
  28. BIN
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/__pycache__/fields.cpython-310.pyc
  29. BIN
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/__pycache__/validators.cpython-310.pyc
  30. BIN
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/__pycache__/widgets.cpython-310.pyc
  31. 17 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/fields.py
  32. 75 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/validators.py
  33. 43 0
      courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/widgets.py
  34. 1 0
      courses/flask/microblog/env/Lib/site-packages/wtforms-3.1.0.dist-info/INSTALLER
  35. 119 0
      courses/flask/microblog/env/Lib/site-packages/wtforms-3.1.0.dist-info/METADATA
  36. 107 0
      courses/flask/microblog/env/Lib/site-packages/wtforms-3.1.0.dist-info/RECORD
  37. 4 0
      courses/flask/microblog/env/Lib/site-packages/wtforms-3.1.0.dist-info/WHEEL
  38. 28 0
      courses/flask/microblog/env/Lib/site-packages/wtforms-3.1.0.dist-info/licenses/LICENSE.rst
  39. 7 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/__init__.py
  40. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/__pycache__/__init__.cpython-310.pyc
  41. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/__pycache__/form.cpython-310.pyc
  42. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/__pycache__/i18n.cpython-310.pyc
  43. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/__pycache__/meta.cpython-310.pyc
  44. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/__pycache__/utils.cpython-310.pyc
  45. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/__pycache__/validators.cpython-310.pyc
  46. 0 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/csrf/__init__.py
  47. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/csrf/__pycache__/__init__.cpython-310.pyc
  48. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/csrf/__pycache__/core.cpython-310.pyc
  49. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/csrf/__pycache__/session.cpython-310.pyc
  50. 96 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/csrf/core.py
  51. 92 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/csrf/session.py
  52. 11 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__init__.py
  53. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/__init__.cpython-310.pyc
  54. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/choices.cpython-310.pyc
  55. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/core.cpython-310.pyc
  56. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/datetime.cpython-310.pyc
  57. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/form.cpython-310.pyc
  58. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/list.cpython-310.pyc
  59. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/numeric.cpython-310.pyc
  60. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/simple.cpython-310.pyc
  61. 219 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/choices.py
  62. 453 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/core.py
  63. 169 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/datetime.py
  64. 97 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/form.py
  65. 201 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/list.py
  66. 213 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/numeric.py
  67. 173 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/fields/simple.py
  68. 329 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/form.py
  69. 72 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/i18n.py
  70. 62 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/README.md
  71. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/ar/LC_MESSAGES/wtforms.mo
  72. 205 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/ar/LC_MESSAGES/wtforms.po
  73. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/bg/LC_MESSAGES/wtforms.mo
  74. 190 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/bg/LC_MESSAGES/wtforms.po
  75. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/ca/LC_MESSAGES/wtforms.mo
  76. 189 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/ca/LC_MESSAGES/wtforms.po
  77. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/cs_CZ/LC_MESSAGES/wtforms.mo
  78. 192 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/cs_CZ/LC_MESSAGES/wtforms.po
  79. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/cy/LC_MESSAGES/wtforms.mo
  80. 189 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/cy/LC_MESSAGES/wtforms.po
  81. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/de/LC_MESSAGES/wtforms.mo
  82. 190 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/de/LC_MESSAGES/wtforms.po
  83. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/de_CH/LC_MESSAGES/wtforms.mo
  84. 190 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/de_CH/LC_MESSAGES/wtforms.po
  85. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/el/LC_MESSAGES/wtforms.mo
  86. 188 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/el/LC_MESSAGES/wtforms.po
  87. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/en/LC_MESSAGES/wtforms.mo
  88. 169 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/en/LC_MESSAGES/wtforms.po
  89. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/es/LC_MESSAGES/wtforms.mo
  90. 187 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/es/LC_MESSAGES/wtforms.po
  91. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/et/LC_MESSAGES/wtforms.mo
  92. 188 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/et/LC_MESSAGES/wtforms.po
  93. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/fa/LC_MESSAGES/wtforms.mo
  94. 187 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/fa/LC_MESSAGES/wtforms.po
  95. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/fi/LC_MESSAGES/wtforms.mo
  96. 188 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/fi/LC_MESSAGES/wtforms.po
  97. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/fr/LC_MESSAGES/wtforms.mo
  98. 188 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/fr/LC_MESSAGES/wtforms.po
  99. BIN
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/he/LC_MESSAGES/wtforms.mo
  100. 188 0
      courses/flask/microblog/env/Lib/site-packages/wtforms/locale/he/LC_MESSAGES/wtforms.po

BIN
courses/flask/microblog/__pycache__/config.cpython-310.pyc


BIN
courses/flask/microblog/__pycache__/microblog.cpython-310.pyc


+ 2 - 0
courses/flask/microblog/app/__init__.py

@@ -1,5 +1,7 @@
 from flask import Flask
+from config import Config
 
 app = Flask(__name__)
+app.config.from_object(Config)
 
 from app import routes

BIN
courses/flask/microblog/app/__pycache__/__init__.cpython-310.pyc


+ 10 - 0
courses/flask/microblog/app/forms.py

@@ -0,0 +1,10 @@
+from flask_wtf import FlaskForm
+from wtforms import StringField, PasswordField, BooleanField, SubmitField
+from wtforms.validators import DataRequired
+
+
+class LiginForm(FlaskForm):
+    username = StringField('Username', validators=[DataRequired()])
+    password = PasswordField('Password', validators=[DataRequired])
+    remember_me = BooleanField('Remember Me')
+    submit = SubmitField('Sign In')

+ 0 - 0
courses/flask/microblog/app/templates/login.html


+ 6 - 0
courses/flask/microblog/config.py

@@ -0,0 +1,6 @@
+import os
+
+class Config(object):
+    SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'
+
+    

+ 1 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf-1.2.1.dist-info/INSTALLER

@@ -0,0 +1 @@
+pip

+ 72 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf-1.2.1.dist-info/METADATA

@@ -0,0 +1,72 @@
+Metadata-Version: 2.1
+Name: Flask-WTF
+Version: 1.2.1
+Summary: Form rendering, validation, and CSRF protection for Flask with WTForms.
+Project-URL: Documentation, https://flask-wtf.readthedocs.io/
+Project-URL: Changes, https://flask-wtf.readthedocs.io/changes/
+Project-URL: Source Code, https://github.com/wtforms/flask-wtf/
+Project-URL: Issue Tracker, https://github.com/wtforms/flask-wtf/issues/
+Project-URL: Chat, https://discord.gg/pallets
+Maintainer: WTForms
+License: Copyright 2010 WTForms
+        
+        Redistribution and use in source and binary forms, with or without
+        modification, are permitted provided that the following conditions are
+        met:
+        
+        1.  Redistributions of source code must retain the above copyright
+            notice, this list of conditions and the following disclaimer.
+        
+        2.  Redistributions in binary form must reproduce the above copyright
+            notice, this list of conditions and the following disclaimer in the
+            documentation and/or other materials provided with the distribution.
+        
+        3.  Neither the name of the copyright holder nor the names of its
+            contributors may be used to endorse or promote products derived from
+            this software without specific prior written permission.
+        
+        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+        "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+        PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+        HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+        SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+        TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+        PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+        LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+        NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+        SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+License-File: LICENSE.rst
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
+Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
+Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
+Requires-Python: >=3.8
+Requires-Dist: flask
+Requires-Dist: itsdangerous
+Requires-Dist: wtforms
+Provides-Extra: email
+Requires-Dist: email-validator; extra == 'email'
+Description-Content-Type: text/x-rst
+
+Flask-WTF
+=========
+
+Simple integration of Flask and WTForms, including CSRF, file upload,
+and reCAPTCHA.
+
+Links
+-----
+
+-   Documentation: https://flask-wtf.readthedocs.io/
+-   Changes: https://flask-wtf.readthedocs.io/changes/
+-   PyPI Releases: https://pypi.org/project/Flask-WTF/
+-   Source Code: https://github.com/wtforms/flask-wtf/
+-   Issue Tracker: https://github.com/wtforms/flask-wtf/issues/
+-   Chat: https://discord.gg/pallets

+ 26 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf-1.2.1.dist-info/RECORD

@@ -0,0 +1,26 @@
+flask_wtf-1.2.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+flask_wtf-1.2.1.dist-info/METADATA,sha256=9Y5upDJ7WU2m2l4erWImF3HcVSWIZKH3TdX6klYpq4M,3373
+flask_wtf-1.2.1.dist-info/RECORD,,
+flask_wtf-1.2.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+flask_wtf-1.2.1.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
+flask_wtf-1.2.1.dist-info/licenses/LICENSE.rst,sha256=1fGQNkUVeMs27u8EyZ6_fXyi5w3PBDY2UZvEIOFafGI,1475
+flask_wtf/__init__.py,sha256=x6ydw5SJzsXZgz-Y6IM_95Sy8VufRepvZH1DUIlFoTo,214
+flask_wtf/__pycache__/__init__.cpython-310.pyc,,
+flask_wtf/__pycache__/_compat.cpython-310.pyc,,
+flask_wtf/__pycache__/csrf.cpython-310.pyc,,
+flask_wtf/__pycache__/file.cpython-310.pyc,,
+flask_wtf/__pycache__/form.cpython-310.pyc,,
+flask_wtf/__pycache__/i18n.cpython-310.pyc,,
+flask_wtf/_compat.py,sha256=N3sqC9yzFWY-3MZ7QazX1sidvkO3d5yy4NR6lkp0s94,248
+flask_wtf/csrf.py,sha256=O-fjnWygxxi_FsIU2koua97ZpIhiOJVDHA57dXLpvTA,10171
+flask_wtf/file.py,sha256=AsfkYTCgtqGWySimc_NjeAxg-DtpdcthhqMLrXIDAhU,4706
+flask_wtf/form.py,sha256=TmR7xCrxin2LHp6thn7fq1OeU8aLB7xsZzvv52nH7Ss,4049
+flask_wtf/i18n.py,sha256=TyO8gqt9DocHMSaNhj0KKgxoUrPYs-G1nVW-jns0SOw,1166
+flask_wtf/recaptcha/__init__.py,sha256=m4eNGoU3Q0Wnt_wP8VvOlA0mwWuoMtAcK9pYT7sPFp8,106
+flask_wtf/recaptcha/__pycache__/__init__.cpython-310.pyc,,
+flask_wtf/recaptcha/__pycache__/fields.cpython-310.pyc,,
+flask_wtf/recaptcha/__pycache__/validators.cpython-310.pyc,,
+flask_wtf/recaptcha/__pycache__/widgets.cpython-310.pyc,,
+flask_wtf/recaptcha/fields.py,sha256=M1-RFuUKOsJAzsLm3xaaxuhX2bB9oRqS-HVSN-NpkmI,433
+flask_wtf/recaptcha/validators.py,sha256=3sd1mUQT3Y3D_WJeKwecxUGstnhh_QD-A_dEBJfkf6s,2434
+flask_wtf/recaptcha/widgets.py,sha256=J_XyxAZt3uB15diIMnkXXGII2dmsWCsVsKV3KQYn4Ns,1512

+ 0 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf-1.2.1.dist-info/REQUESTED


+ 4 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf-1.2.1.dist-info/WHEEL

@@ -0,0 +1,4 @@
+Wheel-Version: 1.0
+Generator: hatchling 1.18.0
+Root-Is-Purelib: true
+Tag: py3-none-any

+ 28 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf-1.2.1.dist-info/licenses/LICENSE.rst

@@ -0,0 +1,28 @@
+Copyright 2010 WTForms
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1.  Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+2.  Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+3.  Neither the name of the copyright holder nor the names of its
+    contributors may be used to endorse or promote products derived from
+    this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 8 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf/__init__.py

@@ -0,0 +1,8 @@
+from .csrf import CSRFProtect
+from .form import FlaskForm
+from .form import Form
+from .recaptcha import Recaptcha
+from .recaptcha import RecaptchaField
+from .recaptcha import RecaptchaWidget
+
+__version__ = "1.2.1"

BIN
courses/flask/microblog/env/Lib/site-packages/flask_wtf/__pycache__/__init__.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/flask_wtf/__pycache__/_compat.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/flask_wtf/__pycache__/csrf.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/flask_wtf/__pycache__/file.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/flask_wtf/__pycache__/form.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/flask_wtf/__pycache__/i18n.cpython-310.pyc


+ 11 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf/_compat.py

@@ -0,0 +1,11 @@
+import warnings
+
+
+class FlaskWTFDeprecationWarning(DeprecationWarning):
+    pass
+
+
+warnings.simplefilter("always", FlaskWTFDeprecationWarning)
+warnings.filterwarnings(
+    "ignore", category=FlaskWTFDeprecationWarning, module="wtforms|flask_wtf"
+)

+ 329 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf/csrf.py

@@ -0,0 +1,329 @@
+import hashlib
+import hmac
+import logging
+import os
+from urllib.parse import urlparse
+
+from flask import Blueprint
+from flask import current_app
+from flask import g
+from flask import request
+from flask import session
+from itsdangerous import BadData
+from itsdangerous import SignatureExpired
+from itsdangerous import URLSafeTimedSerializer
+from werkzeug.exceptions import BadRequest
+from wtforms import ValidationError
+from wtforms.csrf.core import CSRF
+
+__all__ = ("generate_csrf", "validate_csrf", "CSRFProtect")
+logger = logging.getLogger(__name__)
+
+
+def generate_csrf(secret_key=None, token_key=None):
+    """Generate a CSRF token. The token is cached for a request, so multiple
+    calls to this function will generate the same token.
+
+    During testing, it might be useful to access the signed token in
+    ``g.csrf_token`` and the raw token in ``session['csrf_token']``.
+
+    :param secret_key: Used to securely sign the token. Default is
+        ``WTF_CSRF_SECRET_KEY`` or ``SECRET_KEY``.
+    :param token_key: Key where token is stored in session for comparison.
+        Default is ``WTF_CSRF_FIELD_NAME`` or ``'csrf_token'``.
+    """
+
+    secret_key = _get_config(
+        secret_key,
+        "WTF_CSRF_SECRET_KEY",
+        current_app.secret_key,
+        message="A secret key is required to use CSRF.",
+    )
+    field_name = _get_config(
+        token_key,
+        "WTF_CSRF_FIELD_NAME",
+        "csrf_token",
+        message="A field name is required to use CSRF.",
+    )
+
+    if field_name not in g:
+        s = URLSafeTimedSerializer(secret_key, salt="wtf-csrf-token")
+
+        if field_name not in session:
+            session[field_name] = hashlib.sha1(os.urandom(64)).hexdigest()
+
+        try:
+            token = s.dumps(session[field_name])
+        except TypeError:
+            session[field_name] = hashlib.sha1(os.urandom(64)).hexdigest()
+            token = s.dumps(session[field_name])
+
+        setattr(g, field_name, token)
+
+    return g.get(field_name)
+
+
+def validate_csrf(data, secret_key=None, time_limit=None, token_key=None):
+    """Check if the given data is a valid CSRF token. This compares the given
+    signed token to the one stored in the session.
+
+    :param data: The signed CSRF token to be checked.
+    :param secret_key: Used to securely sign the token. Default is
+        ``WTF_CSRF_SECRET_KEY`` or ``SECRET_KEY``.
+    :param time_limit: Number of seconds that the token is valid. Default is
+        ``WTF_CSRF_TIME_LIMIT`` or 3600 seconds (60 minutes).
+    :param token_key: Key where token is stored in session for comparison.
+        Default is ``WTF_CSRF_FIELD_NAME`` or ``'csrf_token'``.
+
+    :raises ValidationError: Contains the reason that validation failed.
+
+    .. versionchanged:: 0.14
+        Raises ``ValidationError`` with a specific error message rather than
+        returning ``True`` or ``False``.
+    """
+
+    secret_key = _get_config(
+        secret_key,
+        "WTF_CSRF_SECRET_KEY",
+        current_app.secret_key,
+        message="A secret key is required to use CSRF.",
+    )
+    field_name = _get_config(
+        token_key,
+        "WTF_CSRF_FIELD_NAME",
+        "csrf_token",
+        message="A field name is required to use CSRF.",
+    )
+    time_limit = _get_config(time_limit, "WTF_CSRF_TIME_LIMIT", 3600, required=False)
+
+    if not data:
+        raise ValidationError("The CSRF token is missing.")
+
+    if field_name not in session:
+        raise ValidationError("The CSRF session token is missing.")
+
+    s = URLSafeTimedSerializer(secret_key, salt="wtf-csrf-token")
+
+    try:
+        token = s.loads(data, max_age=time_limit)
+    except SignatureExpired as e:
+        raise ValidationError("The CSRF token has expired.") from e
+    except BadData as e:
+        raise ValidationError("The CSRF token is invalid.") from e
+
+    if not hmac.compare_digest(session[field_name], token):
+        raise ValidationError("The CSRF tokens do not match.")
+
+
+def _get_config(
+    value, config_name, default=None, required=True, message="CSRF is not configured."
+):
+    """Find config value based on provided value, Flask config, and default
+    value.
+
+    :param value: already provided config value
+    :param config_name: Flask ``config`` key
+    :param default: default value if not provided or configured
+    :param required: whether the value must not be ``None``
+    :param message: error message if required config is not found
+    :raises KeyError: if required config is not found
+    """
+
+    if value is None:
+        value = current_app.config.get(config_name, default)
+
+    if required and value is None:
+        raise RuntimeError(message)
+
+    return value
+
+
+class _FlaskFormCSRF(CSRF):
+    def setup_form(self, form):
+        self.meta = form.meta
+        return super().setup_form(form)
+
+    def generate_csrf_token(self, csrf_token_field):
+        return generate_csrf(
+            secret_key=self.meta.csrf_secret, token_key=self.meta.csrf_field_name
+        )
+
+    def validate_csrf_token(self, form, field):
+        if g.get("csrf_valid", False):
+            # already validated by CSRFProtect
+            return
+
+        try:
+            validate_csrf(
+                field.data,
+                self.meta.csrf_secret,
+                self.meta.csrf_time_limit,
+                self.meta.csrf_field_name,
+            )
+        except ValidationError as e:
+            logger.info(e.args[0])
+            raise
+
+
+class CSRFProtect:
+    """Enable CSRF protection globally for a Flask app.
+
+    ::
+
+        app = Flask(__name__)
+        csrf = CSRFProtect(app)
+
+    Checks the ``csrf_token`` field sent with forms, or the ``X-CSRFToken``
+    header sent with JavaScript requests. Render the token in templates using
+    ``{{ csrf_token() }}``.
+
+    See the :ref:`csrf` documentation.
+    """
+
+    def __init__(self, app=None):
+        self._exempt_views = set()
+        self._exempt_blueprints = set()
+
+        if app:
+            self.init_app(app)
+
+    def init_app(self, app):
+        app.extensions["csrf"] = self
+
+        app.config.setdefault("WTF_CSRF_ENABLED", True)
+        app.config.setdefault("WTF_CSRF_CHECK_DEFAULT", True)
+        app.config["WTF_CSRF_METHODS"] = set(
+            app.config.get("WTF_CSRF_METHODS", ["POST", "PUT", "PATCH", "DELETE"])
+        )
+        app.config.setdefault("WTF_CSRF_FIELD_NAME", "csrf_token")
+        app.config.setdefault("WTF_CSRF_HEADERS", ["X-CSRFToken", "X-CSRF-Token"])
+        app.config.setdefault("WTF_CSRF_TIME_LIMIT", 3600)
+        app.config.setdefault("WTF_CSRF_SSL_STRICT", True)
+
+        app.jinja_env.globals["csrf_token"] = generate_csrf
+        app.context_processor(lambda: {"csrf_token": generate_csrf})
+
+        @app.before_request
+        def csrf_protect():
+            if not app.config["WTF_CSRF_ENABLED"]:
+                return
+
+            if not app.config["WTF_CSRF_CHECK_DEFAULT"]:
+                return
+
+            if request.method not in app.config["WTF_CSRF_METHODS"]:
+                return
+
+            if not request.endpoint:
+                return
+
+            if app.blueprints.get(request.blueprint) in self._exempt_blueprints:
+                return
+
+            view = app.view_functions.get(request.endpoint)
+            dest = f"{view.__module__}.{view.__name__}"
+
+            if dest in self._exempt_views:
+                return
+
+            self.protect()
+
+    def _get_csrf_token(self):
+        # find the token in the form data
+        field_name = current_app.config["WTF_CSRF_FIELD_NAME"]
+        base_token = request.form.get(field_name)
+
+        if base_token:
+            return base_token
+
+        # if the form has a prefix, the name will be {prefix}-csrf_token
+        for key in request.form:
+            if key.endswith(field_name):
+                csrf_token = request.form[key]
+
+                if csrf_token:
+                    return csrf_token
+
+        # find the token in the headers
+        for header_name in current_app.config["WTF_CSRF_HEADERS"]:
+            csrf_token = request.headers.get(header_name)
+
+            if csrf_token:
+                return csrf_token
+
+        return None
+
+    def protect(self):
+        if request.method not in current_app.config["WTF_CSRF_METHODS"]:
+            return
+
+        try:
+            validate_csrf(self._get_csrf_token())
+        except ValidationError as e:
+            logger.info(e.args[0])
+            self._error_response(e.args[0])
+
+        if request.is_secure and current_app.config["WTF_CSRF_SSL_STRICT"]:
+            if not request.referrer:
+                self._error_response("The referrer header is missing.")
+
+            good_referrer = f"https://{request.host}/"
+
+            if not same_origin(request.referrer, good_referrer):
+                self._error_response("The referrer does not match the host.")
+
+        g.csrf_valid = True  # mark this request as CSRF valid
+
+    def exempt(self, view):
+        """Mark a view or blueprint to be excluded from CSRF protection.
+
+        ::
+
+            @app.route('/some-view', methods=['POST'])
+            @csrf.exempt
+            def some_view():
+                ...
+
+        ::
+
+            bp = Blueprint(...)
+            csrf.exempt(bp)
+
+        """
+
+        if isinstance(view, Blueprint):
+            self._exempt_blueprints.add(view)
+            return view
+
+        if isinstance(view, str):
+            view_location = view
+        else:
+            view_location = ".".join((view.__module__, view.__name__))
+
+        self._exempt_views.add(view_location)
+        return view
+
+    def _error_response(self, reason):
+        raise CSRFError(reason)
+
+
+class CSRFError(BadRequest):
+    """Raise if the client sends invalid CSRF data with the request.
+
+    Generates a 400 Bad Request response with the failure reason by default.
+    Customize the response by registering a handler with
+    :meth:`flask.Flask.errorhandler`.
+    """
+
+    description = "CSRF validation failed."
+
+
+def same_origin(current_uri, compare_uri):
+    current = urlparse(current_uri)
+    compare = urlparse(compare_uri)
+
+    return (
+        current.scheme == compare.scheme
+        and current.hostname == compare.hostname
+        and current.port == compare.port
+    )

+ 147 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf/file.py

@@ -0,0 +1,147 @@
+from collections import abc
+
+from werkzeug.datastructures import FileStorage
+from wtforms import FileField as _FileField
+from wtforms import MultipleFileField as _MultipleFileField
+from wtforms.validators import DataRequired
+from wtforms.validators import StopValidation
+from wtforms.validators import ValidationError
+
+
+class FileField(_FileField):
+    """Werkzeug-aware subclass of :class:`wtforms.fields.FileField`."""
+
+    def process_formdata(self, valuelist):
+        valuelist = (x for x in valuelist if isinstance(x, FileStorage) and x)
+        data = next(valuelist, None)
+
+        if data is not None:
+            self.data = data
+        else:
+            self.raw_data = ()
+
+
+class MultipleFileField(_MultipleFileField):
+    """Werkzeug-aware subclass of :class:`wtforms.fields.MultipleFileField`.
+
+    .. versionadded:: 1.2.0
+    """
+
+    def process_formdata(self, valuelist):
+        valuelist = (x for x in valuelist if isinstance(x, FileStorage) and x)
+        data = list(valuelist) or None
+
+        if data is not None:
+            self.data = data
+        else:
+            self.raw_data = ()
+
+
+class FileRequired(DataRequired):
+    """Validates that the uploaded files(s) is a Werkzeug
+    :class:`~werkzeug.datastructures.FileStorage` object.
+
+    :param message: error message
+
+    You can also use the synonym ``file_required``.
+    """
+
+    def __call__(self, form, field):
+        field_data = [field.data] if not isinstance(field.data, list) else field.data
+        if not (
+            all(isinstance(x, FileStorage) and x for x in field_data) and field_data
+        ):
+            raise StopValidation(
+                self.message or field.gettext("This field is required.")
+            )
+
+
+file_required = FileRequired
+
+
+class FileAllowed:
+    """Validates that the uploaded file(s) is allowed by a given list of
+    extensions or a Flask-Uploads :class:`~flaskext.uploads.UploadSet`.
+
+    :param upload_set: A list of extensions or an
+        :class:`~flaskext.uploads.UploadSet`
+    :param message: error message
+
+    You can also use the synonym ``file_allowed``.
+    """
+
+    def __init__(self, upload_set, message=None):
+        self.upload_set = upload_set
+        self.message = message
+
+    def __call__(self, form, field):
+        field_data = [field.data] if not isinstance(field.data, list) else field.data
+        if not (
+            all(isinstance(x, FileStorage) and x for x in field_data) and field_data
+        ):
+            return
+
+        filenames = [f.filename.lower() for f in field_data]
+
+        for filename in filenames:
+            if isinstance(self.upload_set, abc.Iterable):
+                if any(filename.endswith("." + x) for x in self.upload_set):
+                    continue
+
+                raise StopValidation(
+                    self.message
+                    or field.gettext(
+                        "File does not have an approved extension: {extensions}"
+                    ).format(extensions=", ".join(self.upload_set))
+                )
+
+            if not self.upload_set.file_allowed(field_data, filename):
+                raise StopValidation(
+                    self.message
+                    or field.gettext("File does not have an approved extension.")
+                )
+
+
+file_allowed = FileAllowed
+
+
+class FileSize:
+    """Validates that the uploaded file(s) is within a minimum and maximum
+    file size (set in bytes).
+
+    :param min_size: minimum allowed file size (in bytes). Defaults to 0 bytes.
+    :param max_size: maximum allowed file size (in bytes).
+    :param message: error message
+
+    You can also use the synonym ``file_size``.
+    """
+
+    def __init__(self, max_size, min_size=0, message=None):
+        self.min_size = min_size
+        self.max_size = max_size
+        self.message = message
+
+    def __call__(self, form, field):
+        field_data = [field.data] if not isinstance(field.data, list) else field.data
+        if not (
+            all(isinstance(x, FileStorage) and x for x in field_data) and field_data
+        ):
+            return
+
+        for f in field_data:
+            file_size = len(f.read())
+            f.seek(0)  # reset cursor position to beginning of file
+
+            if (file_size < self.min_size) or (file_size > self.max_size):
+                # the file is too small or too big => validation failure
+                raise ValidationError(
+                    self.message
+                    or field.gettext(
+                        "File must be between {min_size} and {max_size} bytes.".format(
+                            min_size=self.min_size, max_size=self.max_size
+                        )
+                    )
+                )
+
+
+file_size = FileSize

+ 127 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf/form.py

@@ -0,0 +1,127 @@
+from flask import current_app
+from flask import request
+from flask import session
+from markupsafe import Markup
+from werkzeug.datastructures import CombinedMultiDict
+from werkzeug.datastructures import ImmutableMultiDict
+from werkzeug.utils import cached_property
+from wtforms import Form
+from wtforms.meta import DefaultMeta
+from wtforms.widgets import HiddenInput
+
+from .csrf import _FlaskFormCSRF
+
+try:
+    from .i18n import translations
+except ImportError:
+    translations = None  # babel not installed
+
+
+SUBMIT_METHODS = {"POST", "PUT", "PATCH", "DELETE"}
+_Auto = object()
+
+
+class FlaskForm(Form):
+    """Flask-specific subclass of WTForms :class:`~wtforms.form.Form`.
+
+    If ``formdata`` is not specified, this will use :attr:`flask.request.form`
+    and :attr:`flask.request.files`.  Explicitly pass ``formdata=None`` to
+    prevent this.
+    """
+
+    class Meta(DefaultMeta):
+        csrf_class = _FlaskFormCSRF
+        csrf_context = session  # not used, provided for custom csrf_class
+
+        @cached_property
+        def csrf(self):
+            return current_app.config.get("WTF_CSRF_ENABLED", True)
+
+        @cached_property
+        def csrf_secret(self):
+            return current_app.config.get("WTF_CSRF_SECRET_KEY", current_app.secret_key)
+
+        @cached_property
+        def csrf_field_name(self):
+            return current_app.config.get("WTF_CSRF_FIELD_NAME", "csrf_token")
+
+        @cached_property
+        def csrf_time_limit(self):
+            return current_app.config.get("WTF_CSRF_TIME_LIMIT", 3600)
+
+        def wrap_formdata(self, form, formdata):
+            if formdata is _Auto:
+                if _is_submitted():
+                    if request.files:
+                        return CombinedMultiDict((request.files, request.form))
+                    elif request.form:
+                        return request.form
+                    elif request.is_json:
+                        return ImmutableMultiDict(request.get_json())
+
+                return None
+
+            return formdata
+
+        def get_translations(self, form):
+            if not current_app.config.get("WTF_I18N_ENABLED", True):
+                return super().get_translations(form)
+
+            return translations
+
+    def __init__(self, formdata=_Auto, **kwargs):
+        super().__init__(formdata=formdata, **kwargs)
+
+    def is_submitted(self):
+        """Consider the form submitted if there is an active request and
+        the method is ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
+        """
+
+        return _is_submitted()
+
+    def validate_on_submit(self, extra_validators=None):
+        """Call :meth:`validate` only if the form is submitted.
+        This is a shortcut for ``form.is_submitted() and form.validate()``.
+        """
+        return self.is_submitted() and self.validate(extra_validators=extra_validators)
+
+    def hidden_tag(self, *fields):
+        """Render the form's hidden fields in one call.
+
+        A field is considered hidden if it uses the
+        :class:`~wtforms.widgets.HiddenInput` widget.
+
+        If ``fields`` are given, only render the given fields that
+        are hidden.  If a string is passed, render the field with that
+        name if it exists.
+
+        .. versionchanged:: 0.13
+
+           No longer wraps inputs in hidden div.
+           This is valid HTML 5.
+
+        .. versionchanged:: 0.13
+
+           Skip passed fields that aren't hidden.
+           Skip passed names that don't exist.
+        """
+
+        def hidden_fields(fields):
+            for f in fields:
+                if isinstance(f, str):
+                    f = getattr(self, f, None)
+
+                if f is None or not isinstance(f.widget, HiddenInput):
+                    continue
+
+                yield f
+
+        return Markup("\n".join(str(f) for f in hidden_fields(fields or self)))
+
+
+def _is_submitted():
+    """Consider the form submitted if there is an active request and
+    the method is ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
+    """
+
+    return bool(request) and request.method in SUBMIT_METHODS

+ 47 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf/i18n.py

@@ -0,0 +1,47 @@
+from babel import support
+from flask import current_app
+from flask import request
+from flask_babel import get_locale
+from wtforms.i18n import messages_path
+
+__all__ = ("Translations", "translations")
+
+
+def _get_translations():
+    """Returns the correct gettext translations.
+    Copy from flask-babel with some modifications.
+    """
+
+    if not request:
+        return None
+
+    # babel should be in extensions for get_locale
+    if "babel" not in current_app.extensions:
+        return None
+
+    translations = getattr(request, "wtforms_translations", None)
+
+    if translations is None:
+        translations = support.Translations.load(
+            messages_path(), [get_locale()], domain="wtforms"
+        )
+        request.wtforms_translations = translations
+
+    return translations
+
+
+class Translations:
+    def gettext(self, string):
+        t = _get_translations()
+        return string if t is None else t.ugettext(string)
+
+    def ngettext(self, singular, plural, n):
+        t = _get_translations()
+
+        if t is None:
+            return singular if n == 1 else plural
+
+        return t.ungettext(singular, plural, n)
+
+
+translations = Translations()

+ 3 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/__init__.py

@@ -0,0 +1,3 @@
+from .fields import RecaptchaField
+from .validators import Recaptcha
+from .widgets import RecaptchaWidget

BIN
courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/__pycache__/__init__.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/__pycache__/fields.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/__pycache__/validators.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/__pycache__/widgets.cpython-310.pyc


+ 17 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/fields.py

@@ -0,0 +1,17 @@
+from wtforms.fields import Field
+
+from . import widgets
+from .validators import Recaptcha
+
+__all__ = ["RecaptchaField"]
+
+
+class RecaptchaField(Field):
+    widget = widgets.RecaptchaWidget()
+
+    # error message if recaptcha validation fails
+    recaptcha_error = None
+
+    def __init__(self, label="", validators=None, **kwargs):
+        validators = validators or [Recaptcha()]
+        super().__init__(label, validators, **kwargs)

+ 75 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/validators.py

@@ -0,0 +1,75 @@
+import json
+from urllib import request as http
+from urllib.parse import urlencode
+
+from flask import current_app
+from flask import request
+from wtforms import ValidationError
+
+RECAPTCHA_VERIFY_SERVER_DEFAULT = "https://www.google.com/recaptcha/api/siteverify"
+RECAPTCHA_ERROR_CODES = {
+    "missing-input-secret": "The secret parameter is missing.",
+    "invalid-input-secret": "The secret parameter is invalid or malformed.",
+    "missing-input-response": "The response parameter is missing.",
+    "invalid-input-response": "The response parameter is invalid or malformed.",
+}
+
+
+__all__ = ["Recaptcha"]
+
+
+class Recaptcha:
+    """Validates a ReCaptcha."""
+
+    def __init__(self, message=None):
+        if message is None:
+            message = RECAPTCHA_ERROR_CODES["missing-input-response"]
+        self.message = message
+
+    def __call__(self, form, field):
+        if current_app.testing:
+            return True
+
+        if request.is_json:
+            response = request.json.get("g-recaptcha-response", "")
+        else:
+            response = request.form.get("g-recaptcha-response", "")
+        remote_ip = request.remote_addr
+
+        if not response:
+            raise ValidationError(field.gettext(self.message))
+
+        if not self._validate_recaptcha(response, remote_ip):
+            field.recaptcha_error = "incorrect-captcha-sol"
+            raise ValidationError(field.gettext(self.message))
+
+    def _validate_recaptcha(self, response, remote_addr):
+        """Performs the actual validation."""
+        try:
+            private_key = current_app.config["RECAPTCHA_PRIVATE_KEY"]
+        except KeyError:
+            raise RuntimeError("No RECAPTCHA_PRIVATE_KEY config set") from None
+
+        verify_server = current_app.config.get("RECAPTCHA_VERIFY_SERVER")
+        if not verify_server:
+            verify_server = RECAPTCHA_VERIFY_SERVER_DEFAULT
+
+        data = urlencode(
+            {"secret": private_key, "remoteip": remote_addr, "response": response}
+        )
+
+        http_response = http.urlopen(verify_server, data.encode("utf-8"))
+
+        if http_response.code != 200:
+            return False
+
+        json_resp = json.loads(http_response.read())
+
+        if json_resp["success"]:
+            return True
+
+        for error in json_resp.get("error-codes", []):
+            if error in RECAPTCHA_ERROR_CODES:
+                raise ValidationError(RECAPTCHA_ERROR_CODES[error])
+
+        return False

+ 43 - 0
courses/flask/microblog/env/Lib/site-packages/flask_wtf/recaptcha/widgets.py

@@ -0,0 +1,43 @@
+from urllib.parse import urlencode
+
+from flask import current_app
+from markupsafe import Markup
+
+RECAPTCHA_SCRIPT_DEFAULT = "https://www.google.com/recaptcha/api.js"
+RECAPTCHA_DIV_CLASS_DEFAULT = "g-recaptcha"
+RECAPTCHA_TEMPLATE = """
+<script src='%s' async defer></script>
+<div class="%s" %s></div>
+"""
+
+__all__ = ["RecaptchaWidget"]
+
+
+class RecaptchaWidget:
+    def recaptcha_html(self, public_key):
+        html = current_app.config.get("RECAPTCHA_HTML")
+        if html:
+            return Markup(html)
+        params = current_app.config.get("RECAPTCHA_PARAMETERS")
+        script = current_app.config.get("RECAPTCHA_SCRIPT")
+        if not script:
+            script = RECAPTCHA_SCRIPT_DEFAULT
+        if params:
+            script += "?" + urlencode(params)
+        attrs = current_app.config.get("RECAPTCHA_DATA_ATTRS", {})
+        attrs["sitekey"] = public_key
+        snippet = " ".join(f'data-{k}="{attrs[k]}"' for k in attrs)  # noqa: B028, B907
+        div_class = current_app.config.get("RECAPTCHA_DIV_CLASS")
+        if not div_class:
+            div_class = RECAPTCHA_DIV_CLASS_DEFAULT
+        return Markup(RECAPTCHA_TEMPLATE % (script, div_class, snippet))
+
+    def __call__(self, field, error=None, **kwargs):
+        """Returns the recaptcha input HTML."""
+
+        try:
+            public_key = current_app.config["RECAPTCHA_PUBLIC_KEY"]
+        except KeyError:
+            raise RuntimeError("RECAPTCHA_PUBLIC_KEY config not set") from None
+
+        return self.recaptcha_html(public_key)

+ 1 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms-3.1.0.dist-info/INSTALLER

@@ -0,0 +1 @@
+pip

+ 119 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms-3.1.0.dist-info/METADATA

@@ -0,0 +1,119 @@
+Metadata-Version: 2.1
+Name: WTForms
+Version: 3.1.0
+Summary: Form validation and rendering for Python web development.
+Project-URL: Documentation, https://wtforms.readthedocs.io
+Project-URL: Changes, https://wtforms.readthedocs.io/changes
+Project-URL: Source Code, https://github.com/wtforms/wtforms/
+Project-URL: Issue Tracker, https://github.com/wtforms/wtforms/issues
+Project-URL: Chat, https://discord.gg/pallets
+Maintainer: WTForms
+License: Copyright 2008 WTForms
+        
+        Redistribution and use in source and binary forms, with or without
+        modification, are permitted provided that the following conditions are
+        met:
+        
+        1.  Redistributions of source code must retain the above copyright
+            notice, this list of conditions and the following disclaimer.
+        
+        2.  Redistributions in binary form must reproduce the above copyright
+            notice, this list of conditions and the following disclaimer in the
+            documentation and/or other materials provided with the distribution.
+        
+        3.  Neither the name of the copyright holder nor the names of its
+            contributors may be used to endorse or promote products derived from
+            this software without specific prior written permission.
+        
+        THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+        "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+        PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+        HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+        SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+        TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+        PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+        LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+        NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+        SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+License-File: LICENSE.rst
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: BSD License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Requires-Python: >=3.8
+Requires-Dist: markupsafe
+Provides-Extra: email
+Requires-Dist: email-validator; extra == 'email'
+Description-Content-Type: text/x-rst
+
+WTForms
+=======
+
+WTForms is a flexible forms validation and rendering library for Python
+web development. It can work with whatever web framework and template
+engine you choose. It supports data validation, CSRF protection,
+internationalization (I18N), and more. There are various community
+libraries that provide closer integration with popular frameworks.
+
+
+Installation
+------------
+
+Install and update using pip:
+
+.. code-block:: text
+
+    pip install -U WTForms
+
+
+Third-Party Library Integrations
+--------------------------------
+
+WTForms is designed to work with any web framework and template engine.
+There are a number of community-provided libraries that make integrating
+with frameworks even better.
+
+-   `Flask-WTF`_ integrates with the Flask framework. It can
+    automatically load data from the request, uses Flask-Babel to
+    translate based on user-selected locale, provides full-application
+    CSRF, and more.
+-   `WTForms-Alchemy`_ provides rich support for generating forms from
+    SQLAlchemy models, including an expanded set of fields and
+    validators.
+-   `WTForms-SQLAlchemy`_ provides ORM-backed fields and form generation
+    from SQLAlchemy models.
+-   `WTForms-AppEngine`_ provides ORM-backed fields and form generation
+    from AppEnding db/ndb schema
+-   `WTForms-Django`_ provides ORM-backed fields and form generation
+    from Django models, as well as integration with Django's I18N
+    support.
+-   `WTForms-Bootstrap5`_ provides Bootstrap 5 favor renderer with
+    great customizability.
+-   `Starlette-WTF`_ integrates with Starlette and the FastAPI
+    framework, based on the features of Flask-WTF.
+-   `Bootstrap-Flask`_ Bootstrap-Flask is a collection of Jinja macros
+    for Bootstrap 4 & 5 and Flask using Flask-WTF.
+
+.. _Flask-WTF: https://flask-wtf.readthedocs.io/
+.. _WTForms-Alchemy: https://wtforms-alchemy.readthedocs.io/
+.. _WTForms-SQLAlchemy: https://github.com/wtforms/wtforms-sqlalchemy
+.. _WTForms-AppEngine: https://github.com/wtforms/wtforms-appengine
+.. _WTForms-Django: https://github.com/wtforms/wtforms-django
+.. _WTForms-Bootstrap5: https://github.com/LaunchPlatform/wtforms-bootstrap5
+.. _Starlette-WTF: https://github.com/muicss/starlette-wtf
+.. _Bootstrap-Flask: https://github.com/helloflask/bootstrap-flask
+
+
+Links
+-----
+
+-   Documentation: https://wtforms.readthedocs.io/
+-   Releases: https://pypi.org/project/WTForms/
+-   Code: https://github.com/wtforms/wtforms
+-   Issue tracker: https://github.com/wtforms/wtforms/issues
+-   Discord Chat: https://discord.gg/F65P7Z9
+-   Translation: https://hosted.weblate.org/projects/wtforms/wtforms/

+ 107 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms-3.1.0.dist-info/RECORD

@@ -0,0 +1,107 @@
+wtforms-3.1.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
+wtforms-3.1.0.dist-info/METADATA,sha256=2YCAS0nEDbX1ar1uxDTj64jmZv7l_-6pso3DzsJV-xA,5277
+wtforms-3.1.0.dist-info/RECORD,,
+wtforms-3.1.0.dist-info/WHEEL,sha256=9QBuHhg6FNW7lppboF2vKVbCGTVzsFykgRQjjlajrhA,87
+wtforms-3.1.0.dist-info/licenses/LICENSE.rst,sha256=z0DWD_NPaytopT0iD4tmVntayN0RGbN7Yv0V6VGP5Zs,1475
+wtforms/__init__.py,sha256=YjO45Vo88hv1rs8Gdgzrdpioi5QOlgxGwls9ZHocmZc,188
+wtforms/__pycache__/__init__.cpython-310.pyc,,
+wtforms/__pycache__/form.cpython-310.pyc,,
+wtforms/__pycache__/i18n.cpython-310.pyc,,
+wtforms/__pycache__/meta.cpython-310.pyc,,
+wtforms/__pycache__/utils.cpython-310.pyc,,
+wtforms/__pycache__/validators.cpython-310.pyc,,
+wtforms/csrf/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
+wtforms/csrf/__pycache__/__init__.cpython-310.pyc,,
+wtforms/csrf/__pycache__/core.cpython-310.pyc,,
+wtforms/csrf/__pycache__/session.cpython-310.pyc,,
+wtforms/csrf/core.py,sha256=8Ka3ZATvo9I1WqreP1Y_i1r0t7m8Wcw5cKynVvJNXes,3097
+wtforms/csrf/session.py,sha256=d-roaNYuBxN2QACwkz1_UIuAdtYyTzJTmcJ3UPe1jks,3091
+wtforms/fields/__init__.py,sha256=Peqt-1SMp4e83FGdjd_imearbY8CYMBHquUC4AHgpkg,435
+wtforms/fields/__pycache__/__init__.cpython-310.pyc,,
+wtforms/fields/__pycache__/choices.cpython-310.pyc,,
+wtforms/fields/__pycache__/core.cpython-310.pyc,,
+wtforms/fields/__pycache__/datetime.cpython-310.pyc,,
+wtforms/fields/__pycache__/form.cpython-310.pyc,,
+wtforms/fields/__pycache__/list.cpython-310.pyc,,
+wtforms/fields/__pycache__/numeric.cpython-310.pyc,,
+wtforms/fields/__pycache__/simple.cpython-310.pyc,,
+wtforms/fields/choices.py,sha256=puDK-tbxip-YRtT7WPtoLZj8_Wj94QyWtv-IPNCJ12E,6604
+wtforms/fields/core.py,sha256=BiIjlNPo3xobvCSIKp_Fr7P9RSnX_Mm3VutQMGChztc,14799
+wtforms/fields/datetime.py,sha256=dYJjDxTAE1LXfzWTML1HPwc1yT0OCA4D42c8FyBgvxk,5010
+wtforms/fields/form.py,sha256=KsEX4NTQsr3nwULTC2gxbDvC5PQWoLdMdFwsm-l6rW4,2896
+wtforms/fields/list.py,sha256=htcVonFLsQfo3iibZyvoCBIq9mOr_GHe-85aU3TeflU,6470
+wtforms/fields/numeric.py,sha256=Y39ODDk9eh6Nctb8gOx26u0ioiChIIUczpxAlK8Vyaw,6157
+wtforms/fields/simple.py,sha256=VBp8mRT5n3hRMH5ErgIjZtbqRr3jaRv2lZj4NMgs6XY,4075
+wtforms/form.py,sha256=CsRwZKHup6H4yfBzVlJJqf7PdMy1KTQRrn9BL9kTtqs,12571
+wtforms/i18n.py,sha256=8AMTTSpQ5d-hONeVN8rt3RH0gRc3Mvl4zUum8Hyif88,1958
+wtforms/locale/README.md,sha256=Rb-tZdT5rErXDoe9lOmXl8Fj8ZCZPyE9fqpb0kQ2o8Y,1515
+wtforms/locale/ar/LC_MESSAGES/wtforms.mo,sha256=og57xcODRZkMxraJc4DYrJFinsBbEVVmO2ZONBq4d4A,4393
+wtforms/locale/ar/LC_MESSAGES/wtforms.po,sha256=p0sJ1RMKDcLj6vuy00ZvNcKXxjusvF77Bnq2rRVZGRE,6917
+wtforms/locale/bg/LC_MESSAGES/wtforms.mo,sha256=xIeutDCZprElc1hVoBXNcaezk6gg103vR0yIhXaNd6c,3932
+wtforms/locale/bg/LC_MESSAGES/wtforms.po,sha256=317ErIay8SyLoqcDNnGqAVRr3wLB-4IY_TFC8tPDfY4,6532
+wtforms/locale/ca/LC_MESSAGES/wtforms.mo,sha256=5N9_Rpkevug8HlzY1oGDyFmpAVGXdAwBerz-IpCzonU,3177
+wtforms/locale/ca/LC_MESSAGES/wtforms.po,sha256=1vetDbiNdNgbVLDcEIMuvFnCqDw85UNJEOyb9MIXhKI,5691
+wtforms/locale/cs_CZ/LC_MESSAGES/wtforms.mo,sha256=xRWbbnkN2EqY4gv4IZmnhXld3hsVZbhSR-wqxTKzPkQ,3398
+wtforms/locale/cs_CZ/LC_MESSAGES/wtforms.po,sha256=nEK6qwex37l9vaj_vE-4RopHKfLe2pcNMJH9-foNvh0,5856
+wtforms/locale/cy/LC_MESSAGES/wtforms.mo,sha256=LOsStjgs8RQRam0sCy213cGupp9DCbnnlVLTg6TqHwE,3142
+wtforms/locale/cy/LC_MESSAGES/wtforms.po,sha256=J_y04pZ5y8uVHIj6j0w9MRYIG4S0m6EUTzrPkr6wyZ8,5645
+wtforms/locale/de/LC_MESSAGES/wtforms.mo,sha256=2GAdeAts26l8OsTfruuScRpHHmEAKvAFgGrpSx4IgYg,3175
+wtforms/locale/de/LC_MESSAGES/wtforms.po,sha256=lZgIK4DdzhRhXr8VZ7rkBarRcgpwIMtKjEVEAYSvOTE,5685
+wtforms/locale/de_CH/LC_MESSAGES/wtforms.mo,sha256=l0ymeBsJb0390HB0mEEpOCWl1xce31YC6xli8u3RWfc,3169
+wtforms/locale/de_CH/LC_MESSAGES/wtforms.po,sha256=eN9bvLRaMdUrlekpA8s-Bjs7kMZAVKJuwZtGVOoyxWY,5692
+wtforms/locale/el/LC_MESSAGES/wtforms.mo,sha256=njX5uOCZ-mHLU2Ex1FOmxTelQAHggoY0U3qYvIBOKFQ,3951
+wtforms/locale/el/LC_MESSAGES/wtforms.po,sha256=_xWxMhVtah6G0emQyLYL7B3TOiUfvikzaFr9WIhd13w,6581
+wtforms/locale/en/LC_MESSAGES/wtforms.mo,sha256=GuMv6x8Lc8wcLcpUaPWPHrHegjP3nCSjgdkbz7H456k,3323
+wtforms/locale/en/LC_MESSAGES/wtforms.po,sha256=Yn7Pb4rFmGxwp3emJW_aAqCBBZZw-E-JTGClfL78DY8,5046
+wtforms/locale/es/LC_MESSAGES/wtforms.mo,sha256=RBHzlY3HNsy3nz_0eTQ9IiqQfCqq4Iq0aPXVWZqVzjo,3880
+wtforms/locale/es/LC_MESSAGES/wtforms.po,sha256=fzyvoPb6qCS1lQItflWIYSYEqEG3t4F-FnuxNElaywE,5855
+wtforms/locale/et/LC_MESSAGES/wtforms.mo,sha256=e_4AiXlmyKRuPBc5d7SVpd6FKXTmlkqN09YlGQfH-fw,3202
+wtforms/locale/et/LC_MESSAGES/wtforms.po,sha256=YNsBzM1sBD7ocOI0r7Fvxw4NPMFW5pgURnIZINFknQ8,5704
+wtforms/locale/fa/LC_MESSAGES/wtforms.mo,sha256=7TBePsrBl7mjIUEKM7ciG7gklIzicerTO9_OEinC7v0,3796
+wtforms/locale/fa/LC_MESSAGES/wtforms.po,sha256=4OoR7G75NIIaLDfbfjfa3Q9kafJUVIlXxpG2QeYVLos,6375
+wtforms/locale/fi/LC_MESSAGES/wtforms.mo,sha256=W5gI_W9SUYYSYsIuteI1RBqYoArxAZonuLwzyKsV1k0,3152
+wtforms/locale/fi/LC_MESSAGES/wtforms.po,sha256=tk-LbQudS_s5rMgo2kFzZTSrw--kXhCY-7R8wNREl7M,5659
+wtforms/locale/fr/LC_MESSAGES/wtforms.mo,sha256=MMNK8ShMMnDYnZgPbwxks1-XbL_mCdMR-3577QlXPrY,3957
+wtforms/locale/fr/LC_MESSAGES/wtforms.po,sha256=axI5kDnXjFNuC3B2MHb5OkbLTuTPEJwPsahhDvA6ud0,5991
+wtforms/locale/he/LC_MESSAGES/wtforms.mo,sha256=xoYlxbJrgzGsqY_nVOJEb8KCjEtiLJZW7YF6ODXmkRo,3265
+wtforms/locale/he/LC_MESSAGES/wtforms.po,sha256=IqZj20FIxkLDALeNmQbbjfBjSxhINpMyKk73iMG-iWg,5851
+wtforms/locale/hu/LC_MESSAGES/wtforms.mo,sha256=NYY-o9ng9NhzE8IhOMEqNtyKuOAUySnsR6B9y5a0SGA,3275
+wtforms/locale/hu/LC_MESSAGES/wtforms.po,sha256=62JZfqVJpj9gNlE-nHlw8iCkwVLf0TkD8Lo5zst3ZMY,5690
+wtforms/locale/it/LC_MESSAGES/wtforms.mo,sha256=ln6Y0DBhPvjDynaITdo1YhqR1mgD3RB5LMjNmQwybP4,3248
+wtforms/locale/it/LC_MESSAGES/wtforms.po,sha256=mqYFBkEtVn2TYlsDDSulSvrEyTcpQPwsoJbjOBBnIJ0,5760
+wtforms/locale/ja/LC_MESSAGES/wtforms.mo,sha256=6mW0arwAObGaF6EOjkGfUKuAxYMvq3AECEVrS-tdSTQ,3481
+wtforms/locale/ja/LC_MESSAGES/wtforms.po,sha256=IHGeRAA0cgjZxaShkwE6XYb5tXtF7i3WONL4DWTzzOQ,5923
+wtforms/locale/ko/LC_MESSAGES/wtforms.mo,sha256=TlBhP0Uv3UGbCiUSZKuguDRvrvnL3dICFrGRZmnWlKs,3671
+wtforms/locale/ko/LC_MESSAGES/wtforms.po,sha256=jGlR-wumoksE7y_HA_3KiUQ5OYJBdAYEnJSc1Qkvhp8,6116
+wtforms/locale/nb/LC_MESSAGES/wtforms.mo,sha256=xhEJ0zny-Db58UaxpM9-kDnb_XxxhzFwGwmcfRFqbAA,3080
+wtforms/locale/nb/LC_MESSAGES/wtforms.po,sha256=XbjjHJydJvjiaKik8tRdlQrGacS2qhPwes3iucS_MW4,5588
+wtforms/locale/nl/LC_MESSAGES/wtforms.mo,sha256=PJMhg0AovDCVDGm8x8wfV76AMxwoVzM7uNXQOnhibL8,3237
+wtforms/locale/nl/LC_MESSAGES/wtforms.po,sha256=BPXPne_e8xTlcVCnb0mHo01lHQIFCbTquN9v2rTCjPY,5728
+wtforms/locale/pl/LC_MESSAGES/wtforms.mo,sha256=fD2AJz5Q4cSMPhsqW8k1niuqC9blo18aYUiTp96w_7Q,3428
+wtforms/locale/pl/LC_MESSAGES/wtforms.po,sha256=7PlPxAt9SnXYj3PFSWGyqZa43UaWUXpSVok2en8PRps,5980
+wtforms/locale/pt/LC_MESSAGES/wtforms.mo,sha256=9CIoPEmQszzoeyWEXein3za-_9VSqLloM4P7PDyCTy0,3187
+wtforms/locale/pt/LC_MESSAGES/wtforms.po,sha256=5Wlx8BUTV_JNXut2SxlQhPmHsLnRveotYCksAh1IYos,5699
+wtforms/locale/ro/LC_MESSAGES/wtforms.mo,sha256=ZRhdPXMq3AMbanvZC3PyP11rhE3WzDee2Nb6OqkLr0A,4263
+wtforms/locale/ro/LC_MESSAGES/wtforms.po,sha256=ELLteEeBQ8ng0eiEQhZzqmmaylx0S0xnlkG9RUj5jUY,6288
+wtforms/locale/ru/LC_MESSAGES/wtforms.mo,sha256=aYLJi4zpTDg6MmWg4CFZdzYhR2xZLf0Y8V1onl2xOfY,4418
+wtforms/locale/ru/LC_MESSAGES/wtforms.po,sha256=cJiMvdYFDc1VP7hazaowNQ28wZIq5h_YUr0_txW9rkY,7128
+wtforms/locale/sk/LC_MESSAGES/wtforms.mo,sha256=KfpAQmAAVXti7DJwdywzevnNzQGZwFVV_d38AklwxkU,4048
+wtforms/locale/sk/LC_MESSAGES/wtforms.po,sha256=nLRlWYADOYNZpYcEKdm2I8KcSHDa4td4QSjCMQKty2M,6064
+wtforms/locale/sv/LC_MESSAGES/wtforms.mo,sha256=7bmjQm5Aeha5snOi8UrF8jMRa2UinNGeSsQHcANJxWg,3314
+wtforms/locale/sv/LC_MESSAGES/wtforms.po,sha256=5ZMWeJ89Y5zmi52fctMJMKsiwzOhr-Ek_MuEcF2jMZw,5886
+wtforms/locale/tr/LC_MESSAGES/wtforms.mo,sha256=TlBZFI_5fzWRkwUyJAND3UAM1zu614fPjReCzWCSij8,3145
+wtforms/locale/tr/LC_MESSAGES/wtforms.po,sha256=ye1d8QM-2GSo1zIhcMXPZ96sCDb-93y9FvkfPHSRWRQ,5618
+wtforms/locale/uk/LC_MESSAGES/wtforms.mo,sha256=cjbPc0RaoFp7Cgxp0zMvjX3948r0-vO5_D6BXHAsv0I,4244
+wtforms/locale/uk/LC_MESSAGES/wtforms.po,sha256=Xy83Ta-3r5I_5oRPzEKH7MbKKXldcgtL1s1QD-7fV-A,6882
+wtforms/locale/wtforms.pot,sha256=NVZ5zI_at7V5-Zy2YNxD5q7RXCTpKs-E5oz7TUVXQkA,4247
+wtforms/locale/zh/LC_MESSAGES/wtforms.mo,sha256=DOIDza0fyS8tyyfZAnqtq--L7mb8bVp4nxiLBqAIMHA,3296
+wtforms/locale/zh/LC_MESSAGES/wtforms.po,sha256=1yuPp30aOGX3afZLifuRaW1hFzAIZxhWVIH28ltIxnU,5810
+wtforms/locale/zh_TW/LC_MESSAGES/wtforms.mo,sha256=EyFUxgRcy_SOJiNsrFH_Kbtxtmwa4TVJSxJ8XHGoXeo,3099
+wtforms/locale/zh_TW/LC_MESSAGES/wtforms.po,sha256=yTbfEDmd6GOIAmHibNpIL6_BdyqVsDKPNYdPDESnl4Y,5518
+wtforms/meta.py,sha256=SU8A6gDcd2wDkVzNmSGMLBBly_fMBTKVB7BD6GCfxYo,4097
+wtforms/utils.py,sha256=_BJIhyT-Fy0ve88OzJvYyaRm7LyJjnLFs7tiTWveslE,2310
+wtforms/validators.py,sha256=R2Hxdx8nTDSO9xz97Xa0bujW8JjkA7CgKSRBjveMJgk,21753
+wtforms/widgets/__init__.py,sha256=4UXr1cMvil5x9zQp4dlXpo52mEQHeSKKRfmiXyS-u5Y,119
+wtforms/widgets/__pycache__/__init__.cpython-310.pyc,,
+wtforms/widgets/__pycache__/core.cpython-310.pyc,,
+wtforms/widgets/core.py,sha256=RT7bkxSW66h5trUGYbgucoqA8gtyyu3cU2IKZuakRmY,15056

+ 4 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms-3.1.0.dist-info/WHEEL

@@ -0,0 +1,4 @@
+Wheel-Version: 1.0
+Generator: hatchling 1.18.0
+Root-Is-Purelib: true
+Tag: py3-none-any

+ 28 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms-3.1.0.dist-info/licenses/LICENSE.rst

@@ -0,0 +1,28 @@
+Copyright 2008 WTForms
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1.  Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+2.  Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+3.  Neither the name of the copyright holder nor the names of its
+    contributors may be used to endorse or promote products derived from
+    this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 7 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/__init__.py

@@ -0,0 +1,7 @@
+from wtforms import validators
+from wtforms import widgets
+from wtforms.fields import *
+from wtforms.form import Form
+from wtforms.validators import ValidationError
+
+__version__ = "3.1.0"

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/__pycache__/__init__.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/__pycache__/form.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/__pycache__/i18n.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/__pycache__/meta.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/__pycache__/utils.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/__pycache__/validators.cpython-310.pyc


+ 0 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/csrf/__init__.py


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/csrf/__pycache__/__init__.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/csrf/__pycache__/core.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/csrf/__pycache__/session.cpython-310.pyc


+ 96 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/csrf/core.py

@@ -0,0 +1,96 @@
+from wtforms.fields import HiddenField
+from wtforms.validators import ValidationError
+
+__all__ = ("CSRFTokenField", "CSRF")
+
+
+class CSRFTokenField(HiddenField):
+    """
+    A subclass of HiddenField designed for sending the CSRF token that is used
+    for most CSRF protection schemes.
+
+    Notably different from a normal field, this field always renders the
+    current token regardless of the submitted value, and also will not be
+    populated over to object data via populate_obj
+    """
+
+    current_token = None
+
+    def __init__(self, *args, **kw):
+        self.csrf_impl = kw.pop("csrf_impl")
+        super().__init__(*args, **kw)
+
+    def _value(self):
+        """
+        We want to always return the current token on render, regardless of
+        whether a good or bad token was passed.
+        """
+        return self.current_token
+
+    def populate_obj(self, *args):
+        """
+        Don't populate objects with the CSRF token
+        """
+        pass
+
+    def pre_validate(self, form):
+        """
+        Handle validation of this token field.
+        """
+        self.csrf_impl.validate_csrf_token(form, self)
+
+    def process(self, *args, **kwargs):
+        super().process(*args, **kwargs)
+        self.current_token = self.csrf_impl.generate_csrf_token(self)
+
+
+class CSRF:
+    field_class = CSRFTokenField
+
+    def setup_form(self, form):
+        """
+        Receive the form we're attached to and set up fields.
+
+        The default implementation creates a single field of
+        type :attr:`field_class` with name taken from the
+        ``csrf_field_name`` of the class meta.
+
+        :param form:
+            The form instance we're attaching to.
+        :return:
+            A sequence of `(field_name, unbound_field)` 2-tuples which
+            are unbound fields to be added to the form.
+        """
+        meta = form.meta
+        field_name = meta.csrf_field_name
+        unbound_field = self.field_class(label="CSRF Token", csrf_impl=self)
+        return [(field_name, unbound_field)]
+
+    def generate_csrf_token(self, csrf_token_field):
+        """
+        Implementations must override this to provide a method with which one
+        can get a CSRF token for this form.
+
+        A CSRF token is usually a string that is generated deterministically
+        based on some sort of user data, though it can be anything which you
+        can validate on a subsequent request.
+
+        :param csrf_token_field:
+            The field which is being used for CSRF.
+        :return:
+            A generated CSRF string.
+        """
+        raise NotImplementedError()
+
+    def validate_csrf_token(self, form, field):
+        """
+        Override this method to provide custom CSRF validation logic.
+
+        The default CSRF validation logic simply checks if the recently
+        generated token equals the one we received as formdata.
+
+        :param form: The form which has this CSRF token.
+        :param field: The CSRF token field.
+        """
+        if field.current_token != field.data:
+            raise ValidationError(field.gettext("Invalid CSRF Token."))

+ 92 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/csrf/session.py

@@ -0,0 +1,92 @@
+"""
+A provided CSRF implementation which puts CSRF data in a session.
+
+This can be used fairly comfortably with many `request.session` type
+objects, including the Werkzeug/Flask session store, Django sessions, and
+potentially other similar objects which use a dict-like API for storing
+session keys.
+
+The basic concept is a randomly generated value is stored in the user's
+session, and an hmac-sha1 of it (along with an optional expiration time,
+for extra security) is used as the value of the csrf_token. If this token
+validates with the hmac of the random value + expiration time, and the
+expiration time is not passed, the CSRF validation will pass.
+"""
+import hmac
+import os
+from datetime import datetime
+from datetime import timedelta
+from hashlib import sha1
+
+from ..validators import ValidationError
+from .core import CSRF
+
+__all__ = ("SessionCSRF",)
+
+
+class SessionCSRF(CSRF):
+    TIME_FORMAT = "%Y%m%d%H%M%S"
+
+    def setup_form(self, form):
+        self.form_meta = form.meta
+        return super().setup_form(form)
+
+    def generate_csrf_token(self, csrf_token_field):
+        meta = self.form_meta
+        if meta.csrf_secret is None:
+            raise Exception(
+                "must set `csrf_secret` on class Meta for SessionCSRF to work"
+            )
+        if meta.csrf_context is None:
+            raise TypeError("Must provide a session-like object as csrf context")
+
+        session = self.session
+
+        if "csrf" not in session:
+            session["csrf"] = sha1(os.urandom(64)).hexdigest()
+
+        if self.time_limit:
+            expires = (self.now() + self.time_limit).strftime(self.TIME_FORMAT)
+            csrf_build = "{}{}".format(session["csrf"], expires)
+        else:
+            expires = ""
+            csrf_build = session["csrf"]
+
+        hmac_csrf = hmac.new(
+            meta.csrf_secret, csrf_build.encode("utf8"), digestmod=sha1
+        )
+        return f"{expires}##{hmac_csrf.hexdigest()}"
+
+    def validate_csrf_token(self, form, field):
+        meta = self.form_meta
+        if not field.data or "##" not in field.data:
+            raise ValidationError(field.gettext("CSRF token missing."))
+
+        expires, hmac_csrf = field.data.split("##", 1)
+
+        check_val = (self.session["csrf"] + expires).encode("utf8")
+
+        hmac_compare = hmac.new(meta.csrf_secret, check_val, digestmod=sha1)
+        if hmac_compare.hexdigest() != hmac_csrf:
+            raise ValidationError(field.gettext("CSRF failed."))
+
+        if self.time_limit:
+            now_formatted = self.now().strftime(self.TIME_FORMAT)
+            if now_formatted > expires:
+                raise ValidationError(field.gettext("CSRF token expired."))
+
+    def now(self):
+        """
+        Get the current time. Used for test mocking/overriding mainly.
+        """
+        return datetime.now()
+
+    @property
+    def time_limit(self):
+        return getattr(self.form_meta, "csrf_time_limit", timedelta(minutes=30))
+
+    @property
+    def session(self):
+        return getattr(
+            self.form_meta.csrf_context, "session", self.form_meta.csrf_context
+        )

+ 11 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__init__.py

@@ -0,0 +1,11 @@
+from wtforms.fields.choices import *
+from wtforms.fields.choices import SelectFieldBase
+from wtforms.fields.core import Field
+from wtforms.fields.core import Flags
+from wtforms.fields.core import Label
+from wtforms.fields.datetime import *
+from wtforms.fields.form import *
+from wtforms.fields.list import *
+from wtforms.fields.numeric import *
+from wtforms.fields.simple import *
+from wtforms.utils import unset_value as _unset_value

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/__init__.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/choices.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/core.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/datetime.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/form.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/list.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/numeric.cpython-310.pyc


BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/__pycache__/simple.cpython-310.pyc


+ 219 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/choices.py

@@ -0,0 +1,219 @@
+import itertools
+
+from wtforms import widgets
+from wtforms.fields.core import Field
+from wtforms.validators import ValidationError
+
+__all__ = (
+    "SelectField",
+    "SelectMultipleField",
+    "RadioField",
+)
+
+
+class SelectFieldBase(Field):
+    option_widget = widgets.Option()
+
+    """
+    Base class for fields which can be iterated to produce options.
+
+    This isn't a field, but an abstract base class for fields which want to
+    provide this functionality.
+    """
+
+    def __init__(self, label=None, validators=None, option_widget=None, **kwargs):
+        super().__init__(label, validators, **kwargs)
+
+        if option_widget is not None:
+            self.option_widget = option_widget
+
+    def iter_choices(self):
+        """
+        Provides data for choice widget rendering. Must return a sequence or
+        iterable of (value, label, selected) tuples.
+        """
+        raise NotImplementedError()
+
+    def has_groups(self):
+        return False
+
+    def iter_groups(self):
+        raise NotImplementedError()
+
+    def __iter__(self):
+        opts = dict(
+            widget=self.option_widget,
+            validators=self.validators,
+            name=self.name,
+            render_kw=self.render_kw,
+            _form=None,
+            _meta=self.meta,
+        )
+        for i, (value, label, checked, render_kw) in enumerate(self.iter_choices()):
+            opt = self._Option(
+                label=label, id="%s-%d" % (self.id, i), **opts, **render_kw
+            )
+            opt.process(None, value)
+            opt.checked = checked
+            yield opt
+
+    class _Option(Field):
+        checked = False
+
+        def _value(self):
+            return str(self.data)
+
+
+class SelectField(SelectFieldBase):
+    widget = widgets.Select()
+
+    def __init__(
+        self,
+        label=None,
+        validators=None,
+        coerce=str,
+        choices=None,
+        validate_choice=True,
+        **kwargs,
+    ):
+        super().__init__(label, validators, **kwargs)
+        self.coerce = coerce
+        if callable(choices):
+            choices = choices()
+        if choices is not None:
+            self.choices = choices if isinstance(choices, dict) else list(choices)
+        else:
+            self.choices = None
+        self.validate_choice = validate_choice
+
+    def iter_choices(self):
+        if not self.choices:
+            choices = []
+        elif isinstance(self.choices, dict):
+            choices = list(itertools.chain.from_iterable(self.choices.values()))
+        else:
+            choices = self.choices
+
+        return self._choices_generator(choices)
+
+    def has_groups(self):
+        return isinstance(self.choices, dict)
+
+    def iter_groups(self):
+        if isinstance(self.choices, dict):
+            for label, choices in self.choices.items():
+                yield (label, self._choices_generator(choices))
+
+    def _choices_generator(self, choices):
+        if not choices:
+            _choices = []
+
+        elif isinstance(choices[0], (list, tuple)):
+            _choices = choices
+
+        else:
+            _choices = zip(choices, choices)
+
+        for value, label, *other_args in _choices:
+            render_kw = other_args[0] if len(other_args) else {}
+            yield (value, label, self.coerce(value) == self.data, render_kw)
+
+    def process_data(self, value):
+        try:
+            # If value is None, don't coerce to a value
+            self.data = self.coerce(value) if value is not None else None
+        except (ValueError, TypeError):
+            self.data = None
+
+    def process_formdata(self, valuelist):
+        if not valuelist:
+            return
+
+        try:
+            self.data = self.coerce(valuelist[0])
+        except ValueError as exc:
+            raise ValueError(self.gettext("Invalid Choice: could not coerce.")) from exc
+
+    def pre_validate(self, form):
+        if self.choices is None:
+            raise TypeError(self.gettext("Choices cannot be None."))
+
+        if not self.validate_choice:
+            return
+
+        for _, _, match, _ in self.iter_choices():
+            if match:
+                break
+        else:
+            raise ValidationError(self.gettext("Not a valid choice."))
+
+
+class SelectMultipleField(SelectField):
+    """
+    No different from a normal select field, except this one can take (and
+    validate) multiple choices.  You'll need to specify the HTML `size`
+    attribute to the select field when rendering.
+    """
+
+    widget = widgets.Select(multiple=True)
+
+    def _choices_generator(self, choices):
+        if choices:
+            if isinstance(choices[0], (list, tuple)):
+                _choices = choices
+            else:
+                _choices = zip(choices, choices)
+        else:
+            _choices = []
+
+        for value, label, *args in _choices:
+            selected = self.data is not None and self.coerce(value) in self.data
+            render_kw = args[0] if len(args) else {}
+            yield (value, label, selected, render_kw)
+
+    def process_data(self, value):
+        try:
+            self.data = list(self.coerce(v) for v in value)
+        except (ValueError, TypeError):
+            self.data = None
+
+    def process_formdata(self, valuelist):
+        try:
+            self.data = list(self.coerce(x) for x in valuelist)
+        except ValueError as exc:
+            raise ValueError(
+                self.gettext(
+                    "Invalid choice(s): one or more data inputs could not be coerced."
+                )
+            ) from exc
+
+    def pre_validate(self, form):
+        if self.choices is None:
+            raise TypeError(self.gettext("Choices cannot be None."))
+
+        if not self.validate_choice or not self.data:
+            return
+
+        acceptable = {c[0] for c in self.iter_choices()}
+        if any(d not in acceptable for d in self.data):
+            unacceptable = [str(d) for d in set(self.data) - acceptable]
+            raise ValidationError(
+                self.ngettext(
+                    "'%(value)s' is not a valid choice for this field.",
+                    "'%(value)s' are not valid choices for this field.",
+                    len(unacceptable),
+                )
+                % dict(value="', '".join(unacceptable))
+            )
+
+
+class RadioField(SelectField):
+    """
+    Like a SelectField, except displays a list of radio buttons.
+
+    Iterating the field will produce subfields (each containing a label as
+    well) in order to allow custom rendering of the individual radio fields.
+    """
+
+    widget = widgets.ListWidget(prefix_label=False)
+    option_widget = widgets.RadioInput()

+ 453 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/core.py

@@ -0,0 +1,453 @@
+import inspect
+import itertools
+import warnings
+
+from markupsafe import escape
+from markupsafe import Markup
+
+from wtforms import widgets
+from wtforms.i18n import DummyTranslations
+from wtforms.utils import unset_value
+from wtforms.validators import StopValidation
+from wtforms.validators import ValidationError
+
+
+class Field:
+    """
+    Field base class
+    """
+
+    errors = tuple()
+    process_errors = tuple()
+    raw_data = None
+    validators = tuple()
+    widget = None
+    _formfield = True
+    _translations = DummyTranslations()
+    do_not_call_in_templates = True  # Allow Django 1.4 traversal
+
+    def __new__(cls, *args, **kwargs):
+        if "_form" in kwargs:
+            return super().__new__(cls)
+        else:
+            return UnboundField(cls, *args, **kwargs)
+
+    def __init__(
+        self,
+        label=None,
+        validators=None,
+        filters=(),
+        description="",
+        id=None,
+        default=None,
+        widget=None,
+        render_kw=None,
+        name=None,
+        _form=None,
+        _prefix="",
+        _translations=None,
+        _meta=None,
+    ):
+        """
+        Construct a new field.
+
+        :param label:
+            The label of the field.
+        :param validators:
+            A sequence of validators to call when `validate` is called.
+        :param filters:
+            A sequence of callable which are run by :meth:`~Field.process`
+            to filter or transform the input data. For example
+            ``StringForm(filters=[str.strip, str.upper])``.
+            Note that filters are applied after processing the default and
+            incoming data, but before validation.
+        :param description:
+            A description for the field, typically used for help text.
+        :param id:
+            An id to use for the field. A reasonable default is set by the form,
+            and you shouldn't need to set this manually.
+        :param default:
+            The default value to assign to the field, if no form or object
+            input is provided. May be a callable.
+        :param widget:
+            If provided, overrides the widget used to render the field.
+        :param dict render_kw:
+            If provided, a dictionary which provides default keywords that
+            will be given to the widget at render time.
+        :param name:
+            The HTML name of this field. The default value is the Python
+            attribute name.
+        :param _form:
+            The form holding this field. It is passed by the form itself during
+            construction. You should never pass this value yourself.
+        :param _prefix:
+            The prefix to prepend to the form name of this field, passed by
+            the enclosing form during construction.
+        :param _translations:
+            A translations object providing message translations. Usually
+            passed by the enclosing form during construction. See
+            :doc:`I18n docs <i18n>` for information on message translations.
+        :param _meta:
+            If provided, this is the 'meta' instance from the form. You usually
+            don't pass this yourself.
+
+        If `_form` isn't provided, an :class:`UnboundField` will be
+        returned instead. Call its :func:`bind` method with a form instance and
+        a name to construct the field.
+        """
+        if _translations is not None:
+            self._translations = _translations
+
+        if _meta is not None:
+            self.meta = _meta
+        elif _form is not None:
+            self.meta = _form.meta
+        else:
+            raise TypeError("Must provide one of _form or _meta")
+
+        self.default = default
+        self.description = description
+        self.render_kw = render_kw
+        self.filters = filters
+        self.flags = Flags()
+        self.name = _prefix + name
+        self.short_name = name
+        self.type = type(self).__name__
+
+        self.check_validators(validators)
+        self.validators = validators or self.validators
+
+        self.id = id or self.name
+        self.label = Label(
+            self.id,
+            label
+            if label is not None
+            else self.gettext(name.replace("_", " ").title()),
+        )
+
+        if widget is not None:
+            self.widget = widget
+
+        for v in itertools.chain(self.validators, [self.widget]):
+            flags = getattr(v, "field_flags", {})
+
+            # check for legacy format, remove eventually
+            if isinstance(flags, tuple):  # pragma: no cover
+                warnings.warn(
+                    "Flags should be stored in dicts and not in tuples. "
+                    "The next version of WTForms will abandon support "
+                    "for flags in tuples.",
+                    DeprecationWarning,
+                    stacklevel=2,
+                )
+                flags = {flag_name: True for flag_name in flags}
+
+            for k, v in flags.items():
+                setattr(self.flags, k, v)
+
+    def __str__(self):
+        """
+        Returns a HTML representation of the field. For more powerful rendering,
+        see the `__call__` method.
+        """
+        return self()
+
+    def __html__(self):
+        """
+        Returns a HTML representation of the field. For more powerful rendering,
+        see the :meth:`__call__` method.
+        """
+        return self()
+
+    def __call__(self, **kwargs):
+        """
+        Render this field as HTML, using keyword args as additional attributes.
+
+        This delegates rendering to
+        :meth:`meta.render_field <wtforms.meta.DefaultMeta.render_field>`
+        whose default behavior is to call the field's widget, passing any
+        keyword arguments from this call along to the widget.
+
+        In all of the WTForms HTML widgets, keyword arguments are turned to
+        HTML attributes, though in theory a widget is free to do anything it
+        wants with the supplied keyword arguments, and widgets don't have to
+        even do anything related to HTML.
+        """
+        return self.meta.render_field(self, kwargs)
+
+    @classmethod
+    def check_validators(cls, validators):
+        if validators is not None:
+            for validator in validators:
+                if not callable(validator):
+                    raise TypeError(
+                        "{} is not a valid validator because it is not "
+                        "callable".format(validator)
+                    )
+
+                if inspect.isclass(validator):
+                    raise TypeError(
+                        "{} is not a valid validator because it is a class, "
+                        "it should be an instance".format(validator)
+                    )
+
+    def gettext(self, string):
+        """
+        Get a translation for the given message.
+
+        This proxies for the internal translations object.
+
+        :param string: A string to be translated.
+        :return: A string which is the translated output.
+        """
+        return self._translations.gettext(string)
+
+    def ngettext(self, singular, plural, n):
+        """
+        Get a translation for a message which can be pluralized.
+
+        :param str singular: The singular form of the message.
+        :param str plural: The plural form of the message.
+        :param int n: The number of elements this message is referring to
+        """
+        return self._translations.ngettext(singular, plural, n)
+
+    def validate(self, form, extra_validators=()):
+        """
+        Validates the field and returns True or False. `self.errors` will
+        contain any errors raised during validation. This is usually only
+        called by `Form.validate`.
+
+        Subfields shouldn't override this, but rather override either
+        `pre_validate`, `post_validate` or both, depending on needs.
+
+        :param form: The form the field belongs to.
+        :param extra_validators: A sequence of extra validators to run.
+        """
+        self.errors = list(self.process_errors)
+        stop_validation = False
+
+        # Check the type of extra_validators
+        self.check_validators(extra_validators)
+
+        # Call pre_validate
+        try:
+            self.pre_validate(form)
+        except StopValidation as e:
+            if e.args and e.args[0]:
+                self.errors.append(e.args[0])
+            stop_validation = True
+        except ValidationError as e:
+            self.errors.append(e.args[0])
+
+        # Run validators
+        if not stop_validation:
+            chain = itertools.chain(self.validators, extra_validators)
+            stop_validation = self._run_validation_chain(form, chain)
+
+        # Call post_validate
+        try:
+            self.post_validate(form, stop_validation)
+        except ValidationError as e:
+            self.errors.append(e.args[0])
+
+        return len(self.errors) == 0
+
+    def _run_validation_chain(self, form, validators):
+        """
+        Run a validation chain, stopping if any validator raises StopValidation.
+
+        :param form: The Form instance this field belongs to.
+        :param validators: a sequence or iterable of validator callables.
+        :return: True if validation was stopped, False otherwise.
+        """
+        for validator in validators:
+            try:
+                validator(form, self)
+            except StopValidation as e:
+                if e.args and e.args[0]:
+                    self.errors.append(e.args[0])
+                return True
+            except ValidationError as e:
+                self.errors.append(e.args[0])
+
+        return False
+
+    def pre_validate(self, form):
+        """
+        Override if you need field-level validation. Runs before any other
+        validators.
+
+        :param form: The form the field belongs to.
+        """
+        pass
+
+    def post_validate(self, form, validation_stopped):
+        """
+        Override if you need to run any field-level validation tasks after
+        normal validation. This shouldn't be needed in most cases.
+
+        :param form: The form the field belongs to.
+        :param validation_stopped:
+            `True` if any validator raised StopValidation.
+        """
+        pass
+
+    def process(self, formdata, data=unset_value, extra_filters=None):
+        """
+        Process incoming data, calling process_data, process_formdata as needed,
+        and run filters.
+
+        If `data` is not provided, process_data will be called on the field's
+        default.
+
+        Field subclasses usually won't override this, instead overriding the
+        process_formdata and process_data methods. Only override this for
+        special advanced processing, such as when a field encapsulates many
+        inputs.
+
+        :param extra_filters: A sequence of extra filters to run.
+        """
+        self.process_errors = []
+        if data is unset_value:
+            try:
+                data = self.default()
+            except TypeError:
+                data = self.default
+
+        self.object_data = data
+
+        try:
+            self.process_data(data)
+        except ValueError as e:
+            self.process_errors.append(e.args[0])
+
+        if formdata is not None:
+            if self.name in formdata:
+                self.raw_data = formdata.getlist(self.name)
+            else:
+                self.raw_data = []
+
+            try:
+                self.process_formdata(self.raw_data)
+            except ValueError as e:
+                self.process_errors.append(e.args[0])
+
+        try:
+            for filter in itertools.chain(self.filters, extra_filters or []):
+                self.data = filter(self.data)
+        except ValueError as e:
+            self.process_errors.append(e.args[0])
+
+    def process_data(self, value):
+        """
+        Process the Python data applied to this field and store the result.
+
+        This will be called during form construction by the form's `kwargs` or
+        `obj` argument.
+
+        :param value: The python object containing the value to process.
+        """
+        self.data = value
+
+    def process_formdata(self, valuelist):
+        """
+        Process data received over the wire from a form.
+
+        This will be called during form construction with data supplied
+        through the `formdata` argument.
+
+        :param valuelist: A list of strings to process.
+        """
+        if valuelist:
+            self.data = valuelist[0]
+
+    def populate_obj(self, obj, name):
+        """
+        Populates `obj.<name>` with the field's data.
+
+        :note: This is a destructive operation. If `obj.<name>` already exists,
+               it will be overridden. Use with caution.
+        """
+        setattr(obj, name, self.data)
+
+
+class UnboundField:
+    _formfield = True
+    creation_counter = 0
+
+    def __init__(self, field_class, *args, name=None, **kwargs):
+        UnboundField.creation_counter += 1
+        self.field_class = field_class
+        self.args = args
+        self.name = name
+        self.kwargs = kwargs
+        self.creation_counter = UnboundField.creation_counter
+        validators = kwargs.get("validators")
+        if validators:
+            self.field_class.check_validators(validators)
+
+    def bind(self, form, name, prefix="", translations=None, **kwargs):
+        kw = dict(
+            self.kwargs,
+            name=name,
+            _form=form,
+            _prefix=prefix,
+            _translations=translations,
+            **kwargs,
+        )
+        return self.field_class(*self.args, **kw)
+
+    def __repr__(self):
+        return "<UnboundField({}, {!r}, {!r})>".format(
+            self.field_class.__name__, self.args, self.kwargs
+        )
+
+
+class Flags:
+    """
+    Holds a set of flags as attributes.
+
+    Accessing a non-existing attribute returns None for its value.
+    """
+
+    def __getattr__(self, name):
+        if name.startswith("_"):
+            return super().__getattr__(name)
+        return None
+
+    def __contains__(self, name):
+        return getattr(self, name)
+
+    def __repr__(self):
+        flags = (name for name in dir(self) if not name.startswith("_"))
+        return "<wtforms.fields.Flags: {%s}>" % ", ".join(flags)
+
+
+class Label:
+    """
+    An HTML form label.
+    """
+
+    def __init__(self, field_id, text):
+        self.field_id = field_id
+        self.text = text
+
+    def __str__(self):
+        return self()
+
+    def __html__(self):
+        return self()
+
+    def __call__(self, text=None, **kwargs):
+        if "for_" in kwargs:
+            kwargs["for"] = kwargs.pop("for_")
+        else:
+            kwargs.setdefault("for", self.field_id)
+
+        attributes = widgets.html_params(**kwargs)
+        text = escape(text or self.text)
+        return Markup(f"<label {attributes}>{text}</label>")
+
+    def __repr__(self):
+        return f"Label({self.field_id!r}, {self.text!r})"

+ 169 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/datetime.py

@@ -0,0 +1,169 @@
+import datetime
+
+from wtforms import widgets
+from wtforms.fields.core import Field
+from wtforms.utils import clean_datetime_format_for_strptime
+
+__all__ = (
+    "DateTimeField",
+    "DateField",
+    "TimeField",
+    "MonthField",
+    "DateTimeLocalField",
+    "WeekField",
+)
+
+
+class DateTimeField(Field):
+    """
+    A text field which stores a :class:`datetime.datetime` matching one or
+    several formats. If ``format`` is a list, any input value matching any
+    format will be accepted, and the first format in the list will be used
+    to produce HTML values.
+    """
+
+    widget = widgets.DateTimeInput()
+
+    def __init__(
+        self, label=None, validators=None, format="%Y-%m-%d %H:%M:%S", **kwargs
+    ):
+        super().__init__(label, validators, **kwargs)
+        self.format = format if isinstance(format, list) else [format]
+        self.strptime_format = clean_datetime_format_for_strptime(self.format)
+
+    def _value(self):
+        if self.raw_data:
+            return " ".join(self.raw_data)
+        return self.data and self.data.strftime(self.format[0]) or ""
+
+    def process_formdata(self, valuelist):
+        if not valuelist:
+            return
+
+        date_str = " ".join(valuelist)
+        for format in self.strptime_format:
+            try:
+                self.data = datetime.datetime.strptime(date_str, format)
+                return
+            except ValueError:
+                self.data = None
+
+        raise ValueError(self.gettext("Not a valid datetime value."))
+
+
+class DateField(DateTimeField):
+    """
+    Same as :class:`~wtforms.fields.DateTimeField`, except stores a
+    :class:`datetime.date`.
+    """
+
+    widget = widgets.DateInput()
+
+    def __init__(self, label=None, validators=None, format="%Y-%m-%d", **kwargs):
+        super().__init__(label, validators, format, **kwargs)
+
+    def process_formdata(self, valuelist):
+        if not valuelist:
+            return
+
+        date_str = " ".join(valuelist)
+        for format in self.strptime_format:
+            try:
+                self.data = datetime.datetime.strptime(date_str, format).date()
+                return
+            except ValueError:
+                self.data = None
+
+        raise ValueError(self.gettext("Not a valid date value."))
+
+
+class TimeField(DateTimeField):
+    """
+    Same as :class:`~wtforms.fields.DateTimeField`, except stores a
+    :class:`datetime.time`.
+    """
+
+    widget = widgets.TimeInput()
+
+    def __init__(self, label=None, validators=None, format="%H:%M", **kwargs):
+        super().__init__(label, validators, format, **kwargs)
+
+    def process_formdata(self, valuelist):
+        if not valuelist:
+            return
+
+        time_str = " ".join(valuelist)
+        for format in self.strptime_format:
+            try:
+                self.data = datetime.datetime.strptime(time_str, format).time()
+                return
+            except ValueError:
+                self.data = None
+
+        raise ValueError(self.gettext("Not a valid time value."))
+
+
+class MonthField(DateField):
+    """
+    Same as :class:`~wtforms.fields.DateField`, except represents a month,
+    stores a :class:`datetime.date` with `day = 1`.
+    """
+
+    widget = widgets.MonthInput()
+
+    def __init__(self, label=None, validators=None, format="%Y-%m", **kwargs):
+        super().__init__(label, validators, format, **kwargs)
+
+
+class WeekField(DateField):
+    """
+    Same as :class:`~wtforms.fields.DateField`, except represents a week,
+    stores a :class:`datetime.date` of the monday of the given week.
+    """
+
+    widget = widgets.WeekInput()
+
+    def __init__(self, label=None, validators=None, format="%Y-W%W", **kwargs):
+        super().__init__(label, validators, format, **kwargs)
+
+    def process_formdata(self, valuelist):
+        if not valuelist:
+            return
+
+        time_str = " ".join(valuelist)
+        for format in self.strptime_format:
+            try:
+                if "%w" not in format:
+                    # The '%w' week starting day is needed. This defaults it to monday
+                    # like ISO 8601 indicates.
+                    self.data = datetime.datetime.strptime(
+                        f"{time_str}-1", f"{format}-%w"
+                    ).date()
+                else:
+                    self.data = datetime.datetime.strptime(time_str, format).date()
+                return
+            except ValueError:
+                self.data = None
+
+        raise ValueError(self.gettext("Not a valid week value."))
+
+
+class DateTimeLocalField(DateTimeField):
+    """
+    Same as :class:`~wtforms.fields.DateTimeField`, but represents an
+    ``<input type="datetime-local">``.
+    """
+
+    widget = widgets.DateTimeLocalInput()
+
+    def __init__(self, *args, **kwargs):
+        kwargs.setdefault(
+            "format",
+            [
+                "%Y-%m-%d %H:%M:%S",
+                "%Y-%m-%dT%H:%M:%S",
+                "%Y-%m-%d %H:%M",
+                "%Y-%m-%dT%H:%M",
+            ],
+        )
+        super().__init__(*args, **kwargs)

+ 97 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/form.py

@@ -0,0 +1,97 @@
+from .. import widgets
+from .core import Field
+from wtforms.utils import unset_value
+
+__all__ = ("FormField",)
+
+
+class FormField(Field):
+    """
+    Encapsulate a form as a field in another form.
+
+    :param form_class:
+        A subclass of Form that will be encapsulated.
+    :param separator:
+        A string which will be suffixed to this field's name to create the
+        prefix to enclosed fields. The default is fine for most uses.
+    """
+
+    widget = widgets.TableWidget()
+
+    def __init__(
+        self, form_class, label=None, validators=None, separator="-", **kwargs
+    ):
+        super().__init__(label, validators, **kwargs)
+        self.form_class = form_class
+        self.separator = separator
+        self._obj = None
+        if self.filters:
+            raise TypeError(
+                "FormField cannot take filters, as the encapsulated"
+                " data is not mutable."
+            )
+        if validators:
+            raise TypeError(
+                "FormField does not accept any validators. Instead,"
+                " define them on the enclosed form."
+            )
+
+    def process(self, formdata, data=unset_value, extra_filters=None):
+        if extra_filters:
+            raise TypeError(
+                "FormField cannot take filters, as the encapsulated"
+                "data is not mutable."
+            )
+
+        if data is unset_value:
+            try:
+                data = self.default()
+            except TypeError:
+                data = self.default
+            self._obj = data
+
+        self.object_data = data
+
+        prefix = self.name + self.separator
+        if isinstance(data, dict):
+            self.form = self.form_class(formdata=formdata, prefix=prefix, **data)
+        else:
+            self.form = self.form_class(formdata=formdata, obj=data, prefix=prefix)
+
+    def validate(self, form, extra_validators=()):
+        if extra_validators:
+            raise TypeError(
+                "FormField does not accept in-line validators, as it"
+                " gets errors from the enclosed form."
+            )
+        return self.form.validate()
+
+    def populate_obj(self, obj, name):
+        candidate = getattr(obj, name, None)
+        if candidate is None:
+            if self._obj is None:
+                raise TypeError(
+                    "populate_obj: cannot find a value to populate from"
+                    " the provided obj or input data/defaults"
+                )
+            candidate = self._obj
+
+        self.form.populate_obj(candidate)
+        setattr(obj, name, candidate)
+
+    def __iter__(self):
+        return iter(self.form)
+
+    def __getitem__(self, name):
+        return self.form[name]
+
+    def __getattr__(self, name):
+        return getattr(self.form, name)
+
+    @property
+    def data(self):
+        return self.form.data
+
+    @property
+    def errors(self):
+        return self.form.errors

+ 201 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/list.py

@@ -0,0 +1,201 @@
+import itertools
+
+from .. import widgets
+from .core import Field
+from .core import UnboundField
+from wtforms.utils import unset_value
+
+__all__ = ("FieldList",)
+
+
+class FieldList(Field):
+    """
+    Encapsulate an ordered list of multiple instances of the same field type,
+    keeping data as a list.
+
+    >>> authors = FieldList(StringField('Name', [validators.DataRequired()]))
+
+    :param unbound_field:
+        A partially-instantiated field definition, just like that would be
+        defined on a form directly.
+    :param min_entries:
+        if provided, always have at least this many entries on the field,
+        creating blank ones if the provided input does not specify a sufficient
+        amount.
+    :param max_entries:
+        accept no more than this many entries as input, even if more exist in
+        formdata.
+    :param separator:
+        A string which will be suffixed to this field's name to create the
+        prefix to enclosed list entries. The default is fine for most uses.
+    """
+
+    widget = widgets.ListWidget()
+
+    def __init__(
+        self,
+        unbound_field,
+        label=None,
+        validators=None,
+        min_entries=0,
+        max_entries=None,
+        separator="-",
+        default=(),
+        **kwargs,
+    ):
+        super().__init__(label, validators, default=default, **kwargs)
+        if self.filters:
+            raise TypeError(
+                "FieldList does not accept any filters. Instead, define"
+                " them on the enclosed field."
+            )
+        assert isinstance(
+            unbound_field, UnboundField
+        ), "Field must be unbound, not a field class"
+        self.unbound_field = unbound_field
+        self.min_entries = min_entries
+        self.max_entries = max_entries
+        self.last_index = -1
+        self._prefix = kwargs.get("_prefix", "")
+        self._separator = separator
+        self._field_separator = unbound_field.kwargs.get("separator", "-")
+
+    def process(self, formdata, data=unset_value, extra_filters=None):
+        if extra_filters:
+            raise TypeError(
+                "FieldList does not accept any filters. Instead, define"
+                " them on the enclosed field."
+            )
+
+        self.entries = []
+        if data is unset_value or not data:
+            try:
+                data = self.default()
+            except TypeError:
+                data = self.default
+
+        self.object_data = data
+
+        if formdata:
+            indices = sorted(set(self._extract_indices(self.name, formdata)))
+            if self.max_entries:
+                indices = indices[: self.max_entries]
+
+            idata = iter(data)
+            for index in indices:
+                try:
+                    obj_data = next(idata)
+                except StopIteration:
+                    obj_data = unset_value
+                self._add_entry(formdata, obj_data, index=index)
+        else:
+            for obj_data in data:
+                self._add_entry(formdata, obj_data)
+
+        while len(self.entries) < self.min_entries:
+            self._add_entry(formdata)
+
+    def _extract_indices(self, prefix, formdata):
+        """
+        Yield indices of any keys with given prefix.
+
+        formdata must be an object which will produce keys when iterated.  For
+        example, if field 'foo' contains keys 'foo-0-bar', 'foo-1-baz', then
+        the numbers 0 and 1 will be yielded, but not necessarily in order.
+        """
+        offset = len(prefix) + 1
+        for k in formdata:
+            if k.startswith(prefix):
+                k = k[offset:].split(self._field_separator, 1)[0]
+                if k.isdigit():
+                    yield int(k)
+
+    def validate(self, form, extra_validators=()):
+        """
+        Validate this FieldList.
+
+        Note that FieldList validation differs from normal field validation in
+        that FieldList validates all its enclosed fields first before running any
+        of its own validators.
+        """
+        self.errors = []
+
+        # Run validators on all entries within
+        for subfield in self.entries:
+            subfield.validate(form)
+            self.errors.append(subfield.errors)
+
+        if not any(x for x in self.errors):
+            self.errors = []
+
+        chain = itertools.chain(self.validators, extra_validators)
+        self._run_validation_chain(form, chain)
+
+        return len(self.errors) == 0
+
+    def populate_obj(self, obj, name):
+        values = getattr(obj, name, None)
+        try:
+            ivalues = iter(values)
+        except TypeError:
+            ivalues = iter([])
+
+        candidates = itertools.chain(ivalues, itertools.repeat(None))
+        _fake = type("_fake", (object,), {})
+        output = []
+        for field, data in zip(self.entries, candidates):
+            fake_obj = _fake()
+            fake_obj.data = data
+            field.populate_obj(fake_obj, "data")
+            output.append(fake_obj.data)
+
+        setattr(obj, name, output)
+
+    def _add_entry(self, formdata=None, data=unset_value, index=None):
+        assert (
+            not self.max_entries or len(self.entries) < self.max_entries
+        ), "You cannot have more than max_entries entries in this FieldList"
+        if index is None:
+            index = self.last_index + 1
+        self.last_index = index
+        name = f"{self.short_name}{self._separator}{index}"
+        id = f"{self.id}{self._separator}{index}"
+        field = self.unbound_field.bind(
+            form=None,
+            name=name,
+            prefix=self._prefix,
+            id=id,
+            _meta=self.meta,
+            translations=self._translations,
+        )
+        field.process(formdata, data)
+        self.entries.append(field)
+        return field
+
+    def append_entry(self, data=unset_value):
+        """
+        Create a new entry with optional default data.
+
+        Entries added in this way will *not* receive formdata however, and can
+        only receive object data.
+        """
+        return self._add_entry(data=data)
+
+    def pop_entry(self):
+        """Removes the last entry from the list and returns it."""
+        entry = self.entries.pop()
+        self.last_index -= 1
+        return entry
+
+    def __iter__(self):
+        return iter(self.entries)
+
+    def __len__(self):
+        return len(self.entries)
+
+    def __getitem__(self, index):
+        return self.entries[index]
+
+    @property
+    def data(self):
+        return [f.data for f in self.entries]

+ 213 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/numeric.py

@@ -0,0 +1,213 @@
+import decimal
+
+from wtforms import widgets
+from wtforms.fields.core import Field
+from wtforms.utils import unset_value
+
+__all__ = (
+    "IntegerField",
+    "DecimalField",
+    "FloatField",
+    "IntegerRangeField",
+    "DecimalRangeField",
+)
+
+
+class LocaleAwareNumberField(Field):
+    """
+    Base class for implementing locale-aware number parsing.
+
+    Locale-aware numbers require the 'babel' package to be present.
+    """
+
+    def __init__(
+        self,
+        label=None,
+        validators=None,
+        use_locale=False,
+        number_format=None,
+        **kwargs,
+    ):
+        super().__init__(label, validators, **kwargs)
+        self.use_locale = use_locale
+        if use_locale:
+            self.number_format = number_format
+            self.locale = kwargs["_form"].meta.locales[0]
+            self._init_babel()
+
+    def _init_babel(self):
+        try:
+            from babel import numbers
+
+            self.babel_numbers = numbers
+        except ImportError as exc:
+            raise ImportError(
+                "Using locale-aware decimals requires the babel library."
+            ) from exc
+
+    def _parse_decimal(self, value):
+        return self.babel_numbers.parse_decimal(value, self.locale)
+
+    def _format_decimal(self, value):
+        return self.babel_numbers.format_decimal(value, self.number_format, self.locale)
+
+
+class IntegerField(Field):
+    """
+    A text field, except all input is coerced to an integer.  Erroneous input
+    is ignored and will not be accepted as a value.
+    """
+
+    widget = widgets.NumberInput()
+
+    def __init__(self, label=None, validators=None, **kwargs):
+        super().__init__(label, validators, **kwargs)
+
+    def _value(self):
+        if self.raw_data:
+            return self.raw_data[0]
+        if self.data is not None:
+            return str(self.data)
+        return ""
+
+    def process_data(self, value):
+        if value is None or value is unset_value:
+            self.data = None
+            return
+
+        try:
+            self.data = int(value)
+        except (ValueError, TypeError) as exc:
+            self.data = None
+            raise ValueError(self.gettext("Not a valid integer value.")) from exc
+
+    def process_formdata(self, valuelist):
+        if not valuelist:
+            return
+
+        try:
+            self.data = int(valuelist[0])
+        except ValueError as exc:
+            self.data = None
+            raise ValueError(self.gettext("Not a valid integer value.")) from exc
+
+
+class DecimalField(LocaleAwareNumberField):
+    """
+    A text field which displays and coerces data of the `decimal.Decimal` type.
+
+    :param places:
+        How many decimal places to quantize the value to for display on form.
+        If unset, use 2 decimal places.
+        If explicitely set to `None`, does not quantize value.
+    :param rounding:
+        How to round the value during quantize, for example
+        `decimal.ROUND_UP`. If unset, uses the rounding value from the
+        current thread's context.
+    :param use_locale:
+        If True, use locale-based number formatting. Locale-based number
+        formatting requires the 'babel' package.
+    :param number_format:
+        Optional number format for locale. If omitted, use the default decimal
+        format for the locale.
+    """
+
+    widget = widgets.NumberInput(step="any")
+
+    def __init__(
+        self, label=None, validators=None, places=unset_value, rounding=None, **kwargs
+    ):
+        super().__init__(label, validators, **kwargs)
+        if self.use_locale and (places is not unset_value or rounding is not None):
+            raise TypeError(
+                "When using locale-aware numbers, 'places' and 'rounding' are ignored."
+            )
+
+        if places is unset_value:
+            places = 2
+        self.places = places
+        self.rounding = rounding
+
+    def _value(self):
+        if self.raw_data:
+            return self.raw_data[0]
+
+        if self.data is None:
+            return ""
+
+        if self.use_locale:
+            return str(self._format_decimal(self.data))
+
+        if self.places is None:
+            return str(self.data)
+
+        if not hasattr(self.data, "quantize"):
+            # If for some reason, data is a float or int, then format
+            # as we would for floats using string formatting.
+            format = "%%0.%df" % self.places
+            return format % self.data
+
+        exp = decimal.Decimal(".1") ** self.places
+        if self.rounding is None:
+            quantized = self.data.quantize(exp)
+        else:
+            quantized = self.data.quantize(exp, rounding=self.rounding)
+        return str(quantized)
+
+    def process_formdata(self, valuelist):
+        if not valuelist:
+            return
+
+        try:
+            if self.use_locale:
+                self.data = self._parse_decimal(valuelist[0])
+            else:
+                self.data = decimal.Decimal(valuelist[0])
+        except (decimal.InvalidOperation, ValueError) as exc:
+            self.data = None
+            raise ValueError(self.gettext("Not a valid decimal value.")) from exc
+
+
+class FloatField(Field):
+    """
+    A text field, except all input is coerced to an float.  Erroneous input
+    is ignored and will not be accepted as a value.
+    """
+
+    widget = widgets.TextInput()
+
+    def __init__(self, label=None, validators=None, **kwargs):
+        super().__init__(label, validators, **kwargs)
+
+    def _value(self):
+        if self.raw_data:
+            return self.raw_data[0]
+        if self.data is not None:
+            return str(self.data)
+        return ""
+
+    def process_formdata(self, valuelist):
+        if not valuelist:
+            return
+
+        try:
+            self.data = float(valuelist[0])
+        except ValueError as exc:
+            self.data = None
+            raise ValueError(self.gettext("Not a valid float value.")) from exc
+
+
+class IntegerRangeField(IntegerField):
+    """
+    Represents an ``<input type="range">``.
+    """
+
+    widget = widgets.RangeInput()
+
+
+class DecimalRangeField(DecimalField):
+    """
+    Represents an ``<input type="range">``.
+    """
+
+    widget = widgets.RangeInput(step="any")

+ 173 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/fields/simple.py

@@ -0,0 +1,173 @@
+from .. import widgets
+from .core import Field
+
+__all__ = (
+    "BooleanField",
+    "TextAreaField",
+    "PasswordField",
+    "FileField",
+    "MultipleFileField",
+    "HiddenField",
+    "SearchField",
+    "SubmitField",
+    "StringField",
+    "TelField",
+    "URLField",
+    "EmailField",
+    "ColorField",
+)
+
+
+class BooleanField(Field):
+    """
+    Represents an ``<input type="checkbox">``. Set the ``checked``-status by using the
+    ``default``-option. Any value for ``default``, e.g. ``default="checked"`` puts
+    ``checked`` into the html-element and sets the ``data`` to ``True``
+
+    :param false_values:
+        If provided, a sequence of strings each of which is an exact match
+        string of what is considered a "false" value. Defaults to the tuple
+        ``(False, "false", "")``
+    """
+
+    widget = widgets.CheckboxInput()
+    false_values = (False, "false", "")
+
+    def __init__(self, label=None, validators=None, false_values=None, **kwargs):
+        super().__init__(label, validators, **kwargs)
+        if false_values is not None:
+            self.false_values = false_values
+
+    def process_data(self, value):
+        self.data = bool(value)
+
+    def process_formdata(self, valuelist):
+        if not valuelist or valuelist[0] in self.false_values:
+            self.data = False
+        else:
+            self.data = True
+
+    def _value(self):
+        if self.raw_data:
+            return str(self.raw_data[0])
+        return "y"
+
+
+class StringField(Field):
+    """
+    This field is the base for most of the more complicated fields, and
+    represents an ``<input type="text">``.
+    """
+
+    widget = widgets.TextInput()
+
+    def process_formdata(self, valuelist):
+        if valuelist:
+            self.data = valuelist[0]
+
+    def _value(self):
+        return str(self.data) if self.data is not None else ""
+
+
+class TextAreaField(StringField):
+    """
+    This field represents an HTML ``<textarea>`` and can be used to take
+    multi-line input.
+    """
+
+    widget = widgets.TextArea()
+
+
+class PasswordField(StringField):
+    """
+    A StringField, except renders an ``<input type="password">``.
+
+    Also, whatever value is accepted by this field is not rendered back
+    to the browser like normal fields.
+    """
+
+    widget = widgets.PasswordInput()
+
+
+class FileField(Field):
+    """Renders a file upload field.
+
+    By default, the value will be the filename sent in the form data.
+    WTForms **does not** deal with frameworks' file handling capabilities.
+    A WTForms extension for a framework may replace the filename value
+    with an object representing the uploaded data.
+    """
+
+    widget = widgets.FileInput()
+
+    def _value(self):
+        # browser ignores value of file input for security
+        return False
+
+
+class MultipleFileField(FileField):
+    """A :class:`FileField` that allows choosing multiple files."""
+
+    widget = widgets.FileInput(multiple=True)
+
+    def process_formdata(self, valuelist):
+        self.data = valuelist
+
+
+class HiddenField(StringField):
+    """
+    HiddenField is a convenience for a StringField with a HiddenInput widget.
+
+    It will render as an ``<input type="hidden">`` but otherwise coerce to a string.
+    """
+
+    widget = widgets.HiddenInput()
+
+
+class SubmitField(BooleanField):
+    """
+    Represents an ``<input type="submit">``.  This allows checking if a given
+    submit button has been pressed.
+    """
+
+    widget = widgets.SubmitInput()
+
+
+class SearchField(StringField):
+    """
+    Represents an ``<input type="search">``.
+    """
+
+    widget = widgets.SearchInput()
+
+
+class TelField(StringField):
+    """
+    Represents an ``<input type="tel">``.
+    """
+
+    widget = widgets.TelInput()
+
+
+class URLField(StringField):
+    """
+    Represents an ``<input type="url">``.
+    """
+
+    widget = widgets.URLInput()
+
+
+class EmailField(StringField):
+    """
+    Represents an ``<input type="email">``.
+    """
+
+    widget = widgets.EmailInput()
+
+
+class ColorField(StringField):
+    """
+    Represents an ``<input type="color">``.
+    """
+
+    widget = widgets.ColorInput()

+ 329 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/form.py

@@ -0,0 +1,329 @@
+import itertools
+from collections import OrderedDict
+
+from wtforms.meta import DefaultMeta
+from wtforms.utils import unset_value
+
+__all__ = ("BaseForm", "Form")
+
+_default_meta = DefaultMeta()
+
+
+class BaseForm:
+    """
+    Base Form Class.  Provides core behaviour like field construction,
+    validation, and data and error proxying.
+    """
+
+    def __init__(self, fields, prefix="", meta=_default_meta):
+        """
+        :param fields:
+            A dict or sequence of 2-tuples of partially-constructed fields.
+        :param prefix:
+            If provided, all fields will have their name prefixed with the
+            value.
+        :param meta:
+            A meta instance which is used for configuration and customization
+            of WTForms behaviors.
+        """
+        if prefix and prefix[-1] not in "-_;:/.":
+            prefix += "-"
+
+        self.meta = meta
+        self._prefix = prefix
+        self._fields = OrderedDict()
+
+        if hasattr(fields, "items"):
+            fields = fields.items()
+
+        translations = self.meta.get_translations(self)
+        extra_fields = []
+        if meta.csrf:
+            self._csrf = meta.build_csrf(self)
+            extra_fields.extend(self._csrf.setup_form(self))
+
+        for name, unbound_field in itertools.chain(fields, extra_fields):
+            field_name = unbound_field.name or name
+            options = dict(name=field_name, prefix=prefix, translations=translations)
+            field = meta.bind_field(self, unbound_field, options)
+            self._fields[name] = field
+
+        self.form_errors = []
+
+    def __iter__(self):
+        """Iterate form fields in creation order."""
+        return iter(self._fields.values())
+
+    def __contains__(self, name):
+        """Returns `True` if the named field is a member of this form."""
+        return name in self._fields
+
+    def __getitem__(self, name):
+        """Dict-style access to this form's fields."""
+        return self._fields[name]
+
+    def __setitem__(self, name, value):
+        """Bind a field to this form."""
+        self._fields[name] = value.bind(form=self, name=name, prefix=self._prefix)
+
+    def __delitem__(self, name):
+        """Remove a field from this form."""
+        del self._fields[name]
+
+    def populate_obj(self, obj):
+        """
+        Populates the attributes of the passed `obj` with data from the form's
+        fields.
+
+        :note: This is a destructive operation; Any attribute with the same name
+               as a field will be overridden. Use with caution.
+        """
+        for name, field in self._fields.items():
+            field.populate_obj(obj, name)
+
+    def process(self, formdata=None, obj=None, data=None, extra_filters=None, **kwargs):
+        """Process default and input data with each field.
+
+        :param formdata: Input data coming from the client, usually
+            ``request.form`` or equivalent. Should provide a "multi
+            dict" interface to get a list of values for a given key,
+            such as what Werkzeug, Django, and WebOb provide.
+        :param obj: Take existing data from attributes on this object
+            matching form field attributes. Only used if ``formdata`` is
+            not passed.
+        :param data: Take existing data from keys in this dict matching
+            form field attributes. ``obj`` takes precedence if it also
+            has a matching attribute. Only used if ``formdata`` is not
+            passed.
+        :param extra_filters: A dict mapping field attribute names to
+            lists of extra filter functions to run. Extra filters run
+            after filters passed when creating the field. If the form
+            has ``filter_<fieldname>``, it is the last extra filter.
+        :param kwargs: Merged with ``data`` to allow passing existing
+            data as parameters. Overwrites any duplicate keys in
+            ``data``. Only used if ``formdata`` is not passed.
+        """
+        formdata = self.meta.wrap_formdata(self, formdata)
+
+        if data is not None:
+            kwargs = dict(data, **kwargs)
+
+        filters = extra_filters.copy() if extra_filters is not None else {}
+
+        for name, field in self._fields.items():
+            field_extra_filters = filters.get(name, [])
+
+            inline_filter = getattr(self, "filter_%s" % name, None)
+            if inline_filter is not None:
+                field_extra_filters.append(inline_filter)
+
+            if obj is not None and hasattr(obj, name):
+                data = getattr(obj, name)
+            elif name in kwargs:
+                data = kwargs[name]
+            else:
+                data = unset_value
+
+            field.process(formdata, data, extra_filters=field_extra_filters)
+
+    def validate(self, extra_validators=None):
+        """
+        Validates the form by calling `validate` on each field.
+
+        :param extra_validators:
+            If provided, is a dict mapping field names to a sequence of
+            callables which will be passed as extra validators to the field's
+            `validate` method.
+
+        Returns `True` if no errors occur.
+        """
+        success = True
+        for name, field in self._fields.items():
+            if extra_validators is not None and name in extra_validators:
+                extra = extra_validators[name]
+            else:
+                extra = tuple()
+            if not field.validate(self, extra):
+                success = False
+        return success
+
+    @property
+    def data(self):
+        return {name: f.data for name, f in self._fields.items()}
+
+    @property
+    def errors(self):
+        errors = {name: f.errors for name, f in self._fields.items() if f.errors}
+        if self.form_errors:
+            errors[None] = self.form_errors
+        return errors
+
+
+class FormMeta(type):
+    """
+    The metaclass for `Form` and any subclasses of `Form`.
+
+    `FormMeta`'s responsibility is to create the `_unbound_fields` list, which
+    is a list of `UnboundField` instances sorted by their order of
+    instantiation.  The list is created at the first instantiation of the form.
+    If any fields are added/removed from the form, the list is cleared to be
+    re-generated on the next instantiation.
+
+    Any properties which begin with an underscore or are not `UnboundField`
+    instances are ignored by the metaclass.
+    """
+
+    def __init__(cls, name, bases, attrs):
+        type.__init__(cls, name, bases, attrs)
+        cls._unbound_fields = None
+        cls._wtforms_meta = None
+
+    def __call__(cls, *args, **kwargs):
+        """
+        Construct a new `Form` instance.
+
+        Creates the `_unbound_fields` list and the internal `_wtforms_meta`
+        subclass of the class Meta in order to allow a proper inheritance
+        hierarchy.
+        """
+        if cls._unbound_fields is None:
+            fields = []
+            for name in dir(cls):
+                if not name.startswith("_"):
+                    unbound_field = getattr(cls, name)
+                    if hasattr(unbound_field, "_formfield"):
+                        fields.append((name, unbound_field))
+            # We keep the name as the second element of the sort
+            # to ensure a stable sort.
+            fields.sort(key=lambda x: (x[1].creation_counter, x[0]))
+            cls._unbound_fields = fields
+
+        # Create a subclass of the 'class Meta' using all the ancestors.
+        if cls._wtforms_meta is None:
+            bases = []
+            for mro_class in cls.__mro__:
+                if "Meta" in mro_class.__dict__:
+                    bases.append(mro_class.Meta)
+            cls._wtforms_meta = type("Meta", tuple(bases), {})
+        return type.__call__(cls, *args, **kwargs)
+
+    def __setattr__(cls, name, value):
+        """
+        Add an attribute to the class, clearing `_unbound_fields` if needed.
+        """
+        if name == "Meta":
+            cls._wtforms_meta = None
+        elif not name.startswith("_") and hasattr(value, "_formfield"):
+            cls._unbound_fields = None
+        type.__setattr__(cls, name, value)
+
+    def __delattr__(cls, name):
+        """
+        Remove an attribute from the class, clearing `_unbound_fields` if
+        needed.
+        """
+        if not name.startswith("_"):
+            cls._unbound_fields = None
+        type.__delattr__(cls, name)
+
+
+class Form(BaseForm, metaclass=FormMeta):
+    """
+    Declarative Form base class. Extends BaseForm's core behaviour allowing
+    fields to be defined on Form subclasses as class attributes.
+
+    In addition, form and instance input data are taken at construction time
+    and passed to `process()`.
+    """
+
+    Meta = DefaultMeta
+
+    def __init__(
+        self,
+        formdata=None,
+        obj=None,
+        prefix="",
+        data=None,
+        meta=None,
+        **kwargs,
+    ):
+        """
+        :param formdata: Input data coming from the client, usually
+            ``request.form`` or equivalent. Should provide a "multi
+            dict" interface to get a list of values for a given key,
+            such as what Werkzeug, Django, and WebOb provide.
+        :param obj: Take existing data from attributes on this object
+            matching form field attributes. Only used if ``formdata`` is
+            not passed.
+        :param prefix: If provided, all fields will have their name
+            prefixed with the value. This is for distinguishing multiple
+            forms on a single page. This only affects the HTML name for
+            matching input data, not the Python name for matching
+            existing data.
+        :param data: Take existing data from keys in this dict matching
+            form field attributes. ``obj`` takes precedence if it also
+            has a matching attribute. Only used if ``formdata`` is not
+            passed.
+        :param meta: A dict of attributes to override on this form's
+            :attr:`meta` instance.
+        :param extra_filters: A dict mapping field attribute names to
+            lists of extra filter functions to run. Extra filters run
+            after filters passed when creating the field. If the form
+            has ``filter_<fieldname>``, it is the last extra filter.
+        :param kwargs: Merged with ``data`` to allow passing existing
+            data as parameters. Overwrites any duplicate keys in
+            ``data``. Only used if ``formdata`` is not passed.
+        """
+        meta_obj = self._wtforms_meta()
+        if meta is not None and isinstance(meta, dict):
+            meta_obj.update_values(meta)
+        super().__init__(self._unbound_fields, meta=meta_obj, prefix=prefix)
+
+        for name, field in self._fields.items():
+            # Set all the fields to attributes so that they obscure the class
+            # attributes with the same names.
+            setattr(self, name, field)
+        self.process(formdata, obj, data=data, **kwargs)
+
+    def __setitem__(self, name, value):
+        raise TypeError("Fields may not be added to Form instances, only classes.")
+
+    def __delitem__(self, name):
+        del self._fields[name]
+        setattr(self, name, None)
+
+    def __delattr__(self, name):
+        if name in self._fields:
+            self.__delitem__(name)
+        else:
+            # This is done for idempotency, if we have a name which is a field,
+            # we want to mask it by setting the value to None.
+            unbound_field = getattr(self.__class__, name, None)
+            if unbound_field is not None and hasattr(unbound_field, "_formfield"):
+                setattr(self, name, None)
+            else:
+                super().__delattr__(name)
+
+    def validate(self, extra_validators=None):
+        """Validate the form by calling ``validate`` on each field.
+        Returns ``True`` if validation passes.
+
+        If the form defines a ``validate_<fieldname>`` method, it is
+        appended as an extra validator for the field's ``validate``.
+
+        :param extra_validators: A dict mapping field names to lists of
+            extra validator methods to run. Extra validators run after
+            validators passed when creating the field. If the form has
+            ``validate_<fieldname>``, it is the last extra validator.
+        """
+        if extra_validators is not None:
+            extra = extra_validators.copy()
+        else:
+            extra = {}
+
+        for name in self._fields:
+            inline = getattr(self.__class__, f"validate_{name}", None)
+            if inline is not None:
+                extra.setdefault(name, []).append(inline)
+
+        return super().validate(extra)

+ 72 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/i18n.py

@@ -0,0 +1,72 @@
+import os
+
+
+def messages_path():
+    """
+    Determine the path to the 'messages' directory as best possible.
+    """
+    module_path = os.path.abspath(__file__)
+    locale_path = os.path.join(os.path.dirname(module_path), "locale")
+    if not os.path.exists(locale_path):  # pragma: no cover
+        locale_path = "/usr/share/locale"
+    return locale_path
+
+
+def get_builtin_gnu_translations(languages=None):
+    """
+    Get a gettext.GNUTranslations object pointing at the
+    included translation files.
+
+    :param languages:
+        A list of languages to try, in order. If omitted or None, then
+        gettext will try to use locale information from the environment.
+    """
+    import gettext
+
+    return gettext.translation("wtforms", messages_path(), languages)
+
+
+def get_translations(languages=None, getter=get_builtin_gnu_translations):
+    """
+    Get a WTForms translation object which wraps a low-level translations object.
+
+    :param languages:
+        A sequence of languages to try, in order.
+    :param getter:
+        A single-argument callable which returns a low-level translations object.
+    """
+    return getter(languages)
+
+
+class DefaultTranslations:
+    """
+    A WTForms translations object to wrap translations objects which use
+    ugettext/ungettext.
+    """
+
+    def __init__(self, translations):
+        self.translations = translations
+
+    def gettext(self, string):
+        return self.translations.ugettext(string)
+
+    def ngettext(self, singular, plural, n):
+        return self.translations.ungettext(singular, plural, n)
+
+
+class DummyTranslations:
+    """
+    A translations object which simply returns unmodified strings.
+
+    This is typically used when translations are disabled or if no valid
+    translations provider can be found.
+    """
+
+    def gettext(self, string):
+        return string
+
+    def ngettext(self, singular, plural, n):
+        if n == 1:
+            return singular
+
+        return plural

+ 62 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/README.md

@@ -0,0 +1,62 @@
+Translations
+============
+
+WTForms uses gettext to provide translations. Translations for various
+strings rendered by WTForms are created and updated by the community. If
+you notice that your locale is missing, or find a translation error,
+please submit a fix.
+
+
+Create
+------
+
+To create a translation, initialize a catalog in the new locale:
+
+```
+$ pybabel init --input-file src/wtforms/locale/wtforms.pot --output-dir src/wtforms/locale --domain wtforms --locale <your locale>
+```
+
+This will create some folders under the locale name and copy the
+template.
+
+Update
+------
+
+To add new translatable string to the catalog:
+
+```
+pybabel extract --copyright-holder="WTForms Team" --project="WTForms" --version="$(python -c 'import wtforms; print(wtforms.__version__)')" --output-file src/wtforms/locale/wtforms.pot src/wtforms
+```
+
+Edit
+----
+
+After creating a translation, or to edit an existing translation, open
+the ``.po`` file. While they can be edited by hand, there are also tools
+that make working with gettext files easier.
+
+Make sure the `.po` file:
+
+- Is a valid UTF-8 text file.
+- Has the header filled out appropriately.
+- Translates all messages.
+
+
+Verify
+------
+
+After working on the catalog, verify that it compiles and produces the
+correct translations.
+
+```
+$ pybabel compile --directory src/wtforms/locale --domain wtforms --statistics
+```
+
+Try loading your translations into some sample code to verify they look
+correct.
+
+
+Submit
+------
+
+To submit your translation, create a pull request on GitHub.

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/ar/LC_MESSAGES/wtforms.mo


+ 205 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/ar/LC_MESSAGES/wtforms.po

@@ -0,0 +1,205 @@
+# Arabic translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 2.0dev\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: 2015-04-08 20:59+0100\n"
+"Last-Translator: Jalal Maqdisi <jalal.maqdisi@gmail.com>\n"
+"Language-Team: ar <LL@li.org>\n"
+"Language: ar\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n>=3 && "
+"n<=10 ? 3 : n>=11 && n<=99 ? 4 : 5)\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "اسم الحقل '%s' غير صالح."
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "يجب على الحقل ان يساوي %(other_name)s ."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "لا يمكن للحقل ان يحتوي على اقل من %(min)d حرف."
+msgstr[1] "لا يمكن للحقل ان يحتوي على اقل من %(min)d حروف."
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "لا يمكن للحقل ان يحتوي على اكثر من %(max)d حرف."
+msgstr[1] "لا يمكن للحقل ان يحتوي على اكثر من %(max)d حروف."
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+msgstr[3] ""
+msgstr[4] ""
+msgstr[5] ""
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "يجب على طول الحقل ان يكون ما بين %(min)d و %(max)d حرف."
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "لا يجب على الرقم ان يقل عن %(min)s."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "لا يجب على الرقم ان يزيد عن %(max)s. "
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "يجب على الرقم ان يكون ما بين %(min)s و %(max)s."
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "هذا الحقل مطلوب."
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "الاملاء غير صالح."
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "البريد الالكتروني غير صالح."
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "پروتوكول الانترنت IP غير صالح."
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "عنوان Mac غير صالح."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "عنوان الرابط غير صالح."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "عنوان UUID غير صالح."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "قيمة غير صالحة، يجب أن تكون واحدة من: %(values)s."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "قيمة غير صالحة، يجب أن تكون اي من: %(values)s."
+
+#: src/wtforms/validators.py:698
+#, fuzzy
+#| msgid "This field is required."
+msgid "This field cannot be edited"
+msgstr "هذا الحقل مطلوب."
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr ""
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "رمز CSRF غير صالح."
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "رمز CSRF مفقود."
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "CSRF قد فشل."
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "انتهت صلاحية رمز CSRF."
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr "اختيار غير صالح: لا يمكن الاجبار."
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr ""
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "اختيار غير صحيح."
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr "اختيارات غير صالحة: واحدة او اكثر من الادخالات لا يمكن اجبارها."
+
+#: src/wtforms/fields/choices.py:204
+#, fuzzy, python-format
+#| msgid "'%(value)s' is not a valid choice for this field."
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "القيمة '%(value)s' ليست باختيار صحيح لهذا الحقل."
+msgstr[1] "القيمة '%(value)s' ليست باختيار صحيح لهذا الحقل."
+msgstr[2] "القيمة '%(value)s' ليست باختيار صحيح لهذا الحقل."
+msgstr[3] "القيمة '%(value)s' ليست باختيار صحيح لهذا الحقل."
+msgstr[4] "القيمة '%(value)s' ليست باختيار صحيح لهذا الحقل."
+msgstr[5] "القيمة '%(value)s' ليست باختيار صحيح لهذا الحقل."
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "قيمة الوقت والتاريخ غير صالحة."
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "قيمة التاريخ غير صالحة."
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr ""
+
+#: src/wtforms/fields/datetime.py:148
+#, fuzzy
+#| msgid "Not a valid date value."
+msgid "Not a valid week value."
+msgstr "قيمة التاريخ غير صالحة."
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "قيمة العدد الحقيقي غير صالحة."
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "القيمة العشرية غير صالحة."
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "القيمة العائمة غير صالحة."

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/bg/LC_MESSAGES/wtforms.mo


+ 190 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/bg/LC_MESSAGES/wtforms.po

@@ -0,0 +1,190 @@
+# Bulgarian (Bulgaria) translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 2.0dev\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: 2017-02-16 11:59+0100\n"
+"Last-Translator: \n"
+"Language-Team: Vladimir Kolev <me@vkolev.net>\n"
+"Language: bg_BG\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "Невалидно име на поле '%s'."
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "Полето трябва да е еднакво с %(other_name)s."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "Полето трябва да бъде дълго поне %(min)d символ."
+msgstr[1] "Полето трябва да бъде дълго поне %(min)d символа."
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "Полето не моде да бъде по-дълго от %(max)d символ."
+msgstr[1] "Полето не моде да бъде по-дълго от %(max)d символа."
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "Дължината на полето трябва да бъде между %(min)d и %(max)d символа."
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "Числото трябва да е поне %(min)s."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "Числото трябва да е максимално %(max)s."
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "Числото трябва да бъде между %(min)s и %(max)s."
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "Това поле е задължително"
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "Невалидно въвеждане."
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "Невалиден Е-мейл адрес."
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "Невалиден IP адрес."
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "Невалиден MAC адрес."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "Невалиден URL."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "Невалиден UUID."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "Невалидна стойност, трябва да бъде една от: %(values)s."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "Невалидна стойност, не може да бъде една от: %(values)s."
+
+#: src/wtforms/validators.py:698
+#, fuzzy
+#| msgid "This field is required."
+msgid "This field cannot be edited"
+msgstr "Това поле е задължително"
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr ""
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "Невалиден CSRF Token"
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "CSRF token липсва"
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "CSRF провален"
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "CSRF token изтече"
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr "Невалиден избор: не може да бъде преобразувана"
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr ""
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "Не е валиден избор"
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr ""
+"Невалиден(и) избор(и): една или повече въведени данни не могат да бъдат "
+"преобразувани"
+
+#: src/wtforms/fields/choices.py:204
+#, fuzzy, python-format
+#| msgid "'%(value)s' is not a valid choice for this field."
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "'%(value)s' не е валиден избор за това поле"
+msgstr[1] "'%(value)s' не е валиден избор за това поле"
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "Не е валидна стойност за дата и време"
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "Не е валидна стойност за дата"
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr ""
+
+#: src/wtforms/fields/datetime.py:148
+#, fuzzy
+#| msgid "Not a valid date value."
+msgid "Not a valid week value."
+msgstr "Не е валидна стойност за дата"
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "Не е валидна цифрова стойност"
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "Не е валидна десетична стойност"
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "Не е валидна стойност с плаваща запетая"

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/ca/LC_MESSAGES/wtforms.mo


+ 189 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/ca/LC_MESSAGES/wtforms.po

@@ -0,0 +1,189 @@
+# Catalan translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 2.0dev\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: 2014-01-16 09:58+0100\n"
+"Last-Translator: Òscar Vilaplana <oscar.vilaplana@paylogic.eu>\n"
+"Language-Team: ca <oscar.vilaplana@paylogic.eu>\n"
+"Language: ca\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "Nom de camp no vàlid '%s'."
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "El camp ha de ser igual a %(other_name)s."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "El camp ha de contenir almenys %(min)d caràcter."
+msgstr[1] "El camp ha de contenir almenys %(min)d caràcters."
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "El camp no pot contenir més d'%(max)d caràcter."
+msgstr[1] "El camp no pot contenir més de %(max)d caràcters."
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "El camp ha de contenir entre %(min)d i %(min)d caràcters."
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "El nombre ha de ser major o igual a %(min)s."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "El nombre ha de ser com a màxim %(max)s."
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "El nombre ha d'estar entre %(min)s i %(max)s."
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "Aquest camp és obligatori."
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "Valor no vàlid."
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "Adreça d'e-mail no vàlida."
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "Adreça IP no vàlida."
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "Adreça MAC no vàlida."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "URL no vàlida."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "UUID no vàlid."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "Valor no vàlid, ha de ser un d'entre: %(values)s."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "Valor no vàlid, no pot ser cap d'aquests: %(values)s."
+
+#: src/wtforms/validators.py:698
+#, fuzzy
+#| msgid "This field is required."
+msgid "This field cannot be edited"
+msgstr "Aquest camp és obligatori."
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr ""
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "Token CSRF no vàlid"
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "Falta el token CSRF"
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "Ha fallat la comprovació de CSRF"
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "Token CSRF caducat"
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr "Opció no vàlida"
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr ""
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "Opció no acceptada"
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr ""
+"Opció o opcions no vàlides: alguna de les entrades no s'ha pogut processar"
+
+#: src/wtforms/fields/choices.py:204
+#, fuzzy, python-format
+#| msgid "'%(value)s' is not a valid choice for this field."
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "'%(value)s' no és una opció acceptada per a aquest camp"
+msgstr[1] "'%(value)s' no és una opció acceptada per a aquest camp"
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "Valor de data i hora no vàlid"
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "Valor de data no vàlid"
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr ""
+
+#: src/wtforms/fields/datetime.py:148
+#, fuzzy
+#| msgid "Not a valid date value."
+msgid "Not a valid week value."
+msgstr "Valor de data no vàlid"
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "Valor enter no vàlid"
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "Valor decimal no vàlid"
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "Valor en coma flotant no vàlid"

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/cs_CZ/LC_MESSAGES/wtforms.mo


+ 192 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/cs_CZ/LC_MESSAGES/wtforms.po

@@ -0,0 +1,192 @@
+# Czech (Czechia) translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 2.0.2dev\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: Daniil Barabash <ghostbarik@gmail.com>\n"
+"Language-Team: cz <ghostbarik@gmail.com>\n"
+"Language: cs_CZ\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2)\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "Neplatný název pole '%s'."
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "Hodnota pole má být stejná jako u %(other_name)s."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "Počet znaků daného pole má být minimálně %(min)d."
+msgstr[1] "Počet znaků daného pole má být minimálně %(min)d."
+msgstr[2] ""
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "Počet znaků daného pole má byt maximálně %(max)d."
+msgstr[1] "Počet znaků daného pole má byt maximálně %(max)d."
+msgstr[2] ""
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] ""
+msgstr[1] ""
+msgstr[2] ""
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "Délka pole ma být mezi %(min)d a %(max)d."
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "Hodnota čísla má být alespoň %(min)s."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "Hodnota čísla má být maximálně %(max)s."
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "Hodnota čísla má být mezi %(min)s and %(max)s."
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "Toto pole je povinné."
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "Neplatný vstup."
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "Neplatná emailová adresa."
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "Neplatná IP adresa."
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "Neplatná MAC adresa."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "Neplatné URL."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "Neplatné UUID."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "Neplatná hodnota, povolené hodnoty jsou: %(values)s."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "Neplatná hodnota, nesmí být mezi: %(values)s."
+
+#: src/wtforms/validators.py:698
+#, fuzzy
+#| msgid "This field is required."
+msgid "This field cannot be edited"
+msgstr "Toto pole je povinné."
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr ""
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "Neplatný CSRF token."
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "Chybí CSRF token."
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "Chyba CSRF."
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "Hodnota CSRF tokenu."
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr "Neplatná volba: nelze převést."
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr ""
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "Neplatná volba."
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr "Neplatná volba: jeden nebo více datových vstupů nemohou být převedeny."
+
+#: src/wtforms/fields/choices.py:204
+#, fuzzy, python-format
+#| msgid "'%(value)s' is not a valid choice for this field."
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "'%(value)s' není platnou volbou pro dané pole."
+msgstr[1] "'%(value)s' není platnou volbou pro dané pole."
+msgstr[2] "'%(value)s' není platnou volbou pro dané pole."
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "Neplatná hodnota pro datum a čas."
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "Neplatná hodnota pro datum."
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr ""
+
+#: src/wtforms/fields/datetime.py:148
+#, fuzzy
+#| msgid "Not a valid date value."
+msgid "Not a valid week value."
+msgstr "Neplatná hodnota pro datum."
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "Neplatná hodnota pro celé číslo."
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "Neplatná hodnota pro desetinné číslo."
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "Neplatná hodnota pro desetinné číslo."

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/cy/LC_MESSAGES/wtforms.mo


+ 189 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/cy/LC_MESSAGES/wtforms.po

@@ -0,0 +1,189 @@
+# Welsh translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 2.0dev\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: 2015-01-29 14:07+0000\n"
+"Last-Translator: Josh Rowe josh.rowe@digital.justice.gov.uk\n"
+"Language-Team: cy <LL@li.org>\n"
+"Language: cy\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "Enw maes annilys '%s'."
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "Rhaid i'r maes fod yr un fath â/ag %(other_name)s."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "Mae'n rhaid i Maes fod o leiaf %(min)d cymeriad hir."
+msgstr[1] "Mae'n rhaid i Maes fod o leiaf %(min)d nod o hyd."
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "Ni all Maes fod yn hirach na %(max)d cymeriad."
+msgstr[1] "Ni all Maes fod yn fwy na %(max)d cymeriadau."
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "Rhaid i'r maes fod rhwng %(min)d a %(max)d o nodau"
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "Rhaid i'r rhif fod o leiaf %(min)s."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "Ni chaiff y rhif fod yn fwy na %(max)s. "
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "Rhaid i'r rhif fod rhwng %(min)s a %(max)s. "
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "Rhaid cwblhau'r maes hwn."
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "Mewnbwn annilys"
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "Cyfeiriad e-bost annilys"
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "Cyfeiriad IP annilys"
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "Cyfeiriad Mac annilys."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "URL annilys."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "UUID annilys."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "Gwerth annilys, rhaid i'r gwerth fod yn un o'r canlynol: %(values)s."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "Gwerth annilys, ni all fod yn un o'r canlynol: %(values)s"
+
+#: src/wtforms/validators.py:698
+#, fuzzy
+#| msgid "This field is required."
+msgid "This field cannot be edited"
+msgstr "Rhaid cwblhau'r maes hwn."
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr ""
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "Tocyn CSRF annilys"
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "Tocyn CSRF ar goll"
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "CSRF wedi methu"
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "Tocyn CSRF wedi dod i ben"
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr "Dewis annilys: ddim yn bosib gweithredu"
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr ""
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "Nid yw hwn yn ddewis dilys"
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr ""
+"Dewis(iadau) annilys: ddim yn bosib gweithredu un neu ragor o fewnbynnau data"
+
+#: src/wtforms/fields/choices.py:204
+#, fuzzy, python-format
+#| msgid "'%(value)s' is not a valid choice for this field."
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "Nid yw '%(value)s' yn ddewis dilys ar gyfer y maes hwn"
+msgstr[1] "Nid yw '%(value)s' yn ddewis dilys ar gyfer y maes hwn"
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "Gwerth dyddiad/amser annilys"
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "Gwerth dyddiad annilys"
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr ""
+
+#: src/wtforms/fields/datetime.py:148
+#, fuzzy
+#| msgid "Not a valid date value."
+msgid "Not a valid week value."
+msgstr "Gwerth dyddiad annilys"
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "Gwerth integer annilys"
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "Gwerth degolyn annilys"
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "Gwerth float annilys"

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/de/LC_MESSAGES/wtforms.mo


+ 190 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/de/LC_MESSAGES/wtforms.po

@@ -0,0 +1,190 @@
+# German translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 1.0.4\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: 2013-05-13 19:27+0100\n"
+"Last-Translator: Chris Buergi <chris.buergi@gmx.net>\n"
+"Language-Team: de <LL@li.org>\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "Ungültiger Feldname '%s'."
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "Feld muss gleich wie %(other_name)s sein."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "Feld muss mindestens %(min)d Zeichen beinhalten."
+msgstr[1] "Feld muss mindestens %(min)d Zeichen beinhalten."
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "Feld kann nicht länger als %(max)d Zeichen sein."
+msgstr[1] "Feld kann nicht länger als %(max)d Zeichen sein."
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "Feld muss zwischen %(min)d und %(max)d Zeichen beinhalten."
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "Zahl muss mindestens %(min)s sein."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "Zahl kann höchstens %(max)s sein."
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "Zahl muss zwischen %(min)s und %(max)s liegen."
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "Dieses Feld wird benötigt."
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "Ungültige Eingabe."
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "Ungültige E-Mail-Adresse."
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "Ungültige IP-Adresse."
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "Ungültige Mac-Adresse."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "Ungültige URL."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "Ungültige UUID."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "Ungültiger Wert. Mögliche Werte: %(values)s."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "Ungültiger Wert. Wert kann keiner von folgenden sein: %(values)s."
+
+#: src/wtforms/validators.py:698
+#, fuzzy
+#| msgid "This field is required."
+msgid "This field cannot be edited"
+msgstr "Dieses Feld wird benötigt."
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr ""
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "Ungültiger CSRF-Code."
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "CSRF-Code nicht vorhanden."
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "CSRF fehlgeschlagen."
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "CSRF-Code verfallen."
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr "Ungültige Auswahl: Konnte nicht umwandeln."
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr ""
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "Keine gültige Auswahl."
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr ""
+"Ungültige Auswahl: Einer oder mehrere Eingaben konnten nicht umgewandelt "
+"werden."
+
+#: src/wtforms/fields/choices.py:204
+#, fuzzy, python-format
+#| msgid "'%(value)s' is not a valid choice for this field."
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "'%(value)s' ist kein gültige Auswahl für dieses Feld."
+msgstr[1] "'%(value)s' ist kein gültige Auswahl für dieses Feld."
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "Kein gültiges Datum mit Zeit."
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "Kein gültiges Datum."
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr ""
+
+#: src/wtforms/fields/datetime.py:148
+#, fuzzy
+#| msgid "Not a valid date value."
+msgid "Not a valid week value."
+msgstr "Kein gültiges Datum."
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "Keine gültige, ganze Zahl."
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "Keine gültige Dezimalzahl."
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "Keine gültige Gleitkommazahl."

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/de_CH/LC_MESSAGES/wtforms.mo


+ 190 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/de_CH/LC_MESSAGES/wtforms.po

@@ -0,0 +1,190 @@
+# German (Switzerland) translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 1.0.4\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: 2013-05-13 19:27+0100\n"
+"Last-Translator: Chris Buergi <chris.buergi@gmx.net>\n"
+"Language-Team: de_CH <LL@li.org>\n"
+"Language: de_CH\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "Ungültiger Feldname '%s'."
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "Feld muss gleich wie %(other_name)s sein."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "Feld muss mindestens %(min)d Zeichen beinhalten."
+msgstr[1] "Feld muss mindestens %(min)d Zeichen beinhalten."
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "Feld kann nicht länger als %(max)d Zeichen sein."
+msgstr[1] "Feld kann nicht länger als %(max)d Zeichen sein."
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "Feld muss zwischen %(min)d und %(max)d Zeichen beinhalten."
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "Zahl muss mindestens %(min)s sein."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "Zahl kann höchstens %(max)s sein."
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "Zahl muss zwischen %(min)s und %(max)s liegen."
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "Dieses Feld wird benötigt."
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "Ungültige Eingabe."
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "Ungültige Email-Adresse."
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "Ungültige IP-Adresse."
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "Ungültige Mac-Adresse."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "Ungültige URL."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "Ungültige UUID."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "Ungültiger Wert. Mögliche Werte: %(values)s."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "Ungültiger Wert. Wert kann keiner von folgenden sein: %(values)s."
+
+#: src/wtforms/validators.py:698
+#, fuzzy
+#| msgid "This field is required."
+msgid "This field cannot be edited"
+msgstr "Dieses Feld wird benötigt."
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr ""
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "Ungültiger CSRF-Code"
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "CSRF-Code nicht vorhanden"
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "CSRF fehlgeschlagen"
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "CSRF-Code verfallen"
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr "Ungültige Auswahl: Konnte nicht umwandeln"
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr ""
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "Keine gültige Auswahl"
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr ""
+"Ungültige Auswahl: Einer oder mehrere Eingaben konnten nicht umgewandelt "
+"werden."
+
+#: src/wtforms/fields/choices.py:204
+#, fuzzy, python-format
+#| msgid "'%(value)s' is not a valid choice for this field."
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "'%(value)s' ist kein gültige Auswahl für dieses Feld."
+msgstr[1] "'%(value)s' ist kein gültige Auswahl für dieses Feld."
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "Kein gültiges Datum mit Zeit"
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "Kein gültiges Datum"
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr ""
+
+#: src/wtforms/fields/datetime.py:148
+#, fuzzy
+#| msgid "Not a valid date value."
+msgid "Not a valid week value."
+msgstr "Kein gültiges Datum"
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "Keine gültige, ganze Zahl"
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "Keine gültige Dezimalzahl"
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "Keine gültige Gleitkommazahl"

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/el/LC_MESSAGES/wtforms.mo


+ 188 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/el/LC_MESSAGES/wtforms.po

@@ -0,0 +1,188 @@
+# Greek translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 2.0dev\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: 2014-04-04 20:18+0300\n"
+"Last-Translator: Daniel Dourvaris <dourvaris@gmail.com>\n"
+"Language-Team: el <LL@li.org>\n"
+"Language: el\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "Λάθος όνομα πεδίου '%s'."
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "Το πεδίο πρέπει να είναι το ίδιο με το %(other_name)s."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "Το πεδίο πρέπει να έχει τουλάχιστον %(min)d χαρακτήρα."
+msgstr[1] "Το πεδίο πρέπει να έχει τουλάχιστον %(min)d χαρακτήρες."
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "Το πεδίο δεν μπορεί να έχει πάνω από %(max)d χαρακτήρα."
+msgstr[1] "Το πεδίο δεν μπορεί να έχει πάνω από %(max)d χαρακτήρες."
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "Το πεδίο πρέπει να είναι ανάμεσα από %(min)d και %(max)d χαρακτήρες."
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "Το νούμερο πρέπει να είναι τουλάχιστον %(min)s."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "Το νούμερο πρέπει να είναι μέγιστο %(max)s."
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "Το νούμερο πρέπει να είναι ανάμεσα %(min)s και %(max)s."
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "Αυτό το πεδίο είναι υποχρεωτικό"
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "Λανθασμένα δεδομένα"
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "Λανθασμένο email."
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "Λανθασμένη διεύθυνση IP."
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "Λανθασμένο διεύθυνση Mac."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "Λανθασμένο URL."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "Λανθασμένο UUID."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "Λάθος επιλογή, πρέπει να είναι ένα από: %(values)s."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "Λάθος επιλογή, δεν μπορεί να είναι ένα από: %(values)s."
+
+#: src/wtforms/validators.py:698
+#, fuzzy
+#| msgid "This field is required."
+msgid "This field cannot be edited"
+msgstr "Αυτό το πεδίο είναι υποχρεωτικό"
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr ""
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "Λάθος CSRF"
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "To CSRF δεν υπάρχει"
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "Αποτυχία CSRF"
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "Έχει λήξει το διακριτικό CSRF"
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr "Λανθασμένη Επιλογή: δεν μετατρέπεται"
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr ""
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "Άγνωστη επιλογή"
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr "Λανθασμένη επιλογή(ές): κάποιες τιμές δεν μπορούσαν να μετατραπούν"
+
+#: src/wtforms/fields/choices.py:204
+#, fuzzy, python-format
+#| msgid "'%(value)s' is not a valid choice for this field."
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "'%(value)s' δεν είναι έγκυρη επιλογή για αυτό το πεδίο"
+msgstr[1] "'%(value)s' δεν είναι έγκυρη επιλογή για αυτό το πεδίο"
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "Δεν είναι σωστή ημερομηνία/ώρα"
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "Δεν είναι σωστή ημερομηνία"
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr ""
+
+#: src/wtforms/fields/datetime.py:148
+#, fuzzy
+#| msgid "Not a valid date value."
+msgid "Not a valid week value."
+msgstr "Δεν είναι σωστή ημερομηνία"
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "Δεν είναι ακέραιο νούμερο"
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "Δεν είναι δεκαδικό"
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "Δεν είναι δεκαδικό"

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/en/LC_MESSAGES/wtforms.mo


+ 169 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/en/LC_MESSAGES/wtforms.po

@@ -0,0 +1,169 @@
+# English translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 1.0.4\n"
+"Report-Msgid-Bugs-To: wtforms@simplecodes.com\n"
+"POT-Creation-Date: 2020-04-25 11:34-0700\n"
+"PO-Revision-Date: 2013-04-28 15:36-0700\n"
+"Last-Translator: James Crasta <james+i18n@simplecodes.com>\n"
+"Language: en\n"
+"Language-Team: en_US <james+i18n@simplecodes.com>\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:87
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "Invalid field name '%s'."
+
+#: src/wtforms/validators.py:98
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "Field must be equal to %(other_name)s."
+
+#: src/wtforms/validators.py:134
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "Field must be at least %(min)d character long."
+msgstr[1] "Field must be at least %(min)d characters long."
+
+#: src/wtforms/validators.py:140
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "Field cannot be longer than %(max)d character."
+msgstr[1] "Field cannot be longer than %(max)d characters."
+
+#: src/wtforms/validators.py:146
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] "Field must be exactly %(max)d character long."
+msgstr[1] "Field must be exactly %(max)d characters long."
+
+#: src/wtforms/validators.py:152
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "Field must be between %(min)d and %(max)d characters long."
+
+#: src/wtforms/validators.py:197
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "Number must be at least %(min)s."
+
+#: src/wtforms/validators.py:199
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "Number must be at most %(max)s."
+
+#: src/wtforms/validators.py:201
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "Number must be between %(min)s and %(max)s."
+
+#: src/wtforms/validators.py:269 src/wtforms/validators.py:294
+msgid "This field is required."
+msgstr "This field is required."
+
+#: src/wtforms/validators.py:327
+msgid "Invalid input."
+msgstr "Invalid input."
+
+#: src/wtforms/validators.py:387
+msgid "Invalid email address."
+msgstr "Invalid email address."
+
+#: src/wtforms/validators.py:423
+msgid "Invalid IP address."
+msgstr "Invalid IP address."
+
+#: src/wtforms/validators.py:466
+msgid "Invalid Mac address."
+msgstr "Invalid MAC address."
+
+#: src/wtforms/validators.py:501
+msgid "Invalid URL."
+msgstr "Invalid URL."
+
+#: src/wtforms/validators.py:522
+msgid "Invalid UUID."
+msgstr "Invalid UUID."
+
+#: src/wtforms/validators.py:553
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "Invalid value, must be one of: %(values)s."
+
+#: src/wtforms/validators.py:588
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "Invalid value, can't be any of: %(values)s."
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "Invalid CSRF Token."
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "CSRF token missing."
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "CSRF failed."
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "CSRF token expired."
+
+#: src/wtforms/fields/core.py:534
+msgid "Invalid Choice: could not coerce."
+msgstr "Invalid Choice: could not coerce."
+
+#: src/wtforms/fields/core.py:538
+msgid "Choices cannot be None."
+msgstr "Choices cannot be None."
+
+#: src/wtforms/fields/core.py:545
+msgid "Not a valid choice."
+msgstr "Not a valid choice."
+
+#: src/wtforms/fields/core.py:573
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr "Invalid choice(s): one or more data inputs could not be coerced."
+
+#: src/wtforms/fields/core.py:584
+#, python-format
+msgid "'%(value)s' is not a valid choice for this field."
+msgstr "'%(value)s' is not a valid choice for this field."
+
+#: src/wtforms/fields/core.py:679 src/wtforms/fields/core.py:689
+msgid "Not a valid integer value."
+msgstr "Not a valid integer value."
+
+#: src/wtforms/fields/core.py:760
+msgid "Not a valid decimal value."
+msgstr "Not a valid decimal value."
+
+#: src/wtforms/fields/core.py:788
+msgid "Not a valid float value."
+msgstr "Not a valid float value."
+
+#: src/wtforms/fields/core.py:853
+msgid "Not a valid datetime value."
+msgstr "Not a valid datetime value."
+
+#: src/wtforms/fields/core.py:871
+msgid "Not a valid date value."
+msgstr "Not a valid date value."
+
+#: src/wtforms/fields/core.py:889
+msgid "Not a valid time value."
+msgstr "Not a valid time value."

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/es/LC_MESSAGES/wtforms.mo


+ 187 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/es/LC_MESSAGES/wtforms.po

@@ -0,0 +1,187 @@
+# Spanish translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 1.0\n"
+"Report-Msgid-Bugs-To: eloi.rivard@nubla.fr\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: 2023-10-06 21:11+0000\n"
+"Last-Translator: gallegonovato <fran-carro@hotmail.es>\n"
+"Language-Team: Spanish <https://hosted.weblate.org/projects/wtforms/wtforms/"
+"es/>\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 5.1-dev\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "Nombre de campo inválido '%s'."
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "El campo debe coincidir con %(other_name)s."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "El campo debe tener al menos %(min)d caracter."
+msgstr[1] "El campo debe tener al menos %(min)d caracteres."
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "El campo no puede tener más de %(max)d caracter."
+msgstr[1] "El campo no puede tener más de %(max)d caracteres."
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] "El campo debe ser exactamente %(max)d caracter."
+msgstr[1] "El campo debe ser exactamente %(max)d caracteres."
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "El campo debe tener entre %(min)d y %(max)d caracteres."
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "El número debe ser mayor que %(min)s."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "El número debe ser menor que %(max)s."
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "El número debe estar entre %(min)s y %(max)s."
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "Este campo es obligatorio."
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "Valor inválido."
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "Email inválido."
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "Dirección IP inválida."
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "Dirección MAC inválida."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "URL inválida."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "UUID inválido."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "Valor inválido, debe ser uno de: %(values)s."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "Valor inválido, no puede ser ninguno de: %(values)s."
+
+#: src/wtforms/validators.py:698
+msgid "This field cannot be edited"
+msgstr "Este campo no se puede editar"
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr "Este campo está deshabilitado y no puede tener un valor"
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "El token CSRF es incorrecto."
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "El token CSRF falta."
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "Fallo CSRF."
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "El token CSRF ha expirado."
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr "Elección inválida: no se puede ajustar."
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr "La elección no puede ser None."
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "Opción inválida."
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr ""
+"Opción(es) inválida(s): una o más entradas de datos no pueden ser "
+"coaccionadas."
+
+#: src/wtforms/fields/choices.py:204
+#, python-format
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "%(value)s' no es una opción válida para este campo."
+msgstr[1] "%(value)s' no son opciones válidas para este campo."
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "No es un valor para la fecha y la hora válido."
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "No es una fecha válida."
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr "No es un tiempo válido."
+
+#: src/wtforms/fields/datetime.py:148
+msgid "Not a valid week value."
+msgstr "No es un valor semanal válido."
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "No es un valor entero válido."
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "No es un numero decimal válido."
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "No es un número de punto flotante válido."

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/et/LC_MESSAGES/wtforms.mo


+ 188 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/et/LC_MESSAGES/wtforms.po

@@ -0,0 +1,188 @@
+# Estonian translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 1.0.6dev\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: 2013-09-22 12:37+0300\n"
+"Last-Translator: Laur Mõtus <laur@povi.ee>\n"
+"Language-Team: Estonian <kde-i18n-doc@kde.org>\n"
+"Language: et\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "Vigane välja nimi: '%s'."
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "Väli peab võrduma %(other_name)s -ga."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "Väli peab olema vähemalt %(min)d tähemärgi pikkune."
+msgstr[1] "Väli peab olema vähemalt %(min)d tähemärgi pikkune."
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "Väli ei tohi olla üle %(max)d tähemärgi pikk."
+msgstr[1] "Väli ei tohi olla üle %(max)d tähemärgi pikk."
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "Välja pikkus peab olema vahemikus %(min)d -  %(max)d."
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "Number peab olema vähemalt %(min)s."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "Number tohib olla maksimaalselt %(max)s."
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "Number peab olema vahemikus %(min)s - %(max)s."
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "Kohustuslik väli."
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "Vigane sisend."
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "Vigane e-posti aadress."
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "Vigane IP aadress."
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "Vigane MAC aadress."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "Vigane URL."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "Vigane UUID."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "Vigane väärtus, peaks hoopis olema üks järgmistest: %(values)s."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "Vigane väärtus, ei tohi olla ükski järgnevatest: %(values)s."
+
+#: src/wtforms/validators.py:698
+#, fuzzy
+#| msgid "This field is required."
+msgid "This field cannot be edited"
+msgstr "Kohustuslik väli."
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr ""
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "Vigane CSRF tunnus"
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "Puudub CSRF tunnus"
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "CSRF nurjus"
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "CSRF tunnus on aegunud"
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr "Vigane valik: ei saa teisendada"
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr ""
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "Pole korrektne valik"
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr "Vigane valik: ühte või rohkemat andmesisendit ei saa teisendada"
+
+#: src/wtforms/fields/choices.py:204
+#, fuzzy, python-format
+#| msgid "'%(value)s' is not a valid choice for this field."
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "'%(value)s' pole sellele väljale korrektne valik"
+msgstr[1] "'%(value)s' pole sellele väljale korrektne valik"
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "Pole korrektne kuupäeva/kellaaja väärtus"
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "Pole korrektne kuupäevaline väärtus"
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr ""
+
+#: src/wtforms/fields/datetime.py:148
+#, fuzzy
+#| msgid "Not a valid date value."
+msgid "Not a valid week value."
+msgstr "Pole korrektne kuupäevaline väärtus"
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "Pole korrektne täisarvuline väärtus"
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "Pole korrektne kümnendarvuline väärtus"
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "Pole korrektne ujukomaarvuline väärtus"

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/fa/LC_MESSAGES/wtforms.mo


+ 187 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/fa/LC_MESSAGES/wtforms.po

@@ -0,0 +1,187 @@
+# persian translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 1.0.3\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: 2013-01-20 16:49+0330\n"
+"Last-Translator: mohammad Efazati <mohammad@efazati.org>\n"
+"Language-Team: fa <mohammad@efazati.org>\n"
+"Language: persian\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "فیلد '%s' اشتباه است."
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "مقدار فیلد باید برابر %(other_name)s باشد."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "طول فیلد حداقل باید %(min)d حرف باشد."
+msgstr[1] "طول فیلد حداقل باید %(min)d حرف باشد."
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "طول فیلد حداکثر باید %(max)d حرف باشد."
+msgstr[1] "طول فیلد حداکثر باید %(max)d حرف باشد."
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "طول فیلد باید بین %(min)d تا %(max)d حرف باشد."
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "عدد باید از %(min)s بزرگتر باشد."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "عدد باید از %(max)s. کوچکتر باشد."
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "عدد باید بین %(min)s  تا  %(max)s باشد."
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "این فیلد اجباریست."
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "ورودی اشتباه است."
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "آدرس پست الکترونیک اشتباه است."
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "آدرس IP اشتباه است."
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "آدرس MAC اشتباه است."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "آدرس وب سایت وارد شده اشتباه است."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "UUID اشتباده است."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "ورودی اشتباه است. باید یکی از %(values)s باشد."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "ورودی اشتباه است. نباید یکی از %(values)s باشد."
+
+#: src/wtforms/validators.py:698
+#, fuzzy
+#| msgid "This field is required."
+msgid "This field cannot be edited"
+msgstr "این فیلد اجباریست."
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr ""
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "مقدار کلید امنیتی اشتباه است."
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "مقدار کلید امنیتی در درخواست شما نیست."
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "کلید امنیتی با خطا مواجه شد."
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "زمان استفاده از کلید امنیتی به اتمام رسیده است."
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr "انتخاب شما اشتباه است. ورودی قابل بررسی نیست."
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr ""
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "انتخاب درستی نیست."
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr "انتخاب شما اشتباه است. یک یا چند تا از ورودی ها قابل بررسی نیست."
+
+#: src/wtforms/fields/choices.py:204
+#, fuzzy, python-format
+#| msgid "'%(value)s' is not a valid choice for this field."
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "'%(value)s انتخاب مناسبی برای این فیلد نیست."
+msgstr[1] "'%(value)s انتخاب مناسبی برای این فیلد نیست."
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "مقداری که وارد کردید، تاریخ نیست."
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "مقداری که وارد کردید، تاریخ نیست."
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr ""
+
+#: src/wtforms/fields/datetime.py:148
+#, fuzzy
+#| msgid "Not a valid date value."
+msgid "Not a valid week value."
+msgstr "مقداری که وارد کردید، تاریخ نیست."
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "یک عدد درست نیست."
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "یک عدد اعشاری درست نیست."
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "یک عدد اعشاری درست نیست."

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/fi/LC_MESSAGES/wtforms.mo


+ 188 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/fi/LC_MESSAGES/wtforms.po

@@ -0,0 +1,188 @@
+# Finnish translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 2.0dev\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: 2016-06-13 15:16+0300\n"
+"Last-Translator: Teijo Mursu <zcmander+wtforms@gmail.com>\n"
+"Language-Team: fi <LL@li.org>\n"
+"Language: fi\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "Epäkelpo kentän nimi '%s'."
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "Täytyy olla sama kuin %(other_name)s."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "Täytyy olla vähintään %(min)d merkki."
+msgstr[1] "Täytyy olla vähintään %(min)d merkkiä."
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "Ei voi olla pidempi kuin %(max)d merkki."
+msgstr[1] "Ei voi olla pidempi kuin %(max)d merkkiä."
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "Täytyy olla pidempi kuin %(min)d ja lyhyempi kuin %(max)d."
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "Vähintään %(min)s."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "Enintään %(max)s."
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "Täytyy olla välillä %(min)s - %(max)s."
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "Pakollinen."
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "Virheellinen syöte."
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "Virheellinen sähköpostiosoite."
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "Virheellinen IP-osoite"
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "Virheellinen MAC-osoite."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "Virheellinen URL-osoite."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "Virheellinen UUID-tunnus."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "Epäkelpo arvo, täytyy olla yksi seuraavista: %(values)s."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "Epäkelpo arvo, ei voi olla yksi seuraavista: %(values)s."
+
+#: src/wtforms/validators.py:698
+#, fuzzy
+#| msgid "This field is required."
+msgid "This field cannot be edited"
+msgstr "Pakollinen."
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr ""
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "Virheellienen CSRF-tunnus."
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "CSRF-tunnus puuttuu."
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "CSRF epäonnistui"
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "CSRF-tunnus vanhentunut"
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr "Virheellinen valinta: ei voida muuntaa"
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr ""
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "Virheellinen valinta"
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr "Virheellinen valinta: Yksi tai useampaa syötettä ei voitu muuntaa"
+
+#: src/wtforms/fields/choices.py:204
+#, fuzzy, python-format
+#| msgid "'%(value)s' is not a valid choice for this field."
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "'%(value)s' ei ole kelvollinen valinta tälle kentälle"
+msgstr[1] "'%(value)s' ei ole kelvollinen valinta tälle kentälle"
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "Ei ole kelvollinen päivämäärä ja aika -arvo"
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "Ei ole kelvollinen päivämäärä-arvo"
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr ""
+
+#: src/wtforms/fields/datetime.py:148
+#, fuzzy
+#| msgid "Not a valid date value."
+msgid "Not a valid week value."
+msgstr "Ei ole kelvollinen päivämäärä-arvo"
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "Ei ole kelvollinen kokonaisluku"
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "Ei ole kelvollinen desimaaliluku"
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "Ei ole kelvollinen liukuluku"

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/fr/LC_MESSAGES/wtforms.mo


+ 188 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/fr/LC_MESSAGES/wtforms.po

@@ -0,0 +1,188 @@
+# French translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+# Stéphane Raimbault <stephane.raimbault@gmail.com>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 1.0.3\n"
+"Report-Msgid-Bugs-To: eloi.rivard@nubla.fr\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: 2023-10-06 21:11+0000\n"
+"Last-Translator: Éloi Rivard <eloi.rivard@nubla.fr>\n"
+"Language-Team: French <https://hosted.weblate.org/projects/wtforms/wtforms/"
+"fr/>\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n > 1;\n"
+"X-Generator: Weblate 5.1-dev\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "Nom de champ non valide « %s »."
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "Le champ doit être égal à %(other_name)s."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "Le champ doit contenir au moins %(min)d caractère."
+msgstr[1] "Le champ doit contenir au moins %(min)d caractères."
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "Le champ ne peut pas contenir plus de %(max)d caractère."
+msgstr[1] "Le champ ne peut pas contenir plus de %(max)d caractères."
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] "Le champ doit contenir exactement %(max)d caractère."
+msgstr[1] "Le champ doit contenir exactement %(max)d caractères."
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr ""
+"La longueur du champ doit être comprise entre %(min)d et %(max)d caractères."
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "Le nombre doit être au minimum %(min)s."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "Le nombre doit être au maximum %(max)s."
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "Le nombre doit être compris entre %(min)s et %(max)s."
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "Ce champ est requis."
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "Saisie non valide."
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "Adresse électronique non valide."
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "Adresse IP non valide."
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "Adresse MAC non valide."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "URL non valide."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "UUID non valide."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "Valeur non valide, doit être parmi : %(values)s."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "Valeur non valide, ne peut contenir : %(values)s."
+
+#: src/wtforms/validators.py:698
+msgid "This field cannot be edited"
+msgstr "Ce champ n’est pas éditable"
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr "Ce champ est désactivé et ne peut avoir de valeur"
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "Jeton CSRF non valide."
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "Jeton CSRF manquant."
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "CSRF a échoué."
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "Jeton CSRF expiré."
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr "Choix non valide, ne peut pas être converti."
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr "Vous devez choisir au moins un élément."
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "N'est pas un choix valide."
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr ""
+"Choix incorrect, une ou plusieurs saisies ne peuvent pas être converties."
+
+#: src/wtforms/fields/choices.py:204
+#, python-format
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "« %(value)s » n'est pas un choix valide pour ce champ."
+msgstr[1] "« %(value)s » n'est pas un choix valide pour ce champ."
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "N'est pas une date/heure valide."
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "N'est pas une date valide."
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr "N'est pas un horaire valide."
+
+#: src/wtforms/fields/datetime.py:148
+msgid "Not a valid week value."
+msgstr "N'est pas une semaine valide."
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "N'est pas un entier valide."
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "N'est pas une valeur décimale valide."
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "N'est pas un flottant valide."

BIN
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/he/LC_MESSAGES/wtforms.mo


+ 188 - 0
courses/flask/microblog/env/Lib/site-packages/wtforms/locale/he/LC_MESSAGES/wtforms.po

@@ -0,0 +1,188 @@
+# Hebrew translations for WTForms.
+# Copyright (C) 2020 WTForms Team
+# This file is distributed under the same license as the WTForms project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: WTForms 2.0dev\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2023-10-05 13:42+0200\n"
+"PO-Revision-Date: 2017-04-19 00:41+0300\n"
+"Last-Translator: Tomer Levy <tmrlvi@gmail.com>\n"
+"Language-Team: he <LL@li.org>\n"
+"Language: he\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"Generated-By: Babel 2.8.0\n"
+
+#: src/wtforms/validators.py:86
+#, python-format
+msgid "Invalid field name '%s'."
+msgstr "שם שדה לא תקין: '%s'"
+
+#: src/wtforms/validators.py:99
+#, python-format
+msgid "Field must be equal to %(other_name)s."
+msgstr "שדה חייב להיות זהה ל-%(other_name)s."
+
+#: src/wtforms/validators.py:145
+#, python-format
+msgid "Field must be at least %(min)d character long."
+msgid_plural "Field must be at least %(min)d characters long."
+msgstr[0] "שדה חייב להכיל לפחות %(min)d תו."
+msgstr[1] "שדה חייב להכיל לפחות %(min)d תווים."
+
+#: src/wtforms/validators.py:151
+#, python-format
+msgid "Field cannot be longer than %(max)d character."
+msgid_plural "Field cannot be longer than %(max)d characters."
+msgstr[0] "שדה אינו יכול להכיל יותר מ-%(max)d תו"
+msgstr[1] "שדה אינו יכול להכיל יותר מ-%(max)d תווים"
+
+#: src/wtforms/validators.py:157
+#, python-format
+msgid "Field must be exactly %(max)d character long."
+msgid_plural "Field must be exactly %(max)d characters long."
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/wtforms/validators.py:163
+#, python-format
+msgid "Field must be between %(min)d and %(max)d characters long."
+msgstr "שדה חייב להכיל בין %(min)d ל-%(max)d תווים"
+
+#: src/wtforms/validators.py:216
+#, python-format
+msgid "Number must be at least %(min)s."
+msgstr "מספר חייב להיות לפחות %(min)s."
+
+#: src/wtforms/validators.py:219
+#, python-format
+msgid "Number must be at most %(max)s."
+msgstr "מספר חייב להיות לכל היותר %(max)s."
+
+#: src/wtforms/validators.py:222
+#, python-format
+msgid "Number must be between %(min)s and %(max)s."
+msgstr "מספר חייב להיות בין %(min)s ו-%(max)s."
+
+#: src/wtforms/validators.py:293 src/wtforms/validators.py:323
+msgid "This field is required."
+msgstr "חובה למלא שדה זה."
+
+#: src/wtforms/validators.py:358
+msgid "Invalid input."
+msgstr "קלט לא תקין."
+
+#: src/wtforms/validators.py:422
+msgid "Invalid email address."
+msgstr "כתובת מייל לא תקינה."
+
+#: src/wtforms/validators.py:460
+msgid "Invalid IP address."
+msgstr "כתובת IP לא תקינה."
+
+#: src/wtforms/validators.py:503
+msgid "Invalid Mac address."
+msgstr "כתובת Mac לא תקינה."
+
+#: src/wtforms/validators.py:540
+msgid "Invalid URL."
+msgstr "URL לא תקין."
+
+#: src/wtforms/validators.py:561
+msgid "Invalid UUID."
+msgstr "UUID לא תקין."
+
+#: src/wtforms/validators.py:594
+#, python-format
+msgid "Invalid value, must be one of: %(values)s."
+msgstr "ערך לא חוקי, חייב להיות מתוך: %(values)s."
+
+#: src/wtforms/validators.py:629
+#, python-format
+msgid "Invalid value, can't be any of: %(values)s."
+msgstr "ערך לא חוקי, לא יכול להיות מתוך: %(values)s."
+
+#: src/wtforms/validators.py:698
+#, fuzzy
+#| msgid "This field is required."
+msgid "This field cannot be edited"
+msgstr "חובה למלא שדה זה."
+
+#: src/wtforms/validators.py:714
+msgid "This field is disabled and cannot have a value"
+msgstr ""
+
+#: src/wtforms/csrf/core.py:96
+msgid "Invalid CSRF Token."
+msgstr "מזהה CSRF לא תקין"
+
+#: src/wtforms/csrf/session.py:63
+msgid "CSRF token missing."
+msgstr "מזהה CSRF חסר"
+
+#: src/wtforms/csrf/session.py:71
+msgid "CSRF failed."
+msgstr "CSRF נכשל"
+
+#: src/wtforms/csrf/session.py:76
+msgid "CSRF token expired."
+msgstr "מזהה CSRF פג תוקף"
+
+#: src/wtforms/fields/choices.py:135
+msgid "Invalid Choice: could not coerce."
+msgstr ""
+
+#: src/wtforms/fields/choices.py:139 src/wtforms/fields/choices.py:192
+msgid "Choices cannot be None."
+msgstr ""
+
+#: src/wtforms/fields/choices.py:148
+msgid "Not a valid choice."
+msgstr "לא בחירה חוקית"
+
+#: src/wtforms/fields/choices.py:185
+msgid "Invalid choice(s): one or more data inputs could not be coerced."
+msgstr "בחירה\\ות לא תקינה: לא ניתן לכפות סוג על קלט אחד או יותר"
+
+#: src/wtforms/fields/choices.py:204
+#, fuzzy, python-format
+#| msgid "'%(value)s' is not a valid choice for this field."
+msgid "'%(value)s' is not a valid choice for this field."
+msgid_plural "'%(value)s' are not valid choices for this field."
+msgstr[0] "'%(value)s' אינו בחירה תקינה עבור השדה הזה"
+msgstr[1] "'%(value)s' אינו בחירה תקינה עבור השדה הזה"
+
+#: src/wtforms/fields/datetime.py:51
+msgid "Not a valid datetime value."
+msgstr "לא ערך תאריך-זמן תקין"
+
+#: src/wtforms/fields/datetime.py:77
+msgid "Not a valid date value."
+msgstr "לא תאריך תקין"
+
+#: src/wtforms/fields/datetime.py:103
+msgid "Not a valid time value."
+msgstr ""
+
+#: src/wtforms/fields/datetime.py:148
+#, fuzzy
+#| msgid "Not a valid date value."
+msgid "Not a valid week value."
+msgstr "לא תאריך תקין"
+
+#: src/wtforms/fields/numeric.py:82 src/wtforms/fields/numeric.py:92
+msgid "Not a valid integer value."
+msgstr "לא מספר שלם תקין"
+
+#: src/wtforms/fields/numeric.py:168
+msgid "Not a valid decimal value."
+msgstr "לא מספר עשרוני"
+
+#: src/wtforms/fields/numeric.py:197
+msgid "Not a valid float value."
+msgstr "לא מספר מסוג float"

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff