Browse Source

mmgen-ticker: various fixes and cleanups

The MMGen Project 1 month ago
parent
commit
a8adef0be5
3 changed files with 41 additions and 36 deletions
  1. 22 17
      mmgen_node_tools/Ticker.py
  2. 1 1
      test/cmdtest_d/httpd/ticker.py
  3. 18 18
      test/cmdtest_d/misc.py

+ 22 - 17
mmgen_node_tools/Ticker.py

@@ -25,7 +25,7 @@ from decimal import Decimal
 from collections import namedtuple
 
 from mmgen.color import red, yellow, green, blue, orange, gray
-from mmgen.util import msg, msg_r, Msg, Msg_r, die, fmt, fmt_list, fmt_dict, list_gen
+from mmgen.util import msg, msg_r, Msg, Msg_r, die, fmt, fmt_list, fmt_dict, list_gen, suf
 from mmgen.ui import do_pager
 
 homedir = os.getenv('HOME')
@@ -99,18 +99,21 @@ class DataSource:
 			if not os.path.exists(cfg.cachedir):
 				os.makedirs(cfg.cachedir)
 
-			if not os.path.exists(self.json_fn):
-				open(self.json_fn, 'w').write('{}')
-
 			use_cached_data = cfg.cached_data and not gcfg.download
 
 			if use_cached_data:
 				data_type = 'json'
-				data_in = open(self.json_fn).read()
+				try:
+					data_in = open(self.json_fn).read()
+				except FileNotFoundError:
+					die(1, f'Cannot use cached data, because {self.json_fn_disp} does not exist')
 			else:
 				data_type = self.net_data_type
-				elapsed = int(time.time() - os.stat(self.json_fn).st_mtime)
-				if elapsed >= self.timeout or gcfg.testing:
+				try:
+					mtime = os.stat(self.json_fn).st_mtime
+				except FileNotFoundError:
+					mtime = 0
+				if (elapsed := int(time.time() - mtime)) >= self.timeout or gcfg.testing:
 					if gcfg.testing:
 						msg('')
 					self.fetch_delay()
@@ -148,14 +151,14 @@ class DataSource:
 
 			if use_cached_data:
 				if not cfg.quiet:
-					msg(f'Using cached data from ~/{self.json_fn_rel}')
+					msg(f'Using cached data from {self.json_fn_disp}')
 			else:
 				if os.path.exists(self.json_fn):
 					os.rename(self.json_fn, self.json_fn + '.bak')
 				with open(self.json_fn, 'w') as fh:
 					fh.write(json_text)
 				if not cfg.quiet:
-					msg(f'JSON data cached to ~/{self.json_fn_rel}')
+					msg(f'JSON data cached to {self.json_fn_disp}')
 				if gcfg.download:
 					sys.exit(0)
 
@@ -168,8 +171,8 @@ class DataSource:
 			return data
 
 		@property
-		def json_fn_rel(self):
-			return os.path.relpath(self.json_fn, start=homedir)
+		def json_fn_disp(self):
+			return '~/' + os.path.relpath(self.json_fn, start=homedir)
 
 	class coinpaprika(base):
 		desc = 'CoinPaprika'
@@ -186,8 +189,9 @@ class DataSource:
 			self.asset_limit = int(cfg.asset_limit or self.dfl_asset_limit)
 
 		def rate_limit_errmsg(self, elapsed):
+			rem = self.timeout - elapsed
 			return (
-				f'Rate limit exceeded!  Retry in {self.timeout-elapsed} seconds' +
+				f'Rate limit exceeded!  Retry in {rem} second{suf(rem)}' +
 				('' if cfg.btc_only else ', or use --cached-data or --btc'))
 
 		@property
@@ -270,7 +274,8 @@ class DataSource:
 				'last_updated': data['regularMarketTime']}
 
 		def rate_limit_errmsg(self, elapsed):
-			return f'Rate limit exceeded!  Retry in {self.timeout-elapsed} seconds, or use --cached-data'
+			rem = self.timeout - elapsed
+			return f'Rate limit exceeded!  Retry in {rem} second{suf(rem)}, or use --cached-data'
 
 		@property
 		def json_fn(self):
