Skip to content

Commit

Permalink
Add Ruff
Browse files Browse the repository at this point in the history
  • Loading branch information
sbrunner committed Dec 3, 2024
1 parent 0dc34bd commit adaaf30
Show file tree
Hide file tree
Showing 108 changed files with 861 additions and 830 deletions.
31 changes: 0 additions & 31 deletions .bandit.yaml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
# When we upgrade this we should also upgrade the requirements
# in the documentation: doc/integrator/requirements.rst
# and the first pyupgrade pre-commit hook in .pre-commit-config.yaml
MIN_PYTHON_VERSION: '3.8'
MIN_PYTHON_VERSION: '3.10'

steps:
- run: '! ls BACKPORT_TODO'
Expand Down
54 changes: 7 additions & 47 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,64 +104,24 @@ repos:
docker/config/haproxy_dev/localhost\.pem
|geoportal/c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter\.project}}/mapserver/data/TM_EUROPE_BORDERS-0.3\.sql
)$
- repo: https://github.com/asottile/pyupgrade
rev: v3.19.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.8.1
hooks:
# The script that will run on the project host
- id: pyupgrade
- id: ruff-format
args:
- --py38-plus
files: |-
(?x)^(
geoportal/c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter\.project}}/(build
|scripts/.*)
|scripts/(get-version
|upgrade)
)$
# All other
- id: pyupgrade
args:
- --py310-plus
# geoportal/c2cgeoportal_geoportal/views/theme\.py is present because of issue:
# https://bugs.launchpad.net/lxml/+bug/2079018
exclude: |-
(?x)^(
geoportal/c2cgeoportal_geoportal/scaffolds/create/{{cookiecutter\.project}}/(build
|scripts/.*)
|scripts/(get-version
|upgrade)
|geoportal/c2cgeoportal_geoportal/views/theme\.py
)$
- repo: https://github.com/PyCQA/autoflake
rev: v2.3.1
hooks:
- id: autoflake
- repo: https://github.com/PyCQA/isort
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 24.10.0
hooks:
- id: black
exclude: |-
(?x)^(
commons/c2cgeoportal_commons/alembic/script\.py\.mako
|.*\.rst
|.*\.rst\.tmpl
|geoportal/c2cgeoportal_geoportal/scaffolds/advance_create/{{cookiecutter.project}}/geoportal/{{cookiecutter.package}}_geoportal/__init__\.py
)$
- --line-length=110
- repo: https://github.com/PyCQA/prospector
rev: v1.13.3
hooks:
- id: prospector
args:
- --tool=pydocstyle
- --tool=ruff
- --die-on-tool-error
- --output-format=pylint
additional_dependencies:
- prospector-profile-duplicated==1.8.0 # pypi
- prospector-profile-duplicated==1.8.1 # pypi
- prospector-profile-utils==1.13.0 # pypi
- ruff==0.8.1 # pypi
- repo: https://github.com/sbrunner/jsonschema-validator
rev: 0.3.2
hooks:
Expand Down
30 changes: 9 additions & 21 deletions .prospector.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,35 +3,23 @@ inherits:
- utils:base
- utils:fix
- utils:no-design-checks
- utils:unsafe
- utils:c2cwsgiutils

ignore-paths:
- commons/setup.py
- geoportal/setup.py
- admin/setup.py
- geoportal/c2cgeoportal_geoportal/scaffolds
- docker/qgisserver
- commons/c2cgeoportal_commons/alembic/main
- commons/c2cgeoportal_commons/alembic/static

pycodestyle:
disable:
# Buggy checks with Python 3.12
- W604 # backticks are deprecated, use 'repr()'
- W603 # '<>' is deprecated, use '!='
- E702 # multiple statements on one line (semicolon)
- E713 # test for membership should be 'not in'
mypy:
options:
python_version: '3.10'

pydocstyle:
ruff:
disable:
- D102 # Missing docstring in public method
- D104 # Missing docstring in public package
- D105 # Missing docstring in magic method
- D107 # Missing docstring in __init__
- D200 # One-line docstring should fit on one line with quotes
- D202 # No blank lines allowed after function docstring (found 1)
- D203 # 1 blank line required before class docstring (found 0)
- D212 # Multi-line docstring summary should start at the first line
- D407 # Missing dashed underline after section ('Arguments')
- D412 # No blank lines allowed between a section header and its content ('Arguments')

bandit:
options:
config: .bandit.yaml
- D107 # Missing docstring in `__init__`
4 changes: 3 additions & 1 deletion admin/c2cgeoportal_admin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ def get_tm_session(
)

