3
0
Fork 0

Compare commits

..

4 commits

23 changed files with 127 additions and 63 deletions

View file

@ -36,8 +36,3 @@ disable=fixme,
ungrouped-imports,
unidiomatic-typecheck,
unnecessary-comprehension,
unnecessary-lambda,
unnecessary-lambda-assignment,
unspecified-encoding,
unused-argument,
use-a-generator,

View file

@ -52,7 +52,7 @@ class WebAppProvider(AppProvider):
email_modules = ["wuttaweb.emails"]
email_templates = ["wuttaweb:email-templates"]
def get_web_handler(self, **kwargs):
def get_web_handler(self):
"""
Get the configured "web" handler for the app.
@ -167,7 +167,7 @@ def make_pyramid_config(settings):
return pyramid_config
def main(global_config, **settings):
def main(global_config, **settings): # pylint: disable=unused-argument
"""
Make and return the WSGI application, per given settings.

View file

@ -137,7 +137,7 @@ class WuttaSecurityPolicy:
def forget(self, request, **kw):
return self.session_helper.forget(request, **kw)
def permits(self, request, context, permission):
def permits(self, request, context, permission): # pylint: disable=unused-argument
# nb. root user can do anything
if getattr(request, "is_root", False):

View file

@ -35,7 +35,7 @@ from wuttjamaican.cli import wutta_typer
@wutta_typer.command()
def webapp(
def webapp( # pylint: disable=unused-argument
ctx: typer.Context,
auto_reload: Annotated[
bool,

View file

@ -982,7 +982,7 @@ class Form: # pylint: disable=too-many-instance-attributes
output = render(template, context)
return HTML.literal(output)
def render_vue_field(
def render_vue_field( # pylint: disable=unused-argument
self,
fieldname,
readonly=None,

View file

@ -352,7 +352,9 @@ class ObjectRef(colander.SchemaType):
"""
return obj.uuid.hex
def deserialize(self, node, cstruct): # pylint: disable=empty-docstring
def deserialize( # pylint: disable=empty-docstring,unused-argument
self, node, cstruct
):
""" """
if not cstruct:
return colander.null

View file

@ -438,7 +438,9 @@ class RoleRefsWidget(WuttaCheckboxChoiceWidget):
kw["roles"] = roles
# url
url = lambda role: self.request.route_url("roles.view", uuid=role.uuid)
def url(role):
return self.request.route_url("roles.view", uuid=role.uuid)
kw["url"] = url
# default logic from here

View file

@ -835,7 +835,7 @@ class Grid: # pylint: disable=too-many-instance-attributes
This will normalize the list/dict to desired internal format.
"""
if tools and isinstance(tools, list):
if not any([isinstance(t, (tuple, list)) for t in tools]):
if not any(isinstance(t, (tuple, list)) for t in tools):
tools = [(self.app.make_uuid(), t) for t in tools]
self.tools = OrderedDict(tools or [])
@ -1058,13 +1058,27 @@ class Grid: # pylint: disable=too-many-instance-attributes
# TODO: may need this for String etc. as well?
if isinstance(model_property.type, sa.Text):
if foldcase:
kfunc = lambda obj: (obj[key] or "").lower()
def kfunc_folded(obj):
return (obj[key] or "").lower()
kfunc = kfunc_folded
else:
kfunc = lambda obj: obj[key] or ""
def kfunc_standard(obj):
return obj[key] or ""
kfunc = kfunc_standard
if not kfunc:
# nb. sorting with this can raise error if data
# contains varying types, e.g. str and None
kfunc = lambda obj: obj[key]
def kfunc_fallback(obj):
return obj[key]
kfunc = kfunc_fallback
# then sort the data and return
return sorted(data, key=kfunc, reverse=direction == "desc")
@ -1738,7 +1752,7 @@ class Grid: # pylint: disable=too-many-instance-attributes
raise ValueError(f"invalid dest identifier: {dest}")
# func to save a setting value to user session
def persist(key, value=lambda k: settings.get(k)):
def persist(key, value=settings.get):
assert dest == "session"
skey = f"grid.{self.key}.{key}"
self.request.session[skey] = value(key)
@ -1932,7 +1946,7 @@ class Grid: # pylint: disable=too-many-instance-attributes
# rendering methods
##############################
def render_batch_id(self, obj, key, value):
def render_batch_id(self, obj, key, value): # pylint: disable=unused-argument
"""
Column renderer for batch ID values.
@ -1946,7 +1960,7 @@ class Grid: # pylint: disable=too-many-instance-attributes
batch_id = int(value)
return f"{batch_id:08d}"
def render_boolean(self, obj, key, value):
def render_boolean(self, obj, key, value): # pylint: disable=unused-argument
"""
Column renderer for boolean values.
@ -1961,7 +1975,9 @@ class Grid: # pylint: disable=too-many-instance-attributes
"""
return self.app.render_boolean(value)
def render_currency(self, obj, key, value, **kwargs):
def render_currency( # pylint: disable=unused-argument
self, obj, key, value, **kwargs
):
"""
Column renderer for currency values.
@ -1976,7 +1992,7 @@ class Grid: # pylint: disable=too-many-instance-attributes
"""
return self.app.render_currency(value, **kwargs)
def render_date(self, obj, key, value):
def render_date(self, obj, key, value): # pylint: disable=unused-argument
"""
Column renderer for :class:`python:datetime.date` values.
@ -1992,7 +2008,7 @@ class Grid: # pylint: disable=too-many-instance-attributes
dt = getattr(obj, key)
return self.app.render_date(dt)
def render_datetime(self, obj, key, value):
def render_datetime(self, obj, key, value): # pylint: disable=unused-argument
"""
Column renderer for :class:`python:datetime.datetime` values.
@ -2035,7 +2051,9 @@ class Grid: # pylint: disable=too-many-instance-attributes
return value
def render_percent(self, obj, key, value, **kwargs):
def render_percent( # pylint: disable=unused-argument
self, obj, key, value, **kwargs
):
"""
Column renderer for percentage values.
@ -2049,7 +2067,7 @@ class Grid: # pylint: disable=too-many-instance-attributes
"""
return self.app.render_percent(value, **kwargs)
def render_quantity(self, obj, key, value):
def render_quantity(self, obj, key, value): # pylint: disable=unused-argument
"""
Column renderer for quantity values.

View file

@ -380,7 +380,7 @@ class GridFilter: # pylint: disable=too-many-instance-attributes
# invoke filter method
return func(data, value)
def filter_is_any(self, data, value):
def filter_is_any(self, data, value): # pylint: disable=unused-argument
"""
This is a no-op which always ignores the value and returns the
data as-is.
@ -487,13 +487,13 @@ class AlchemyFilter(GridFilter):
return query
return query.filter(self.model_property <= value)
def filter_is_null(self, query, value):
def filter_is_null(self, query, value): # pylint: disable=unused-argument
"""
Filter data with an ``IS NULL`` query. The value is ignored.
"""
return query.filter(self.model_property == None)
def filter_is_not_null(self, query, value):
def filter_is_not_null(self, query, value): # pylint: disable=unused-argument
"""
Filter data with an ``IS NOT NULL`` query. The value is
ignored.
@ -623,21 +623,21 @@ class BooleanAlchemyFilter(AlchemyFilter):
return bool(value)
return None
def filter_is_true(self, query, value):
def filter_is_true(self, query, value): # pylint: disable=unused-argument
"""
Filter data with an "is true" condition. The value is
ignored.
"""
return query.filter(self.model_property == True)
def filter_is_false(self, query, value):
def filter_is_false(self, query, value): # pylint: disable=unused-argument
"""
Filter data with an "is false" condition. The value is
ignored.
"""
return query.filter(self.model_property == False)
def filter_is_false_null(self, query, value):
def filter_is_false_null(self, query, value): # pylint: disable=unused-argument
"""
Filter data with "is false or null" condition. The value is
ignored.

View file

@ -107,7 +107,7 @@ class WebHandler(GenericHandler):
return url
return self.get_fanstatic_url(request, static.logo)
def get_menu_handler(self, **kwargs):
def get_menu_handler(self):
"""
Get the configured :term:`menu handler` for the web app.

View file

@ -89,7 +89,7 @@ class MenuHandler(GenericHandler):
# default menu definitions
##############################
def make_menus(self, request, **kwargs):
def make_menus(self, request):
"""
Generate the full set of menus for the app.
@ -109,7 +109,7 @@ class MenuHandler(GenericHandler):
self.make_admin_menu(request),
]
def make_people_menu(self, request, **kwargs):
def make_people_menu(self, request): # pylint: disable=unused-argument
"""
Generate a typical People menu.
@ -132,7 +132,7 @@ class MenuHandler(GenericHandler):
],
}
def make_admin_menu(self, request, **kwargs):
def make_admin_menu(self, request, **kwargs): # pylint: disable=unused-argument
"""
Generate a typical Admin menu.

View file

@ -76,7 +76,7 @@ class WebTestCase(DataTestCase):
event = MagicMock(request=self.request)
subscribers.new_request(event)
def user_getter(request, **kwargs):
def user_getter(request, **kwargs): # pylint: disable=unused-argument
pass
subscribers.new_request_set_user(

View file

@ -54,7 +54,7 @@ class View:
Reference to the app :term:`config object`.
"""
def __init__(self, request, context=None):
def __init__(self, request, context=None): # pylint: disable=unused-argument
self.request = request
self.config = self.request.wutta_config
self.app = self.config.get_app()

View file

@ -144,7 +144,9 @@ class BatchMasterView(MasterView):
# description
g.set_link("description")
def render_batch_id(self, batch, key, value): # pylint: disable=empty-docstring
def render_batch_id( # pylint: disable=empty-docstring,unused-argument
self, batch, key, value
):
""" """
if value:
batch_id = int(value)
@ -406,7 +408,9 @@ class BatchMasterView(MasterView):
g.set_renderer("status_code", self.render_row_status)
def render_row_status(self, row, key, value): # pylint: disable=empty-docstring
def render_row_status( # pylint: disable=empty-docstring,unused-argument
self, row, key, value
):
""" """
return row.STATUS.get(value, value)

View file

@ -122,7 +122,9 @@ class EmailSettingView(MasterView):
# to
g.set_renderer("to", self.render_to_short)
def render_to_short(self, setting, field, value): # pylint: disable=empty-docstring
def render_to_short( # pylint: disable=empty-docstring,unused-argument
self, setting, field, value
):
""" """
recips = value
if not recips:

View file

@ -42,7 +42,9 @@ That will in turn include the following modules:
def defaults(config, **kwargs):
mod = lambda spec: kwargs.get(spec, spec)
def mod(spec):
return kwargs.get(spec, spec)
config.include(mod("wuttaweb.views.common"))
config.include(mod("wuttaweb.views.auth"))

View file

@ -814,7 +814,7 @@ class MasterView(View):
return self.render_progress(progress)
def delete_bulk_thread( # pylint: disable=empty-docstring
self, query, success_url=None, progress=None
self, query, progress=None
):
""" """
model_title_plural = self.get_model_title_plural()
@ -859,7 +859,7 @@ class MasterView(View):
"""
model_title_plural = self.get_model_title_plural()
def delete(obj, i):
def delete(obj, i): # pylint: disable=unused-argument
if self.is_deletable(obj):
self.delete_instance(obj)
@ -1440,7 +1440,7 @@ class MasterView(View):
# grid rendering methods
##############################
def grid_render_bool(self, record, key, value):
def grid_render_bool(self, record, key, value): # pylint: disable=unused-argument
"""
Custom grid value renderer for "boolean" fields.
@ -1537,7 +1537,9 @@ class MasterView(View):
return value
def grid_render_notes(self, record, key, value, maxlen=100):
def grid_render_notes( # pylint: disable=unused-argument
self, record, key, value, maxlen=100
):
"""
Custom grid value renderer for "notes" fields.
@ -1694,7 +1696,7 @@ class MasterView(View):
return button
def get_xref_buttons(self, obj):
def get_xref_buttons(self, obj): # pylint: disable=unused-argument
"""
Should return a list of "cross-reference" buttons to be shown
when viewing the given object.
@ -2078,7 +2080,9 @@ class MasterView(View):
return self.grid_columns
return None
def get_grid_data(self, columns=None, session=None):
def get_grid_data( # pylint: disable=unused-argument
self, columns=None, session=None
):
"""
Returns the grid data for the :meth:`index()` view.
@ -2268,7 +2272,7 @@ class MasterView(View):
route_prefix = self.get_route_prefix()
return self.request.route_url(f"{route_prefix}.{action}", **kw)
def get_action_url_view(self, obj, i):
def get_action_url_view(self, obj, i): # pylint: disable=unused-argument
"""
Returns the "view" grid action URL for the given object.
@ -2279,7 +2283,7 @@ class MasterView(View):
"""
return self.get_action_url("view", obj)
def get_action_url_edit(self, obj, i):
def get_action_url_edit(self, obj, i): # pylint: disable=unused-argument
"""
Returns the "edit" grid action URL for the given object, if
applicable.
@ -2296,7 +2300,7 @@ class MasterView(View):
return self.get_action_url("edit", obj)
return None
def get_action_url_delete(self, obj, i):
def get_action_url_delete(self, obj, i): # pylint: disable=unused-argument
"""
Returns the "delete" grid action URL for the given object, if
applicable.
@ -2313,7 +2317,7 @@ class MasterView(View):
return self.get_action_url("delete", obj)
return None
def is_editable(self, obj):
def is_editable(self, obj): # pylint: disable=unused-argument
"""
Returns a boolean indicating whether "edit" should be allowed
for the given model instance (and for current user).
@ -2326,7 +2330,7 @@ class MasterView(View):
"""
return True
def is_deletable(self, obj):
def is_deletable(self, obj): # pylint: disable=unused-argument
"""
Returns a boolean indicating whether "delete" should be
allowed for the given model instance (and for current user).
@ -2807,7 +2811,7 @@ class MasterView(View):
[
prop.key
for prop in inspector.column_attrs
if all([col.name in keys for col in prop.columns])
if all(col.name in keys for col in prop.columns)
]
)

View file

@ -119,13 +119,19 @@ class PersonView(MasterView):
)
if self.request.has_perm("users.view"):
url = lambda user, i: self.request.route_url("users.view", uuid=user.uuid)
grid.add_action("view", icon="eye", url=url)
def view_url(user, i): # pylint: disable=unused-argument
return self.request.route_url("users.view", uuid=user.uuid)
grid.add_action("view", icon="eye", url=view_url)
grid.set_link("username")
if self.request.has_perm("users.edit"):
url = lambda user, i: self.request.route_url("users.edit", uuid=user.uuid)
grid.add_action("edit", url=url)
def edit_url(user, i): # pylint: disable=unused-argument
return self.request.route_url("users.edit", uuid=user.uuid)
grid.add_action("edit", url=edit_url)
return grid

View file

@ -160,14 +160,20 @@ class RoleView(MasterView):
)
if self.request.has_perm("users.view"):
url = lambda user, i: self.request.route_url("users.view", uuid=user.uuid)
grid.add_action("view", icon="eye", url=url)
def view_url(user, i): # pylint: disable=unused-argument
return self.request.route_url("users.view", uuid=user.uuid)
grid.add_action("view", icon="eye", url=view_url)
grid.set_link("person")
grid.set_link("username")
if self.request.has_perm("users.edit"):
url = lambda user, i: self.request.route_url("users.edit", uuid=user.uuid)
grid.add_action("edit", url=url)
def edit_url(user, i): # pylint: disable=unused-argument
return self.request.route_url("users.edit", uuid=user.uuid)
grid.add_action("edit", url=edit_url)
return grid

