def test_brackets_wrapping(self): """A bracket block that wraps over multiple lines.""" cases = [ [[ 'abcd [ inside block', 'abcd ', ], [ 'inside block ] efg', ' efg', ]], [[ 'abcd', 'abcd', ], [ 'abcd [ inside block', 'abcd ', ], [ 'inside block', '', ], [ 'inside block comment ] efg', ' efg', ]], ] blocks = Blocks() for lines in cases: blocks.reset() for line in lines: self.assertEqual(blocks.remove(line[0]), line[1])
def execute_strategy(strategy, args, options): """Compile the proze project using the strategy. @type strategy: BaseStrategy @param strategy: Strategy to use. @type args: object @param args: Parsed command line args. @type options: DotMap @param options: Compile options parsed from the config file. """ blocks = Blocks() names = Names(options) state = State() output_path = args.output + '.' + args.doctype os.makedirs(os.path.dirname(output_path), exist_ok=True) with strategy.compile(output_path) as compiler: for filename in options.compile.order: path = args.path + '/' + filename try: with open(path, 'r') as proze_file: blocks.reset() state.reset() line_number = 0 for raw_line in proze_file: line_number = line_number + 1 line = blocks.remove(raw_line) state.update(raw_line) check_invalid_names(line, path, line_number, names) if line: compiler.write(line, state) except FileNotFoundError: print('MISSING: Cannot find file "{}". '.format(path) + 'Update the file names in your config file.')
def test_wrapped_blocks_hiding(self): """Test wrapped blocks hiding each other..""" cases = [ [[ 'abcd ### inside block comment', 'abcd ', ], [ '[inside block comment ### efg', ' efg', ]], [[ 'abcd [ inside block comment', 'abcd ', ], [ '###inside block comment ] efg', ' efg', ]], [[ 'abcd', 'abcd', ], [ 'abcd ### inside block ] comment', 'abcd ', ], [ 'inside block [ comment', '', ], [ 'inside block comment ### efg', ' efg', ]], [[ 'abcd', 'abcd', ], [ 'abcd [ inside block ### comment', 'abcd ', ], [ 'inside block comment', '', ], [ 'inside block comment ] efg', ' efg', ]], [[ 'abcd ## hidden by [ line comment', 'abcd ', ], [ 'efg', 'efg', ]], ] blocks = Blocks() for lines in cases: blocks.reset() for line in lines: self.assertEqual(blocks.remove(line[0]), line[1])
def test_no_blocks(self): """A line that doesn't have any comments.""" lines = [ '"Furthermore," she said, "I would never take a deal like that."', 'Use the hashtag #withoutHoldings on that post.', 'Nothing looks right in here.', '', ] blocks = Blocks() for line in lines: self.assertEqual(blocks.remove(line), line)
def test_comment_block_line_comment_adjacent(self): """A line comment is adjacent to the ending block comment.""" lines = [ [ 'abcd ### test of hidden ##### and this is hidden too', 'abcd ', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def test_comment_block_wrapping(self): """Test a block comment wrapping across multiple lines.""" cases = [ [[ 'abcd ### inside block comment', 'abcd ', ], [ 'inside block comment ### efg', ' efg', ]], [[ 'abcd', 'abcd', ], [ 'abcd ### inside block comment', 'abcd ', ], [ 'inside block comment', '', ], [ 'inside block comment ### efg', ' efg', ]], [[ 'abcd ### inside block comment', 'abcd ', ], [ 'this is all ## inside block comment', '', ], [ 'inside block comment ### efg', ' efg', ]], [[ 'abcd ## this will not start ### a block comment', 'abcd ', ], [ 'abcd ### inside block comment', 'abcd ', ], [ 'this is all ## inside block comment', '', ], [ 'inside block comment ### efg', ' efg', ]], ] blocks = Blocks() for lines in cases: blocks.reset() for line in lines: self.assertEqual(blocks.remove(line[0]), line[1])
def test_comment_tokens_in_brackets(self): """Comment tokens aren't recognized inside bracket blocks.""" lines = [ [ 'abcd [ hidden ### hidden ] ef', 'abcd ef', ], [ 'abcd [ ## hidden ## hidden ] efg', 'abcd efg', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def test_comment_block_hides_line_comment(self): """A line comment token is hidden by a block token.""" lines = [ [ 'abcd ### test of hidden ## token ### ef', 'abcd ef', ], [ 'abcd ### test of hidden ## token', 'abcd ', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def test_line_comment_hides_block_comment(self): """A block comment token is hidden by a line token.""" lines = [ [ 'abcd ## test of ### hidden block ### comment token', 'abcd ', ], [ 'abcd ## test of ### hidden block comment token', 'abcd ', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def test_comment_block_no_spacing(self): """Block tokens without spacing between them.""" lines = [ [ 'abcd ### hidden ###### also hidden ### ef', 'abcd ef', ], [ 'abcd### hidden ###ef', 'abcdef', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def test_multiple_brackets_per_line(self): """Lines that have multiple blocks.""" lines = [ [ 'a [ test ] b [ test ] c', 'a b c', ], [ 'a [ test ] bcde [ f g ]', 'a bcde ', ], [ 'a [ test ] bcde [ f g', 'a bcde ', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def test_escape_comment_line(self): """Bracket tokens aren't matched if they are escaped.""" lines = [ [ r'abcd \## efg', r'abcd \## efg', ], [ r'abcd \## efg ## test', r'abcd \## efg ', ], [ r'abcd ## efg ## test', r'abcd ', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def test_escape_brackets(self): """Bracket tokens aren't matched if they are escaped.""" lines = [ [ r'abcd \[ efg', r'abcd \[ efg', ], [ r'abcd \[ efg [ this is hidden ]', r'abcd \[ efg ', ], [ r'abcd \[ efg [ this is hidden \] hij ]', r'abcd \[ efg ', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def test_comments_hide_brackets(self): """A comment token hides a bracket block.""" lines = [ [ 'abcd ## test of [ hidden block ] comment token', 'abcd ', ], [ 'abcd ### test of [ hidden block ] comment token', 'abcd ', ], [ 'abcd ### test of [ hidden block ] comment token ### efg', 'abcd efg', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def test_multiple_mixed_comment_bracket_blocks(self): """Lines that have multiple block comments.""" lines = [ [ 'a ### test ### b [ test ] c', 'a b c', ], [ 'a [ test] bcde ### f g ###', 'a bcde ', ], [ 'a ### test ### bcde [ f g', 'a bcde ', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def test_comment_block(self): """Normal usage of a block comment.""" lines = [ [ 'abcd ### hidden ### efg', 'abcd efg', ], [ '### hidden ###', '', ], [ ' ### hidden ### ', ' ', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def test_brackets_on_same_line(self): """Brackets open and close on same line.""" lines = [ [ 'abcd [hidden] efg', 'abcd efg', ], [ 'abcd[hidden]efg', 'abcdefg', ], [ '[ hidden ]', '', ], [ ' [ hidden ] ', ' ', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def test_line_comment_token(self): """Normal usage of a line comment token.""" lines = [ [ 'abcd ## The rest of the line is hidden', 'abcd ', ], [ 'abcd ##', 'abcd ', ], [ '## The entire line is hidden', '', ], [ ' ## The entire line is hidden', ' ', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def test_brackets_hide_comments(self): """A bracket block hiding comment tokens.""" lines = [ [ 'abcd [ test of ### hidden block ### comment token ]', 'abcd ', ], [ 'abcd [ test of ## hidden block comment token]', 'abcd ', ], [ 'abcd [ test of ### hidden block ### comment token ] efg', 'abcd efg', ], [ 'abcd [ test of ## hidden block comment token ] efg', 'abcd efg', ], ] blocks = Blocks() for line in lines: blocks.reset() self.assertEqual(blocks.remove(line[0]), line[1])
def __init__(self): self.delegate = Delegates() self.account = Accounts() self.blocks = Blocks()
class Monitor: """ 1.监控top101受托人的丢块信息,超过50分钟未出块视为丢块 2.监控top101受托人的XAS余额,不足50000或者150000的要报警,已剔除官方账号asch_gxx done 3.监控top101受托人节点记录的账户余额top100的信息是否一致(随机抽取2个节点在整点的时候进行对比,时间对10取模为0) """ def __init__(self): self.delegate = Delegates() self.account = Accounts() self.blocks = Blocks() def get_top_101(self): payload = {'limit': 100, 'orderBy': 'approval:desc'} return self.delegate.get_delegates(payload) def check_block(self, publickey): payload = { 'generatorPublicKey': publickey, 'limit': 1, 'orderBy': 'height:desc' } return self.blocks.get_blocks(payload) @staticmethod def check_time(last_block_time): now = int(time.time()) - 1467057600 # UTC+8时区-asch创世块生成时间,即asch纪元元年0点(2016/6/28 4:0:0,js时间为UTC(2016, 5, 27, 20, 0, 0, 0) ) difftime = now - last_block_time return difftime def check_time_batch(self, top_delegates): data = top_delegates issuse_delegates = [] # for delegate in data['delegates'][1:3]: for delegate in data['delegates']: pubkey = delegate['publicKey'] data = self.check_block(pubkey) if data['success']: if len(data['blocks']) > 0: last_block_time = data['blocks'][0][ 'timestamp'] # 这个是自asch主链创世块生成时间以来经历的秒数 difftime = self.check_time(last_block_time) if difftime > 50 * 60: res = { 'username': delegate['username'], 'rate': delegate['rate'], 'height': data['blocks'][0]['height'], 'behind_seconds': difftime } issuse_delegates.append(res) else: print "api返回成功但貌似没有数据", data return issuse_delegates @staticmethod def check_balance(top_delegates): data = top_delegates nsf = [] # 余额不足5万XAS(not sufficient funds)受托人账户列表 if data['success']: for delegate in data['delegates']: if delegate['username'].find('asch_g') < 0: if delegate['balance'] < 50000 * 100000000: res = { 'username': delegate['username'], 'balance': delegate['balance'] / 10**8 } nsf.append(res) return nsf @staticmethod def send_main(content): sub = 'asch_monitor' return send_mail(mailto_list, sub, content)
class AschQQBot(QQBot): dsp = '请给受托人zhenxi投票,非常感谢。本广告位租赁价格:100XAS/天' delegates = Delegates() accounts = Accounts() blocks = Blocks() mt = Monitor() httpapi = HttpApi() headers = {'content-type': 'application/json'} def onPollComplete(self, msgtype, from_uin, buddy_uin, message): if message.find('@Asch小妹') == 0: if message == '@Asch小妹 price': res = self.price() elif message.find('@Asch小妹 delegate') == 0: res = self.delegate(message) elif message.find('@Asch小妹 balance') == 0: res = self.balance(message) elif message == '@Asch小妹 getheight': res = self.getheight(message) elif message.find('@Asch小妹 gettestcoin') == 0: res = self.gettestcoin(message) elif message == '@Asch小妹 info': res = self.info() elif message == "@Asch小妹 help": res = self.usage() else: res = ["face", 33] print res self.send(msgtype, from_uin, res) @staticmethod def get_price(host, coin): url = host + '/api/v1/ticker?coin=' + coin res = json.loads(requests.get(url).text) # https not verify CA python 2.7.9 SNI return res def price(self): btc_price = float(self.get_price('https://jubi.com', 'btc')['last']) res_all = [] platforms = [('https://btcbox.com', 'BTC'), ('http://jubi.com', 'CNY')] for i in platforms: host, unit = i res = self.get_price(host, 'xas') if unit == 'CNY': price = str(round(float(res['last']), 3)) + ' CNY' elif unit == 'BTC': price_btc = res['last'] price_cny = round(float(price_btc) * btc_price, 3) price = str(price_btc) + ' BTC(' + str(price_cny) + 'CNY)' res = [ host, "最新成交价:" + price, "24小时成交:" + str(int(res['vol']) / 10000) + '万XAS' ] res_all.extend(res) res_all = "\n".join(res_all) res_all = res_all + "\n\n" + self.dsp return res_all def delegate(self, message): m_li = message.split() # ['Asch小妹','delegate','zhenxi'] if len(m_li) == 3: delegate_name = m_li[2].strip() payload = {'username': delegate_name} dres = self.delegates.get_info(payload) if dres['success']: delegate = dres['delegate'] pubkey = delegate['publicKey'] address = delegate['address'] balance = self.get_balance(address) data = self.mt.check_block(pubkey) if data['success']: if len(data['blocks']) > 0: last_block_time = data['blocks'][0]['timestamp'] # 这个是自asch主链创世块生成时间以来经历的秒数 difftime = str( self.mt.check_time(last_block_time) / 60) + '分钟之前' else: # print "warings:api返回成功但貌似没有数据 or not top101", data difftime = '非前101名,不产块' res = [ '受托人:' + delegate_name, '排名:' + str(delegate['rate']), '生产率:' + str(delegate['productivity']), '锻造总额:' + str(delegate['rewards'] / 10**8) + 'XAS', '账户余额:' + str(balance) + 'XAS', '最后出块时间:' + difftime ] else: res = ['受托人' + delegate_name + '不存在'] res.append(self.dsp) res = '\n'.join(res) else: res = self.usage() return str(res) def getheight(self): res = self.blocks.get_height() if res['success']: height = res['height'] else: height = None return '当前区块高度为:' + str(height) def gettestcoin(self, message): m_li = message.split() # ['Asch小妹','delegate','1111'] info = '用法:@Asch小妹 gettestcoin Asch地址' if len(m_li) == 3: addr = m_li[2].strip() secret = "lounge barrel episode lock bounce power club boring slush disorder cluster client" amount = 500 * 10**8 payload = {"secret": secret, "amount": amount, "recipientId": addr} api = "http://45.32.248.33:4096/api/transactions" rs = json.loads( requests.put(api, data=json.dumps(payload), headers=self.headers).text) print rs if rs['success']: info = '成功给%s转账500 XAS。\n测试地址为:http://45.32.248.33:4096' % addr else: info = '转账失败.报错信息:%s' % str(rs) return info def get_balance(self, address): payload = {'address': address} rs = self.accounts.balance(payload) if rs['success']: balance = round(rs['balance'] / 10**8, 1) else: balance = '查询出错' return balance def balance(self, message): m_li = message.split() # ['Asch小妹','balance','top101_delegates'] if len(m_li) == 3: address = m_li[2].strip() if address == 'top101_delegates': pass elif address.isdigit(): balance = self.get_balance(address) res = address + '余额为:' + str(balance) + 'XAS' else: res = self.usage() else: res = self.usage() return res @staticmethod def info(): info = ''' 官网:www.asch.so 白皮书:www.asch.so/asch-whitepaper.pdf github:github.com/sqfasd/asch asch相关文档:https://github.com/sqfasd/asch_docs asch共识机制:http://blog.asch.so/2016/08/11/asch-consensus-and-fault-tolerance/ QQ群:545183438(开发者) 社区:forum.asch.so ''' return info @staticmethod def usage(): usage = ''' Asch小妹目前可以实现的功能: 1、price,查询asch的价格 2、delegate 受托人名字,查询受托人的出块情况 3、getheight,查询当前区块链高度 4、info,asch相关介绍,如官网、github等 5、gettestcoin 地址,申请测试币(500 XAS) 6、help,查看Asch小妹的功能列表 举例:@Asch小妹 price,可以获取到XAS当前的价格 ''' usage = usage + '\t' + AschQQBot.dsp return usage
class Monitor: """ 1.监控top101受托人的丢块信息,超过50分钟未出块视为丢块 done 2.监控top101受托人的XAS余额,不足50000或者150000的要报警,已剔除官方账号asch_g done 3.监控top101受托人节点记录的账户余额top100的信息是否一致(随机抽取2个节点在整点的时候进行对比,时间对10取模为0)done """ def __init__(self): self.delegate = Delegates() self.account = Accounts() self.blocks = Blocks() self.peers = Peers() def get_peers(self): rs = self.peers.peers('') if rs['success']: res = rs['peers'] else: res = None return res def get_top100_balance(self): res = self.account.top('') return res def check_peers(self): peers = self.get_peers() if peers is not None: cnt = len(peers) num = random.randint(0, cnt-1) ip = peers[num]['ip'] port = str(peers[num]['port']) url = 'http://' + ip + ':' + port + '/api/accounts/top' rs = json.loads(requests.get(url).text) # print 'rs is:', rs rs_official = self.get_top100_balance() # print 'rs_official is:', rs_official res = [] if rs['success'] and rs_official['success']: for i in range(0, 99): balance = rs['accounts'][i]['balance'] balance_official = rs_official['accounts'][i]['balance'] # print 'balance:', balance, 'balance_official', balance_official if balance != balance_official: res.append([ip, rs['accounts'][i]['address'], str(balance)+'XAS']) res.append(['mainnet.asch.so', rs_official['accounts'][i]['address'], str(balance_official) + 'XAS']) break if len(res) == 0: res.append("The top 100 accounts's balance of "+ip+":"+str(port)+" is same with mainnet.asch.so.") return res def get_top_101(self): payload = {'limit': 100, 'orderBy': 'approval:desc' } return self.delegate.get_delegates(payload) def check_block(self, publickey): payload = {'generatorPublicKey': publickey, 'limit': 1, 'orderBy': 'height:desc' } return self.blocks.get_blocks(payload) @staticmethod def check_time(last_block_time): now = int(time.time()) - 1467057600 # UTC+8时区-asch创世块生成时间,即asch纪元元年0点(2016/6/28 4:0:0,js时间为UTC(2016, 5, 27, 20, 0, 0, 0) ) difftime = now - last_block_time return difftime def check_time_batch(self, top_delegates): data = top_delegates issue_delegates = [] # for delegate in data['delegates'][1:3]: for delegate in data['delegates']: pubkey = delegate['publicKey'] data = self.check_block(pubkey) if data['success']: if len(data['blocks']) > 0: last_block_time = data['blocks'][0]['timestamp'] # 这个是自asch主链创世块生成时间以来经历的秒数 difftime = self.check_time(last_block_time) if difftime > 50*60: res = [delegate['username'], str(delegate['rate']), str(data['blocks'][0]['height']), str(round(difftime/60/60, 2))] issue_delegates.append(res) else: print "warings:api返回成功但貌似没有数据", data return issue_delegates @staticmethod def check_balance(top_delegates): data = top_delegates del_150k_xas = open('config/delegate_150k_xas.txt', 'r').readlines() nsf = [] # 余额不足5万XAS(not sufficient funds)受托人账户列表 if data['success']: for delegate in data['delegates']: name = delegate['username'].strip() balance = delegate['balance']/10**8 if name.find('asch_g') < 0: if name+'\n' in del_150k_xas: # 需要150k的受托人 # print name, balance if balance < 15*10000: res = [name, str(balance)] nsf.append(res) else: # 需要50k的受托人 if balance < 5*10000: res = [name, str(balance)] nsf.append(res) return nsf @staticmethod def send_mail(content): sub = 'asch_monitor' return send_mail(mailto_list, sub, content)