Skip to content

Commit

Permalink
Merge branch 'main' into profile-follow
Browse files Browse the repository at this point in the history
  • Loading branch information
vidya-ram committed Dec 28, 2023
2 parents a6b2f6d + d668f35 commit 2247496
Show file tree
Hide file tree
Showing 120 changed files with 3,685 additions and 3,800 deletions.
17 changes: 8 additions & 9 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ repos:
- id: pip-compile-multi-verify
files: ^requirements/.*\.(in|txt)$
- repo: https://github.com/pypa/pip-audit
rev: v2.6.1
rev: v2.6.2
hooks:
- id: pip-audit
args: [
Expand All @@ -51,7 +51,7 @@ repos:
- id: pyupgrade
args: ['--keep-runtime-typing', '--py311-plus']
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.1.6
rev: v0.1.9
hooks:
- id: ruff
args: ['--fix', '--exit-non-zero-on-fix']
Expand Down Expand Up @@ -91,13 +91,13 @@ repos:
- toml
- tomli
- repo: https://github.com/PyCQA/isort
rev: 5.12.0
rev: 5.13.2
hooks:
- id: isort
additional_dependencies:
- tomli
- repo: https://github.com/psf/black
rev: 23.11.0
rev: 23.12.1
hooks:
- id: black
# Mypy is temporarily disabled until the SQLAlchemy 2.0 migration is complete
Expand Down Expand Up @@ -126,7 +126,7 @@ repos:
- id: flake8
additional_dependencies: *flake8deps
- repo: https://github.com/PyCQA/pylint
rev: v3.0.1
rev: v3.0.3
hooks:
- id: pylint
args: [
Expand All @@ -138,7 +138,7 @@ repos:
additional_dependencies:
- tomli
- repo: https://github.com/PyCQA/bandit
rev: 1.7.5
rev: 1.7.6
hooks:
- id: bandit
language_version: python3
Expand Down Expand Up @@ -208,11 +208,10 @@ repos:
- id: forbid-tabs
- id: remove-tabs
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v3.1.0
rev: v4.0.0-alpha.8
hooks:
- id: prettier
args:
['--single-quote', '--trailing-comma', 'es5', '--end-of-line', 'lf']
args: ['--single-quote', '--trailing-comma', 'es5', '--end-of-line', 'lf']
exclude: funnel/templates/js/
- repo: https://github.com/ducminh-phan/reformat-gherkin
rev: v3.0.1
Expand Down
1 change: 1 addition & 0 deletions .prettierrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ module.exports = {
endOfLine: 'lf',
singleQuote: true,
trailingComma: 'es5',
printWidth: 88,
};
24 changes: 13 additions & 11 deletions funnel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@

#: Main app for hasgeek.com
app = Flask(__name__, instance_relative_config=True)
app.name = 'funnel'
app.name = 'funnel' # pyright: ignore[reportGeneralTypeIssues]
app.config['SITE_TITLE'] = __("Hasgeek")
#: Shortlink app at has.gy
#: Short link app at has.gy
shortlinkapp = Flask(__name__, static_folder=None, instance_relative_config=True)
shortlinkapp.name = 'shortlink'
shortlinkapp.name = 'shortlink' # pyright: ignore[reportGeneralTypeIssues]
#: Unsubscribe app at bye.li
unsubscribeapp = Flask(__name__, static_folder=None, instance_relative_config=True)
unsubscribeapp.name = 'unsubscribe'
unsubscribeapp.name = 'unsubscribe' # pyright: ignore[reportGeneralTypeIssues]

all_apps = [app, shortlinkapp, unsubscribeapp]

Expand Down Expand Up @@ -79,7 +79,7 @@
views,
cli,
)
from .models import db, sa # isort:skip # pylint: disable=wrong-import-position
from .models import db, sa_orm # isort:skip

# --- Configuration---------------------------------------------------------------------

Expand All @@ -92,9 +92,6 @@
each_app, ['py', 'env'], env_prefix=['FLASK', f'APP_{each_app.name.upper()}']
)

# Legacy additional config for the main app (pending deprecation)
coaster.app.load_config_from_file(app, 'hasgeekapp.py')

# Force specific config settings, overriding deployment config
shortlinkapp.config['SERVER_NAME'] = app.config['SHORTLINK_DOMAIN']
if app.config.get('UNSUBSCRIBE_DOMAIN'):
Expand Down Expand Up @@ -147,7 +144,12 @@
geoip.geoip.init_app(app)

