def acquire_rates_data(self): """Request rates data from the site and processes them returns True on successful receiving and data processing """ prinf('%s params: %s', self.base_url, self.my_params) g_start() try: self.response_data = requests.get(self.base_url, params=self.my_params, timeout=self.timeout) except OSError: prinw('%s host not available', self.name) return False g_end('request responded') if not self.response_data: return False else: status_code = self.response_data.status_code prinf(status_code ) if status_code > 400 : prinw('%s currency converter site response not found. %s', self.nam, status_code) return False elif status_code == 200: prinf('%s response ok', self.name) self.update_rates_valid_data() self.in_ccode = self.response_data.json()[self.strs[jpn.key_in_ccode]] self.rates = self.response_data.json()[self.strs[jpn.key_output]] return True
def internet_on(): """Tries to reach google.com to find out if the connection to internet is established returns True on conected to internet False otherwise """ try: # connect to the google.com -- tells us if the host is actually reachable g_start() socket.create_connection(("www.google.com", 80), timeout=1) g_end('connection to internet is available') return True except OSError: pass return False
def save_to_sql(self, rates_df, rates_info_lines): """Saves rates database into sql file and database info file to disk""" self.create_engine() self.touch_db_file() with self.engine.connect() as conn, conn.begin(): # rates sql database g_start() rates_df.to_sql(self.rates_table_name, conn, if_exists='replace') g_end('saved rates_df.to_sql') # database info file g_start() with open(self.rates_info_txt_file, 'w', encoding=self.encoding) as f: f.writelines(rates_info_lines) g_end('saved rates_info_txt_file')
def get_rates_from_sql(self, in_ccode=None, out_ccode=None): """Queries the sql database for input rates according to input arguments [in_ccode, out_ccode] - on no rates table or no sql database it returns None - when both arguments are None, returns the full database - when out_ccode is None, returns the [in_ccode] rates column - otherwise returns the exchange rate for the arguments """ if self.db_file_exist(): self.create_engine() rates_table_exist = self.engine.dialect.has_table( self.engine, self.rates_table_name) if rates_table_exist: if not (in_ccode or out_ccode): g_start() # load whole database to pandas (time consuming) rates_df = pd.read_sql_table(self.rates_table_name, self.engine) g_end('loaded database') rates_df.index = rates_df['index'] rate = rates_df[self.in_code].loc[self.out_code] return rate elif in_ccode: sql_query = 'SELECT "index", {} FROM {} ;'.format( in_ccode, self.rates_table_name) g_start() in_col_df = pd.read_sql_query(sql_query, self.engine) g_end('loaded query read_sql_query') if out_ccode: in_col_df.index = in_col_df['index'] rate = in_col_df[in_ccode].loc[out_ccode] return rate else: rates = { ccode: float(rate) for ccode, rate in zip(in_col_df['index'], in_col_df[in_ccode]) } return rates else: return None else: return None
def get_db_valid_from_via_txt(self): """Returns offline sql database valid_from utc time from txt file [rates_info_txt_file]""" rates_info_txt_exist = Path(self.rates_info_txt_file).is_file() if rates_info_txt_exist: g_start() with open(self.rates_info_txt_file, 'r', encoding=self.encoding) as f: whole = f.readlines() if len(whole) < 2: prinw( 'rates_info_txt_file does not contain lines with db_valid_to_str, db_valid_from_str!' ) return None else: db_valid_to_str, db_valid_from_str = whole[0:2] db_valid_from = arrow.get(db_valid_from_str) g_end('loaded rates_info_txt_file') # ~ 8 ms return db_valid_from else: prinw('rates_info_txt_file does not exist') return None
def _init_redis_(self, use_redis): """Initialize redis variables and connections - even if use_redis is True, the first_contact_max_sec test is still used ::WINDOWS NOTE:: the first access to redis has about 1 second time penalty on windows platform. idiocracy """ self.use_redis = use_redis self.first_contact_max_sec = 2.5 # should be at most 300 ms to be better than hdd sql database self.redis_host = 'localhost' self.redis_port = 6379 self.r = None if not self.use_redis: return g_start() redis_db = redis.StrictRedis(host="localhost", port=6379, db=0) g_end('redis strictRedis initialized') g_start() redis_db.set('redis', 'running') # takes ~ 1000 ms on windows first_contact = g_end('first redis access') g_start() redis_running = redis_db.get( 'redis') == 'running' # takes ~ 0.1 ms on windows g_end('second redis access', 'd') redis_running = redis_db.info()['loading'] == 0 if first_contact > self.first_contact_max_sec: # we don't want the redis to actually slow things down on Windows redis_running = False if redis_running: g_start() self.r = Root(host="localhost", port=6379, db=0) g_end('redisworks root initialized') prinf('Redis works root server running.')
def create_engine(self): """Creates engine for sql database manipulation, if one does not exist yet""" g_start() if self.engine is None: self.engine = create_engine(self.db_engine_path) g_end('created engine')
if platform.system() == 'Windows': truly_use_redis = use_redis_on_windows prinw( 'Not using redis - Windows platform has 1 sec latency on first contact!' ) return truly_use_redis if __name__ == '__main__': """Converts amount of currency according to program arguments - Program arguments parsing - Redis usage decision - CurrencyConverter initializaton - Conversion according to parsed arguments """ g_start('complete code') # parsing of arguments params = parse_arguments() # redis usage use_redis = setup_redis(use_redis=True, use_redis_on_windows=False) # main code cc = CurrencyConverter(use_redis=use_redis) cc.update_rates_data_if_needed() cc.convert(*params) g_end('complete program run', 'complete code') # ~ 44 ms on windows w/o redis