From e95c1c3e95f9f093457806921ddb065cba5cae6a Mon Sep 17 00:00:00 2001 From: Peter Tim Soriano Date: Wed, 21 Apr 2021 01:00:26 -0400 Subject: [PATCH] behavioral pattern (state) --- scraping/webscraper.py | 26 ++----- scraping/webscraper_state_pattern.py | 107 +++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 19 deletions(-) create mode 100644 scraping/webscraper_state_pattern.py diff --git a/scraping/webscraper.py b/scraping/webscraper.py index 556b1c01..fd9ef906 100644 --- a/scraping/webscraper.py +++ b/scraping/webscraper.py @@ -30,6 +30,7 @@ import json import os.path import logging +from webscraper_state import Context, ConcreteSaveState, ConcreteConnectState mydb = None @@ -74,28 +75,14 @@ def localtime_to_ust(datetime): def connect(): global mydb - - # populate this from env file - path_to_json = "./db.json" - - with open(path_to_json, "r") as handler: - info = json.load(handler) - print(info) - - mydb = mysql.connector.connect( - host=info["host"], - user=info["user"], - passwd=info["passwd"], - database=info["database"], - ) - - print(mydb) + + context = Context(ConcreteConnectState()) + context.request_connect() def save_to_db(): - connect() - for newsObject in newsObject_stack: - insert(newsObject) + context = Context(ConcreteSaveState()) + context.request_connect() def insert(data_dict): @@ -143,6 +130,7 @@ def insert(data_dict): key = ["新型コロナウイルス", "新型肺炎", "新型ウィルス", "武漢肺炎", "新型冠狀病毒"] +global newsObject_stack newsObject_stack = [] NEWS_URLs = { diff --git a/scraping/webscraper_state_pattern.py b/scraping/webscraper_state_pattern.py new file mode 100644 index 00000000..9a35849e --- /dev/null +++ b/scraping/webscraper_state_pattern.py @@ -0,0 +1,107 @@ +from __future__ import annotations +from abc import ABC, abstractmethod +import json +import mysql.connector +from webscraper import insert + + +class Context: + """ + The Context defines the interface of interest to clients. It also maintains + a reference to an instance of a State subclass, which represents the current + state of the Context. + """ + + _state = None + """ + A reference to the current state of the Context. + """ + + def __init__(self, state: State) -> None: + self.transition_to(state) + + def transition_to(self, state: State): + """ + The Context allows changing the State object at runtime. + """ + + print(f"Context: Transition to {type(state).__name__}") + self._state = state + self._state.context = self + + """ + The Context delegates part of its behavior to the current State object. + """ + + def request_connect(self): + self._state.connectDB() + + def request_save_to_db(self): + self._state.saveDB() + + +class State(ABC): + """ + The base State class declares methods that all Concrete State should + implement and also provides a backreference to the Context object, + associated with the State. This backreference can be used by States to + transition the Context to another State. + """ + + @property + def context(self) -> Context: + return self._context + + @context.setter + def context(self, context: Context) -> None: + self._context = context + + @abstractmethod + def connectDB(self) -> None: + pass + + @abstractmethod + def saveDB(self) -> None: + pass + + +""" +Concrete States implement various behaviors, associated with a state of the +Context. +""" + + +class ConcreteConnectState(State): + def connectDB(self) -> None: + path_to_json = "./db.json" + + with open(path_to_json, "r") as handler: + info = json.load(handler) + print(info) + + mydb = mysql.connector.connect( + host=info["host"], + user=info["user"], + passwd=info["passwd"], + database=info["database"], + ) + + print(mydb) + print("ConcreteStateA handles request1.") + print("ConcreteStateA wants to change the state of the context.") + self.context.transition_to(ConcreteSaveState()) + + def saveDB(self) -> None: + print("ConcreteStateA handles request2.") + + +class ConcreteSaveState(State): + def connectDB(self) -> None: + print("ConcreteStateB handles request1.") + + def saveDB(self, newsObject_stack) -> None: + for newsObject in newsObject_stack: + insert(newsObject) + print("ConcreteStateB handles request2.") + print("ConcreteStateB wants to change the state of the context.") + self.context.transition_to(ConcreteConnectState()) \ No newline at end of file