Semgrep rule to validate Django's ForeignKey related_name field - semgrep

I'm trying to create a rule to enforce the usage of related_name when defining a ForeignKey field in Django, as well as its format.
Enforcing the usage of the field is done by the following rule:
- id: python.custom.foreign-key-must-set-related-name
message: ForeignKey relationships must explicitly set the `related_name` property as `<model>_<field>_set`
languages: [python]
severity: ERROR
patterns:
- pattern-inside: |
class $M(...):
...
- pattern-not: $F = django.db.models.ForeignKey(..., related_name=..., ...)
- pattern: $F = django.db.models.ForeignKey(...)
My goal now is to modify this rule to also be able to validate the format of the related_name, so that it is: <model>_<field>_set (or, following the variables in the rule: $M_$F_set)
I've been trying several combinations and haven't been lucky so far.
Is this possible to do?
Edit:
As an example, look at the following model:
class MyCoolModel(models.Model):
correct_field = models.ForeignKey(to='something', related_name='mycoolmodel_correct_field_set')
incorrect_field = models.ForeignKey(to='something', related_name='something_set')

Related

DBT Test configuration for particular scenario

Hello Could anyone help me how to simulate this scenario. Example I want to validate these 3 fields on my table "symbol_type", "symbol_subtype", "taker_symbol" and return unique combination/result.
I tried to use this command, however Its not working properly on my test. Not sure if this is the correct syntax to simulate my scenario. Your response is highly appreciated.
Expected Result: These 3 fields should return my unique combination using DBT commands.
I'd recommend to either:
use the generate_surrogate_key (docs) macro in the model, or
use the dbt_utils.unique_combination_of_columns (docs) generic test.
For the first case, you would need to define the following in the model:
select
{{- dbt_utils.generate_surrogate_key(['symbol_type', 'symbol_subtype', 'taker_symbol']) }} as hashed_key_,
(...)
from your_model
This would create a hashed value of the three columns. You could then use a unique test in your YAML file.
For the second case, you would only need to add the generic test in your YAML file as follows:
# your model's YAML file
- name: your_model_name
description: ""
tests:
- dbt_utils.unique_combination_of_columns:
combination_of_columns:
- symbol_type
- symbol_subtype
- taker_symbol
Both these approaches will let you check whether the combination of the three columns is unique over the whole model's output.

Odoo: how to set default field for many2many field by id?

