def run(self): params = self.params duration = params.get_duration() location_id = params.get_location_id() if location_id is None: task_id = params.get_task_id() task = self.task_repository.find_by_id(id_=task_id) default_location = self.location_repository.get_default( user_id=task.user_id, ) location_id = default_location.id repeat_type = params.get_repeat_type() if repeat_type and not Plan.is_valid_repeat_type(repeat_type): raise InvalidRepeatTypeError(repeat_type) task_id = params.get_task_id() trigger_time = params.get_trigger_time() visible_hours = params.get_visible_hours() visible_wdays = params.get_visible_wdays() # TODO: 检查task_id是否能找到一个任务 plan = Plan.new( task_id, trigger_time, duration=duration, location_id=location_id, repeat_interval=params.get_repeat_interval(), repeat_type=repeat_type, visible_hours=visible_hours, visible_wdays=visible_wdays, ) self.plan_repository.add(plan) return self.plan_repository.find_by_id(plan.id)
def test_visible_wdays(): """ 测试星期几可见的判断逻辑。 """ plan = Plan() plan.visible_wdays = {0, 4} trigger_time1 = datetime(2021, 4, 12) trigger_time2 = datetime(2021, 4, 13) assert plan.is_visible(trigger_time=trigger_time1) assert not plan.is_visible(trigger_time=trigger_time2)
def test_visible_hours(): """ 测试可见小时的判断逻辑。 """ plan = Plan() plan.visible_hours = {12, 22} trigger_time1 = datetime(2020, 3, 12, 22, 14) trigger_time2 = datetime(2021, 4, 13, 23, 15) assert plan.is_visible(trigger_time=trigger_time1) assert not plan.is_visible(trigger_time=trigger_time2)
def test_repeating_description(): plan = Plan.new( task_id=0, trigger_time=datetime.now(), repeat_interval=timedelta(days=13), repeat_type='periodically', ) description = plan.get_repeating_description() assert description == '每13天'
def test_visible_hours_description(): plan = Plan.new( task_id=0, trigger_time=datetime.now(), repeat_interval=timedelta(days=13), repeat_type='periodically', visible_hours={1, 2, 3, 5, 8, 13, 21}, ) description = plan.get_visible_hours_description() assert description == '1/2/3/5/8/13/21点可见'
def test_visible_wdays_description(): plan = Plan.new( task_id=0, trigger_time=datetime.now(), repeat_interval=timedelta(days=13), repeat_type='periodically', visible_wdays={1, 2, 3, 5}, ) description = plan.get_visible_wdays_description() assert description == '星期1/2/3/5可见'
class MockPlanRepository(IPlanRepository): def __init__(self): self.plan = Plan() self.plan.terminate() def add(self, plan: Plan): pass def clear(self): pass def commit(self): pass def find_as_queue(self, *, location_ids: Union[None, List[int]] = None, max_trigger_time=None, min_trigger_time: datetime = None, page: Optional[int] = None, per_page: Optional[int] = None, status: PlanStatus = None, user_id: int) -> List[Plan]: pass def find_by_id(self, id_: int) -> Plan: return self.plan def find_by_task_id(self, *, task_id: int) -> List[Plan]: pass def remove(self, id_: int): pass def rollback(self): pass def start_transaction(self): pass
def add(self, plan: Plan): """ 将计划存储到数据库,或更新数据库已有的计划。 """ # TODO: 统一一下插入和更新时两种不同风格的写法。这里统一为用pypika、而不是自己发明一种写法会更好。 if plan.id is None: now = datetime.now() repeat_interval: Union[None, timedelta, int] = plan.repeat_interval if repeat_interval is not None: repeat_interval = int(repeat_interval.total_seconds()) insert_id = self.insert_to_db({ 'duration': plan.duration, 'location_id': plan.location_id, 'repeat_interval': repeat_interval, 'repeat_type': plan.repeat_type, 'status': plan.status.value, 'task_id': plan.task_id, 'trigger_time': plan.trigger_time, 'visible_hours': json.dumps(list(plan.visible_hours)), 'visible_wdays': json.dumps(list(plan.visible_wdays)), 'ctime': now, 'mtime': now, }, 't_plan') plan.id = insert_id else: plan_table = Table('t_plan') repeat_interval: Union[None, timedelta] = plan.repeat_interval if repeat_interval is not None: repeat_interval = int(repeat_interval.total_seconds()) query = Query\ .update(plan_table)\ .set(plan_table.duration, plan.duration)\ .set(plan_table.location_id, plan.location_id)\ .set(plan_table.repeat_interval, repeat_interval)\ .set(plan_table.repeat_type, plan.repeat_type)\ .set(plan_table.status, plan.status.value)\ .set(plan_table.trigger_time, plan.trigger_time)\ .set(plan_table.visible_hours, json.dumps(plan.visible_hours)) \ .set(plan_table.visible_wdays, json.dumps(plan.visible_wdays))\ .where(plan_table.id == plan.id) sql = query.get_sql(quote_char=None) with self.get_connection() as connection: with connection.cursor() as cursor: cursor.execute(sql)
def test_rebirth(): trigger_time = datetime.now() plan = Plan.new( duration=2, repeat_interval=timedelta(days=3), repeat_type='periodically', task_id=1, trigger_time=trigger_time, visible_hours={1}, visible_wdays={6}, ) rebirth_plan = plan.rebirth() for attr, value in plan.__dict__.items(): if attr in ['id', 'trigger_time']: continue assert getattr(rebirth_plan, attr) == getattr(plan, attr) assert rebirth_plan.trigger_time.timestamp() - trigger_time.timestamp( ) == 3 * 24 * 60 * 60
def run(self): params = self.params plan_id = params.get_plan_id() plan = self.plan_repository.find_by_id(plan_id) if plan is None: raise PlanNotFoundError(plan_id=plan_id) if not plan.is_changeable(): raise UnchangeableError() # TODO: 如何优化这类重复代码?引入元编程之类的写法划算吗? found, duration = params.get_duration() if found: plan.duration = duration found, location_id = params.get_location_id() if found: if location_id: location = self.location_repository.get(id_=location_id) if not location: raise LocationNotFoundError(location_id=location_id) plan.location_id = location_id found, repeat_interval = params.get_repeat_interval() if found: plan.repeat_interval = repeat_interval found, repeat_type = params.get_repeat_type() if found: if not Plan.is_valid_repeat_type(repeat_type): raise InvalidRepeatTypeError(repeat_type) plan.repeat_type = repeat_type found, trigger_time = params.get_trigger_time() if found: plan.trigger_time = trigger_time found, visible_hours = params.get_visible_hours() if found: plan.visible_hours = visible_hours found, visible_wdays = params.get_visible_wdays() if found: plan.visible_wdays = visible_wdays self.plan_repository.add(plan)
def add(self, plan: Plan): plan.id = 123 self.plan = plan
def find_as_queue(self, *, location_ids: Union[None, List[int]] = None, max_trigger_time=None, page: int, per_page: int, status=None, user_id=None) -> Tuple[List[Plan], int]: return [Plan()], 1
def _row2entity(self, row: dict): plan = Plan() plan.duration = row['duration'] plan.id = row['id'] plan.location_id = row['location_id'] if isinstance(row['repeat_interval'], int): plan.repeat_interval = timedelta(seconds=row['repeat_interval']) plan.repeat_type = row['repeat_type'] plan.status = row['status'] and PlanStatus(row['status']) plan.task_id = row['task_id'] plan.trigger_time = row['trigger_time'] plan.visible_hours = json.loads(row.get('visible_hours') or '[]') plan.visible_wdays = json.loads(row.get('visible_wdays') or '[]') return plan
def __init__(self): self.plan = Plan() self.plan.terminate()