# Baseframe is required for apps with UI ('funnel' theme is registered above)
baseframe.init_app(app, requires=['funnel'], theme='funnel', error_handlers=False)
baseframe.init_app(
app,
requires=['funnel'],
theme='funnel', # type: ignore[arg-type]
error_handlers=False,
)

# Initialize available login providers from app config
loginproviders.init_app(app)
Expand Down Expand Up @@ -195,7 +197,7 @@

views.siteadmin.init_rq_dashboard()

# --- Serve static files with Whitenoise -----------------------------------------------
# --- Serve static files with WhiteNoise -----------------------------------------------

app.wsgi_app = WhiteNoise( # type: ignore[method-assign]
app.wsgi_app, root=app.static_folder, prefix=app.static_url_path
Expand All @@ -208,4 +210,4 @@

# Database model loading (from Funnel or extensions) is complete.
# Configure database mappers now, before the process is forked for workers.
sa.orm.configure_mappers()
sa_orm.configure_mappers()
9 changes: 5 additions & 4 deletions funnel/assets/sass/pages/schedule.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@use 'sass:math';
@import '../base/variable';
@import '../components/draggablebox';
@import '../components/collapsible';
Expand Down Expand Up @@ -43,7 +44,7 @@

.schedule__row__column__content__description {
clear: both;
padding-top: $mui-grid-padding/4;
padding-top: math.div($mui-grid-padding, 4);
padding-bottom: $mui-grid-padding;
word-break: break-word;

Expand All @@ -62,7 +63,7 @@
h5 {
font-size: 12px;
margin-top: 0;
margin-bottom: $mui-grid-padding/4;
margin-bottom: math.div($mui-grid-padding, 4);
}
}

Expand Down Expand Up @@ -109,8 +110,8 @@
.schedule__row--sticky {
display: flex;
overflow-x: auto;
position: sticky;
position: -webkit-sticky;
position: sticky;
top: 0; // header height in home page
order: 1;
z-index: 2;
Expand All @@ -131,7 +132,7 @@
min-height: 50px;
min-width: 60%;
width: 100% !important;
padding: $mui-grid-padding/2;
padding: math.div($mui-grid-padding, 2);
}

.schedule__row__column--header.js-tab-active {
Expand Down
6 changes: 3 additions & 3 deletions funnel/cli/periodic/notification.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from datetime import timedelta

from ... import models
from ...models import db, sa
from ...models import db, sa, sa_orm
from ...views.notification import dispatch_notification
from . import periodic

Expand All @@ -27,15 +27,15 @@ def project_starting_alert() -> None:
# the prior hour.

# Any eager-loading columns and relationships should be deferred with
# sa.orm.defer(column) and sa.orm.noload(relationship). There are none as of this
# sa_orm.defer(column) and sa_orm.noload(relationship). There are none as of this
# commit.
for project in (
models.Project.starting_at(
use_now + timedelta(minutes=10),
timedelta(minutes=5),
timedelta(minutes=60),
)
.options(sa.orm.load_only(models.Project.uuid))
.options(sa_orm.load_only(models.Project.uuid))
.all()
):
dispatch_notification(
Expand Down
4 changes: 2 additions & 2 deletions funnel/cli/refresh/markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import rich.progress

from ... import models
from ...models import MarkdownModelUnion, db, sa
from ...models import MarkdownModelUnion, db, sa_orm
from . import refresh

_M = TypeVar('_M', bound=MarkdownModelUnion)
Expand Down Expand Up @@ -60,7 +60,7 @@ def reparse(self, config: str | None = None, obj: _M | None = None) -> None:
)
iter_list = (
self.model.query.order_by(self.model.id)
.options(sa.orm.load_only(*load_columns))
.options(sa_orm.load_only(*load_columns))
.yield_per(10)
)
iter_total = self.model.query.count()
Expand Down
17 changes: 11 additions & 6 deletions funnel/devtest.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Support for development and testing environments."""
# pyright: reportGeneralTypeIssues=false

from __future__ import annotations

Expand All @@ -13,7 +14,7 @@
import weakref
from collections.abc import Callable, Iterable
from secrets import token_urlsafe
from typing import Any, NamedTuple, Protocol
from typing import Any, NamedTuple, Protocol, cast

from flask import Flask

Expand All @@ -29,7 +30,7 @@
# Pytest `live_server` fixture used for end-to-end tests. Fork on macOS is not
# compatible with the Objective C framework. If you have a framework Python build and
# experience crashes, try setting the environment variable
# OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
# `OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES`
mpcontext = multiprocessing.get_context('fork')

# --- Development and testing app multiplexer ------------------------------------------
Expand Down Expand Up @@ -160,7 +161,7 @@ def install_mock(func: Callable, mock: Callable) -> None:
# Use weakref to dereference func from local namespace
func = weakref.ref(func)
gc.collect()
refs = gc.get_referrers(func()) # type: ignore[misc]
refs = gc.get_referrers(func()) # type: ignore[misc] # Typeshed says not callable
# Recover func from the weakref so we can do an `is` match in referrers
func = func() # type: ignore[misc]
for ref in refs:
Expand All @@ -170,6 +171,10 @@ def install_mock(func: Callable, mock: Callable) -> None:
for key, value in ref.items():
if value is func:
ref[key] = mock
else:
raise RuntimeError(
f"Can't patch {func.__qualname__} in unknown reference type {ref!r}"
)


def _prepare_subprocess(
Expand Down Expand Up @@ -267,9 +272,9 @@ def __init__(
self.mock_transports = mock_transports

manager = mpcontext.Manager()
self.calls: CapturedCalls = manager.Namespace()
self.calls.email = manager.list()
self.calls.sms = manager.list()
self.calls = cast(CapturedCalls, manager.Namespace())
self.calls.email = cast(list[CapturedEmail], manager.list())
self.calls.sms = cast(list[CapturedSms], manager.list())

def start(self) -> None:
"""Start worker in a separate process."""
Expand Down
15 changes: 8 additions & 7 deletions funnel/forms/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
PASSWORD_MIN_LENGTH,
Account,
Anchor,
User,
check_password_strength,
getuser,
)
Expand Down Expand Up @@ -158,7 +159,7 @@ class PasswordForm(forms.Form):
"""Form to validate a user's password, for password-gated sudo actions."""

__expects__ = ('edit_user',)
edit_user: Account
edit_user: User

password = forms.PasswordField(
__("Password"),
Expand All @@ -181,7 +182,7 @@ class PasswordPolicyForm(forms.Form):

__expects__ = ('edit_user',)
__returns__ = ('password_strength', 'is_weak', 'warning', 'suggestions')
edit_user: Account
edit_user: User
password_strength: int | None = None
is_weak: bool | None = None
warning: str | None = None
Expand Down Expand Up @@ -252,7 +253,7 @@ class PasswordCreateForm(forms.Form):

__returns__ = ('password_strength',)
__expects__ = ('edit_user',)
edit_user: Account
edit_user: User
password_strength: int | None = None

password = forms.PasswordField(
Expand Down Expand Up @@ -334,7 +335,7 @@ class PasswordChangeForm(forms.Form):

__returns__ = ('password_strength',)
__expects__ = ('edit_user',)
edit_user: Account
edit_user: User
password_strength: int | None = None

old_password = forms.PasswordField(
Expand Down Expand Up @@ -473,7 +474,7 @@ class UsernameAvailableForm(forms.Form):
"""Form to check for whether a username is available to use."""

__expects__ = ('edit_user',)
edit_user: Account
edit_user: User

username = forms.StringField(
__("Username"),
Expand Down Expand Up @@ -519,7 +520,7 @@ class NewEmailAddressForm(
"""Form to add a new email address to an account."""

__expects__ = ('edit_user',)
edit_user: Account
edit_user: User

email = forms.EmailField(
__("Email address"),
Expand Down Expand Up @@ -566,7 +567,7 @@ class NewPhoneForm(EnableNotificationsDescriptionProtoMixin, forms.RecaptchaForm
"""Form to add a new mobile number (SMS-capable) to an account."""

__expects__ = ('edit_user',)
edit_user: Account
edit_user: User

phone = forms.TelField(
__("Phone number"),
Expand Down
6 changes: 4 additions & 2 deletions funnel/forms/auth_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
AuthClient,
AuthClientCredential,
AuthClientPermissions,
User,
valid_name,
)
from .helpers import strip_filters
Expand All @@ -29,7 +30,8 @@ class AuthClientForm(forms.Form):
"""Register a new OAuth client application."""

__returns__ = ('account',)
account: Account | None = None
edit_user: User
account: Account

title = forms.StringField(
__("Application title"),
Expand Down Expand Up @@ -127,7 +129,7 @@ def _urls_match(self, url1: str, url2: str) -> bool:
def validate_redirect_uri(self, field: forms.Field) -> None:
"""Validate redirect URI points to the website for confidential clients."""
if self.confidential.data and not self._urls_match(
self.website.data, field.data
self.website.data or '', field.data
):
raise forms.validators.ValidationError(
_("The scheme, domain and port must match that of the website URL")
Expand Down
Loading

0 comments on commit 2247496

Please sign in to comment.