View file

@ -110,7 +110,9 @@ class UpgradeView(MasterView):
)
g.set_filter("executed_by", Executor.username, label="Executed By Username")
def grid_row_class(self, upgrade, data, i): # pylint: disable=empty-docstring
def grid_row_class( # pylint: disable=empty-docstring,unused-argument
self, upgrade, data, i
):
""" """
enum = self.app.enum
if upgrade.status == enum.UpgradeStatus.EXECUTING:
@ -321,7 +323,7 @@ class UpgradeView(MasterView):
size = os.path.getsize(path) - offset
if size > 0:
# with open(path, 'rb') as f:
with open(path) as f:
with open(path, "rt", encoding="utf_8") as f:
f.seek(offset)
chunk = f.read(size)
# data['stdout'] = chunk.decode('utf8').replace('\n', '<br />')

View file

@ -98,7 +98,9 @@ class UserView(MasterView):
g.set_sorter("person", model.Person.full_name)
g.set_filter("person", model.Person.full_name, label="Person Full Name")
def grid_row_class(self, user, data, i): # pylint: disable=empty-docstring
def grid_row_class( # pylint: disable=empty-docstring,unused-argument
self, user, data, i
):
""" """
if not user.active:
return "has-background-warning"

View file

@ -54,9 +54,15 @@ class TestPersonView(WebTestCase):
self.assertIsInstance(form.widgets["users"], GridWidget)
def test_make_users_grid(self):
self.pyramid_config.add_route("users.view", "/users/{uuid}/view")
self.pyramid_config.add_route("users.edit", "/users/{uuid}/edit")
model = self.app.model
view = self.make_view()
person = model.Person(full_name="John Doe")
self.session.add(person)
user = model.User(username="john", person=person)
self.session.add(user)
self.session.commit()
# basic
grid = view.make_users_grid(person)
@ -73,6 +79,9 @@ class TestPersonView(WebTestCase):
self.assertEqual(grid.actions[0].key, "view")
self.assertEqual(grid.actions[1].key, "edit")
# render grid to ensure coverage for link urls
grid.render_vue_template()
def test_objectify(self):
model = self.app.model
view = self.make_view()

View file

@ -95,9 +95,16 @@ class TestRoleView(WebTestCase):
self.assertIsNotNone(form.validators["name"])
def test_make_users_grid(self):
self.pyramid_config.add_route("users.view", "/users/{uuid}/view")
self.pyramid_config.add_route("users.edit", "/users/{uuid}/edit")
model = self.app.model
view = self.make_view()
role = model.Role(name="Manager")
self.session.add(role)
user = model.User(username="freddie")
user.roles.append(role)
self.session.add(user)
self.session.commit()
# basic
grid = view.make_users_grid(role)
@ -115,6 +122,9 @@ class TestRoleView(WebTestCase):
self.assertEqual(grid.actions[0].key, "view")
self.assertEqual(grid.actions[1].key, "edit")
# render grid to ensure coverage for link urls
grid.render_vue_template()
def test_unique_name(self):
model = self.app.model
view = self.make_view()