Browse Source

mmnode-blocks-info: remove --summary* options, add --stats option

The MMGen Project 4 years ago
parent
commit
0952e17837
2 changed files with 53 additions and 33 deletions
  1. 27 15
      mmgen/node_tools/BlocksInfo.py
  2. 26 18
      mmnode-blocks-info

+ 27 - 15
mmgen/node_tools/BlocksInfo.py

@@ -93,6 +93,9 @@ class BlocksInfo:
 	]
 	fs_lsqueeze2 = ['interval']
 
+	all_stats = ['range','diff']
+	dfl_stats = ['range','diff']
+
 	funcs = {
 		'df': lambda self,loc: strftime('%Y-%m-%d %X',gmtime(self.t_cur)),
 		'td': lambda self,loc: (
@@ -110,15 +113,24 @@ class BlocksInfo:
 
 	def __init__(self,cmd_args,opt,rpc):
 
+		def parse_cslist(uarg,full_set,dfl_set,desc):
+			usr_set = uarg.lstrip('+').split(',')
+			for e in usr_set:
+				if e not in full_set:
+					die(1,f'{e!r}: unrecognized {desc}')
+			res = dfl_set + usr_set if uarg[0] == '+' else usr_set
+			# display elements in order:
+			return [e for e in full_set if e in res]
+
 		def get_fields():
-			if opt.fields:
-				ufields = opt.fields.lstrip('+').split(',')
-				for field in ufields:
-					if field not in self.fields:
-						die(1,f'{field!r}: unrecognized field')
-				return self.dfl_fields + ufields if opt.fields[0] == '+' else ufields
-			else:
-				return self.dfl_fields
+			return parse_cslist(opt.fields,self.fields,self.dfl_fields,'field')
+
+		def get_stats():
+			arg = opt.stats.lower()
+			return (
+				self.all_stats if arg == 'all' else [] if arg == 'none' else
+				parse_cslist(arg,self.all_stats,self.dfl_stats,'stat')
+			)
 
 		def gen_fs(fnames):
 			for i in range(len(fnames)):
@@ -153,7 +165,8 @@ class BlocksInfo:
 
 		self.block_list,self.first,self.last = parse_cmd_args()
 
-		fnames     = get_fields()
+		fnames = get_fields() if opt.fields else self.dfl_fields
+
 		self.fvals = list(self.fields[name] for name in fnames)
 		self.fs    = ''.join(gen_fs(fnames)).strip()
 		self.deps  = set(' '.join(v.varname + ' ' + ' '.join(v.deps) for v in self.fvals).split())
@@ -180,6 +193,7 @@ class BlocksInfo:
 			self.miner_pats = None
 
 		self.block_data = namedtuple('block_data',fnames)
+		self.stats = get_stats() if opt.stats else self.dfl_stats
 
 	def conv_blkspec(self,arg):
 		if arg == 'cur':
@@ -297,7 +311,7 @@ class BlocksInfo:
 			if self.block_list:
 				await init(n)
 			ret = await self.process_block(heights[n],hashes[n],self.hdrs[n])
-			if self.opt.summary:
+			if opt.stats_only:
 				continue
 			else:
 				Msg(self.fs.format(*ret))
@@ -361,6 +375,9 @@ class BlocksInfo:
 			Msg(self.fs.format(*hdr1))
 		Msg(self.fs.format(*hdr2))
 
+	def print_stats(self,name):
+		return getattr(self,f'print_{name}_stats')()
+
 	async def print_range_stats(self):
 
 		# These figures don’t include the Genesis Block:
@@ -388,11 +405,6 @@ class BlocksInfo:
 	async def print_diff_stats(self):
 
 		c = self.rpc
-
-		# Only display stats if user-requested range ends with chain tip
-		if self.last != self.tip:
-			return
-
 		rel = self.tip % 2016
 
 		tip_hdr = (

+ 26 - 18
mmnode-blocks-info

@@ -25,11 +25,10 @@ from mmgen.node_tools.BlocksInfo import BlocksInfo
 
 opts_data = {
 	'sets': [
-		('raw_miner_info', True, 'miner_info',     True),
-		('summary',        True, 'raw_miner_info', False),
-		('summary',        True, 'miner_info',     False),
-		('hashes',         True, 'fields',         'block,hash'),
-		('hashes',         True, 'no_summary',     True),
+		('hashes',     True,   'fields',     'block,hash'),
+		('hashes',     True,   'stats',      'none'),
+		('stats',      'none', 'stats_only', False),
+		('stats_only', True,   'no_header',  True),
 	],
 	'text': {
 		'desc':    'Display information about a block or range of blocks',
@@ -42,16 +41,18 @@ opts_data = {
 		'options': """
 -h, --help            Print this help message
 --, --longhelp        Print help message for long options (common options)
--D, --no-diff-stats   Omit difficulty adjustment stats from summary
 -H, --hashes          Display only block numbers and hashes
 -m, --miner-info      Display miner info in coinbase transaction
 -M, --raw-miner-info  Display miner info in uninterpreted form
 -n, --no-header       Don’t print the column header
--o, --fields=         Display the specified fields (comma-separated list)
+-o, --fields=         Display the specified fields (comma-separated list).
                       See AVAILABLE FIELDS below.  If the first character
-                      is '+', fields are appended to the defaults.
--s, --summary         Print the summary only
--S, --no-summary      Don’t print the summary
+                      is '+', specified fields are added to the defaults.
+-s, --stats=          Display the specified stats (comma-separated list).
+                      See AVAILABLE STATS below.  If the first character is
+                      '+', specified stats are added to the defaults.  Use
+                      'none' to disable, or 'all' for all available stats.
+-S, --stats-only      Display stats only.  Skip display of per-block data.
 """,
 	'notes': """
 If no block number is specified, the current block is assumed.  The string
@@ -65,6 +66,8 @@ All fee fields except for 'totalfee' are in satoshis per virtual byte.
 
 AVAILABLE FIELDS: {f}
 
+AVAILABLE STATS: {s}
+
 EXAMPLES:
 
     # Display info for current block:
@@ -99,9 +102,13 @@ EXAMPLES:
     # multiplication is allowed in the nBlocks spec:
     {p} +144*14+144
 
+    # Display only range stats for the last ten blocks:
+    {p} -s range -S +10
+
 This program requires a txindex-enabled daemon for correct operation.
 """.format(
 		f = fmt_list(BlocksInfo.fields,fmt='bare'),
+		s = fmt_list(BlocksInfo.all_stats,fmt='bare'),
 		p = g.prog_name )
 	}
 }
@@ -116,17 +123,18 @@ async def main():
 	from mmgen.rpc import rpc_init
 	m = BlocksInfo( cmd_args, opt, await rpc_init(proto) )
 
-	if not (opt.summary or opt.no_header):
+	if not opt.no_header:
 		m.print_header()
 
 	await m.run()
 
-	if m.last and not opt.no_summary:
-		Msg('')
-		await m.print_range_stats()
-
-		if not opt.no_diff_stats:
-			Msg('')
-			await m.print_diff_stats()
+	if m.last and m.stats:
+		for i,stat in enumerate(m.stats):
+			if stat == 'diff': # Display diff stats by default only if user-requested range ends with chain tip
+				if not opt.stats and m.last != m.tip:
+					continue
+			if not (opt.stats_only and i == 0):
+				Msg('')
+			await m.print_stats(stat)
 
 run_session(main())