diff --git a/make_post_sell/lib/hex_color.py b/make_post_sell/lib/hex_color.py
index b2865e4..0267340 100644
--- a/make_post_sell/lib/hex_color.py
+++ b/make_post_sell/lib/hex_color.py
@@ -39,5 +39,5 @@ def color_scale(hex_str, scale_factor):
g = int(clamp(g * scale_factor))
b = int(clamp(b * scale_factor))
- #return "#%02x%02x%02x" % (r, g, b)
- return "#%02x%02x%02x" % (r, g, b)
+ # return "#%02x%02x%02x" % (r, g, b)
+ return f"#{r:02x}{g:02x}{b:02x}"
diff --git a/make_post_sell/lib/mail.py b/make_post_sell/lib/mail.py
index 78aff7c..a74fa79 100644
--- a/make_post_sell/lib/mail.py
+++ b/make_post_sell/lib/mail.py
@@ -43,7 +43,6 @@ def send_email(
dkim_selector="",
dkim_signature_algorithm="ed25519-sha256",
):
-
# the `email` library assumes it is working with string objects.
# the `dkim` library assumes it is working with byte objects.
# this function performs the acrobatics to make them both happy.
@@ -106,13 +105,15 @@ def send_email(
def send_pyramid_email(request, to_email, subject, message_text, message_html):
"""Thin wrapper around `send_email` to customise settings using request object."""
- default_sender = "no-reply@{}".format(request.domain)
+ default_sender = f"no-reply@{request.domain}"
sender_email = request.app.get("email.sender", default_sender)
- subject = "{} | {}".format(subject, request.app.get("email.subject_postfix", request.domain))
+ subject = f"{subject} | {request.app.get('email.subject_postfix', request.domain)}"
relay = request.app.get("email.relay", "localhost")
dkim_private_key_path = request.app.get("email.dkim_private_key_path", "")
dkim_selector = request.app.get("email.dkim_selector", "")
- dkim_signature_algorithm = request.app.get("email.dkim_signature_algorithm", "ed25519-sha256")
+ dkim_signature_algorithm = request.app.get(
+ "email.dkim_signature_algorithm", "ed25519-sha256"
+ )
send_email(
to_email,
@@ -140,7 +141,7 @@ def send_verification_digits_to_email(request, to_email, raw_digits):
raw_digits:
the raw (unencrypted) digits the user may use to verify & authenticate.
"""
- subject = "Verification Code | {}".format(raw_digits)
+ subject = f"Verification Code | {raw_digits}"
message_text = WELCOME_1_TEXT.format(raw_digits)
message_html = WELCOME_1_HTML.format(subject, raw_digits)
send_pyramid_email(request, to_email, subject, message_text, message_html)
@@ -174,17 +175,13 @@ def send_purchase_email(request, to_email, products, total_cost):
)
product_text_list.append(
- '
{}
{}
'.format(
- p.absolute_url(request), p.title, thumbnail
- )
+ f'{p.title}
{thumbnail}
'
)
product_text = "
".join(product_text_list)
- message_text = PURCHASE_1_TEXT.format(
- "%.2f" % total_cost, request.host_url
- )
+ message_text = PURCHASE_1_TEXT.format(f"{total_cost:.2f}", request.host_url)
message_html = PURCHASE_1_HTML.format(
- subject, request.host_url, product_text, "%.2f" % total_cost
+ subject, request.host_url, product_text, f"{total_cost:.2f}"
)
send_pyramid_email(request, to_email, subject, message_text, message_html)
@@ -217,17 +214,15 @@ def send_sale_email(request, shop, products, total_cost):
)
product_text_list.append(
- '{}
{}
'.format(
- p.absolute_url(request), p.title, thumbnail
- )
+ f'{p.title}
{thumbnail}
'
)
product_text = "
".join(product_text_list)
message_text = SALE_1_TEXT.format(
- "%.2f" % total_cost, shop.absolute_sales_url(request)
+ f"{total_cost:.2f}", shop.absolute_sales_url(request)
)
message_html = SALE_1_HTML.format(
- subject, shop.absolute_sales_url(request), product_text, "%.2f" % total_cost
+ subject, shop.absolute_sales_url(request), product_text, f"{total_cost:.2f}"
)
# send a separate email for each shop owner.
@@ -241,7 +236,7 @@ def send_invite_email(request, to_email, user, shop):
request
the request (of the successful log in attempt)
-
+
to_email
the email address to send the shop invitation to.
@@ -251,7 +246,7 @@ def send_invite_email(request, to_email, user, shop):
shop
the shop the invitation is for.
"""
- subject = "You have been invited to {}".format(shop.name)
+ subject = f"You have been invited to {shop.name}"
join_link = request.route_url("join-or-log-in")
message_text = INVITE_1_TEXT.format(user.email, shop.name, join_link)
message_html = INVITE_1_HTML.format(subject, user.email, shop.name, join_link)
diff --git a/make_post_sell/lib/sanitize_html.py b/make_post_sell/lib/sanitize_html.py
index cc5dea3..d2a5c6a 100644
--- a/make_post_sell/lib/sanitize_html.py
+++ b/make_post_sell/lib/sanitize_html.py
@@ -62,13 +62,10 @@ def default_cleaner(tag_acl=None):
# to get past bleach.
# We will conditionally filter tags using BeautifulSoup.
for tag_name in tag_acl.keys():
-
# tag_name, for example "script".
for attr_name, attr_value, allow_or_deny in tag_acl[tag_name]:
-
if allow_or_deny == "allow":
-
# attr_name, for example "type".
# attr_value, for example "math/tex; mode=display".
@@ -84,7 +81,7 @@ def default_cleaner(tag_acl=None):
# doesn't do anything, but i used to be able to pass it via constructor.
# https://github.com/yourcelf/bleach-allowlist/blob/main/bleach_allowlist/bleach_allowlist.py
- #cleaner.all_styles=all_styles
+ # cleaner.all_styles=all_styles
# disable link_protection by default.
cleaner.link_protection = False
@@ -122,17 +119,14 @@ def conditional_tag_filter(soup, cleaner):
# for each tag_name in the tag_acl ...
for tag_name in cleaner.tag_acl.keys():
-
# find all the tags in the DOM that match the tag_name, for example "script".
for tag in soup.find_all(tag_name):
-
# tag is a BeautifulSoup tag object.
# by default, assume we will extract tag (remove it from the DOM).
extract_tag = True
for attr_name, attr_value, allow_or_deny in cleaner.tag_acl[tag_name]:
-
# tag attr_name:
#
# * "type"
@@ -151,10 +145,9 @@ def conditional_tag_filter(soup, cleaner):
# * "allow"
# * "deny"
- log.info("{} {} {}".format(attr_name, attr_value, allow_or_deny))
+ log.info(f"{attr_name} {attr_value} {allow_or_deny}")
if allow_or_deny == "allow":
-
if tag.attrs.get(attr_name) == attr_value:
# this tag attr_name/attr_value is whitelisted.
# do not extract tag (remove it from the DOM)
@@ -175,7 +168,6 @@ def conditional_tag_filter(soup, cleaner):
def protect_links(soup, cleaner):
-
for a_tag in soup.find_all("a"):
uri = miniuri.Uri(a_tag.attrs.get("href", ""))
diff --git a/make_post_sell/models/coupon.py b/make_post_sell/models/coupon.py
index 862e09c..78e55de 100644
--- a/make_post_sell/models/coupon.py
+++ b/make_post_sell/models/coupon.py
@@ -50,9 +50,7 @@ class Coupon(RBase, Base):
description = Column(Unicode(256), nullable=False)
# the type of action that this coupon applies to a cart.
- action_type = Column(
- Enum(*COUPON_ACTION_TYPES, name="action_type"), nullable=False
- )
+ action_type = Column(Enum(*COUPON_ACTION_TYPES, name="action_type"), nullable=False)
action_value = Column(BigInteger, nullable=False)
# The amount of times this code may be used.
@@ -77,13 +75,17 @@ class Coupon(RBase, Base):
shop = relationship(argument="Shop", uselist=False, lazy="joined")
# many to many uses association_proxy.
- carts = association_proxy("coupon_carts", "cart", creator=lambda c: CartCoupon(cart=c))
+ carts = association_proxy(
+ "coupon_carts", "cart", creator=lambda c: CartCoupon(cart=c)
+ )
# one to many.
# returns this coupon's redemptions.
# lazy="dynamic" returns a query object instread of an InstrumentedList.
# this is ideal when we want to further filter the results.
- redemptions = relationship(argument="CouponRedemption", lazy="dynamic", back_populates="coupon")
+ redemptions = relationship(
+ argument="CouponRedemption", lazy="dynamic", back_populates="coupon"
+ )
def __init__(
self,
@@ -94,10 +96,9 @@ class Coupon(RBase, Base):
action_value,
max_redemptions=None,
max_redemptions_per_user=None,
- expiration_date = None,
- cart_qualifier = None,
+ expiration_date=None,
+ cart_qualifier=None,
):
-
self.id = uuid.uuid1()
self.shop = shop
self.created_timestamp = now_timestamp()
@@ -124,15 +125,12 @@ class Coupon(RBase, Base):
self.expired_timestamp = None
if expiration_date:
# convert date string into datetime.
- expiration_datetime = datetime.strptime(
- expiration_date,
- '%Y-%m-%d'
- )
+ expiration_datetime = datetime.strptime(expiration_date, "%Y-%m-%d")
# convert datetime into timestamp.
# adding 86399000 to get the end of day.
- self.expired_timestamp = datetime_to_timestamp(
- expiration_datetime
- ) + 86399000
+ self.expired_timestamp = (
+ datetime_to_timestamp(expiration_datetime) + 86399000
+ )
@property
def expired_datetime(self):
@@ -160,34 +158,32 @@ class Coupon(RBase, Base):
@property
def human_discount(self):
if self.action_type == "percent-off":
- return "{}% off".format(self.action_value)
- return "${0:.2f} off".format(
- cents_to_dollars(self.action_value)
- )
+ return f"{self.action_value}% off"
+ return f"${cents_to_dollars(self.action_value):.2f} off"
@property
def human_max_redemptions(self):
if self.max_redemptions:
- return "{}".format(self.max_redemptions)
+ return f"{self.max_redemptions}"
return "∞"
@property
def human_limit_per_customer(self):
if self.max_redemptions_per_user:
- return "Limit {} per customer.".format(self.max_redemptions_per_user)
+ return f"Limit {self.max_redemptions_per_user} per customer."
return ""
@property
def human_valid_thru(self):
if self.expired_timestamp:
x = self.expired_datetime.strftime("%A, %b %d, %Y")
- return "Valid thru {}.".format(x)
+ return f"Valid thru {x}."
return ""
@property
def human_minimum_cart(self):
if self.cart_qualifier:
- return "any ${0:.0f} cart.".format(cents_to_dollars(self.cart_qualifier))
+ return f"any ${cents_to_dollars(self.cart_qualifier):.0f} cart."
return "any cart."
def compute_discount(self, cents):
@@ -221,7 +217,5 @@ def get_coupons_by_code(dbsession, code, shop=None):
Remember a coupon code may not be unique across all shops.
"""
if shop is not None:
- return shop.coupons.filter(
- Coupon.code == code
- ).all()
+ return shop.coupons.filter(Coupon.code == code).all()
return dbsession.query(Coupon).filter(Coupon.code == code).all()
diff --git a/make_post_sell/models/meta.py b/make_post_sell/models/meta.py
index 7368a9e..814c7d2 100644
--- a/make_post_sell/models/meta.py
+++ b/make_post_sell/models/meta.py
@@ -55,11 +55,11 @@ Base = declarative_base()
COUPON_ACTION_TYPES = {
- "dollar-off",
- "percent-off",
+ "dollar-off",
+ "percent-off",
}
-VISIBILITY_INT_TO_HUMAN ={
+VISIBILITY_INT_TO_HUMAN = {
0: "private",
1: "public",
2: "unlisted",
@@ -131,7 +131,6 @@ def get_objects_by_ids(dbsession, object_ids, cls):
object_uuids = [id_to_uuid(object_id) for object_id in object_ids]
if object_uuids:
-
# reference: https://stackoverflow.com/q/444475
return dbsession.query(cls).filter(cls.id.in_(object_uuids)).all()
@@ -153,7 +152,7 @@ def now_timestamp():
def foreign_key(class_name, column_name):
- return ForeignKey("{}.{}".format(CLASS_TO_TABLE[class_name], column_name))
+ return ForeignKey(f"{CLASS_TO_TABLE[class_name]}.{column_name}")
class RBase(object):
diff --git a/make_post_sell/models/product.py b/make_post_sell/models/product.py
index 706054c..7e11bcb 100644
--- a/make_post_sell/models/product.py
+++ b/make_post_sell/models/product.py
@@ -251,21 +251,21 @@ class Product(RBase, Base):
@property
def s3_path(self):
"""return the S3 path shop.id/product.id"""
- return "{}/{}".format(self.shop.id, self.id)
+ return f"{self.shop.id}/{self.id}"
@property
def s3_key(self):
"""return the product S3 key"""
- return "{}/product".format(self.s3_path)
+ return f"{self.s3_path}/product"
@property
def s3_key_preview(self):
"""return the product preview S3 key"""
- return "{}/preview".format(self.s3_path)
+ return f"{self.s3_path}/preview"
def s3_key_thumbnail(self, file_key):
"""return the thumbail S3 key"""
- return "{}/{}".format(self.s3_path, file_key)
+ return f"{self.s3_path}/{file_key}"
@property
def s3_key_thumbnails(self):
@@ -344,15 +344,15 @@ class Product(RBase, Base):
* an inline image (thumbnails)
* an attachment (file download)
"""
- file_prefix = "" if file_key == "product" else "{}-".format(file_key)
+ file_prefix = "" if file_key == "product" else f"{file_key}-"
extension = self.extensions.get(file_key, "")
- filename = "{}{}.{}".format(file_prefix, self.slug, extension)
- content_disposition = "attachment; filename={}".format(filename)
+ filename = f"{file_prefix}{self.slug}.{extension}"
+ content_disposition = f"attachment; filename={filename}"
if file_key in self.file_thumbnail_keys:
- content_disposition = "inline; filename={}".format(filename)
+ content_disposition = f"inline; filename={filename}"
elif self.is_not_sellable:
- content_disposition = "inline; filename={}".format(filename)
+ content_disposition = f"inline; filename={filename}"
return content_disposition
@@ -375,8 +375,8 @@ class Product(RBase, Base):
https://my.makepostsell.com/p/product-uuid
"""
if slug:
- return "{}/p/{}/{}".format(request.host_url, self.id, self.slug)
- return "{}/p/{}".format(request.host_url, self.id)
+ return f"{request.host_url}/p/{self.id}/{self.slug}"
+ return f"{request.host_url}/p/{self.id}"
def absolute_edit_url(self, request):
"""
@@ -387,7 +387,7 @@ class Product(RBase, Base):
https://makepostsell.com/p/product-uuid/edit
"""
- return "{}/edit".format(self.absolute_url(request, slug=False))
+ return f"{self.absolute_url(request, slug=False)}/edit"
@property
def shop_uuid_str(self):
@@ -518,7 +518,7 @@ def get_products_by_keywords(dbsession, keywords, shop=None):
product_query = dbsession.query(Product)
for keyword in keywords:
- keyword_filter = Product.title.ilike("%{}%".format(keyword))
+ keyword_filter = Product.title.ilike(f"%{keyword}%")
# the product _must_ be public (1).
products = (
product_query.filter(keyword_filter).filter(Product.visibility == 1).all()
diff --git a/make_post_sell/models/shop.py b/make_post_sell/models/shop.py
index 856f28b..8a2ce9a 100644
--- a/make_post_sell/models/shop.py
+++ b/make_post_sell/models/shop.py
@@ -1,10 +1,18 @@
import uuid
from sqlalchemy import Column, BigInteger, Boolean, Unicode, UnicodeText, func
-
+
from sqlalchemy import and_
-from .meta import Base, RBase, UUIDType, now_timestamp, foreign_key, get_object_by_id, get_objects_by_ids
+from .meta import (
+ Base,
+ RBase,
+ UUIDType,
+ now_timestamp,
+ foreign_key,
+ get_object_by_id,
+ get_objects_by_ids,
+)
from sqlalchemy.ext.associationproxy import association_proxy
@@ -62,8 +70,8 @@ class Shop(RBase, Base):
# these keys allow make_post_sell to charge
# cards on behalf of the shop's stripe account.
- #stripe_secret_api_key = Column(Unicode(64), nullable=True)
- #stripe_public_api_key = Column(Unicode(64), nullable=True)
+ # stripe_secret_api_key = Column(Unicode(64), nullable=True)
+ # stripe_public_api_key = Column(Unicode(64), nullable=True)
stripe_secret_api_key = Column(Unicode(128), nullable=True)
stripe_public_api_key = Column(Unicode(128), nullable=True)
@@ -101,7 +109,9 @@ class Shop(RBase, Base):
# lazy='dynamic' returns a query object instead of collection.
# Reference: http://docs.sqlalchemy.org/en/latest/orm/collections.html
- shop_locations = relationship(argument="ShopLocation", lazy="dynamic", back_populates="shop")
+ shop_locations = relationship(
+ argument="ShopLocation", lazy="dynamic", back_populates="shop"
+ )
# lazy='dynamic' returns a query object instead of collection.
# Reference: http://docs.sqlalchemy.org/en/latest/orm/collections.html
@@ -121,10 +131,14 @@ class Shop(RBase, Base):
def get_usershop_for_user(self, user):
"""Given a User object, return the UserShop object or None."""
if self.dbsession is not None:
- return self.dbsession.query(UserShop).filter(
- UserShop.shop == self,
- UserShop.user == user,
- ).one_or_none()
+ return (
+ self.dbsession.query(UserShop)
+ .filter(
+ UserShop.shop == self,
+ UserShop.user == user,
+ )
+ .one_or_none()
+ )
def add_user_to_shop(self, user, role_id=0):
"""Add User object to UserShop."""
@@ -172,6 +186,7 @@ class Shop(RBase, Base):
if hasattr(self, "_stripe") == False:
if self.stripe_secret_api_key:
import stripe
+
stripe.api_key = self.stripe_secret_api_key
self._stripe = stripe
else:
@@ -180,15 +195,19 @@ class Shop(RBase, Base):
def stripe_user_shop(self, user):
"""Return the stripe_user_shop object from our database for this user, or None."""
- return self.dbsession.query(StripeUserShop).filter(
- StripeUserShop.user == user,
- StripeUserShop.shop == self,
- ).one_or_none()
+ return (
+ self.dbsession.query(StripeUserShop)
+ .filter(
+ StripeUserShop.user == user,
+ StripeUserShop.shop == self,
+ )
+ .one_or_none()
+ )
def stripe_customer_id(self, user):
"""Return the stripe_customer id from our database for this user, or None."""
stripe_user_shop = self.stripe_user_shop(user)
-
+
if stripe_user_shop:
return stripe_user_shop.cus_id
@@ -201,7 +220,6 @@ class Shop(RBase, Base):
stripe_customer_id = self.stripe_customer_id(user)
if stripe_customer_id is None:
-
if create == False:
return None
@@ -236,7 +254,7 @@ class Shop(RBase, Base):
@property
def theme_link_color(self):
- return color_scale(self.theme_base_color, .75)
+ return color_scale(self.theme_base_color, 0.75)
def absolute_url(self, request, slug=True):
"""
@@ -247,8 +265,8 @@ class Shop(RBase, Base):
https://my.makepostsell.com/s/
"""
if slug:
- return "{}/s/{}/{}".format(request.host_url, self.id, self.slug)
- return "{}/s/{}".format(request.host_url, self.id)
+ return f"{request.host_url}/s/{self.id}/{self.slug}"
+ return f"{request.host_url}/s/{self.id}"
def absolute_settings_url(self, request):
"""
@@ -258,7 +276,7 @@ class Shop(RBase, Base):
https://my.makepostsell.com/s//settings
"""
- return "{}/settings".format(self.absolute_url(request, slug=False))
+ return f"{self.absolute_url(request, slug=False)}/settings"
def absolute_about_url(self, request):
"""
@@ -269,16 +287,16 @@ class Shop(RBase, Base):
https://my.makepostsell.com/s//about
"""
# why ure slug for this URL, is it for SEO?
- return "{}/about".format(self.absolute_url(request))
+ return f"{self.absolute_url(request)}/about"
def absolute_terms_url(self, request):
- return "{}/terms".format(self.absolute_url(request, slug=False))
-
+ return f"{self.absolute_url(request, slug=False)}/terms"
+
def absolute_privacy_policy_url(self, request):
- return "{}/privacy-policy".format(self.absolute_url(request, slug=False))
+ return f"{self.absolute_url(request, slug=False)}/privacy-policy"
def absolute_sales_url(self, request):
- return "{}/sales".format(self.absolute_url(request, slug=False))
+ return f"{self.absolute_url(request, slug=False)}/sales"
def set_description(self, new_description):
self.description = new_description
@@ -303,8 +321,9 @@ class Shop(RBase, Base):
self.terms_of_service_html = markdown_to_html(self.terms_of_service_raw, self)
def get_carts_for_user(self, user):
- """return all of this Shop's Cart objects for the given User."""
+ """return all of this Shop's Cart objects for the given User."""
from .cart import Cart
+
return self.carts.filter(and_(Cart.shop == self, Cart.user == user))
def make_cart_active_for_user(self, user, cart):
@@ -324,6 +343,7 @@ class Shop(RBase, Base):
def create_new_cart_for_user(self, user):
from .cart import Cart
+
cart = Cart()
cart.user = user
cart.shop = self
@@ -382,7 +402,7 @@ def get_shop_by_id(dbsession, shop_id):
"""Try to get Shop object by id or return None."""
return get_object_by_id(dbsession, shop_id, Shop)
+
def get_shops_by_ids(dbsession, shop_ids):
"""Try to get Shop objects by ids or return None."""
return get_objects_by_ids(dbsession, shop_ids, Shop)
-
diff --git a/make_post_sell/models/user.py b/make_post_sell/models/user.py
index 84d5e40..cdf57c4 100644
--- a/make_post_sell/models/user.py
+++ b/make_post_sell/models/user.py
@@ -38,6 +38,7 @@ except:
def generate_password(size=32):
"""Return a system generated password"""
from random import choice
+
letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
digits = "0123456789"
pool = letters + digits
@@ -56,7 +57,7 @@ class User(RBase, Base):
name = Column(Unicode(64), unique=True, nullable=False)
full_name = Column(Unicode(64))
email = Column(Unicode(64), unique=True, nullable=False)
- #email_unverified = Column(Unicode(64))
+ # email_unverified = Column(Unicode(64))
password = Column(Unicode(64))
password_attempts = Column(Integer, default=0)
password_timestamp = Column(BigInteger)
@@ -81,7 +82,9 @@ class User(RBase, Base):
shops = association_proxy("user_shops", "shop", creator=lambda s: UserShop(shop=s))
# many to many uses association_proxy.
- stripe_shops = association_proxy("stripe_shops", "shop", creator=lambda s: StripeUserShop(shop=s))
+ stripe_shops = association_proxy(
+ "stripe_shops", "shop", creator=lambda s: StripeUserShop(shop=s)
+ )
# many to many uses association_proxy.
# returns all the products that a user has purchased.
@@ -101,15 +104,16 @@ class User(RBase, Base):
# this is ideal when we want to further filter the results.
carts = relationship(argument="Cart", lazy="dynamic", back_populates="user")
- addresses = relationship(argument="UserAddress", lazy="dynamic", back_populates="user")
+ addresses = relationship(
+ argument="UserAddress", lazy="dynamic", back_populates="user"
+ )
def __init__(self, email):
- self.name = unicode("user-{}".format(generate_password(size=8)))
+ self.name = unicode(f"user-{generate_password(size=8)}")
self.created_timestamp = now_timestamp()
self.id = uuid.uuid1()
self.email = unicode(email)
-
# TODO: remove this column.
self.active_cart_id = uuid.uuid1()
@@ -119,10 +123,11 @@ class User(RBase, Base):
def _generate_raw_password(self):
"""Return a system generated password"""
- #return generate_password(size)
+ # return generate_password(size)
from random import choice
- numbers = '0123456789'
- return "".join([choice(numbers) for i in range(0,6)])
+
+ numbers = "0123456789"
+ return "".join([choice(numbers) for i in range(0, 6)])
def new_password(self):
"""Generate and return raw password, store password hash into DB."""
@@ -130,8 +135,7 @@ class User(RBase, Base):
# bcrypt works with bytes so we encode to utf-8.
self.password = bcrypt.hashpw(
- raw_password.encode("utf-8"),
- bcrypt.gensalt()
+ raw_password.encode("utf-8"), bcrypt.gensalt()
).decode("utf-8")
self.password_timestamp = now_timestamp()
self.password_attempts = 0
@@ -159,7 +163,7 @@ class User(RBase, Base):
stored_hash.encode("utf-8"),
).decode("utf-8")
- log.info("new_hash={} stored_hash={}".format(new_hash, stored_hash))
+ log.info(f"new_hash={new_hash} stored_hash={stored_hash}")
if new_hash == stored_hash:
return True
@@ -184,9 +188,11 @@ class User(RBase, Base):
def active_shop(self):
"""Return the user's active shop, or None."""
if self.active_shop_id:
- return self.dbsession.query(Shop).filter(
- Shop.id == self.active_shop_id
- ).one_or_none()
+ return (
+ self.dbsession.query(Shop)
+ .filter(Shop.id == self.active_shop_id)
+ .one_or_none()
+ )
elif self.shops:
# if a user doesn't have an active shop but it has
@@ -244,7 +250,7 @@ class User(RBase, Base):
for address in self.addresses:
if address.id == self.active_address_id:
return address
-
+
def _user_by_name_query(dbsession, name):
"""query User by case insensitive name."""
diff --git a/make_post_sell/tests/test_functional.py b/make_post_sell/tests/test_functional.py
index c3eaa9a..74e2a44 100644
--- a/make_post_sell/tests/test_functional.py
+++ b/make_post_sell/tests/test_functional.py
@@ -83,16 +83,17 @@ class UnauthenticatedFunctionalTests(FunctionalTests):
@patch("smtplib.SMTP")
def test_user_log_in(self, mock_smtp):
- redirect_res1 = self.testapp.post("/join-or-log-in", {"email": "test@example.com"})
+ redirect_res1 = self.testapp.post(
+ "/join-or-log-in", {"email": "test@example.com"}
+ )
self.assertIn(
b"Check email for a 6 digit verification code to log in. test@example.com",
- redirect_res1.follow().body)
+ redirect_res1.follow().body,
+ )
class AuthenticatedFunctionalTests(FunctionalTests):
-
def setUp(self):
-
super(AuthenticatedFunctionalTests, self).setUp()
self.shop1_params = {
@@ -134,25 +135,21 @@ class AuthenticatedFunctionalTests(FunctionalTests):
}
# create test user1 and user2.
- self.user1 = get_or_create_user_by_email(
- self.dbsession, "test1@example.com"
- )
- self.user2 = get_or_create_user_by_email(
- self.dbsession, "test2@example.com"
- )
+ self.user1 = get_or_create_user_by_email(self.dbsession, "test1@example.com")
+ self.user2 = get_or_create_user_by_email(self.dbsession, "test2@example.com")
# capture user credentials needed for authentication.
self.user1_creds = (
"test1@example.com",
# returns the raw auto-generated password used
# in one-time-password links OTP
- self.user1.new_password()
+ self.user1.new_password(),
)
self.user2_creds = (
"test2@example.com",
# returns the raw auto-generated password used
# in one-time-password links OTP
- self.user2.new_password()
+ self.user2.new_password(),
)
# flush new users to database.
@@ -164,12 +161,8 @@ class AuthenticatedFunctionalTests(FunctionalTests):
transaction.manager.commit()
# requery User objects to avoid detached instance error.
- self.user1 = get_or_create_user_by_email(
- self.dbsession, "test1@example.com"
- )
- self.user2 = get_or_create_user_by_email(
- self.dbsession, "test2@example.com"
- )
+ self.user1 = get_or_create_user_by_email(self.dbsession, "test1@example.com")
+ self.user2 = get_or_create_user_by_email(self.dbsession, "test2@example.com")
def _clean_up_user(self, user):
# print("deleteing user {} from dbsession.".format(user.name))
@@ -199,7 +192,6 @@ class AuthenticatedFunctionalTests(FunctionalTests):
# transaction.manager.commit()
super(AuthenticatedFunctionalTests, self).tearDown()
-
def log_in_user(self, user_creds):
# log in user.
res_login = self.testapp.post(
@@ -217,7 +209,7 @@ class AuthenticatedFunctionalTests(FunctionalTests):
valid_creds = self.user1_creds
invalid_creds = (self.user1_creds[0], "invalid")
- for i in range(0,12):
+ for i in range(0, 12):
self.log_in_user(invalid_creds)
self.log_in_user(valid_creds)
@@ -260,8 +252,9 @@ class AuthenticatedFunctionalTests(FunctionalTests):
res = redirect_res.follow()
self.assertIn(b"You must have a shop editor role to access that.", res.body)
- def test_create_new_shop(self, user_creds=None, shop_params=None, log_out_user=False):
-
+ def test_create_new_shop(
+ self, user_creds=None, shop_params=None, log_out_user=False
+ ):
if user_creds is None:
user_creds = self.user1_creds
@@ -287,7 +280,7 @@ class AuthenticatedFunctionalTests(FunctionalTests):
self.assertTrue(shop.is_not_ready)
# add stripe keys to the newly created shop to make it ready.
- res = self.testapp.post("/s/{}/settings".format(shop.id), shop_params)
+ res = self.testapp.post(f"/s/{shop.id}/settings", shop_params)
res_body = res.body.decode()
self.assertIn(
"You set the shop's stripe_public_api_key.",
@@ -337,23 +330,23 @@ class AuthenticatedFunctionalTests(FunctionalTests):
)
def test_new_product_missing_required_fields(self):
-
# log in and create a new shop.
shop = self.test_create_new_shop(
user_creds=self.user1_creds,
shop_params=self.shop1_params,
- log_out_user=False
+ log_out_user=False,
)
product_params = self.product1_params
del product_params["description"]
- #redirect_res1 = self.testapp.post("/p/new", product_params)
- #res = redirect_res1.follow()
- res = self.testapp.post("/p/new?shop_id={}".format(shop.id), product_params)
+ # redirect_res1 = self.testapp.post("/p/new", product_params)
+ # res = redirect_res1.follow()
+ res = self.testapp.post(f"/p/new?shop_id={shop.id}", product_params)
self.assertIn("You must fill out all fields.", res.body.decode())
- def test_new_product(self, user_creds=None, shop_params=None, product_params=None, log_out_user=False):
-
+ def test_new_product(
+ self, user_creds=None, shop_params=None, product_params=None, log_out_user=False
+ ):
if user_creds is None:
user_creds = self.user1_creds
@@ -369,7 +362,7 @@ class AuthenticatedFunctionalTests(FunctionalTests):
shop_params=shop_params,
)
- redirect_res = self.testapp.post("/p/new?shop_id={}".format(shop.id), product_params)
+ redirect_res = self.testapp.post(f"/p/new?shop_id={shop.id}", product_params)
res = redirect_res.follow()
self.assertIn("Great, next you may upload files.", res.body.decode())
@@ -377,7 +370,6 @@ class AuthenticatedFunctionalTests(FunctionalTests):
self.testapp.get("/log-out")
def test_new_product_when_user_does_not_have_editor_role_on_shop(self):
-
# log in user1.
self.log_in_user(self.user1_creds)
@@ -396,9 +388,11 @@ class AuthenticatedFunctionalTests(FunctionalTests):
# make user2 create a new product on a shop she doesn't own.
params = self.product1_params
- redirect_res = self.testapp.post("/p/new?shop_id={}".format(shop_id), params)
+ redirect_res = self.testapp.post(f"/p/new?shop_id={shop_id}", params)
res = redirect_res.follow()
- self.assertIn("You must have a shop editor role to access that.", res.body.decode())
+ self.assertIn(
+ "You must have a shop editor role to access that.", res.body.decode()
+ )
def test_new_product_price_history(self):
self.test_new_product(
@@ -416,12 +410,10 @@ class AuthenticatedFunctionalTests(FunctionalTests):
self.assertEqual(product.price_history.count(), 1)
self.assertEqual(product.price_in_cents, 350)
-
# this patch requires an argument added to test method `mock_smtp`.
@patch("smtplib.SMTP")
@patch("make_post_sell.models.Product.is_ready", mock_always_true)
def test_cart_checkout_for_shop(self, mock_smtp):
-
# 1. log in as user1.
# 2. create new shop.
# 3. make new shop ready for checkout.
@@ -446,12 +438,14 @@ class AuthenticatedFunctionalTests(FunctionalTests):
self.log_in_user(self.user2_creds)
# add product to cart.
- redirect_res1 = self.testapp.get("/cart/add?product_id={}&shop_id={}".format(product.id, shop.id))
+ redirect_res1 = self.testapp.get(
+ f"/cart/add?product_id={product.id}&shop_id={shop.id}"
+ )
redirect_res2 = redirect_res1.follow()
res = redirect_res2.follow()
res_body = res.body.decode()
- self.assertIn("You added \"russell\'s product\" to your cart.", res_body)
+ self.assertIn('You added "russell\'s product" to your cart.', res_body)
carts = get_all_carts(self.dbsession)
@@ -472,10 +466,7 @@ class AuthenticatedFunctionalTests(FunctionalTests):
self.assertEqual(1, user_2_cart.count)
redirect_res = self.testapp.get(
- "/u/cart/{}/checkout?shop_id={}".format(
- user_2_cart.id,
- shop.id
- )
+ f"/u/cart/{user_2_cart.id}/checkout?shop_id={shop.id}"
)
redirect_res2 = redirect_res1.follow()
res = redirect_res2.follow()
@@ -529,7 +520,6 @@ class AuthenticatedFunctionalTests(FunctionalTests):
@patch("make_post_sell.models.Product.is_ready", mock_always_true)
def make_new_coupon_for_shop(self, coupon_params=None):
-
# 1. log in as user1.
# 2. create new shop.
# 3. make new shop ready for checkout.
@@ -553,7 +543,7 @@ class AuthenticatedFunctionalTests(FunctionalTests):
# create a new shop coupon.
res = self.testapp.post(
- "/s/{}/coupon/new".format(shop.id),
+ f"/s/{shop.id}/coupon/new",
coupon_params,
)
return res
@@ -572,7 +562,7 @@ class AuthenticatedFunctionalTests(FunctionalTests):
# this patch requires an argument added to test method `mock_smtp`.
@patch("smtplib.SMTP")
@patch("make_post_sell.models.Product.is_ready", mock_always_true)
- def test_checkout_with_coupon_code(self, mock_smtp):
+ def test_checkout_with_coupon_code(self, mock_smtp):
res = self.make_new_coupon_for_shop()
res = res.follow()
self.assertIn("You created a new coupon!", res.body.decode())
@@ -585,20 +575,15 @@ class AuthenticatedFunctionalTests(FunctionalTests):
# query the new shop from database.
shop = get_shop_by_name(self.dbsession, self.shop1_params["name"])
-
+
coupons = get_coupons_by_code(self.dbsession, self.coupon1_params["code"])
coupon = coupons[0]
# apply coupon to user2's active cart.
- self.testapp.post(
- "/coupon/apply?&coupon_id={}&shop_id={}".format(
- coupon.id,
- shop.id,
- )
- )
+ self.testapp.post(f"/coupon/apply?&coupon_id={coupon.id}&shop_id={shop.id}")
# verify coupon was applied.
- res_redirect1 = self.testapp.get("/cart?shop_id={}".format(shop.id))
+ res_redirect1 = self.testapp.get(f"/cart?shop_id={shop.id}")
res = res_redirect1.follow()
res_body = res.body.decode()
self.assertIn("Slippery Halloween Party", res_body)
@@ -610,7 +595,7 @@ class AuthenticatedFunctionalTests(FunctionalTests):
product = all_products.one()
# add product to user2's active cart.
- self.testapp.get("/cart/add?product_id={}&shop_id={}".format(product.uuid_str, shop.id))
+ self.testapp.get(f"/cart/add?product_id={product.uuid_str}&shop_id={shop.id}")
# the stripe migration to SetupIntents broke this end-to-end test routine.
"""
diff --git a/make_post_sell/views/authentication.py b/make_post_sell/views/authentication.py
index 54f09d0..742309c 100644
--- a/make_post_sell/views/authentication.py
+++ b/make_post_sell/views/authentication.py
@@ -58,9 +58,7 @@ def join_or_log_in(request):
if user.throttle_password():
msg = (
- "Check email for a 6 digit verification code to log in. {}".format(
- user.email
- ),
+ f"Check email for a 6 digit verification code to log in. {user.email}",
"info",
)
@@ -74,9 +72,7 @@ def join_or_log_in(request):
send_verification_digits_to_email(request, user.email, raw_otp)
msg = (
- "Check email for a 6 digit verification code to log in. {}".format(
- user.email
- ),
+ f"Check email for a 6 digit verification code to log in. {user.email}",
"info",
)
@@ -85,7 +81,7 @@ def join_or_log_in(request):
email_encoded = urlencode(
{"email": email, "next": request.params.get("next", "")}
)
- return HTTPFound("/verification-challenge?{}".format(email_encoded))
+ return HTTPFound(f"/verification-challenge?{email_encoded}")
return {
"title": "join or log in",
@@ -113,7 +109,7 @@ def verification_challenge(request):
name = ""
if user.full_name:
name = user.name
- msg = ("Welcome {}".format(name), "success")
+ msg = (f"Welcome {name}", "success")
request.session["authenticated_user_id"] = str(user.id)
request.session.flash(msg)
diff --git a/make_post_sell/views/cart.py b/make_post_sell/views/cart.py
index d7202f2..a0c0809 100644
--- a/make_post_sell/views/cart.py
+++ b/make_post_sell/views/cart.py
@@ -128,7 +128,7 @@ def cart_activate(request):
request.dbsession.add(new_cart)
request.session.flash(msg)
request.session["active_cart_id"] = new_cart.uuid_str
- return HTTPFound("/cart/{}".format(new_cart.id))
+ return HTTPFound(f"/cart/{new_cart.id}")
request.session.flash(msg)
return HTTPFound(get_referer_or_home(request))
@@ -162,7 +162,7 @@ def cart_delete(request):
@view_config(route_name="cart")
def cart(request):
"""Load active cart from session. Create cart if not in session."""
- return HTTPFound("/cart/{}".format(request.active_cart.id))
+ return HTTPFound(f"/cart/{request.active_cart.id}")
@view_config(route_name="cart_by_id", renderer="cart.j2")
@@ -186,7 +186,7 @@ def cart_by_id(request):
request.dbsession.add(cart)
request.dbsession.flush()
msg = (
- "Invalid coupon ({}) removed from cart.".format(coupon.code),
+ f"Invalid coupon ({coupon.code}) removed from cart.",
"info",
)
request.session.flash(msg)
@@ -234,7 +234,7 @@ def cart_add_product(request):
msg = ("that content is not for sale or purchase.", "error")
else:
- msg = ('You added "{}" to your cart.'.format(product.title), "success")
+ msg = (f'You added "{product.title}" to your cart.', "success")
request.active_cart.add_product(product)
request.dbsession.add(request.active_cart)
request.dbsession.flush()
@@ -273,7 +273,7 @@ def cart_remove_product(request):
msg = ("That product_id does not exist.", "error")
else:
- msg = ('You removed "{}" from the cart.'.format(product.title), "success")
+ msg = (f'You removed "{product.title}" from the cart.', "success")
cart.remove_product(product)
cart.remove_handling_if_no_physical_products()
request.dbsession.add(cart)
@@ -335,7 +335,7 @@ def cart_quantity_product(request):
return HTTPFound("/cart")
else:
msg = (
- 'You updated the quantity of "{}" in the cart.'.format(product.title),
+ f'You updated the quantity of "{product.title}" in the cart.',
"success",
)
cart.set_product_quantity(product, quantity)
@@ -390,7 +390,7 @@ def cart_checkout(request):
stripe_user_shop = request.shop.stripe_user_shop(request.user)
if "cart_id" not in request.matchdict:
- return HTTPFound("/u/cart/{}/checkout".format(request.active_cart.id))
+ return HTTPFound(f"/u/cart/{request.active_cart.id}/checkout")
cart = get_cart_from_matchdict(request)
@@ -420,12 +420,18 @@ def cart_checkout(request):
return HTTPFound(get_referer_or_home(request))
if not cart.handling_option:
- msg = ("Please select a handling option for your physical items.", "error")
+ msg = (
+ "Please select a handling option for your physical items.",
+ "error",
+ )
request.session.flash(msg)
return HTTPFound(get_referer_or_home(request))
if not request.user.active_address:
- msg = ("Please add a shipping address to proceed with checkout.", "info")
+ msg = (
+ "Please add a shipping address to proceed with checkout.",
+ "info",
+ )
request.session.flash(msg)
return HTTPFound("/u/addresses")
diff --git a/make_post_sell/views/content.py b/make_post_sell/views/content.py
index 22bd62e..495dd19 100644
--- a/make_post_sell/views/content.py
+++ b/make_post_sell/views/content.py
@@ -21,10 +21,10 @@ def content(request):
return HTTPFound(get_referer_or_home(request))
if product.is_sellable:
- return HTTPFound("/p/{}/{}".format(product.id, product.slug))
+ return HTTPFound(f"/p/{product.id}/{product.slug}")
if "slug" not in request.matchdict:
- return HTTPFound("/c/{}/{}".format(product.id, product.slug))
+ return HTTPFound(f"/c/{product.id}/{product.slug}")
signed_get_object_url = None
diff --git a/make_post_sell/views/coupon.py b/make_post_sell/views/coupon.py
index 47dbf69..f15c6fd 100644
--- a/make_post_sell/views/coupon.py
+++ b/make_post_sell/views/coupon.py
@@ -68,7 +68,7 @@ def coupon_new(request):
)
request.dbsession.add(coupon)
request.dbsession.flush()
- return HTTPFound("/s/{}/coupons".format(request.shop.id))
+ return HTTPFound(f"/s/{request.shop.id}/coupons")
return request.params
@@ -82,7 +82,7 @@ def coupon_apply_to_cart(request):
if coupon is None:
msg = ("That coupon_id does not exist.", "error")
request.session.flash(msg)
- return HTTPFound("/cart/{}".format(request.active_cart.id))
+ return HTTPFound(f"/cart/{request.active_cart.id}")
if coupon not in request.active_cart.coupons:
msg = ("The coupon was applied to your cart.", "success")
@@ -93,7 +93,7 @@ def coupon_apply_to_cart(request):
msg = ("The coupon was already applied to your cart.", "success")
request.session.flash(msg)
- return HTTPFound("/cart/{}".format(request.active_cart.id))
+ return HTTPFound(f"/cart/{request.active_cart.id}")
@view_config(route_name="coupon_remove_from_cart", request_method="POST")
@@ -125,7 +125,7 @@ def coupon_remove_from_cart(request):
else:
msg = ("The coupon was already removed from your cart.", "success")
request.session.flash(msg)
- return HTTPFound("/cart/{}".format(cart_id))
+ return HTTPFound(f"/cart/{cart_id}")
request.session.flash(msg)
return HTTPFound(get_referer_or_home(request))
diff --git a/make_post_sell/views/product.py b/make_post_sell/views/product.py
index 3f2b2b6..0c383b8 100644
--- a/make_post_sell/views/product.py
+++ b/make_post_sell/views/product.py
@@ -35,10 +35,10 @@ def product(request):
return HTTPFound(get_referer_or_home(request))
if product.is_not_sellable:
- return HTTPFound("/c/{}/{}".format(product.id, product.slug))
+ return HTTPFound(f"/c/{product.id}/{product.slug}")
if "slug" not in request.matchdict:
- return HTTPFound("/p/{}/{}".format(product.id, product.slug))
+ return HTTPFound(f"/p/{product.id}/{product.slug}")
signed_get_object_url = None
@@ -134,7 +134,7 @@ def product_new(request):
request.dbsession.flush()
msg = ("Great, next you may upload files.", "success")
request.session.flash(msg)
- return HTTPFound("/p/{}/edit".format(product.id))
+ return HTTPFound(f"/p/{product.id}/edit")
elif title or description or price:
msg = ("You must fill out all fields.", "error")
@@ -172,12 +172,10 @@ def product_edit_description(request):
request.dbsession.flush()
return {
- "markup_subject": "Product Description for {}".format(product.title),
+ "markup_subject": f"Product Description for {product.title}",
"markup_rendered": product.description_html,
"markup_raw": product.description,
- "markup_form_path": "{}/description".format(
- product.absolute_url(request, slug=False)
- ),
+ "markup_form_path": f"{product.absolute_url(request, slug=False)}/description",
}
@@ -266,7 +264,7 @@ def product_edit(request):
ContentDisposition=product.get_content_disposition(file_key),
ContentType=product.get_content_type(file_key),
CacheControl=cache_control,
- Key="{}/{}".format(product.s3_path, file_key),
+ Key=f"{product.s3_path}/{file_key}",
MetadataDirective="REPLACE",
)
@@ -279,7 +277,7 @@ def product_edit(request):
# get file size & store in our database.
response = request.secure_uploads_client.head_object(
Bucket=request.app["bucket.secure_uploads"],
- Key="{}/{}".format(product.s3_path, file_key),
+ Key=f"{product.s3_path}/{file_key}",
)
product_content_length = response["ContentLength"]
@@ -294,9 +292,7 @@ def product_edit(request):
# redirect back to this page to clear
# the params posted by the s3 webhooks.
- return HTTPFound(
- "/p/{}/{}/edit?uploaded={}".format(product.id, product.slug, file_key)
- )
+ return HTTPFound(f"/p/{product.id}/{product.slug}/edit?uploaded={file_key}")
if product_modified and product.error_message is None:
request.dbsession.add(product)
@@ -305,7 +301,7 @@ def product_edit(request):
signed_posts = {}
for file_key in product.file_keys:
- key_starts_with = "{}/{}.".format(product.s3_path, file_key)
+ key_starts_with = f"{product.s3_path}/{file_key}."
conditions = [
{"success_action_redirect": product.absolute_edit_url(request)},
["starts-with", "$key", key_starts_with],
@@ -374,18 +370,29 @@ def product_inventory_edit(request):
if quantity is not None:
try:
quantity = int(quantity)
- inventory = next((inv for inv in product.inventories if inv.shop_location_id == location.id), None)
+ inventory = next(
+ (
+ inv
+ for inv in product.inventories
+ if inv.shop_location_id == location.id
+ ),
+ None,
+ )
if inventory:
if inventory.quantity != quantity:
inventory.update_quantity(quantity)
request.dbsession.add(inventory)
updated = True
else:
- inventory = Inventory(shop_location=location, product=product, quantity=quantity)
+ inventory = Inventory(
+ shop_location=location, product=product, quantity=quantity
+ )
request.dbsession.add(inventory)
updated = True
except ValueError:
- request.session.flash((f"Invalid quantity for location {location.name}.", "error"))
+ request.session.flash(
+ (f"Invalid quantity for location {location.name}.", "error")
+ )
if updated:
request.dbsession.flush()
diff --git a/make_post_sell/views/shop.py b/make_post_sell/views/shop.py
index dddb805..75d6b60 100644
--- a/make_post_sell/views/shop.py
+++ b/make_post_sell/views/shop.py
@@ -76,7 +76,7 @@ def home(request):
def shop(request):
shop = get_shop_from_matchdict(request)
if "slug" not in request.matchdict:
- return HTTPFound("/s/{}/{}".format(shop.id, shop.slug))
+ return HTTPFound(f"/s/{shop.id}/{shop.slug}")
return {
"products": get_products_from_a_shop(shop),
@@ -106,7 +106,7 @@ def shop_products(request):
def shop_about(request):
shop = get_shop_from_matchdict(request)
if "slug" not in request.matchdict:
- return HTTPFound("/s/{}/{}/about".format(shop.id, shop.slug))
+ return HTTPFound(f"/s/{shop.id}/{shop.slug}/about")
return {}
@@ -177,7 +177,7 @@ def shop_new(request):
"success",
)
request.session.flash(msg)
- return HTTPFound("/s/{}/settings".format(shop.id))
+ return HTTPFound(f"/s/{shop.id}/settings")
elif name or description or billing_address or phone_number:
msg = ("You must fill out all fields.", "error")
@@ -301,7 +301,7 @@ def shop_users(request):
# send an invitation email to the new user.
send_invite_email(request, email_to_invite, request.user, request.shop)
- msg = ("You invited {} to the shop.".format(email_to_invite), "success")
+ msg = (f"You invited {email_to_invite} to the shop.", "success")
request.session.flash(msg)
return {
@@ -327,9 +327,9 @@ def shop_user_remove(request):
else:
user_shop = request.shop.get_usershop_for_user(user)
request.dbsession.delete(user_shop)
- msg = ("You removed {} from the shop.".format(user.email), "success")
+ msg = (f"You removed {user.email} from the shop.", "success")
request.session.flash(msg)
- return HTTPFound("/s/{}/users".format(request.shop.id))
+ return HTTPFound(f"/s/{request.shop.id}/users")
@view_config(route_name="shop_settings", renderer="shop_settings.j2")
@@ -376,7 +376,7 @@ def shop_settings(request):
if uploaded_file_key:
request.session.flash(
(
- "You successfully uploaded a new {} file!".format(uploaded_file_key),
+ f"You successfully uploaded a new {uploaded_file_key} file!",
"success",
)
)
@@ -478,7 +478,7 @@ def shop_settings(request):
shop.maint_mode = maint_mode
request.session.flash(
(
- "You turned {} maint_mode".format(maint_mode_checkbox),
+ f"You turned {maint_mode_checkbox} maint_mode",
"success",
)
)
@@ -508,10 +508,10 @@ def shop_settings(request):
"Bucket": s3_webhook_bucket,
"Key": s3_webhook_key,
},
- ContentDisposition="inline; filename={}".format(file_key),
+ ContentDisposition=f"inline; filename={file_key}",
ContentType=content_type,
CacheControl=cache_control,
- Key="{}/meta/{}".format(shop.id, file_key),
+ Key=f"{shop.id}/meta/{file_key}",
MetadataDirective="REPLACE",
)
@@ -531,7 +531,7 @@ def shop_settings(request):
# redirect back to this page to clear
# the params posted by the s3 webhooks.
- return HTTPFound("/s/{}/settings?uploaded={}".format(shop.id, file_key))
+ return HTTPFound(f"/s/{shop.id}/settings?uploaded={file_key}")
signed_posts = {}
get_endpoints = {}
@@ -541,7 +541,7 @@ def shop_settings(request):
# object path start's with the shop's s3 namespace (uuid) and only for
# particular file keys. This prevents a user from writing files into
# a shops namespace which is owned by a different user.
- key_starts_with = "{}/meta/{}.{}".format(shop.id, file_key, "$filename")
+ key_starts_with = f"{shop.id}/meta/{file_key}.$filename"
conditions = [
{"success_action_redirect": shop.absolute_settings_url(request)},
["starts-with", "$key", key_starts_with],