Custom python linters¶
See: Notion page ⧉
NoQA codes¶
ALN002¶
Checks that we don't import components in shared
ALN004¶
Checks that we don't import apps in shared
ALN009¶
Checks that models do not import business logic
ALN010¶
UUID foreign keys must be called as UUID(as_uuid=True)
ALN011¶
cache.memoize() must always have a timeout argument to make them eligible for eviction by our current redis policy"
ALN014¶
Checks that modification of attributes, or instantiation of policies, enrollments, employments and exemptions are only done inside the fr health insurance affiliation component only
ALN015¶
Checks that we don't call legacy user lifecycle functions
ALN016¶
logger can't use keyword arguments
ALN017¶
Do not use top of file imports for business_logic or services in controllers, admin_tools or models, unless for typing. See this Notion page : https://www.notion.so/alaninsurance/Imports-and-start-up-time-WIP-5495c8713847434986ef03ad09158bf1 ⧉
ALN018¶
Do not put python code to init files. It's executed when the module is loaded, it can generate weird side effects, and slow the loading of the application
ALN021¶
Foreign keys must use models, not string. See this Notion page : https://www.notion.so/alaninsurance/Imports-5495c8713847434986ef03ad09158bf1 ⧉
ALN023¶
Do not use top of file imports for #{nice_output}, they are slow to load and make the app starts slower
ALN024¶
Single health contract is deprecated: a company can have multiple contracts. Prefer using company.contracts.
ALN025¶
Prevents prevoyance_claim_management to import claim_management
ALN026¶
Prevents claim_management to import prevoyance_claim_management
ALN027¶
This class checks that no protected attribute access is used.
ALN030¶
@command_XXX must be after @XXX.command
ALN032¶
Checks module names
ALN034¶
While the shareable feature code lives in fr_api, you should consider it as a standalone feature and not as a part of Alan France. You should avoid imports from other features and other modules of apps/fr_api. See https://www.notion.so/alaninsurance/Building-shareable-features-0c4a2681e88d4b8c8e68aaaf66794e99 ⧉",
ALN036¶
URL or URI parameters can lead to Server Side Request Forgery (SSRF) attacks. Attackers could get the server to make requests to an unintended location, which could lead to unauthorized actions or access to data within the network. https://cheatsheetseries.owasp.org/cheatsheets/Server_Side_Request_Forgery_Prevention_Cheat_Sheet.html ⧉
ALN037¶
@property are not serialized by dataclass_json. If not a problem for your use case, please ignore (# noqa: ALN037). "See this Notion page: https://www.notion.so/alaninsurance/Dataclass-the-good-parts-8f387ec2a8e24a55af294237b97dc210#a611a9154af448a38e552c61415169df ⧉
ALN038¶
ALN038: Calling tracer.{func_name} directly is not allowed. Please use shared.helpers.tracing.tag_current_request_root_span instead. Refer to https://www.notion.so/alaninsurance/Performance-Monitoring-APM-50bda306a47446a3912cc1eb10977335#25eb69a5452040d68f512f2cded9970b ⧉ to understand why in more details.
ALN039¶
The module public cannot import other components (or from apps/), it's meant to be the public interface of the component #{self.component_name}, see: https://www.notion.so/alaninsurance/Modular-monolith-a9d84f1318d34115bbd08b3648e5a587 ⧉",
ALN041¶
As the model '{node.name}' is in a component it must be part of specific schema that is declared in components/{self.component_name}/models/helpers.py",
ALN042¶
1/n or n/1 relationships must define an explicit 'order_by' clause.
ALN043¶
You can only import things from a Component public module, see: https://www.notion.so/alaninsurance/Modular-monolith-a9d84f1318d34115bbd08b3648e5a587 ⧉",
ALN045¶
HealthContract.query should not be called directly outside from the contracts_management/ module.
Please check the guidelines: https://www.notion.so/alaninsurance/Contract-management-module-WIP-405f318eae714430a9e29ce40b2811bb?pvs=4#0ea62ff6f41148c5a385f7bc94a6b250 ⧉
ALN046¶
to use owner_only strategy the class must be wrapped with the @with_ownership decorator
ALN047¶
ForeignKey columns must be indexed. Please add index=True to the Column definition and make sure the migration is created
ALN049¶
app is a globally shared fixture with the same controllers as the production one, registering blueprints will impact other tests
ALN051¶
Check that we use isodate_field(), optional_isodate_field(), isodatetime_field() and optional_isodatetime_field() in json dataclasses for es/be/ca apps
ALN053¶
Importing a model at the top of load_all_models is not allowed as it can break the versioning manager. All imports should be made in the load_all_models method after the versioning manager call.
ALN054¶
Migrations should not raise exceptions. Please update raise_when_too_many_locks to False before committing
ALN055¶
Files containing tests should be prefixed with 'test_' or tests won't run!
ALN056¶
freeze_time as a function decorator isn't working well with pytest, you should convert it to a context manager
ALN057¶
Don't use context managers (aka with xxx) with mocker in pytest. They do not work as expected.
ALN058¶
import inside freeze_time context managers can break the imported module
ALN059¶
Checks that all component dependencies are declared in the root of a component
ALN061¶
invalid AWS Secrets Manager secret name - it must follow the defined naming scheme https://www.notion.so/alaninsurance/Using-AWS-Secrets-Manager-1bb472e7a620429ab362052c91b729a4?pvs=4#0e4fae3a55b74b08b3651efabcb2cc12 ⧉
ALN062¶
Opening and closing curly braces in strings don't match
ALN063¶
Don't use the @dataclass_json decorator, use the DataClassJsonMixin instead, as it provides better typing.
ALN064¶
Default factory fields should not contain date or datetime objects, Please use factory.LazyFunction or factory.LazyAttribute instead
ALN065¶
This checker is used to ensure that the decryption of medical conversation messages can only be done in the dedicated clinic_ai.py file Decided here: https://github.com/alan-eu/Topics/discussions/25049?sort=old#discussioncomment-8569509 ⧉ (item 5)
ALN066¶
Using strings to indicate column or relationship paths in loader options is deprecated and will be removed in SQLAlchemy 2.0. Please use the class-bound attribute directly.
ALN068¶
cached() must always have an expire_in argument to make them eligible for eviction by our current redis policy"
ALN069¶
You can't import models from other components, see: https://www.notion.so/alaninsurance/Modular-monolith-a9d84f1318d34115bbd08b3648e5a587 ⧉",
ALN070¶
import inside freeze_time context managers can break the imported module
ALN071¶
SQLAlchemy v2 migration, in models all attributes (or functions with
@declared_attr) must return a Mapped[...] type. If it's a class variable
type it with ClassVar[...]
ALN072¶
Functions decorated with @enqueueable should not use non-primitive type
arguments. The function is used by RQ and the arguments must be serializable
and robust for code moves/refactors.
ALN073¶
Don't call functions without assigning their return value to a variable.
ALN076¶
The tablename class attribute is mandatory on all SQLAlchemy models inheriting from DbModel, AlanNonVersionedModel, BaseModel or any of their derived classes.
ALN077¶
Check for usage of backref in SQLAlchemy relationships and suggest using back_populates instead.
ALN079¶
Check for direct instantiation of AlanBaseFactory or its derived classes. Always use the .create() class method instead of direct instantiation.
ALN080¶
The Model.query.get(...) method is considered legacy as of the 1.x series of SQLAlchemy and will be removed. Use " current_session.get(Model, ...) instead.
ALN081¶
@view_method must be before @request_argument
TODO Long term solution will be implemented in Q2¶
ALN083¶
Flake8 plugin to check ProfileService constructor usage.
ALN084¶
Prevents the use of Flask's current_app.config. Use shared.helpers.config.current_config instead.
ALN085¶
Enforces SQLAlchemy 2.0 query style by detecting deprecated patterns that will be removed in SQLAlchemy 2.0.
This linter checks for: 1. Usage of session.query() which is deprecated in favor of session.scalar(), session.scalars(), or session.execute()
Note: Other SQLAlchemy 2.0 deprecation warnings are already being turned into errors at runtime by the _turn_sql_alchemy_warning_into_errors function in backend/shared/models/orm/sqlalchemy.py.
ALN086¶
Enforces the use of mapped_column instead of Column in SQLAlchemy 2.0+ models.
This linter checks for usage of Column() calls which should be replaced with mapped_column().
In SQLAlchemy 2.0+, Column is deprecated in favor of mapped_column for better type annotation support and modern SQLAlchemy patterns.
Note: Migration files (in directories containing "migrations") and Column() calls inside Table() definitions are excluded from this check as they legitimately need to use Column().
ALN087¶
Suppress SQLAlchemy query tracker warnings for N+1 queries and unused eager loads.
This linter serves as a marker to suppress specific SQLAlchemy query optimization warnings. When the SQLAlchemy query tracker detects potential N+1 queries or unused eager loads, it will check for the presence of this linter (ALN087) at the exact line number where the issue occurs. If found, the warning will be suppressed.
ALN088¶
Prevents the use of unless=is_test_mode in cache decorators.
This pattern changes behavior between test and production environments,
which is not a best practice.
ALN089¶
pytest fixtures with autouse=True in conftest.py files can have unwanted side-effects as they will be used in any tests in the subfolders and can inadvertently use other fixtures that add functionality. Instead, mark tests that need the fixture explicitly with @pytest.mark.usefixtures("fixture_name") or use the fixture as a parameter.
ALN090¶
All modular monolith components must have an observability.py file with a ServiceObservability instance. This ensures all components are properly instrumented for observability.
ALN091¶
All API endpoint functions in components/*/public/ must have @obs.api_call decorator. This ensures all public API endpoints are properly instrumented for observability.