mirror of
https://github.com/donlon/cloudflare-error-page.git
synced 2026-01-06 15:41:45 +00:00
format Python files with ruff
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -9,5 +9,6 @@ build/
|
||||
dist/
|
||||
*.egg-info/
|
||||
__pycache__/
|
||||
.ruff_cache/
|
||||
|
||||
instance/
|
||||
|
||||
@@ -8,6 +8,7 @@ if sys.version_info >= (3, 11):
|
||||
from typing import NotRequired
|
||||
else:
|
||||
from typing import _SpecialForm
|
||||
|
||||
NotRequired: _SpecialForm
|
||||
|
||||
|
||||
@@ -69,12 +70,14 @@ class ErrorPageParams(TypedDict):
|
||||
creator_info: NotRequired[CreatorInfo]
|
||||
|
||||
|
||||
def render(params: ErrorPageParams,
|
||||
allow_html: bool = True,
|
||||
template: Template | None = None,
|
||||
*args: Any,
|
||||
**kwargs: Any) -> str:
|
||||
'''Render a customized Cloudflare error page.
|
||||
def render(
|
||||
params: ErrorPageParams,
|
||||
allow_html: bool = True,
|
||||
template: Template | None = None,
|
||||
*args: Any,
|
||||
**kwargs: Any,
|
||||
) -> str:
|
||||
"""Render a customized Cloudflare error page.
|
||||
|
||||
:param params: Parameters passed to the template. Refer to the project homepage for more information.
|
||||
:param allow_html: Allow output raw HTML content from parameters. Set to False if you don't trust the source of the params.
|
||||
@@ -83,7 +86,7 @@ def render(params: ErrorPageParams,
|
||||
:param args: Additional positional arguments passed to ``Template.render`` function.
|
||||
:param kwargs: Additional keyword arguments passed to ``Template.render`` function.
|
||||
:return: The rendered error page as a string.
|
||||
'''
|
||||
"""
|
||||
if not template:
|
||||
template = base_template
|
||||
|
||||
@@ -106,5 +109,6 @@ def render(params: ErrorPageParams,
|
||||
|
||||
return template.render(params=params, *args, **kwargs)
|
||||
|
||||
|
||||
__version__ = '0.2.0'
|
||||
__all__ = ['jinja_env', 'base_template', 'render']
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
import secrets
|
||||
import string
|
||||
import sys
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
from flask import Flask, redirect, url_for
|
||||
from flask_limiter import Limiter
|
||||
@@ -16,17 +15,24 @@ from werkzeug.middleware.proxy_fix import ProxyFix
|
||||
|
||||
root_dir = Path(__file__).parent.parent.parent.parent
|
||||
|
||||
|
||||
class Base(DeclarativeBase):
|
||||
pass
|
||||
|
||||
db: SQLAlchemy = SQLAlchemy(model_class=Base, session_options={
|
||||
# 'autobegin': False,
|
||||
# 'expire_on_commit': False,
|
||||
})
|
||||
|
||||
db: SQLAlchemy = SQLAlchemy(
|
||||
model_class=Base,
|
||||
session_options={
|
||||
# 'autobegin': False,
|
||||
# 'expire_on_commit': False,
|
||||
},
|
||||
)
|
||||
|
||||
limiter: Limiter = Limiter(
|
||||
key_func=get_remote_address, # Uses client's IP address by default
|
||||
)
|
||||
static_dir: str | None = None
|
||||
|
||||
|
||||
def _generate_secret(length=32) -> str:
|
||||
characters = string.ascii_letters + string.digits # A-Z, a-z, 0-9
|
||||
@@ -34,10 +40,9 @@ def _generate_secret(length=32) -> str:
|
||||
|
||||
|
||||
def _initialize_app_config(app: Flask):
|
||||
global static_dir
|
||||
if app.config.get('BEHIND_PROXY', True):
|
||||
app.wsgi_app = ProxyFix(
|
||||
app.wsgi_app, x_for=1, x_proto=1
|
||||
)
|
||||
app.wsgi_app = ProxyFix(app.wsgi_app, x_for=1, x_proto=1)
|
||||
secret_key = app.config.get('SECRET_KEY', '')
|
||||
if secret_key:
|
||||
app.secret_key = secret_key
|
||||
@@ -45,12 +50,14 @@ def _initialize_app_config(app: Flask):
|
||||
app.logger.info('Using generated secret')
|
||||
app.secret_key = _generate_secret()
|
||||
|
||||
app.config["SQLALCHEMY_DATABASE_URI"] = app.config.get('SQLALCHEMY_DATABASE_URI', 'sqlite:///example.db')
|
||||
if app.config["SQLALCHEMY_DATABASE_URI"].startswith('sqlite'):
|
||||
app.config["SQLALCHEMY_ENGINE_OPTIONS"] = {
|
||||
app.config['SQLALCHEMY_DATABASE_URI'] = app.config.get('SQLALCHEMY_DATABASE_URI', 'sqlite:///example.db')
|
||||
if app.config['SQLALCHEMY_DATABASE_URI'].startswith('sqlite'):
|
||||
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
|
||||
'isolation_level': 'SERIALIZABLE',
|
||||
# "execution_options": {"autobegin": False}
|
||||
}
|
||||
static_dir = os.path.join(app.instance_path, app.config.get('STATIC_DIR', '../../web/dist'))
|
||||
app.logger.info(f'Static directory: {static_dir}')
|
||||
|
||||
|
||||
def create_app(test_config=None) -> Flask:
|
||||
@@ -60,16 +67,12 @@ def create_app(test_config=None) -> Flask:
|
||||
os.makedirs(instance_path, exist_ok=True)
|
||||
print(f'App instance path: {instance_path}')
|
||||
|
||||
app = Flask(__name__,
|
||||
instance_path=instance_path,
|
||||
instance_relative_config=True
|
||||
)
|
||||
app.config.from_file("config.toml", load=tomllib.load, text=False)
|
||||
app = Flask(__name__, instance_path=instance_path, instance_relative_config=True)
|
||||
app.config.from_file('config.toml', load=tomllib.load, text=False)
|
||||
_initialize_app_config(app)
|
||||
|
||||
|
||||
from . import utils
|
||||
from . import models
|
||||
from . import utils # noqa: F401
|
||||
from . import models # noqa: F401
|
||||
from . import examples
|
||||
from . import editor
|
||||
from . import share
|
||||
|
||||
@@ -30,13 +30,14 @@ bp_short = Blueprint('share_short', __name__, url_prefix='/')
|
||||
|
||||
rand_charset = string.ascii_lowercase + string.digits
|
||||
|
||||
|
||||
def get_rand_name(digits=8):
|
||||
return ''.join(random.choice(rand_charset) for _ in range(digits))
|
||||
|
||||
|
||||
@bp.post('/create')
|
||||
@limiter.limit("20 per minute")
|
||||
@limiter.limit("500 per hour")
|
||||
@limiter.limit('20 per minute')
|
||||
@limiter.limit('500 per hour')
|
||||
def create():
|
||||
if len(request.data) > 4096:
|
||||
abort(413)
|
||||
@@ -82,9 +83,7 @@ def get(name: str):
|
||||
item = db.session.query(models.Item).filter_by(name=name).first()
|
||||
if not item:
|
||||
if is_json:
|
||||
return {
|
||||
'status': 'notfound'
|
||||
}
|
||||
return {'status': 'notfound'}
|
||||
else:
|
||||
return abort(404)
|
||||
params = cast(ErrorPageParams, item.params)
|
||||
@@ -104,8 +103,7 @@ def get(name: str):
|
||||
'link': request.host_url[:-1] + url_for('editor.index') + f'#from={name}',
|
||||
}
|
||||
sanitize_page_param_links(params)
|
||||
return render_extended_template(params=params,
|
||||
allow_html=False)
|
||||
return render_extended_template(params=params, allow_html=False)
|
||||
|
||||
|
||||
@bp.get('/<name>')
|
||||
|
||||
@@ -17,7 +17,7 @@ env = Environment(
|
||||
trim_blocks=True,
|
||||
lstrip_blocks=True,
|
||||
)
|
||||
template = env.from_string('''{% extends base %}
|
||||
template = env.from_string("""{% extends base %}
|
||||
|
||||
{% block html_head %}
|
||||
{% if page_icon_url %}
|
||||
@@ -45,11 +45,12 @@ template = env.from_string('''{% extends base %}
|
||||
<meta property="twitter:image" content="{{ page_image_url }}" />
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
''')
|
||||
""")
|
||||
|
||||
|
||||
loc_data: dict = None
|
||||
|
||||
|
||||
def read_loc_file(path: str):
|
||||
try:
|
||||
with open(os.path.join(Path(__file__).parent / path)) as f:
|
||||
@@ -117,11 +118,9 @@ def sanitize_page_param_links(param: ErrorPageParams):
|
||||
perf_sec_by['link'] = sanitize_user_link(link)
|
||||
|
||||
|
||||
def render_extended_template(params: ErrorPageParams,
|
||||
*args: Any,
|
||||
**kwargs: Any) -> str:
|
||||
def render_extended_template(params: ErrorPageParams, *args: Any, **kwargs: Any) -> str:
|
||||
fill_cf_template_params(params)
|
||||
description = params.get('what_happened') or 'There is an internal server error on Cloudflare\'s network.'
|
||||
description = params.get('what_happened') or "There is an internal server error on Cloudflare's network."
|
||||
description = re.sub(r'<\/?.*?>', '', description).strip()
|
||||
|
||||
status = 'ok'
|
||||
@@ -133,13 +132,15 @@ def render_extended_template(params: ErrorPageParams,
|
||||
page_icon_url = current_app.config.get('PAGE_ICON_URL', '').replace('{status}', status)
|
||||
page_icon_type = current_app.config.get('PAGE_ICON_TYPE')
|
||||
page_image_url = current_app.config.get('PAGE_IMAGE_URL', '').replace('{status}', status)
|
||||
return render_cf_error_page(params=params,
|
||||
template=template,
|
||||
base=base_template,
|
||||
page_icon_url=page_icon_url,
|
||||
page_icon_type=page_icon_type,
|
||||
page_url=request.url,
|
||||
page_description=description,
|
||||
page_image_url=page_image_url,
|
||||
*args,
|
||||
**kwargs)
|
||||
return render_cf_error_page(
|
||||
params=params,
|
||||
template=template,
|
||||
base=base_template,
|
||||
page_icon_url=page_icon_url,
|
||||
page_icon_type=page_icon_type,
|
||||
page_url=request.url,
|
||||
page_description=description,
|
||||
page_image_url=page_image_url,
|
||||
*args,
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
@@ -24,3 +24,15 @@ include = ["app/**/*"]
|
||||
|
||||
[tool.hatch.build.targets.wheel.hooks.custom]
|
||||
path = "hatch_build.py"
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
target-version = "py313"
|
||||
|
||||
[tool.ruff.lint]
|
||||
ignore = [
|
||||
'E722', # Bare-except
|
||||
]
|
||||
|
||||
[tool.ruff.format]
|
||||
quote-style = "single"
|
||||
|
||||
@@ -46,3 +46,19 @@ path = "scripts/hatch_build.py"
|
||||
|
||||
[tool.hatch.version]
|
||||
path = "cloudflare_error_page/__init__.py"
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 120
|
||||
target-version = "py310"
|
||||
include = [
|
||||
"cloudflare_error_page/**/*.py",
|
||||
"scripts/**/*.py",
|
||||
]
|
||||
|
||||
[tool.ruff.lint]
|
||||
ignore = [
|
||||
'E722', # Bare-except
|
||||
]
|
||||
|
||||
[tool.ruff.format]
|
||||
quote-style = "single"
|
||||
|
||||
@@ -9,6 +9,7 @@ from hatchling.builders.hooks.plugin.interface import BuildHookInterface
|
||||
sys.path.append(os.path.dirname(__file__))
|
||||
from inline_resources import generate_inlined_css
|
||||
|
||||
|
||||
class CustomBuildHook(BuildHookInterface):
|
||||
def initialize(self, version: str, build_data: dict[str, Any]):
|
||||
generate_inlined_css()
|
||||
|
||||
@@ -38,8 +38,7 @@ def inline_svg_resources(css_file: str, svg_files: list[str], output_file: str):
|
||||
def inline_css_resource(original_file: str, css_file: str, output_file: str):
|
||||
css_data = read_file(css_file)
|
||||
original_data = read_file(original_file)
|
||||
original_data = original_data.replace('<!-- @INLINE_CSS_HERE@ -->',
|
||||
f'<style>{css_data}</style>')
|
||||
original_data = original_data.replace('<!-- @INLINE_CSS_HERE@ -->', f'<style>{css_data}</style>')
|
||||
note = 'Note: This file is generated with scripts/inline_resources.py. Please do not edit manually.'
|
||||
if original_file.endswith('.ejs'):
|
||||
original_data = f'<%# {note} %>\n' + original_data
|
||||
@@ -60,7 +59,7 @@ def generate_inlined_css():
|
||||
'../images/cf-icon-error.svg',
|
||||
],
|
||||
os.path.join(resources_folder, 'styles/main.css'),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
Reference in New Issue
Block a user