# Add fake user as we do not have authentication from geoportal
from c2cgeoportal_commons.models.static import User # pylint: disable=import-outside-toplevel
from c2cgeoportal_commons.models.static import ( # pylint: disable=import-outside-toplevel
User,
)

config.add_request_method(
lambda request: User(
Expand Down
15 changes: 7 additions & 8 deletions admin/c2cgeoportal_admin/lib/ogcserver_synchronizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,15 @@
import functools
import logging
from io import StringIO
from typing import Any, Optional, cast
from typing import Any, cast
from xml.etree.ElementTree import Element # nosec

import pyramid.request
import requests
from defusedxml import ElementTree
from sqlalchemy.orm.session import Session

from c2cgeoportal_commons.lib.url import get_url2
from c2cgeoportal_commons.models import main
from defusedxml import ElementTree
from sqlalchemy.orm.session import Session


class dry_run_transaction: # noqa ignore=N801: class names should use CapWords convention
Expand Down Expand Up @@ -238,7 +237,7 @@ def get_theme(self, el: ElementTree) -> main.Theme:
name = name_el.text

theme = cast(
Optional[main.Theme],
main.Theme | None,
self._request.dbsession.query(main.Theme).filter(main.Theme.name == name).one_or_none(),
)

Expand All @@ -263,7 +262,7 @@ def get_layer_group(self, el: Element, parent: main.TreeGroup) -> main.LayerGrou
assert name is not None

group = cast(
Optional[main.LayerGroup],
main.LayerGroup | None,
(
self._request.dbsession.query(main.LayerGroup)
.filter(main.LayerGroup.name == name)
Expand Down Expand Up @@ -294,7 +293,7 @@ def get_layer_wms(self, el: Element, parent: main.TreeGroup | None = None) -> ma
assert name is not None

layer = cast(
Optional[main.LayerWMS],
main.LayerWMS | None,
self._request.dbsession.query(main.LayerWMS).filter(main.LayerWMS.name == name).one_or_none(),
)

Expand Down Expand Up @@ -358,7 +357,7 @@ def get_layer_wms(self, el: Element, parent: main.TreeGroup | None = None) -> ma

return layer

@functools.lru_cache(maxsize=10)
@functools.lru_cache(maxsize=10) # noqa: B019
def wms_capabilities(self) -> bytes:
errors: set[str] = set()
url = get_url2(
Expand Down
3 changes: 1 addition & 2 deletions admin/c2cgeoportal_admin/schemas/dimensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,10 @@

import colander
from c2cgeoform.schema import GeoFormSchemaNode
from c2cgeoportal_commons.models.main import Dimension
from deform.widget import MappingWidget, SequenceWidget
from sqlalchemy.orm.attributes import InstrumentedAttribute

from c2cgeoportal_commons.models.main import Dimension


def dimensions_schema_node(
prop: InstrumentedAttribute[Any], # pylint: disable=unsubscriptable-object
Expand Down
4 changes: 1 addition & 3 deletions admin/c2cgeoportal_admin/schemas/functionalities.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,11 @@
import colander
from c2cgeoform.ext.deform_ext import RelationCheckBoxListWidget
from c2cgeoform.schema import GeoFormManyToManySchemaNode, manytomany_validator
from c2cgeoportal_commons.models.main import Functionality
from sqlalchemy import inspect, select
from sqlalchemy.orm.attributes import InstrumentedAttribute
from sqlalchemy.sql.functions import concat

from c2cgeoportal_commons.models.main import Functionality


def available_functionalities_for(settings: dict[str, Any], model: type[Any]) -> list[dict[str, Any]]:
"""Return filtered list of functionality definitions."""
Expand Down Expand Up @@ -81,7 +80,6 @@ def functionalities_schema_node(
prop: InstrumentedAttribute[Any], model: type[Any]
) -> colander.SequenceSchema:
"""Get the schema of the functionalities."""

return colander.SequenceSchema(
GeoFormManyToManySchemaNode(Functionality, None),
name=prop.key,
Expand Down
3 changes: 1 addition & 2 deletions admin/c2cgeoportal_admin/schemas/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@
import colander
from c2cgeoform.ext.deform_ext import RelationCheckBoxListWidget
from c2cgeoform.schema import GeoFormManyToManySchemaNode, manytomany_validator
from sqlalchemy.orm.attributes import InstrumentedAttribute

from c2cgeoportal_commons.models.main import Interface
from sqlalchemy.orm.attributes import InstrumentedAttribute


def interfaces_schema_node(
Expand Down
5 changes: 2 additions & 3 deletions admin/c2cgeoportal_admin/schemas/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@
import colander
import pyramid.request
from c2cgeoform.schema import GeoFormSchemaNode
from c2cgeoportal_commons.lib.validators import url
from c2cgeoportal_commons.models.main import Metadata
from deform.widget import MappingWidget, SelectWidget, SequenceWidget, TextAreaWidget
from sqlalchemy import inspect
from sqlalchemy.orm.attributes import InstrumentedAttribute
from sqlalchemy.orm.mapper import Mapper

from c2cgeoportal_admin import _
from c2cgeoportal_commons.lib.validators import url
from c2cgeoportal_commons.models.main import Metadata


def get_relevant_for(model: type[Any] | Mapper[Any]) -> set[str]:
Expand Down Expand Up @@ -202,7 +202,6 @@ def _translate_available_metadata(

def metadata_schema_node(prop: InstrumentedAttribute[Any], model: type[Any]) -> colander.SequenceSchema:
"""Get the schema of a collection of metadata."""

# Deferred which returns a dictionary with metadata name as key and metadata definition as value.
# Needed to get the metadata types on UI side.
metadata_definitions_dict = colander.deferred(
Expand Down
3 changes: 1 addition & 2 deletions admin/c2cgeoportal_admin/schemas/restriction_areas.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@
import colander
from c2cgeoform.ext.deform_ext import RelationCheckBoxListWidget
from c2cgeoform.schema import GeoFormManyToManySchemaNode, manytomany_validator
from sqlalchemy.orm.attributes import InstrumentedAttribute

from c2cgeoportal_commons.models.main import RestrictionArea
from sqlalchemy.orm.attributes import InstrumentedAttribute


def restrictionareas_schema_node(
Expand Down
3 changes: 1 addition & 2 deletions admin/c2cgeoportal_admin/schemas/roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,8 @@
import colander
from c2cgeoform.ext.deform_ext import RelationCheckBoxListWidget
from c2cgeoform.schema import GeoFormManyToManySchemaNode, manytomany_validator
from sqlalchemy.orm.attributes import InstrumentedAttribute

from c2cgeoportal_commons.models.main import Role
from sqlalchemy.orm.attributes import InstrumentedAttribute


def roles_schema_node(
Expand Down
9 changes: 5 additions & 4 deletions admin/c2cgeoportal_admin/schemas/treegroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@
import pyramid.request
import sqlalchemy
from c2cgeoform.schema import GeoFormSchemaNode
from c2cgeoportal_commons.lib.literal import Literal
from c2cgeoportal_commons.models.main import LayergroupTreeitem, TreeGroup, TreeItem
from sqlalchemy.orm import aliased
from sqlalchemy.sql.expression import case, func

from c2cgeoportal_admin import _
from c2cgeoportal_admin.widgets import ChildrenWidget, ChildWidget
from c2cgeoportal_commons.lib.literal import Literal
from c2cgeoportal_commons.models.main import LayergroupTreeitem, TreeGroup, TreeItem

_LOG = logging.getLogger(__name__)

Expand Down Expand Up @@ -74,7 +74,8 @@ def treeitems(
assert isinstance(dbsession, sqlalchemy.orm.Session)

group = case(
(func.count(LayergroupTreeitem.id) == 0, "Unlinked"), else_="Others" # pylint: disable=not-callable
(func.count(LayergroupTreeitem.id) == 0, "Unlinked"), # pylint: disable=not-callable
else_="Others",
)

query = (
Expand Down Expand Up @@ -123,7 +124,7 @@ def treeitems(
def children_validator(node, cstruct):
"""Get the validator on the children nodes."""
for dict_ in cstruct:
if not dict_["treeitem_id"] in [item["id"] for item in node.candidates]:
if dict_["treeitem_id"] not in [item["id"] for item in node.candidates]:
raise colander.Invalid(
node,
_("Value {} does not exist in table {} or is not allowed to avoid cycles").format(
Expand Down
4 changes: 1 addition & 3 deletions admin/c2cgeoportal_admin/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@


class IsAdminPredicate:
"""
A custom predicate that checks if the request is for the admin interface.
"""
"""A custom predicate that checks if the request is for the admin interface."""

def __init__(self, val, info):
del info
Expand Down
2 changes: 1 addition & 1 deletion admin/c2cgeoportal_admin/views/dimension_layers.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@

import sqlalchemy.orm.query
from c2cgeoform.views.abstract_views import ListField
from c2cgeoportal_commons.models.main import DimensionLayer
from sqlalchemy.orm import subqueryload

from c2cgeoportal_admin.views.layers import LayerViews
from c2cgeoportal_commons.models.main import DimensionLayer

_list_field = partial(ListField, DimensionLayer)

Expand Down
Loading

0 comments on commit adaaf30

Please sign in to comment.