|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | +"""Base Sender, father of all other providers""" |
| 3 | +import random |
| 4 | +import threading |
| 5 | +import time |
| 6 | +from datetime import datetime, timedelta |
| 7 | +from pycron import is_now |
| 8 | +from .template_parser import TemplateParser |
| 9 | + |
| 10 | + |
| 11 | +class BaseFakeGenerator(threading.Thread): |
| 12 | + """Base provider main class""" |
| 13 | + |
| 14 | + def __init__(self, engine=None, template=None, **kwargs): |
| 15 | + """ |
| 16 | + Init BaseFakeGenerator, all generator use this class as father |
| 17 | +
|
| 18 | + :param engine (Sender): Sender object, if neccesary, for send data |
| 19 | + :param template (str, bytes): Template, read, in a variable, not the |
| 20 | + path to a file |
| 21 | + :param kwargs: List of accepted variables below |
| 22 | + :param time_rules (dict): Time rules as crondates format for |
| 23 | + variable frequeny and probability |
| 24 | + :param frequency (list): Fixed shipping frequency list (min, max) |
| 25 | + in seconds |
| 26 | + :param probability (int): Fixed shipping probability |
| 27 | + from 0 to 100(%) |
| 28 | + :param interactive (bool): Interactive mode |
| 29 | + :param simulation (bool): Simulation mode, not send/write if true |
| 30 | + :param verbose (bool): Verbose mode |
| 31 | + :param date_generator (object): Alternative date generator |
| 32 | + for templates |
| 33 | + :param providers (dict): Custom providers dict |
| 34 | + """ |
| 35 | + |
| 36 | + threading.Thread.__init__(self) |
| 37 | + self.engine = engine |
| 38 | + |
| 39 | + if kwargs.get('time_rules', None) is not None: |
| 40 | + self.time_rules = kwargs.get("time_rules") |
| 41 | + self.set_last_time_rule() |
| 42 | + |
| 43 | + self.cron_child = threading.Thread( |
| 44 | + target=self.check_time_rules |
| 45 | + ) |
| 46 | + self.cron_child.setDaemon(True) |
| 47 | + self.cron_child.start() |
| 48 | + else: |
| 49 | + self.prob = kwargs.get('probability', 100) |
| 50 | + self.freq = kwargs.get('frequency', (1, 1)) |
| 51 | + |
| 52 | + self.interactive = kwargs.get('interactive', False) |
| 53 | + self.simulation = kwargs.get('simulation', False) |
| 54 | + self.verbose = kwargs.get('verbose', False) |
| 55 | + self.parser = TemplateParser(template=str(template), |
| 56 | + providers=kwargs.get('providers', {}), |
| 57 | + date_generator= |
| 58 | + kwargs.get('date_generator', None)) |
| 59 | + |
| 60 | + def process(self, date_generator=None, **kwargs): |
| 61 | + """Process template""" |
| 62 | + return self.parser.process(date_generator=date_generator, |
| 63 | + **kwargs) |
| 64 | + |
| 65 | + def wait(self): |
| 66 | + """Time to wait between events""" |
| 67 | + # freq[0] is the minimum |
| 68 | + # freq[1] is the maximum |
| 69 | + if self.freq[0] == self.freq[1]: |
| 70 | + secs = self.freq[0] |
| 71 | + elif self.freq[1] < self.freq[0]: |
| 72 | + secs = random.uniform(self.freq[1], self.freq[0]) |
| 73 | + else: |
| 74 | + secs = random.uniform(self.freq[0], self.freq[1]) |
| 75 | + time.sleep(secs) |
| 76 | + |
| 77 | + def set_last_time_rule(self): |
| 78 | + """ |
| 79 | + When crondate time rules are used, it is found which one should have |
| 80 | + been executed last and the probability and frequency are set |
| 81 | + :return None |
| 82 | + """ |
| 83 | + now = datetime.now() |
| 84 | + try: |
| 85 | + for _ in range(0, 525600): |
| 86 | + for item in self.time_rules: |
| 87 | + if is_now(item["rule"], now): |
| 88 | + self.prob = item['probability'] |
| 89 | + self.freq = item['frequency'] |
| 90 | + raise Exception('found') |
| 91 | + now = now - timedelta(minutes=1) |
| 92 | + except Exception as inst: |
| 93 | + if inst.args[0] != "found": |
| 94 | + raise Exception(inst) |
| 95 | + |
| 96 | + def check_time_rules(self): |
| 97 | + """ |
| 98 | + Controls every minute if a change in frequency and probability |
| 99 | + is to be made based on the specified rules |
| 100 | + :return: |
| 101 | + """ |
| 102 | + while True: |
| 103 | + for item in self.time_rules: |
| 104 | + if is_now(item["rule"]): |
| 105 | + self.prob = item['probability'] |
| 106 | + self.freq = item['frequency'] |
| 107 | + break |
| 108 | + time.sleep(60) |
| 109 | + |
| 110 | + def probability(self): |
| 111 | + """Calculate probability""" |
| 112 | + k = random.randint(0, 100) |
| 113 | + if k <= int(self.prob): |
| 114 | + return True |
| 115 | + return False |
| 116 | + |
| 117 | + def run(self): |
| 118 | + """Run example (for override)""" |
| 119 | + while True: |
| 120 | + if self.probability(): |
| 121 | + # Do something |
| 122 | + pass |
| 123 | + self.wait() |
0 commit comments