@@ -364,10 +369,10 @@ def gen_data(data):
 	checking for duplicates.
 	"""
 
-	def dup_sym_errmsg(dup_sym):
+	def dup_sym_errmsg(data_type, dup_sym):
 		return (
 			f'The symbol {dup_sym!r} is shared by the following assets:\n' +
-			'\n  ' + '\n  '.join(d['id'] for d in data['cc'] if d['symbol'] == dup_sym) +
+			'\n  ' + '\n  '.join(d['id'] for d in data[data_type].data if d['symbol'] == dup_sym) +
 			'\n\nPlease specify the asset by one of the full IDs listed above\n' +
 			f'instead of {dup_sym!r}')
 
@@ -421,7 +426,7 @@ def gen_data(data):
 				if not isinstance(v, dict):
 					die(2, str(v))
 				if id in found['id']:
-					die(1, dup_sym_errmsg(id))
+					die(1, dup_sym_errmsg('fi', id))
 				if m := data['hi'].get(k):
 					spot = v['regularMarketPrice']['raw']
 					hist = tuple(m.values())
@@ -444,7 +449,7 @@ def gen_data(data):
 			if wants[k]:
 				if d[k] in wants[k]:
 					if d[k] in found[k]:
-						die(1, dup_sym_errmsg(d[k]))
+						die(1, dup_sym_errmsg('cc', d[k]))
 					if not 'price_usd' in d:
 						d['price_usd'] = Decimal(str(d['quotes']['USD']['price']))
 						d['price_btc'] = Decimal(str(d['quotes']['USD']['price'])) / btcusd

+ 1 - 1
test/cmdtest_d/httpd/ticker.py

@@ -21,7 +21,7 @@ class TickerServer(HTTPD):
 
 	def make_response_body(self, method, environ):
 
-		with open(f'test/ref/ticker/ticker.json') as fh:
+		with open('test/ref/ticker/ticker.json') as fh:
 			text = fh.read()
 
 		return text.encode()

+ 18 - 18
test/cmdtest_d/misc.py

@@ -61,19 +61,16 @@ class CmdTestScripts(CmdTestBase):
 	color = True
 
 	cmd_group_in = (
-		('subgroup.ticker_setup', []),
-		('subgroup.ticker',       ['ticker_setup']),
+		('subgroup.ticker',       []),
 	)
 	cmd_subgroups = {
-	'ticker_setup': (
-		"setup for 'ticker' subgroup",
-		('ticker_setup', 'ticker setup'),
-	),
 	'ticker': (
 		"'mmnode-ticker' script",
 		('ticker1',  'ticker [--help]'),
+		('copy_files', 'copying JSON files to cache'),
+		('ticker1a', 'ticker [--download=cc] (early caching)'),
+		('ticker1b', 'ticker [--download=cc] (late caching)'),
 		('ticker2',  'ticker (bad proxy)'),
-		('ticker2a', 'ticker [--download=cc]'),
 		('ticker3',  'ticker [--cached-data]'),
 		('ticker4',  'ticker [--cached-data --wide]'),
 		('ticker5',  'ticker [--cached-data --wide --adjust=-0.766] (usr cfg file)'),
@@ -103,7 +100,7 @@ class CmdTestScripts(CmdTestBase):
 	def nt_datadir(self):
 		return os.path.join( cfg.data_dir_root, 'node_tools' )
 
-	def ticker_setup(self):
+	def copy_files(self):
 		self.spawn('',msg_only=True)
 		shutil.copy2(os.path.join(refdir,'ticker-finance.json'),self.tmpdir)
 		shutil.copy2(os.path.join(refdir,'ticker-finance-history.json'),self.tmpdir)
@@ -135,20 +132,23 @@ class CmdTestScripts(CmdTestBase):
 		t.expect('USAGE:')
 		return t
 
-	def ticker2(self):
-		t = self.ticker(cached_data=False)
-		if not cfg.skipping_deps:
-			t.expect('Creating')
-			t.expect('Creating')
-		ret = t.expect(['proxy host could not be resolved', 'unexpected keyword'])
-		t.exit_val = 1 if ret else 3
-		return t
-
-	def ticker2a(self):
+	def ticker1a(self, first_run=True):
 		t = self.ticker(
 			add_opts = ['--proxy', '', '--download=cc'],
 			cached_data = False,
 			use_proxy = False)
+		if first_run and not cfg.skipping_deps:
+			t.expect('Creating')
+			t.expect('Creating')
+		return t
+
+	def ticker1b(self):
+		return self.ticker1a(first_run=False)
+
+	def ticker2(self):
+		t = self.ticker(cached_data=False)
+		ret = t.expect(['proxy host could not be resolved', 'unexpected keyword'])
+		t.exit_val = 1 if ret else 3
 		return t
 
 	def ticker3(self):