diff --git a/ordr3/__init__.py b/ordr3/__init__.py index b2cf134..e7fd142 100644 --- a/ordr3/__init__.py +++ b/ordr3/__init__.py @@ -1,4 +1,4 @@ -""" Ordr3 +"""Ordr3 A rewrite of our CPI ordering system. """ @@ -10,10 +10,9 @@ from pyramid.config import Configurator from pyramid.session import JSONSerializer, SignedCookieSessionFactory -def main(global_config, **settings): +def main(global_config, **settings): # noqa: ARG001 """This function returns a Pyramid WSGI application.""" with Configurator(settings=settings) as config: - session_factory = SignedCookieSessionFactory( settings["session.secret"], serializer=JSONSerializer() ) diff --git a/ordr3/adapters.py b/ordr3/adapters.py index f490390..eebaa93 100644 --- a/ordr3/adapters.py +++ b/ordr3/adapters.py @@ -1,23 +1,23 @@ -""" sqlalchemy metadata configuration """ +"""sqlalchemy metadata configuration""" from datetime import datetime import zope.sqlalchemy from sqlalchemy import ( - Enum, - Text, - Float, - Table, Column, - Integer, DateTime, + Enum, + Float, ForeignKey, + Integer, + Table, + Text, engine_from_config, ) from sqlalchemy.orm import mapper, relationship, sessionmaker from sqlalchemy.schema import MetaData -from . import repo, models +from . import models, repo # Recommended naming convention used by Alembic, as various different database # providers will autogenerate vastly different names making migrations more @@ -141,9 +141,7 @@ def get_tm_session(session_factory, transaction_manager): """ dbsession = session_factory() - zope.sqlalchemy.register( - dbsession, transaction_manager=transaction_manager - ) + zope.sqlalchemy.register(dbsession, transaction_manager=transaction_manager) return dbsession diff --git a/ordr3/events.py b/ordr3/events.py index 25e9568..883fceb 100644 --- a/ordr3/events.py +++ b/ordr3/events.py @@ -73,7 +73,6 @@ def handle_flash_message_event(event): return session = event.request.session message = SerializableFlashMessage(event.text, event.more) - print(message) session.flash(message, event.channel, allow_duplicate=False) diff --git a/ordr3/models.py b/ordr3/models.py index 60ae2c4..d4d1fd7 100644 --- a/ordr3/models.py +++ b/ordr3/models.py @@ -1,6 +1,6 @@ import enum -from datetime import datetime, timedelta from collections import namedtuple +from datetime import datetime, timedelta VendorAggregate = namedtuple("VendorAggregate", ["name", "terms"]) @@ -40,7 +40,7 @@ class UserRole(enum.Enum): class Model: def __hash__(self): items = sorted(self.__dict__.items()) - no_log = ((k, v) for k, v in items if not k == "log") + no_log = ((k, v) for k, v in items if k != "log") content = ((k, v) for k, v in no_log if not k.startswith("_")) return hash(tuple(content)) @@ -69,7 +69,7 @@ class OrderItem(Model): created_by = None status = None - def __init__( + def __init__( # noqa: PLR0913 self, id, cas_description, @@ -167,7 +167,6 @@ class Vendor(Model): class User(Model): - id = None username = None first_name = None @@ -176,7 +175,7 @@ class User(Model): password = None role = None - def __init__( + def __init__( # noqa: PLR0913 self, id, username, first_name, last_name, email, password, role ): self.id = id @@ -216,7 +215,6 @@ class User(Model): class PasswordResetToken(Model): - token = None user_id = None valid_until = None diff --git a/ordr3/repo.py b/ordr3/repo.py index 394836f..eb8b82e 100644 --- a/ordr3/repo.py +++ b/ordr3/repo.py @@ -1,4 +1,4 @@ -""" Classes for acessing a datastore """ +"""Classes for acessing a datastore""" import abc from datetime import datetime @@ -12,8 +12,6 @@ from . import models class RepoItemNotFound(StopIteration): """repo error for a not found item""" - pass - class AbstractOrderRepository(abc.ABC): """Abstract base class for a datastore""" @@ -141,9 +139,7 @@ class SqlAlchemyRepository(AbstractOrderRepository): def get_user(self, reference): """get a user from the database by primary key""" try: - return ( - self.session.query(models.User).filter_by(id=reference).one() - ) + return self.session.query(models.User).filter_by(id=reference).one() except NoResultFound as exc: raise RepoItemNotFound from exc diff --git a/ordr3/resources.py b/ordr3/resources.py index 04384eb..b57cca8 100644 --- a/ordr3/resources.py +++ b/ordr3/resources.py @@ -1,8 +1,8 @@ -""" base resource and resource root factory """ +"""base resource and resource root factory""" import abc -from pyramid.authorization import DENY_ALL, Allow, Everyone, Authenticated +from pyramid.authorization import DENY_ALL, Allow, Authenticated, Everyone class BaseResource(abc.ABC): @@ -69,8 +69,8 @@ class Order(BaseResource): (Allow, "role:purchaser", "delete"), ] if self.model.in_process: - acl.append((Allow, "role:purchaser", "reorder")), - acl.append((Allow, "role:user", "reorder")), + (acl.append((Allow, "role:purchaser", "reorder")),) + (acl.append((Allow, "role:user", "reorder")),) else: acl.append((Allow, f"user:{self.model.created_by}", "edit")) acl.append((Allow, f"user:{self.model.created_by}", "delete")) diff --git a/ordr3/schemas/__init__.py b/ordr3/schemas/__init__.py index 4315f54..0bf356c 100644 --- a/ordr3/schemas/__init__.py +++ b/ordr3/schemas/__init__.py @@ -1,19 +1,18 @@ -""" schemas package """ +"""schemas package""" from deform import Form from pkg_resources import resource_filename -def includeme(config): +def includeme(config): # noqa: ARG001 """Defining form templates overrides Activate this setup using ``config.include('ordr3.schemas')``. """ # this allows to use the request object like this: - # request.flash(channel, message, description) + # > request.flash(channel, message, description) ordr_templates = resource_filename("ordr3", "templates/deform") deform_templates = resource_filename("deform", "templates") search_path = (ordr_templates, deform_templates) - # search_path = (ordr_templates, ) Form.set_zpt_renderer(search_path) diff --git a/ordr3/schemas/account.py b/ordr3/schemas/account.py index 290dd02..32e8508 100644 --- a/ordr3/schemas/account.py +++ b/ordr3/schemas/account.py @@ -1,16 +1,16 @@ -""" Schemas for form input and validation """ +"""Schemas for form input and validation""" -import deform import colander +import deform -from .base import CSRFSchema from ..models import UserRole +from .base import CSRFSchema ROLES = [(role.name, role.name.capitalize()) for role in UserRole] @colander.deferred -def deferred_unique_username_validator(node, kw): +def deferred_unique_username_validator(node, kw): # noqa: ARG001 """checks if an username is not registered already""" def validate_unique_username(node, value): @@ -25,7 +25,7 @@ def deferred_unique_username_validator(node, kw): @colander.deferred -def deferred_unique_email_validator(node, kw): +def deferred_unique_email_validator(node, kw): # noqa: ARG001 """checks if an email is not registered already""" email_validator = colander.Email() @@ -85,7 +85,6 @@ class RegistrationSchema(CSRFSchema): class ForgottenPasswordSchema(CSRFSchema): - email_or_username = colander.SchemaNode(colander.String()) @classmethod @@ -99,7 +98,6 @@ class ForgottenPasswordSchema(CSRFSchema): class ResetPasswordSchema(CSRFSchema): - new_password = colander.SchemaNode( colander.String(), widget=deform.widget.PasswordWidget(template="viewable_password.pt"), diff --git a/ordr3/schemas/base.py b/ordr3/schemas/base.py index 1f61f2f..c2fa3a1 100644 --- a/ordr3/schemas/base.py +++ b/ordr3/schemas/base.py @@ -1,22 +1,22 @@ -""" Schemas for form input and validation """ +"""Schemas for form input and validation""" -import deform import colander -from pyramid.csrf import get_csrf_token, check_csrf_token +import deform +from pyramid.csrf import check_csrf_token, get_csrf_token @colander.deferred -def deferred_csrf_default(node, kw): +def deferred_csrf_default(node, kw): # noqa: ARG001 """sets the current csrf token""" request = kw.get("request") return get_csrf_token(request) @colander.deferred -def deferred_csrf_validator(node, kw): +def deferred_csrf_validator(node, kw): # noqa: ARG001 """validates a submitted csrf token""" - def validate_csrf(node, value): + def validate_csrf(node, value): # noqa: ARG001 request = kw.get("request") if not check_csrf_token(request, raises=False): raise colander.Invalid(node, "Bad CSRF token") diff --git a/ordr3/schemas/orders.py b/ordr3/schemas/orders.py index c53b536..ed73238 100644 --- a/ordr3/schemas/orders.py +++ b/ordr3/schemas/orders.py @@ -1,10 +1,10 @@ -""" Schemas for form input and validation """ +"""Schemas for form input and validation""" -import deform import colander +import deform +from ..models import OrderCategory, OrderStatus, UserRole from .base import CSRFSchema -from ..models import UserRole, OrderStatus, OrderCategory CATEGORIES = [(c.name, c.name.capitalize()) for c in OrderCategory] STATI = [(s.name, s.name.capitalize()) for s in OrderStatus] @@ -64,7 +64,7 @@ class OrderItem(colander.Schema): item_css_class="row", label_css_class="col-sm-3 col-form-label o3-form-copy", css_class="col-sm-9 o3-vendor", - attributes={"data-url": ""}, # noqa: E231 + attributes={"data-url": ""}, ), ) package_size = colander.SchemaNode( @@ -139,15 +139,15 @@ class OrderPricing(colander.Schema): ) -class OrderOptionals(colander.Schema): +class OrderFunding(colander.Schema): """schema for editing optional information parital schema, used in NewOrderSchema and EditOrderSchema """ - account = colander.SchemaNode( + funds = colander.SchemaNode( colander.String(), - required=False, + required=True, missing="", widget=deform.widget.TextInputWidget( item_css_class="row", @@ -155,6 +155,14 @@ class OrderOptionals(colander.Schema): css_class="col-sm-9", ), ) + + +class OrderOptionals(colander.Schema): + """schema for editing optional information + + parital schema, used in NewOrderSchema and EditOrderSchema + """ + comment = colander.SchemaNode( colander.String(), missing="", @@ -173,6 +181,7 @@ class EditOrderSchema(CSRFSchema): status = OrderStatus() item = OrderItem() pricing = OrderPricing() + funding = OrderFunding() optional = OrderOptionals() @classmethod diff --git a/ordr3/scripts/migrate_db.py b/ordr3/scripts/migrate_db.py index a680abc..a5f8328 100644 --- a/ordr3/scripts/migrate_db.py +++ b/ordr3/scripts/migrate_db.py @@ -1,16 +1,16 @@ -import sys -import sqlite3 import argparse -from pathlib import Path +import sqlite3 +import sys from datetime import datetime +from pathlib import Path from urllib.parse import urlparse +from pyramid.paster import bootstrap, get_appsettings, setup_logging from sqlalchemy import func -from pyramid.paster import bootstrap, setup_logging, get_appsettings from sqlalchemy.exc import OperationalError from sqlalchemy.orm.exc import NoResultFound -from .. import models, adapters, services +from .. import adapters, models, services vendor_map = { "Accurion GmbH": ["accurion"], @@ -238,9 +238,10 @@ def _case_insensitive_query_user_by_username(repo, reference): .filter(func.lower(models.User.username) == func.lower(reference)) .one() ) - return user.username except NoResultFound: return reference + else: + return user.username def migrate(old_db, repo): @@ -265,13 +266,13 @@ def migrate_users(cursor, repo): repo.add_user(user) -def migrate_vendors(cursor, repo): +def migrate_vendors(cursor, repo): # noqa: ARG001 for name, replacements in vendor_map.items(): vendor = models.Vendor(name.lower(), name) - repo._add_item_to_db(vendor) + repo._add_item_to_db(vendor) # noqa: SLF001 for replacement in replacements: vendor = models.Vendor(replacement.lower(), name) - repo._add_item_to_db(vendor) + repo._add_item_to_db(vendor) # noqa: SLF001 def migrate_orders(cursor, repo): @@ -283,13 +284,12 @@ def migrate_orders(cursor, repo): ] for old_order in _query_table(cursor, "orders"): - result = services.check_vendor_name(repo, old_order["vendor"]) if result.found: vendor = result.name else: vendor = old_order["vendor"] - repo._add_item_to_db(models.Vendor(result.name.lower(), vendor)) + repo._add_item_to_db(models.Vendor(result.name.lower(), vendor)) # noqa: SLF001 order = models.OrderItem( old_order["id"], @@ -354,7 +354,7 @@ def main(argv=sys.argv): adapters.metadata.create_all(repo.session.get_bind()) migrate(args.old_db, repo) except OperationalError: - print( + print( # noqa: T201 """ Pyramid is having a problem using your SQL database. The problem might be caused by one of the following things: diff --git a/ordr3/security.py b/ordr3/security.py index fd72527..4bc236b 100644 --- a/ordr3/security.py +++ b/ordr3/security.py @@ -1,9 +1,9 @@ -""" User Authentication and Authorization """ +"""User Authentication and Authorization""" from passlib.context import CryptContext -from sqlalchemy.orm.exc import NoResultFound -from pyramid.authorization import Everyone, ACLHelper, Authenticated from pyramid.authentication import AuthTktCookieHelper +from pyramid.authorization import ACLHelper, Authenticated, Everyone +from sqlalchemy.orm.exc import NoResultFound class SecurityPolicy: @@ -40,9 +40,10 @@ class SecurityPolicy: identity = request.identity try: user = request.repo.get_user(identity["userid"]) - return user.id except (NoResultFound, TypeError): return None + else: + return user.id def permits(self, request, context, permission): # use the identity to build a list of principals, and pass them @@ -68,9 +69,10 @@ def get_user(request): return None try: user = request.repo.get_user(identity["userid"]) - return user if user.is_active else None except (NoResultFound, TypeError): return None + else: + return user if user.is_active else None def get_passlib_context(): diff --git a/ordr3/services.py b/ordr3/services.py index f0e19d7..768a44a 100644 --- a/ordr3/services.py +++ b/ordr3/services.py @@ -1,7 +1,7 @@ -import uuid import hashlib -from datetime import datetime, timedelta +import uuid from collections import namedtuple +from datetime import datetime, timedelta from urllib.parse import urlparse import requests @@ -83,8 +83,7 @@ def _vendor_from_url(vendor): parsed = urlparse(vendor) if parsed.netloc != "": return parsed.netloc - else: - return vendor + return vendor def _vendor_with_common_domain(vendor): @@ -114,8 +113,7 @@ def check_vendor_name(repo, to_check): if vendor is None: return CheckVendorResult(canonical_name, False) - else: - return CheckVendorResult(vendor.name, True) + return CheckVendorResult(vendor.name, True) def set_new_password(user, password, event_queue): @@ -135,7 +133,7 @@ def check_have_i_been_pwned(password, event_queue): """public function for checking haveibeenpwned this is just a small shim to eas testing""" - password_hash = hashlib.sha1(password.encode()).hexdigest() # noqa: S303 + password_hash = hashlib.sha1(password.encode()).hexdigest() # noqa: S324 return _check_have_i_been_pwned(password_hash, event_queue) diff --git a/ordr3/views/__init__.py b/ordr3/views/__init__.py index 50c8b90..3a85aa0 100644 --- a/ordr3/views/__init__.py +++ b/ordr3/views/__init__.py @@ -1,4 +1,4 @@ -""" views package +"""views package some view helpers are defined here """ diff --git a/ordr3/views/account.py b/ordr3/views/account.py index 7324310..9b7f516 100644 --- a/ordr3/views/account.py +++ b/ordr3/views/account.py @@ -1,14 +1,13 @@ -""" static and login pages """ - +"""static and login pages""" import deform -from pyramid.view import view_config -from pyramid.security import forget, remember from pyramid.httpexceptions import HTTPFound +from pyramid.security import forget, remember +from pyramid.view import view_config from .. import models, security, services -from ..repo import RepoItemNotFound from ..events import FlashMessage, PasswordResetEmail +from ..repo import RepoItemNotFound from ..schemas import account @@ -19,7 +18,7 @@ from ..schemas import account request_method="GET", renderer="ordr3:templates/account/login.jinja2", ) -def login(context, request): +def login(context, request): # noqa: ARG001 return {"error": False} @@ -31,7 +30,7 @@ def login(context, request): require_csrf=False, renderer="ordr3:templates/account/login.jinja2", ) -def check_credentials(context, request): +def check_credentials(context, request): # noqa: ARG001 username = request.POST.get("username", "") password = request.POST.get("password", "") @@ -47,10 +46,8 @@ def check_credentials(context, request): return {"error": True} -@view_config( - context="ordr3:resources.Root", name="logout", permission="logout" -) -def logout(context, request): +@view_config(context="ordr3:resources.Root", name="logout", permission="logout") +def logout(context, request): # noqa: ARG001 """logout of a user""" return HTTPFound( request.resource_path(request.root, "login"), headers=forget(request) @@ -64,7 +61,7 @@ def logout(context, request): request_method="GET", renderer="ordr3:templates/account/registration.jinja2", ) -def registration(context, request): +def registration(context, request): # noqa: ARG001 form = account.RegistrationSchema.as_form(request) return {"form": form} @@ -76,7 +73,7 @@ def registration(context, request): request_method="POST", renderer="ordr3:templates/account/registration.jinja2", ) -def register_new_user(context, request): +def register_new_user(context, request): # noqa: ARG001 if "Create_Account" not in request.POST: return HTTPFound(request.resource_path(request.root)) @@ -108,7 +105,7 @@ def register_new_user(context, request): permission="view", renderer="ordr3:templates/account/registration_complete.jinja2", ) -def registration_complete(context, request): +def registration_complete(context, request): # noqa: ARG001 return {} @@ -118,7 +115,7 @@ def registration_complete(context, request): permission="view", renderer="ordr3:templates/account/breached_password.jinja2", ) -def breached_password(context, request): +def breached_password(context, request): # noqa: ARG001 return {} @@ -129,7 +126,7 @@ def breached_password(context, request): request_method="GET", renderer="ordr3:templates/account/forgotten_password.jinja2", ) -def forgotten_password(context, request): +def forgotten_password(context, request): # noqa: ARG001 form = account.ForgottenPasswordSchema.as_form(request) return {"form": form} @@ -141,7 +138,7 @@ def forgotten_password(context, request): request_method="POST", renderer="ordr3:templates/account/forgotten_password.jinja2", ) -def send_reset_link(context, request): +def send_reset_link(context, request): # noqa: ARG001 if "Send_Reset_Link" not in request.POST: return HTTPFound(request.resource_path(request.root)) @@ -167,7 +164,7 @@ def send_reset_link(context, request): permission="view", renderer="ordr3:templates/account/reset_link_sent.jinja2", ) -def reset_link_sent(context, request): +def reset_link_sent(context, request): # noqa: ARG001 return {} @@ -178,7 +175,7 @@ def reset_link_sent(context, request): request_method="GET", renderer="ordr3:templates/account/reset_password_form.jinja2", ) -def reset_password_form(context, request): +def reset_password_form(context, request): # noqa: ARG001 token = request.GET.get("t") user = services.get_user_from_reset_token(request.repo, token) if user is None: @@ -195,7 +192,7 @@ def reset_password_form(context, request): request_method="POST", renderer="ordr3:templates/account/reset_password_form.jinja2", ) -def reset_password(context, request): +def reset_password(context, request): # noqa: ARG001 if "Reset_Password" not in request.POST: return HTTPFound(request.resource_path(request.root)) @@ -223,7 +220,7 @@ def reset_password(context, request): permission="view", renderer="ordr3:templates/account/password_reseted.jinja2", ) -def password_reseted(context, request): +def password_reseted(context, request): # noqa: ARG001 return {} @@ -234,7 +231,7 @@ def password_reseted(context, request): request_method="GET", renderer="ordr3:templates/account/myaccount.jinja2", ) -def myaccount(context, request): +def myaccount(context, request): # noqa: ARG001 form = account.MyAccountSchema.as_form(request) form_data = { "user_name": request.user.username, @@ -253,7 +250,7 @@ def myaccount(context, request): request_method="POST", renderer="ordr3:templates/account/myaccount.jinja2", ) -def edit_myaccount(context, request): +def edit_myaccount(context, request): # noqa: ARG001 if "Save_Changes" not in request.POST: return HTTPFound(request.resource_path(request.root)) @@ -274,7 +271,7 @@ def edit_myaccount(context, request): @view_config( context="ordr3:resources.Root", name="mypassword", permission="account" ) -def myaccount_reset_link(context, request): +def myaccount_reset_link(context, request): # noqa: ARG001 token = services.create_token_for_user(request.repo, request.user) request.emit(PasswordResetEmail(request.user, token.token)) request.emit( diff --git a/ordr3/views/orders.py b/ordr3/views/orders.py index c0d84e6..738ee17 100644 --- a/ordr3/views/orders.py +++ b/ordr3/views/orders.py @@ -1,12 +1,12 @@ import deform -from sqlalchemy import or_ # , func from pyramid.csrf import get_csrf_token -from pyramid.view import view_config from pyramid.httpexceptions import HTTPFound +from pyramid.view import view_config +from sqlalchemy import or_ # , func -from . import DefaultQueryParams, get_offset -from .. import events, models, services, resources +from .. import events, models, resources, services from ..schemas import orders +from . import DefaultQueryParams, get_offset QUERY_LIMIT = 25 @@ -27,7 +27,7 @@ def get_category(request): return None -def get_multiple_orders(context, request): +def get_multiple_orders(context, request): # noqa: ARG001 order_ids = {v for k, v in request.POST.items() if k == "selection"} return ( request.repo.session.query(models.OrderItem) @@ -57,12 +57,16 @@ def get_form_data_from_order(order): "currency": order.currency, }, } - optional = {"account": order.account, "comment": order.comment} + + funding = {"funds": order.account} + + optional = {"comment": order.comment} form_data = { "status": status, "item": item, "pricing": pricing, + "funding": funding, "optional": optional, } return form_data @@ -83,7 +87,7 @@ def update_order_with_form_data(order, form_data): order.currency = form_pricing["unit_price"]["currency"] order.amount = form_pricing["quantity"] - order.account = form_optional["account"] + order.account = form_optional["funds"] order.comment = form_optional["comment"] @@ -124,7 +128,7 @@ def order_list(context, request): elif username: query = query.filter(models.OrderItem.created_by == username) if search: - term = "%{}%".format(search) + term = f"%{search}%" query = query.filter( or_( models.OrderItem.cas_description.ilike(term), @@ -134,7 +138,7 @@ def order_list(context, request): models.OrderItem.created_by.ilike(term), ) ) - orders = query[offset : offset + limit] # noqa: E203 + orders = query[offset : offset + limit] next_offset = None if limit != len(orders) else (offset + limit) order_resources = [resources.Order.from_model(u, context) for u in orders] @@ -213,9 +217,7 @@ def batch_delete_confirmed(context, request): for order in orders: request.repo.delete_order(order) request.emit( - events.FlashMessage.info( - f"{len(orders)} orders have been deleted." - ) + events.FlashMessage.info(f"{len(orders)} orders have been deleted.") ) return HTTPFound(request.resource_url(context)) @@ -295,9 +297,7 @@ def batch_edit_confirm(context, request): if len(orders): request.emit( - events.FlashMessage.info( - f"{len(orders)} orders have been updated." - ) + events.FlashMessage.info(f"{len(orders)} orders have been updated.") ) return HTTPFound(request.resource_url(context)) @@ -312,7 +312,7 @@ def batch_edit_confirm(context, request): require_csrf=False, renderer="json", ) -def check_vendor_name(context, request): +def check_vendor_name(context, request): # noqa: ARG001 vendor = request.POST.get("vendor", "") result = services.check_vendor_name(request.repo, vendor) return result._asdict() @@ -391,7 +391,7 @@ def place_new_order(context, request): request_method="GET", renderer="ordr3:templates/orders/view.jinja2", ) -def view_order(context, request): +def view_order(context, request): # noqa: ARG001 return {"csrf_token": get_csrf_token(request)} @@ -526,7 +526,7 @@ def place_reorder(context, request): request_method="GET", renderer="ordr3:templates/orders/delete.jinja2", ) -def delete_order(context, request): +def delete_order(context, request): # noqa: ARG001 return {"csrf_token": get_csrf_token(request)} diff --git a/ordr3/views/root.py b/ordr3/views/root.py index ef60841..2c4a438 100644 --- a/ordr3/views/root.py +++ b/ordr3/views/root.py @@ -1,19 +1,17 @@ -""" static and login pages """ - +"""static and login pages""" +from pyramid.httpexceptions import HTTPFound from pyramid.view import ( - view_config, - notfound_view_config, forbidden_view_config, + notfound_view_config, + view_config, ) -from pyramid.httpexceptions import HTTPFound @forbidden_view_config() @notfound_view_config() @view_config(context="ordr3:resources.Root", permission="view") -def root(context, request): +def root(context, request): # noqa: ARG001 if request.user: return HTTPFound(request.resource_path(request.root, "orders")) - else: - return HTTPFound(request.resource_path(request.root, "login")) + return HTTPFound(request.resource_path(request.root, "login")) diff --git a/ordr3/views/users.py b/ordr3/views/users.py index 5e3da77..32700b0 100644 --- a/ordr3/views/users.py +++ b/ordr3/views/users.py @@ -1,12 +1,12 @@ import deform -from sqlalchemy import func from pyramid.csrf import get_csrf_token -from pyramid.view import view_config from pyramid.httpexceptions import HTTPFound +from pyramid.view import view_config +from sqlalchemy import func -from . import get_offset -from .. import events, models, services, resources +from .. import events, models, resources, services from ..schemas import account +from . import get_offset def get_role(request): @@ -39,7 +39,7 @@ def user_list(context, request): if role: query = query.filter(models.User.role == role) query = query.order_by(func.lower(models.User.username)) - users = query[offset : offset + limit] # noqa: E203 + users = query[offset : offset + limit] next_offset = None if limit != len(users) else (offset + limit) filter_role = "all" if role is None else role.name.lower() @@ -131,7 +131,7 @@ def user_reset_password(context, request): request_method="GET", renderer="ordr3:templates/users/delete.jinja2", ) -def delete_user(context, request): +def delete_user(context, request): # noqa: ARG001 return {"csrf_token": get_csrf_token(request)} diff --git a/ordr3/views/vendors.py b/ordr3/views/vendors.py index df3067a..95072e1 100644 --- a/ordr3/views/vendors.py +++ b/ordr3/views/vendors.py @@ -1,7 +1,7 @@ -from sqlalchemy import func from pyramid.csrf import get_csrf_token -from pyramid.view import view_config from pyramid.httpexceptions import HTTPFound +from pyramid.view import view_config +from sqlalchemy import func from .. import events, models, services @@ -12,8 +12,7 @@ from .. import events, models, services request_method="GET", renderer="ordr3:templates/vendors/list.jinja2", ) -def vendor_list(context, request): - +def vendor_list(context, request): # noqa: ARG001 vendors = ( request.repo.session.query(models.Vendor.name) .distinct(models.Vendor.name) @@ -30,7 +29,7 @@ def vendor_list(context, request): request_method="GET", renderer="ordr3:templates/vendors/edit.jinja2", ) -def vendor_edit_form(context, request): +def vendor_edit_form(context, request): # noqa: ARG001 return {"form_error": False, "csrf_token": get_csrf_token(request)} diff --git a/tests/conftest.py b/tests/conftest.py index 64ccc65..f4730f8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,6 @@ import pytest from sqlalchemy import create_engine -from sqlalchemy.orm import sessionmaker, clear_mappers +from sqlalchemy.orm import clear_mappers, sessionmaker from ordr3.adapters import metadata, start_mappers diff --git a/tests/functional/conftest.py b/tests/functional/conftest.py index aec64f6..7aaa295 100644 --- a/tests/functional/conftest.py +++ b/tests/functional/conftest.py @@ -207,7 +207,7 @@ def _example_data(_sqlite_repo): def testapp(_pyramid_app, _example_data): from webtest import TestApp - yield TestApp(_pyramid_app) + return TestApp(_pyramid_app) @pytest.fixture @@ -220,7 +220,7 @@ def login_as(testapp): form["password"] = password return form.submit("submit") - yield _do_login + return _do_login @pytest.fixture @@ -236,13 +236,13 @@ def parse_latest_mail(testapp): link = links[0] if links else None return ParsedMail(body, link) - yield _parse_mail + return _parse_mail @pytest.fixture -def contains(testapp): +def contains(testapp): # noqa: ARG001 def _contains(response, **what): result = [(key in response) == value for key, value in what.items()] return all(result) - yield _contains + return _contains diff --git a/tests/functional/test_order.py b/tests/functional/test_order.py index 2c0c786..c9fe537 100644 --- a/tests/functional/test_order.py +++ b/tests/functional/test_order.py @@ -297,7 +297,7 @@ def test_edit_order_cancel(testapp, login_as, contains): @pytest.mark.fun -def test_edit_order_purchaser_vs_user(testapp, login_as, contains): +def test_edit_order_purchaser_vs_user(testapp, login_as, contains): # noqa: ARG001 response = testapp.get("/", status=302).follow() assert "Please Log In" in response diff --git a/tests/functional/test_order_list.py b/tests/functional/test_order_list.py index 32462e9..82ba6a5 100644 --- a/tests/functional/test_order_list.py +++ b/tests/functional/test_order_list.py @@ -34,9 +34,7 @@ def test_order_list(testapp, login_as, contains): response, Eppis=False, Ethanol=True, NaCl=False, Spritzen=False ) - response = testapp.get( - "/orders?user=TestAdmin&status=approval", status=200 - ) + response = testapp.get("/orders?user=TestAdmin&status=approval", status=200) assert contains( response, Eppis=False, Ethanol=False, NaCl=True, Spritzen=False ) diff --git a/tests/functional/test_password_reset.py b/tests/functional/test_password_reset.py index a456760..24a1c58 100644 --- a/tests/functional/test_password_reset.py +++ b/tests/functional/test_password_reset.py @@ -132,7 +132,7 @@ def test_password_reset_empty_password(testapp, parse_latest_mail): assert "You can now set a new password" in response form = response.form - form["new_password"] = "" # noqa: S105 + form["new_password"] = "" response = form.submit("Reset_Password") assert "There was a problem with your submission" in response diff --git a/tests/functional/test_registration.py b/tests/functional/test_registration.py index de808b6..acbc461 100644 --- a/tests/functional/test_registration.py +++ b/tests/functional/test_registration.py @@ -49,7 +49,9 @@ def test_registration_procedure(testapp, login_as, parse_latest_mail): @pytest.mark.fun def test_registration_procedure_form_error( - testapp, login_as, parse_latest_mail + testapp, + login_as, # noqa: ARG001 + parse_latest_mail, # noqa: ARG001 ): response = testapp.get("/", status=302).follow() assert "Please Log In" in response @@ -64,7 +66,9 @@ def test_registration_procedure_form_error( @pytest.mark.fun def test_registration_procedure_not_unique_username( - testapp, login_as, parse_latest_mail + testapp, + login_as, # noqa: ARG001 + parse_latest_mail, # noqa: ARG001 ): response = testapp.get("/", status=302).follow() assert "Please Log In" in response @@ -85,7 +89,9 @@ def test_registration_procedure_not_unique_username( @pytest.mark.fun def test_registration_procedure_not_unique_email( - testapp, login_as, parse_latest_mail + testapp, + login_as, # noqa: ARG001 + parse_latest_mail, # noqa: ARG001 ): response = testapp.get("/", status=302).follow() assert "Please Log In" in response @@ -106,7 +112,9 @@ def test_registration_procedure_not_unique_email( @pytest.mark.fun def test_registration_procedure_bad_csrf_token( - testapp, login_as, parse_latest_mail + testapp, + login_as, # noqa: ARG001 + parse_latest_mail, # noqa: ARG001 ): response = testapp.get("/", status=302).follow() assert "Please Log In" in response @@ -126,7 +134,7 @@ def test_registration_procedure_bad_csrf_token( @pytest.mark.fun -def test_registration_procedure_canceled(testapp, login_as, parse_latest_mail): +def test_registration_procedure_canceled(testapp, login_as, parse_latest_mail): # noqa: ARG001 response = testapp.get("/", status=302).follow() assert "Please Log In" in response diff --git a/tests/functional/test_user_edit.py b/tests/functional/test_user_edit.py index c1f572b..a610285 100644 --- a/tests/functional/test_user_edit.py +++ b/tests/functional/test_user_edit.py @@ -100,7 +100,7 @@ def test_user_edit_reset_password(testapp, login_as, parse_latest_mail): @pytest.mark.fun -def test_user_delete(testapp, login_as, parse_latest_mail): +def test_user_delete(testapp, login_as, parse_latest_mail): # noqa: ARG001 response = testapp.get("/", status=302).follow() assert "Please Log In" in response @@ -123,7 +123,7 @@ def test_user_delete(testapp, login_as, parse_latest_mail): @pytest.mark.fun -def test_user_delete_cancel(testapp, login_as, parse_latest_mail): +def test_user_delete_cancel(testapp, login_as, parse_latest_mail): # noqa: ARG001 response = testapp.get("/", status=302).follow() assert "Please Log In" in response @@ -146,7 +146,7 @@ def test_user_delete_cancel(testapp, login_as, parse_latest_mail): @pytest.mark.fun -def test_user_delete_no_confirm(testapp, login_as, parse_latest_mail): +def test_user_delete_no_confirm(testapp, login_as, parse_latest_mail): # noqa: ARG001 response = testapp.get("/", status=302).follow() assert "Please Log In" in response diff --git a/tests/test_adapters.py b/tests/test_adapters.py index 3fe7ae8..6bacfbc 100644 --- a/tests/test_adapters.py +++ b/tests/test_adapters.py @@ -23,7 +23,7 @@ def order_sql(): def test_order_mapper(session, order_sql): - from ordr3.models import OrderItem, OrderStatus, OrderCategory + from ordr3.models import OrderCategory, OrderItem, OrderStatus session.execute(order_sql) expected = [ @@ -119,7 +119,7 @@ def test_user_mapper(session): def test_adapter_behaviour(session): - from ordr3.models import LogEntry, OrderItem, OrderStatus, OrderCategory + from ordr3.models import LogEntry, OrderCategory, OrderItem, OrderStatus order = OrderItem( None, diff --git a/tests/test_models.py b/tests/test_models.py index e014c51..7462894 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -130,7 +130,7 @@ def test_user_init(): assert user.first_name == "C" assert user.last_name == "D" assert user.email == "E" - assert user.password == "F" + assert user.password == "F" # noqa: S105 assert user.role == "G" @@ -197,7 +197,7 @@ def test_password_reset_token_init(): token = PasswordResetToken(*list("ABC")) - assert token.token == "A" + assert token.token == "A" # noqa: S105 assert token.user_id == "B" assert token.valid_until == "C" @@ -209,7 +209,7 @@ def test_password_reset_token_init_auto_validity(): token = PasswordResetToken(*list("AB")) - assert token.token == "A" + assert token.token == "A" # noqa: S105 assert token.user_id == "B" assert token.valid_until - datetime.utcnow() <= timedelta(hours=1) diff --git a/tests/test_ordr3.py b/tests/test_ordr3.py index 0acc5a4..a513094 100644 --- a/tests/test_ordr3.py +++ b/tests/test_ordr3.py @@ -1,4 +1,4 @@ -""" Stub file for testing the project """ +"""Stub file for testing the project""" def test_dummy(): diff --git a/tests/test_repo.py b/tests/test_repo.py index 58688c4..353a05b 100644 --- a/tests/test_repo.py +++ b/tests/test_repo.py @@ -1,11 +1,11 @@ import pytest -@pytest.fixture() +@pytest.fixture def example_order_data(): from datetime import datetime - from ordr3.models import OrderStatus, OrderCategory + from ordr3.models import OrderCategory, OrderStatus return [ ( @@ -43,14 +43,14 @@ def example_order_data(): ] -@pytest.fixture() +@pytest.fixture def example_orders(example_order_data): from ordr3.models import OrderItem return [OrderItem(*data) for data in example_order_data] -@pytest.fixture() +@pytest.fixture def example_consumables(example_order_data): from datetime import datetime, timedelta @@ -67,7 +67,7 @@ def example_consumables(example_order_data): return consumables -@pytest.fixture() +@pytest.fixture def example_users(): from ordr3.models import User, UserRole @@ -77,7 +77,7 @@ def example_users(): ] -@pytest.fixture() +@pytest.fixture def example_tokens(): from datetime import datetime, timedelta @@ -92,7 +92,7 @@ def example_tokens(): ] -@pytest.fixture() +@pytest.fixture def example_vendors(): from ordr3.models import Vendor @@ -105,8 +105,8 @@ def example_vendors(): def test_sql_repo_add_order(session, example_orders): - from ordr3.repo import SqlAlchemyRepository from ordr3.models import OrderItem + from ordr3.repo import SqlAlchemyRepository repo = SqlAlchemyRepository(session) repo.add_order(example_orders[0]) @@ -118,8 +118,8 @@ def test_sql_repo_add_order(session, example_orders): def test_sql_repo_delete_order(session, example_orders): + from ordr3.models import LogEntry, OrderItem, OrderStatus, User from ordr3.repo import SqlAlchemyRepository - from ordr3.models import User, LogEntry, OrderItem, OrderStatus from ordr3.services import create_log_entry repo = SqlAlchemyRepository(session) @@ -162,13 +162,12 @@ def test_sql_repo_get_order_raises_exception(session, example_orders): def test_sql_list_consumable_candidates(session, example_consumables): from datetime import datetime, timedelta - from ordr3.repo import SqlAlchemyRepository from ordr3.models import OrderStatus + from ordr3.repo import SqlAlchemyRepository repo = SqlAlchemyRepository(session) for example in example_consumables: repo.add_order(example) - print(example.id, example.created_on) session.flush() limit_date = datetime.utcnow() - timedelta(days=2 * 365) @@ -181,8 +180,8 @@ def test_sql_list_consumable_candidates(session, example_consumables): def test_sql_repo_add_user(session, example_users): - from ordr3.repo import SqlAlchemyRepository from ordr3.models import User + from ordr3.repo import SqlAlchemyRepository repo = SqlAlchemyRepository(session) repo.add_user(example_users[0]) @@ -194,8 +193,8 @@ def test_sql_repo_add_user(session, example_users): def test_sql_repo_delte_user(session, example_users): - from ordr3.repo import SqlAlchemyRepository from ordr3.models import User + from ordr3.repo import SqlAlchemyRepository repo = SqlAlchemyRepository(session) repo.add_user(example_users[0]) @@ -274,8 +273,8 @@ def test_sql_repo_get_user_by_email_exception(session, example_users): def test_sql_repo_count_new_users(session, example_users): - from ordr3.repo import SqlAlchemyRepository from ordr3.models import UserRole + from ordr3.repo import SqlAlchemyRepository repo = SqlAlchemyRepository(session) example_users[0].role = UserRole.NEW @@ -286,9 +285,9 @@ def test_sql_repo_count_new_users(session, example_users): assert repo.count_new_users() == 1 -def test_sql_search_vendor(session, example_users): - from ordr3.repo import SqlAlchemyRepository +def test_sql_search_vendor(session, example_users): # noqa: ARG001 from ordr3.models import Vendor + from ordr3.repo import SqlAlchemyRepository repo = SqlAlchemyRepository(session) entry = Vendor("sa", "Sigma Aldrich") @@ -300,8 +299,8 @@ def test_sql_search_vendor(session, example_users): def test_sql_get_vendor_aggregates(session, example_vendors): - from ordr3.repo import SqlAlchemyRepository from ordr3.models import VendorAggregate + from ordr3.repo import SqlAlchemyRepository repo = SqlAlchemyRepository(session) session.add_all(example_vendors) @@ -324,8 +323,8 @@ def test_sql_get_vendor_aggregates_raises_error(session): def test_sql_update_vendors(session, example_vendors): - from ordr3.repo import SqlAlchemyRepository from ordr3.models import Vendor, VendorAggregate + from ordr3.repo import SqlAlchemyRepository repo = SqlAlchemyRepository(session) session.add_all(example_vendors) @@ -346,8 +345,8 @@ def test_sql_update_vendors(session, example_vendors): def test_sql_repo_add_reset_token(session, example_tokens): - from ordr3.repo import SqlAlchemyRepository from ordr3.models import PasswordResetToken + from ordr3.repo import SqlAlchemyRepository repo = SqlAlchemyRepository(session) repo.add_reset_token(example_tokens[0]) @@ -359,8 +358,8 @@ def test_sql_repo_add_reset_token(session, example_tokens): def test_sql_repo_delete_reset_token(session, example_tokens): - from ordr3.repo import SqlAlchemyRepository from ordr3.models import PasswordResetToken + from ordr3.repo import SqlAlchemyRepository repo = SqlAlchemyRepository(session) repo.add_reset_token(example_tokens[0]) @@ -398,8 +397,8 @@ def test_sql_repo_get_reset_token_raises_exception(session, example_tokens): def test_sql_clear_stale_reset_tokens(session, example_tokens): - from ordr3.repo import SqlAlchemyRepository from ordr3.models import PasswordResetToken + from ordr3.repo import SqlAlchemyRepository repo = SqlAlchemyRepository(session) repo.add_reset_token(example_tokens[0]) diff --git a/tests/test_services.py b/tests/test_services.py index dd41ee0..6f237f0 100644 --- a/tests/test_services.py +++ b/tests/test_services.py @@ -2,14 +2,14 @@ from datetime import datetime, timedelta import pytest -from ordr3.repo import AbstractOrderRepository from ordr3.models import Vendor, VendorAggregate +from ordr3.repo import AbstractOrderRepository class FakeOrderRepository(AbstractOrderRepository): """Repository implementation for testing""" - def __init__(self, session): + def __init__(self, session): # noqa: ARG002 self._orders = set() self._users = set() self._vendors = set() @@ -104,8 +104,7 @@ class FakePasslibContext: return False, None if self.needs_update: return True, password[::-1] - else: - return True, None + return True, None class FakeEventQueue(list): @@ -117,7 +116,7 @@ class FakeEventQueue(list): def prefilled_repo(): from itertools import count - from ordr3.models import Vendor, OrderItem, OrderStatus + from ordr3.models import OrderItem, OrderStatus, Vendor i = count() catalog = {1: "Ethanol", 2: "Aceton", 3: "NaOH", 4: "Coffee", 5: "Water"} @@ -166,7 +165,7 @@ def test_service_find_consumables(prefilled_repo): def test_create_log_entry_noteworthy(prefilled_repo): - from ordr3.models import User, OrderStatus + from ordr3.models import OrderStatus, User from ordr3.services import create_log_entry order = prefilled_repo.get_order(1) @@ -191,7 +190,7 @@ def test_create_log_entry_noteworthy(prefilled_repo): def test_create_log_entry_not_noteworthy_same_user(prefilled_repo): - from ordr3.models import User, OrderStatus + from ordr3.models import OrderStatus, User from ordr3.services import create_log_entry order = prefilled_repo.get_order(1) @@ -204,7 +203,7 @@ def test_create_log_entry_not_noteworthy_same_user(prefilled_repo): def test_create_log_entry_not_noteworthy_same_status(prefilled_repo): - from ordr3.models import User, OrderStatus + from ordr3.models import OrderStatus, User from ordr3.services import create_log_entry order = prefilled_repo.get_order(1) @@ -216,7 +215,8 @@ def test_create_log_entry_not_noteworthy_same_status(prefilled_repo): @pytest.mark.parametrize( - "update,new_hash", [(False, "1234"), (True, "4321")] # noqa: E231 + "update,new_hash", + [(False, "1234"), (True, "4321")], ) def test_verify_username_and_password_valid(update, new_hash): from ordr3.models import User, UserRole @@ -233,7 +233,8 @@ def test_verify_username_and_password_valid(update, new_hash): @pytest.mark.parametrize( - "name,pwd", [("You", "1234"), ("Me", "abcd")] # noqa: E231 + "name,pwd", + [("You", "1234"), ("Me", "abcd")], ) def test_verify_username_and_password_invalid(name, pwd): from ordr3.models import User, UserRole @@ -289,7 +290,6 @@ def test_check_vendor_name(prefilled_repo, input, name, found): from ordr3.services import check_vendor_name result = check_vendor_name(prefilled_repo, input) - print(prefilled_repo._vendors) assert result.name == name assert result.found == found @@ -369,9 +369,7 @@ def test_set_new_password_breached(monkeypatch): user = User(*list("ABCDEFG")) queue = FakeEventQueue() - monkeypatch.setattr( - services, "_check_have_i_been_pwned", lambda x, y: True - ) + monkeypatch.setattr(services, "_check_have_i_been_pwned", lambda x, y: True) result = services.set_new_password(user, "1234567890123456", queue) assert not result @@ -386,9 +384,7 @@ def test_set_new_password_to_short_and_breached(monkeypatch): user = User(*list("ABCDEFG")) queue = FakeEventQueue() - monkeypatch.setattr( - services, "_check_have_i_been_pwned", lambda x, y: True - ) + monkeypatch.setattr(services, "_check_have_i_been_pwned", lambda x, y: True) result = services.set_new_password(user, "1", queue) assert not result @@ -399,7 +395,7 @@ def test_set_new_password_to_short_and_breached(monkeypatch): def test_get_user_from_reset_token_ok(): from ordr3 import services - from ordr3.models import User, PasswordResetToken + from ordr3.models import PasswordResetToken, User repo = FakeOrderRepository(None) user = User(*list("ABCDEFG")) @@ -414,7 +410,7 @@ def test_get_user_from_reset_token_ok(): def test_get_user_from_reset_token_wrong_token(): from ordr3 import services - from ordr3.models import User, PasswordResetToken + from ordr3.models import PasswordResetToken, User repo = FakeOrderRepository(None) user = User(*list("ABCDEFG")) @@ -431,7 +427,7 @@ def test_get_user_from_reset_token_invalid_token(): from datetime import datetime, timedelta from ordr3 import services - from ordr3.models import User, PasswordResetToken + from ordr3.models import PasswordResetToken, User repo = FakeOrderRepository(None) user = User(*list("ABCDEFG")) @@ -447,7 +443,7 @@ def test_get_user_from_reset_token_invalid_token(): def test_get_user_from_reset_token_unknown_user(): from ordr3 import services - from ordr3.models import User, PasswordResetToken + from ordr3.models import PasswordResetToken, User repo = FakeOrderRepository(None) user = User(*list("ABCDEFG")) @@ -461,7 +457,7 @@ def test_get_user_from_reset_token_unknown_user(): def test_create_token_for_user(): - from ordr3.models import User, PasswordResetToken + from ordr3.models import PasswordResetToken, User from ordr3.services import create_token_for_user repo = FakeOrderRepository(None)