From ce02d2da3c37b3212eebafa9392c429b91d13923 Mon Sep 17 00:00:00 2001 From: Hiromasa Ihara Date: Thu, 25 May 2023 02:22:56 +0900 Subject: [PATCH 01/11] fix: migrate from deprecated `flask.Markup` to `markupsafe.Markup` (#203) --- setup.py | 1 + src/flask_debugtoolbar/utils.py | 4 +++- test/test_utils.py | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 94054b0..6bf3d8b 100644 --- a/setup.py +++ b/setup.py @@ -8,5 +8,6 @@ 'Blinker', 'itsdangerous', 'werkzeug', + 'MarkupSafe', ], ) diff --git a/src/flask_debugtoolbar/utils.py b/src/flask_debugtoolbar/utils.py index fc8ac70..267a2e3 100644 --- a/src/flask_debugtoolbar/utils.py +++ b/src/flask_debugtoolbar/utils.py @@ -20,7 +20,9 @@ except ImportError: HAVE_SQLPARSE = False -from flask import current_app, Markup +from flask import current_app + +from markupsafe import Markup def format_fname(value): diff --git a/test/test_utils.py b/test/test_utils.py index 22b29b3..4c4bea6 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -1,7 +1,8 @@ import ntpath import posixpath -from flask import Markup +from markupsafe import Markup + import pytest from flask_debugtoolbar.utils import (_relative_paths, _shortest_relative_path, From f7ae3fd591f6f7e9cd6f26517607027e303214f4 Mon Sep 17 00:00:00 2001 From: Hiromasa Ihara Date: Sun, 1 Oct 2023 16:03:15 +0900 Subject: [PATCH 02/11] fix: use urllib.parse.quote_plus and drop werkzeug.urls.url_quote_plus --- src/flask_debugtoolbar/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flask_debugtoolbar/__init__.py b/src/flask_debugtoolbar/__init__.py index 08185ea..0e11dd0 100644 --- a/src/flask_debugtoolbar/__init__.py +++ b/src/flask_debugtoolbar/__init__.py @@ -1,4 +1,5 @@ import os +import urllib.parse import warnings import flask @@ -14,7 +15,6 @@ from jinja2 import __version__ as __jinja_version__ from jinja2 import Environment, PackageLoader -from werkzeug.urls import url_quote_plus from flask_debugtoolbar.compat import iteritems from flask_debugtoolbar.toolbar import DebugToolbar @@ -76,7 +76,7 @@ def __init__(self, app=None): autoescape=True, extensions=jinja_extensions, loader=PackageLoader(__name__, 'templates')) - self.jinja_env.filters['urlencode'] = url_quote_plus + self.jinja_env.filters['urlencode'] = urllib.parse.quote_plus self.jinja_env.filters['printable'] = _printable self.jinja_env.globals['url_for'] = url_for From 9571d06df527344f7dd310f95017cf761600ec0b Mon Sep 17 00:00:00 2001 From: Hiromasa Ihara Date: Fri, 13 Oct 2023 22:35:25 +0900 Subject: [PATCH 03/11] fix: drop response.charset because charset deprecated (#206) I took a quick peek at upstream to see if this has any backwards-breaking issues whereby we'd need to check the `werkzeug` version, but from my reading it looks it should be fine most of the time. Also, this was deprecated back in April's `2.3.0` release and then removed in the recent `3.0.0` release, so I suspect most of our userbase will have already migrated to those versions. Given this lib is a dev-tooling library not typically used in production, I'm not too worried about ensuring we support the 0.01% case where someone is using an old version of `werkzeug` + a custom charset. More context: * https://github.com/pallets/werkzeug/issues/2602 * https://github.com/pallets/werkzeug/pull/2641 * https://github.com/pallets/werkzeug/pull/2768 --- src/flask_debugtoolbar/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flask_debugtoolbar/__init__.py b/src/flask_debugtoolbar/__init__.py index 0e11dd0..f02994d 100644 --- a/src/flask_debugtoolbar/__init__.py +++ b/src/flask_debugtoolbar/__init__.py @@ -231,9 +231,9 @@ def process_response(self, response): return response if 'gzip' in response.headers.get('Content-Encoding', ''): - response_html = gzip_decompress(response.data).decode(response.charset) + response_html = gzip_decompress(response.data).decode() else: - response_html = response.data.decode(response.charset) + response_html = response.get_data(as_text=True) no_case = response_html.lower() body_end = no_case.rfind('') From 5712e578699810f89b385de70a2342860945220f Mon Sep 17 00:00:00 2001 From: Jeff Widman Date: Fri, 13 Oct 2023 06:23:09 -0700 Subject: [PATCH 04/11] No need to specify custom default value if key not found The `''` arg specifies a custom default value if the key isn't found. However, the default of `None` works fine for boolean testing: ```python >>> 'gzip' in [None] False ``` I missed this when I originally reviewed https://github.com/pallets-eco/flask-debugtoolbar/pull/154. --- src/flask_debugtoolbar/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flask_debugtoolbar/__init__.py b/src/flask_debugtoolbar/__init__.py index f02994d..9c59cf5 100644 --- a/src/flask_debugtoolbar/__init__.py +++ b/src/flask_debugtoolbar/__init__.py @@ -230,7 +230,7 @@ def process_response(self, response): response.headers['content-type'].startswith('text/html')): return response - if 'gzip' in response.headers.get('Content-Encoding', ''): + if 'gzip' in response.headers.get('Content-Encoding'): response_html = gzip_decompress(response.data).decode() else: response_html = response.get_data(as_text=True) @@ -258,7 +258,7 @@ def process_response(self, response): content = ''.join((before, toolbar_html, after)) content = content.encode(response.charset) - if 'gzip' in response.headers.get('Content-Encoding', ''): + if 'gzip' in response.headers.get('Content-Encoding'): content = gzip_compress(content) response.response = [content] response.content_length = len(content) From 15192f19e0e2930b9a077e156c053983e758c8fb Mon Sep 17 00:00:00 2001 From: Grey Li Date: Wed, 15 Nov 2023 22:00:21 +0800 Subject: [PATCH 05/11] Set up github actions --- .github/workflows/tests.yml | 41 +++++++++++++++++++++++++++++++++++++ .travis.yml | 9 -------- README.rst | 4 ++-- tox.ini | 2 +- 4 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/tests.yml delete mode 100644 .travis.yml diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..26878dc --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,41 @@ +name: Tests +on: + push: + branches: + - master + paths-ignore: + - 'docs/**' + - '*.rst' + pull_request: + branches: + - master + paths-ignore: + - 'docs/**' + - '*.rst' +jobs: + tests: + name: ${{ matrix.name }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + include: + - {name: Linux, python: '3.11', os: ubuntu-latest, tox: py311} + - {name: Windows, python: '3.11', os: windows-latest, tox: py311} + - {name: Mac, python: '3.11', os: macos-latest, tox: py311} + - {name: '3.10', python: '3.10', os: ubuntu-latest, tox: py310} + - {name: '3.9', python: '3.9', os: ubuntu-latest, tox: py39} + - {name: '3.8', python: '3.8', os: ubuntu-latest, tox: py38} + - {name: '3.7', python: '3.7', os: ubuntu-latest, tox: py37} + - {name: '3.6', python: '3.6', os: ubuntu-latest, tox: py36} + - {name: '2.7', python: '2.7', os: ubuntu-latest, tox: py27} + - {name: Style, python: '3.10', os: ubuntu-latest, tox: stylecheck} + steps: + - uses: actions/checkout@v4 + - name: update pip + run: | + pip install -U wheel + pip install -U setuptools + python -m pip install -U pip + - run: pip install tox + - run: tox -e ${{ matrix.tox }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 043bbbc..0000000 --- a/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -sudo: false -language: python -python: "3.8" -env: - - TOXENV=py27 - - TOXENV=py38 -install: - - pip install tox -script: tox diff --git a/README.rst b/README.rst index ab44675..8cdec78 100644 --- a/README.rst +++ b/README.rst @@ -4,8 +4,8 @@ Flask Debug-toolbar This is a port of the excellent `django-debug-toolbar `_ for Flask applications. -.. image:: https://travis-ci.org/flask-debugtoolbar/flask-debugtoolbar.png?branch=master - :target: https://travis-ci.org/flask-debugtoolbar/flask-debugtoolbar +.. image:: https://github.com/pallets-eco/flask-debugtoolbar/actions/workflows/tests.yml/badge.svg + :target: https://github.com/pallets-eco/flask-debugtoolbar/actions Installation diff --git a/tox.ini b/tox.ini index a4a8573..6483179 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist = py27,py36,py37,py38,stylecheck +envlist = py27,py36,py37,py38,py39,py310,py311,stylecheck [testenv] deps = From e1c8704444210e11b230c9995b2d186cc8ed3335 Mon Sep 17 00:00:00 2001 From: dadavec <47655762+dadavec@users.noreply.github.com> Date: Thu, 16 Nov 2023 04:53:02 +0100 Subject: [PATCH 06/11] Remove deprecated charset property from process_response content crafting (#211) The `Request.charset` property is deprecated since Werkzeug version 2.3. It was removed in Werkzeug 3.0. Request data must always be UTF-8. https://werkzeug.palletsprojects.com/en/2.3.x/wrappers/#werkzeug.wrappers.Request.charset --- src/flask_debugtoolbar/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flask_debugtoolbar/__init__.py b/src/flask_debugtoolbar/__init__.py index 9c59cf5..15f4772 100644 --- a/src/flask_debugtoolbar/__init__.py +++ b/src/flask_debugtoolbar/__init__.py @@ -257,7 +257,7 @@ def process_response(self, response): toolbar_html = toolbar.render_toolbar() content = ''.join((before, toolbar_html, after)) - content = content.encode(response.charset) + content = content.encode('utf-8') if 'gzip' in response.headers.get('Content-Encoding'): content = gzip_compress(content) response.response = [content] From f959951185e0a6e6abfba51fa9d23cece2c63ec0 Mon Sep 17 00:00:00 2001 From: Grey Li Date: Fri, 17 Nov 2023 06:41:30 +0800 Subject: [PATCH 07/11] Fix tox and GitHub actions settings (#217) * Remove the branch constraint for pull request triggering * Use Python 3.12 for main tests * Use `ubuntu-20.04` for Python 3.6 since it's been removed in `ubuntu-latest` * Remove Python 2.7 since it's not supported by GitHub Actions anymore (https://github.com/actions/setup-python/issues/672) * Add the missing `setup-python` step * Merge the `pip install` commands --- .github/workflows/tests.yml | 18 +++++++++--------- tox.ini | 6 +++++- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 26878dc..95d8091 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,8 +7,6 @@ on: - 'docs/**' - '*.rst' pull_request: - branches: - - master paths-ignore: - 'docs/**' - '*.rst' @@ -20,22 +18,24 @@ jobs: fail-fast: false matrix: include: - - {name: Linux, python: '3.11', os: ubuntu-latest, tox: py311} - - {name: Windows, python: '3.11', os: windows-latest, tox: py311} - - {name: Mac, python: '3.11', os: macos-latest, tox: py311} + - {name: Linux, python: '3.12', os: ubuntu-latest, tox: py312} + - {name: Windows, python: '3.12', os: windows-latest, tox: py312} + - {name: Mac, python: '3.12', os: macos-latest, tox: py312} + - {name: '3.11', python: '3.11', os: ubuntu-latest, tox: py311} - {name: '3.10', python: '3.10', os: ubuntu-latest, tox: py310} - {name: '3.9', python: '3.9', os: ubuntu-latest, tox: py39} - {name: '3.8', python: '3.8', os: ubuntu-latest, tox: py38} - {name: '3.7', python: '3.7', os: ubuntu-latest, tox: py37} - - {name: '3.6', python: '3.6', os: ubuntu-latest, tox: py36} - - {name: '2.7', python: '2.7', os: ubuntu-latest, tox: py27} + - {name: '3.6', python: '3.6', os: ubuntu-20.04, tox: py36} # ubuntu-latest doesn't support 3.6 - {name: Style, python: '3.10', os: ubuntu-latest, tox: stylecheck} steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python }} - name: update pip run: | - pip install -U wheel - pip install -U setuptools + pip install -U setuptools wheel python -m pip install -U pip - run: pip install tox - run: tox -e ${{ matrix.tox }} diff --git a/tox.ini b/tox.ini index 6483179..a2d3df4 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,9 @@ [tox] -envlist = py27,py36,py37,py38,py39,py310,py311,stylecheck +envlist = + py27 + py3{12,11,10,9,8,7,6} + stylecheck +skip_missing_interpreters = True [testenv] deps = From 42d859534a6c525f4e9c65792a1e4e8a8b73c102 Mon Sep 17 00:00:00 2001 From: Grey Li Date: Thu, 16 Nov 2023 21:08:57 +0800 Subject: [PATCH 08/11] Remove the use of before_first_request --- example/app.py | 9 ++++----- test/basic_app.py | 11 +++++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/example/app.py b/example/app.py index 77c688e..cd35b9e 100644 --- a/example/app.py +++ b/example/app.py @@ -28,11 +28,6 @@ class ExampleModel(db.Model): value = db.Column(db.String(100), primary_key=True) -@app.before_first_request -def setup(): - db.create_all() - - @app.route('/') def index(): app.logger.info("Hello there") @@ -45,3 +40,7 @@ def redirect_example(): response = redirect(url_for('index')) response.set_cookie('test_cookie', '1') return response + + +with app.app_context(): + db.create_all() diff --git a/test/basic_app.py b/test/basic_app.py index 6ec1ddd..689d14a 100644 --- a/test/basic_app.py +++ b/test/basic_app.py @@ -6,7 +6,7 @@ app = Flask('basic_app') app.config['SECRET_KEY'] = 'abc123' app.config['SQLALCHEMY_RECORD_QUERIES'] = True -app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db' +app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:' # This is no longer needed for Flask-SQLAlchemy 3.0+, if you're using 2.X you'll want to define this: # app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False @@ -23,12 +23,11 @@ class Foo(db.Model): id = db.Column(db.Integer, primary_key=True) -@app.before_first_request -def setup(): - db.create_all() - - @app.route('/') def index(): Foo.query.filter_by(id=1).all() return render_template('basic_app.html') + + +with app.app_context(): + db.create_all() From 62ce443f8b3eaafbe82594c4d2aded88122de2aa Mon Sep 17 00:00:00 2001 From: Grey Li Date: Tue, 21 Nov 2023 02:59:24 +0800 Subject: [PATCH 09/11] Fix lint issues and lint config (#219) For the two ignored rules: - E731: It's OK to use lambda - W504: W503 and W504 are conflicts with each other, we need to disable one of them. --- src/flask_debugtoolbar/panels/profiler.py | 4 ++-- src/flask_debugtoolbar/panels/sqlalchemy.py | 3 +-- src/flask_debugtoolbar/panels/timer.py | 3 +-- src/flask_debugtoolbar/utils.py | 1 + test/basic_app.py | 3 ++- tox.ini | 4 +++- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/flask_debugtoolbar/panels/profiler.py b/src/flask_debugtoolbar/panels/profiler.py index 3294e4a..66f22aa 100644 --- a/src/flask_debugtoolbar/panels/profiler.py +++ b/src/flask_debugtoolbar/panels/profiler.py @@ -94,7 +94,7 @@ def process_response(self, request, response): def title(self): if not self.is_active: return "Profiler not active" - return 'View: %.2fms' % (float(self.stats.total_tt)*1000,) + return 'View: %.2fms' % (float(self.stats.total_tt) * 1000,) def nav_title(self): return 'Profiler' @@ -102,7 +102,7 @@ def nav_title(self): def nav_subtitle(self): if not self.is_active: return "in-active" - return 'View: %.2fms' % (float(self.stats.total_tt)*1000,) + return 'View: %.2fms' % (float(self.stats.total_tt) * 1000,) def url(self): return '' diff --git a/src/flask_debugtoolbar/panels/sqlalchemy.py b/src/flask_debugtoolbar/panels/sqlalchemy.py index 87f4bdd..13211eb 100644 --- a/src/flask_debugtoolbar/panels/sqlalchemy.py +++ b/src/flask_debugtoolbar/panels/sqlalchemy.py @@ -62,8 +62,7 @@ def extension_used(): def recording_enabled(): - return (current_app.debug - or current_app.config.get('SQLALCHEMY_RECORD_QUERIES')) + return (current_app.debug or current_app.config.get('SQLALCHEMY_RECORD_QUERIES')) def is_available(): diff --git a/src/flask_debugtoolbar/panels/timer.py b/src/flask_debugtoolbar/panels/timer.py index 2e04aa6..df3317e 100644 --- a/src/flask_debugtoolbar/panels/timer.py +++ b/src/flask_debugtoolbar/panels/timer.py @@ -52,8 +52,7 @@ def url(self): return '' def _elapsed_ru(self, name): - return (getattr(self._end_rusage, name) - - getattr(self._start_rusage, name)) + return (getattr(self._end_rusage, name) - getattr(self._start_rusage, name)) def content(self): diff --git a/src/flask_debugtoolbar/utils.py b/src/flask_debugtoolbar/utils.py index 267a2e3..76957e1 100644 --- a/src/flask_debugtoolbar/utils.py +++ b/src/flask_debugtoolbar/utils.py @@ -88,6 +88,7 @@ def format_sql(query, args): SqlLexer(), HtmlFormatter(noclasses=True, style=PYGMENT_STYLE))) + def gzip_compress(data, compresslevel=6): buff = io.BytesIO() with gzip.GzipFile(fileobj=buff, mode='wb', compresslevel=compresslevel) as f: diff --git a/test/basic_app.py b/test/basic_app.py index 689d14a..e10671d 100644 --- a/test/basic_app.py +++ b/test/basic_app.py @@ -7,7 +7,8 @@ app.config['SECRET_KEY'] = 'abc123' app.config['SQLALCHEMY_RECORD_QUERIES'] = True app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:' -# This is no longer needed for Flask-SQLAlchemy 3.0+, if you're using 2.X you'll want to define this: +# This is no longer needed for Flask-SQLAlchemy 3.0+, +# if you're using 2.X you'll want to define this: # app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # make sure these are printable in the config panel diff --git a/tox.ini b/tox.ini index a2d3df4..48be4c1 100644 --- a/tox.ini +++ b/tox.ini @@ -17,7 +17,9 @@ commands = deps = pycodestyle commands = - pycodestyle flask_debugtoolbar test + # E731: do not assign a lambda expression, use a def + # W504: line break after binary operator + pycodestyle src/flask_debugtoolbar test --ignore=E731,W504 [pycodestyle] max-line-length = 100 From e6ae9d0288c2f2c68a9ce84a3af9832bae8d516c Mon Sep 17 00:00:00 2001 From: Grey Li Date: Tue, 21 Nov 2023 10:21:38 +0800 Subject: [PATCH 10/11] Fix the test for basic app (#221) 1. Update the test app If I understand correctly, the debug toolbar will only be enabled if `app.debug` is `True`. So I added the `DEBUG=True` to the test app. Related code: https://github.com/pallets-eco/flask-debugtoolbar/blob/2b8bf9cc449a95f442b99dfdfb6147fa1ae2230a/src/flask_debugtoolbar/__init__.py#L114 2. Update the `src/flask_debugtoolbar/__init__.py` Fix the two if statements to prevent the following errors: ``` > if 'gzip' in response.headers.get('Content-Encoding'): E TypeError: argument of type 'NoneType' is not iterable ``` Since the `response.headers.get('Content-Encoding')` could be None. With this PR, all the tests will be passed. The failed style checker will be fixed in #219 --- src/flask_debugtoolbar/__init__.py | 5 +++-- test/basic_app.py | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/flask_debugtoolbar/__init__.py b/src/flask_debugtoolbar/__init__.py index 15f4772..3b3a7b7 100644 --- a/src/flask_debugtoolbar/__init__.py +++ b/src/flask_debugtoolbar/__init__.py @@ -230,7 +230,8 @@ def process_response(self, response): response.headers['content-type'].startswith('text/html')): return response - if 'gzip' in response.headers.get('Content-Encoding'): + content_encoding = response.headers.get('Content-Encoding') + if content_encoding and 'gzip' in content_encoding: response_html = gzip_decompress(response.data).decode() else: response_html = response.get_data(as_text=True) @@ -258,7 +259,7 @@ def process_response(self, response): content = ''.join((before, toolbar_html, after)) content = content.encode('utf-8') - if 'gzip' in response.headers.get('Content-Encoding'): + if content_encoding and 'gzip' in content_encoding: content = gzip_compress(content) response.response = [content] response.content_length = len(content) diff --git a/test/basic_app.py b/test/basic_app.py index e10671d..9c3618d 100644 --- a/test/basic_app.py +++ b/test/basic_app.py @@ -4,6 +4,7 @@ from flask_debugtoolbar import DebugToolbarExtension app = Flask('basic_app') +app.config['DEBUG'] = True app.config['SECRET_KEY'] = 'abc123' app.config['SQLALCHEMY_RECORD_QUERIES'] = True app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:' From 1aedfb0e2ee4b26116168d3ba8ee7a112a813a9f Mon Sep 17 00:00:00 2001 From: Grey Li Date: Tue, 21 Nov 2023 10:29:03 +0800 Subject: [PATCH 11/11] Use standard Python gitignore file (#220) Created from https://github.com/github/gitignore/blob/main/Python.gitignore --- .gitignore | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 158 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 3a389af..68bc17f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,160 @@ -*.egg-info -*.pyc +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python build/ +develop-eggs/ dist/ -docs/_build -.tox +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/