Dangerous default value [] as argument
411 end_date,
412 granularity,
413 customer=None,
414 group_by=[], 415 proration=None,
416 ) -> dict[Customer.customer_name, dict[datetime.datetime, float]]:
417 from metering_billing.billable_metrics import METRIC_HANDLER_MAP
Dangerous default value [] as argument
444 return usage
445
446 def get_earned_usage_per_day(
447 self, start, end, customer, group_by=[], proration=None 448 ):
449 from metering_billing.billable_metrics import METRIC_HANDLER_MAP
450
Dangerous default value [] as argument
75 def get_current_usage(
76 self,
77 subscription: Subscription,
78 group_by: list[str] = [], 79 ) -> float:
80 """This method will be used to calculate how much usage a customer currently has on a subscription. THough there are cases where get_usage and get_current_usage will be the same, there are cases where they will not. For example, if your billable metric is Stateful with a Max aggregation, then your usage over some period will be the max over past readings, but your current usage will be the latest reading."""
81 pass
Dangerous default value [] as argument
86 start: datetime.date,
87 end: datetime.date,
88 customer: Customer,
89 group_by: list[str] = [], 90 proration: Optional[METRIC_GRANULARITY] = None,
91 ) -> dict[datetime.datetime, float]:
92 """This method will be used when calculating a concept known as "earned revenue" which is very important in accounting. It essentially states that revenue is "earned" not when someone pays, but when you deliver the goods/services at a previously agreed upon price. To accurately calculate accounting metrics, we will need to be able to tell for a given susbcription, where each cent of revenue came from, and the first step for that is to calculate how much billable usage was delivered each day. This method will be used to calculate that.
Dangerous default value [] as argument
95 pass
96
97 @abc.abstractmethod
98 def _build_filter_kwargs(self, start, end, customer, group_by=[]): 99 """This method will be used to build the filter args for the get_usage and get_earned_usage_per_day methods. You should build the filter args for the Event model, and return them as a dictionary. You should also handle the case where customer is None, which means that you should return the usage for all customers."""
100 now = now_utc()
101 filter_kwargs = {
Dangerous default value [] as argument
131 return filter_args, filter_kwargs
132
133 @abc.abstractmethod
134 def _build_pre_groupby_annotation_kwargs(self, group_by=[]): 135 pre_groupby_annotation_kwargs = {
136 "customer_name": F("customer__customer_name"),
137 }
Dangerous default value [] as argument
147
148 @abc.abstractmethod
149 def _build_groupby_kwargs(
150 self, customer, results_granularity, start, group_by=[], proration=None 151 ):
152 groupby_kwargs = {}
153 for group_by_property in group_by:
Dangerous default value [] as argument
255 METRIC_AGGREGATION.MAX,
256 ]
257
258 def _build_filter_kwargs(self, start, end, customer, group_by=[]): 259 return super()._build_filter_kwargs(start, end, customer, group_by)
260
261 def _build_pre_groupby_annotation_kwargs(self, group_by=[]):
Dangerous default value [] as argument
258 def _build_filter_kwargs(self, start, end, customer, group_by=[]):
259 return super()._build_filter_kwargs(start, end, customer, group_by)
260
261 def _build_pre_groupby_annotation_kwargs(self, group_by=[]): 262 return super()._build_pre_groupby_annotation_kwargs(group_by)
263
264 def _build_groupby_kwargs(
Dangerous default value [] as argument
262 return super()._build_pre_groupby_annotation_kwargs(group_by)
263
264 def _build_groupby_kwargs(
265 self, customer, results_granularity, start, group_by=[], proration=None 266 ):
267 return super()._build_groupby_kwargs(
268 customer, results_granularity, start, group_by, proration
Dangerous default value [] as argument
274 start,
275 end,
276 customer=None,
277 group_by=[], 278 proration=None,
279 ):
280 filter_args, filter_kwargs = self._build_filter_kwargs(
Dangerous default value [] as argument
325 return_dict[cust_name][unique_tup][tc_trunc] = usage_qty
326 return return_dict
327
328 def get_current_usage(self, subscription, group_by=[]): 329 per_customer = self.get_usage(
330 start=subscription.start_date,
331 end=subscription.end_date,
Dangerous default value [] as argument
340 return per_customer
341
342 def get_earned_usage_per_day(
343 self, start, end, customer, group_by=[], proration=None 344 ):
345 filter_args, filter_kwargs = self._build_filter_kwargs(
346 start, end, customer, group_by
Dangerous default value [] as argument
551 assert property_name, "[METRIC TYPE: STATEFUL] Must specify property name."
552 return data
553
554 def _build_filter_kwargs(self, start, end, customer, group_by=[]): 555 return super()._build_filter_kwargs(start, end, customer, group_by)
556
557 def _build_pre_groupby_annotation_kwargs(self, group_by=[]):
Dangerous default value [] as argument
554 def _build_filter_kwargs(self, start, end, customer, group_by=[]):
555 return super()._build_filter_kwargs(start, end, customer, group_by)
556
557 def _build_pre_groupby_annotation_kwargs(self, group_by=[]): 558 return super()._build_pre_groupby_annotation_kwargs(group_by)
559
560 def _build_groupby_kwargs(
Dangerous default value [] as argument
558 return super()._build_pre_groupby_annotation_kwargs(group_by)
559
560 def _build_groupby_kwargs(
561 self, customer, results_granularity, start, group_by=[], proration=None 562 ):
563 return super()._build_groupby_kwargs(
564 customer, results_granularity, start, group_by, proration
Dangerous default value [] as argument
570 start,
571 end,
572 customer=None,
573 group_by=[], 574 proration=None,
575 ):
576 filter_args, filter_kwargs = self._build_filter_kwargs(
Dangerous default value [] as argument
819 usage_dict = new_usage_dict
820 return usage_dict
821
822 def get_current_usage(self, subscription, group_by=[]): 823 cur_usg_agg = self.usage_aggregation_type
824 cur_granularity = self.granularity
825 self.usage_aggregation_type = METRIC_AGGREGATION.LATEST
Dangerous default value [] as argument
837 return usg
838
839 def get_earned_usage_per_day(
840 self, start, end, customer, group_by=[], proration=None 841 ):
842 per_customer = self.get_usage(
843 start=start,
Dangerous default value [] as argument
1021 start = None
1022 return start, end
1023
1024 def _build_filter_kwargs(self, start, end, customer, group_by=[]):1025 return super()._build_filter_kwargs(start, end, customer, group_by)
1026
1027 def _build_pre_groupby_annotation_kwargs(self, group_by=[]):
Dangerous default value [] as argument
1024 def _build_filter_kwargs(self, start, end, customer, group_by=[]):
1025 return super()._build_filter_kwargs(start, end, customer, group_by)
1026
1027 def _build_pre_groupby_annotation_kwargs(self, group_by=[]):1028 return super()._build_pre_groupby_annotation_kwargs(group_by)
1029
1030 def _build_groupby_kwargs(
Dangerous default value [] as argument
1028 return super()._build_pre_groupby_annotation_kwargs(group_by)
1029
1030 def _build_groupby_kwargs(
1031 self, customer, results_granularity, start, group_by=[], proration=None1032 ):
1033 return super()._build_groupby_kwargs(
1034 customer, results_granularity, start, group_by, proration
Dangerous default value [] as argument
1034 customer, results_granularity, start, group_by, proration
1035 )
1036
1037 def get_current_usage(self, subscription, group_by=[]):1038 start, end = self._get_current_query_start_end()
1039 start = start if start else subscription.start_date
1040 filter_args, filter_kwargs = self._build_filter_kwargs(
Dangerous default value [] as argument
1096 start,
1097 end,
1098 customer=None,
1099 group_by=[],1100 proration=None,
1101 ):
1102 filter_args, filter_kwargs = self._build_filter_kwargs(
Dangerous default value [] as argument
1164 return return_dict
1165
1166 def get_earned_usage_per_day(
1167 self, start, end, customer, group_by=[], proration=None1168 ):
1169 per_customer = self.get_usage(
1170 start=start,
Description
Do not use a mutable like list
or dictionary
as a default value to an argument. Python’s default arguments are evaluated once when the function is defined. Using a mutable default argument and mutating it will mutate that object for all future calls to the function as well.
Bad practice
def my_function(elem, l=[]):
l.append(elem)
return l
print(my_function(2)) # [2]
print(my_function(5)) # [2, 5]
Recommended:
def my_function(elem, l=None):
if l is None:
l = []
l.append(elem)
return l
print(my_function(2)) # [2]
print(my_function(5)) # [5]