i want to set default value in many2many field for example:
that field in models.py:
# alarms
alarm_ids = fields.Many2many(
'calendar.alarm', 'calendar_alarm_calendar_event_rel',
string='Reminders', ondelete="restrict",
help="Notifications sent to all attendees to remind of the meeting.")
also it is default values created by system, and i want first variant by default:
i know that i can set it by id, but dont know how.
You can use Command to set X2many field values.
From the documentation:
Via Python, we encourage developers craft new commands via the various functions of this namespace. We also encourage developers to use the command identifier constant names when comparing the 1st element of existing commands.
Example:
from odoo import Command, models, fields
class CalendarEvent(models.Model):
_inherit = 'calendar.event'
alarm_ids = fields.Many2many(default=lambda self: [Command.link(self.env.ref('calendar.alarm_notif_1').id)])
i just watch in postgres, there is no id`s like in xml screenshots, i just take id of a record and find some documentation.
next example works:

How to persist column descriptions in BigQuery tables

I have created models in my dbt(data build tool) where I have specified column description. In my dbt_project.yml file as shown below
models:
sakila_dbt_project:
# Applies to all files under models/example/
+persist_docs:
relation: true
columns: true
events:
materialized: table
+schema: examples
I have added +persist_docs as described by dbt as the fix to make column description appear but still no description appears in bigquery table.
My models/events/events.yml looks like this
version: 2
models:
- name: events
description: This table contains clickstream events from the marketing website
columns:
- name: event_id
description: This is a unique identifier for the event
tests:
- unique
- not_null
- name: user-id
quote: true
description: The user who performed the event
tests:
- not_null
What I'm I missing?
p.s I'm using dbt version 0.21.0
Looks consistent with the required format as shown in the docs:
dbt_project.yml
models:
..[<resource-path>](resource-path):
....+persist_docs:
......relation: true
......columns: true
models/schema.yml
version: 2
models:
..- name: dim_customers
....description: One record per customer
....columns:
......- name: customer_id
........description: Primary key
Maybe spacing? I converted the spaces to periods in the examples above because the number of spaces is unforgivingly specific for yml files.
I've started using the vscode yml formatter because of how often I run into spacing issues on these keys in both the schema.yml and the dbt_project.yml
Otherwise, this isn't for a source or external-table right? Those are the only two artifacts that persist-docs is unsupported for.
Sources unsupported persist_docs -> sources tab
External Tables unsupported (Can't find in docs again but read today in docs or github issue)
Also Apache Spark unsupported (irrelevant here) Apache Spark Profile
Also, if you're going to be working with persist_docs a lot, check out this macro example persist_docs_op that Jeremy left for a run-operation to update your persisted docs in case that's all you changed!

TypeORM View Entity synchronization (creation) order problems

Using TypeORM, I'm trying to create ViewEntities that depend on each other, for example "View B" select from "View A". No matter what I do I can't get the ViewEntities to get created in the order of dependency. Sometimes "View B" is created first, and the synchronization process fails, because it can't find "View A", since it's not created yet.
The error:
QueryFailedError: relation "public.course_item_view" does not exist
Solutions I have tried:
Renaming the ViewEntity files (to check if the system uses ABC ordering on file names)
Renaming the ViewEntity classes (to check if the system uses ABC ordering on class names)
Renaming the ViewEntity's "name" property (to check if the system uses ABC ordering on the final SQL view names)
Reordering the ViewEntity class references in the "entities: []" array of the connection options
Reordering the ViewEntity class imports in the file where I declare the connection options
Removing/Adding the file again (to check if the system uses Creation Date based ordering)
Modifying the files (to check if the system uses Modification Date based ordering)
All of these failed. I cannot figure out how the system determines the order in which the view's are created.
Any help would be GREATLY appreciated!!
Expected Behavior
The view's should be created in an order that is either specified by a property inside the views, or the order should be resolved automatically from the SELECT statements (dependency array), or it should be based on the order in which I reference the ViewEntities in the "entities: []" array of the connection options, or any other solution would be perfect where one could determine the order in which the ViewEntities are created.
Actual Behavior
The ViewEntites are created in an order that I honestly can't understand. Sometimes a dependent ViewEntity is created before the ViewEntitiy it depends on. This causes the synchronization to fail.
File name: "CourseItemView" which resolves to: "course_item_view"
#ViewEntity({
expression: `
SELECT
"uvcv"."userId",
"uvcv"."courseId",
"uvcv"."videoId",
CAST (null AS integer) AS "examId",
"uvcv"."isComplete" AS "isComplete"
FROM public.video_completed_view AS "uvcv"
UNION ALL
SELECT
"uecv"."userId",
"uecv"."courseId",
CAST (null AS integer) AS "videoId",
"uecv"."examId",
"uecv"."isCompleted" AS "isComplete"
FROM public.user_exam_completed_view AS "uecv"
.
.
File name: "CourseItemStateView" which resolves to: "course_item_state_view"
This DEPENDS on the "course_item_view", as you can see in the SQL
#ViewEntity({
expression: `
SELECT
"course"."id" AS "courseId",
"user"."id" AS "userId",
"civ"."videoId" AS "videoId",
"civ"."isComplete" AS "isVideoCompleted",
"civ"."examId" AS "examId",
"civ"."isComplete" AS "isExamCompleted"
FROM public."course"
LEFT JOIN public."user"
ON 1 = 1
LEFT JOIN public.course_item_view AS "civ" ------------------- HERE
ON "civ"."courseId" = "course"."id"
AND "civ"."userId" = "user"."id"
ORDER BY "civ"."videoId","civ"."examId"
`
})
.
.
My connection options:
const postgresOptions = {
// properties, passwords etc...
entities: [
// entities....
// ...
// ...
// views
VideoCompletedView,
UserExamCompletedView,
UserExamAnswerSessionView,
UserVideoMaxWatchedSecondsView,
CourseItemView, --------------------------------HERE
CourseItemStateView ---------------------------HERE
],
} as ConnectionOptions;
createConnection(postgresOptions )
Steps to Reproduce
Create ViewEntites that depend on each other
You will run into this issue, but is hard to say exactly why and when, this is the main problem.

how to generate a subfactory based on condition of a parent attribute

I have a factory like so:
class PayInFactory(factory.DjangoModelFactory):
class Meta:
model = PayIn
#factory.lazy_attribute
def card(self):
if self.booking_payment and self.booking_payment.payment_type in [bkg_cts.PAYMENT_CARD, bkg_cts.PAYMENT_CARD_2X]:
factory.SubFactory(
CardFactory,
user=self.user,
)
I'm trying to generate a field card only if the booking_payment field has a payment_type value in [bkg_cts.PAYMENT_CARD, bkg_cts.PAYMENT_CARD_2X]
The code goes into that statement but card field is empty after generation.
How can I do that properly ?
Is SubFactory allowed in lazy_attribute ?
I'd like to be able to modify Card field from PayInFactory if possible like so:
>>> PayInFactory(card__user=some_user)
PostGeneration won't do as I need this Card to be available before the call to create. I overrided _create and it may use the card if available.
Thanks !
The solution lies in factory.Maybe:
class PayInFactory(factory.django.DjangoModelFactory):
class Meta:
model = models.PayIn
card = factory.Maybe(
factory.LazyAttribute(
lambda o: o.booking_payment and o.booking_payment.payment_type in ...
),
factory.SubFactory(
CardFactory,
# Fetch 'user' one level up from CardFactory: PayInFactory
user=factory.SelfAttribute('..user'),
),
)
However, I haven't tested whether the extra params get actually passed to the CardFactory, nor what happens when CardFactory is not called — you'll have to check (and maybe open an issue on the project if you get an unexpected behaviour!).