def wrapper_decorator(*args, **kwargs): gl_project = args[1] project_id = str(gl_project.id) last_activity_current = gl_project.attributes["last_activity_at"] global language_cache if language_cache: projects = language_cache.get(gitlab_url) else: projects = dict() language_cache = dict() if projects.get(project_id): last_activity_cached, language_items = projects[project_id] last_activity_cached = MayaDT.from_iso8601(last_activity_cached) last_activity_current = MayaDT.from_iso8601(last_activity_current) if last_activity_cached >= last_activity_current: logger.debug(f"Using cache for project {gl_project.name}") return language_items """runs function normally, in-case no cache or cache is invalid""" languages = func(*args, **kwargs) """cache result""" projects[project_id] = ( gl_project.attributes["last_activity_at"], list(languages), ) language_cache[gitlab_url] = projects return languages
def create_specific_mock_state( nickname: Nickname = Nickname.from_seed(seed=None), updated: maya.MayaDT = maya.now()): # 0 out microseconds since it causes issues converting from rfc2822 and rfc3339 updated = updated.subtract(microseconds=updated.datetime().microsecond) state = MagicMock(nickname=nickname, updated=updated) return state
def paint_worklock_status(emitter, registry: BaseContractRegistry): from maya import MayaDT worklock_agent = ContractAgency.get_agent( WorkLockAgent, registry=registry) # type: WorkLockAgent blockchain = worklock_agent.blockchain # Time bidding_start = MayaDT( worklock_agent.contract.functions.startBidDate().call()) bidding_end = MayaDT(worklock_agent.contract.functions.endBidDate().call()) cancellation_end = MayaDT( worklock_agent.contract.functions.endCancellationDate().call()) bidding_duration = bidding_end - bidding_start cancellation_duration = cancellation_end - bidding_start now = maya.now() bidding_remaining = bidding_end - now if bidding_end > now else timedelta() cancellation_remaining = cancellation_end - now if cancellation_end > now else timedelta( ) payload = f""" Time ====================================================== Bidding Start Date ................... {bidding_start} Bidding End Date ..................... {bidding_end} Bidding Duration ..................... {bidding_duration} Bidding Time Remaining ............... {bidding_remaining} Cancellation Window End Date ......... {cancellation_end} Cancellation Window Duration ......... {cancellation_duration} Cancellation Window Time Remaining ... {cancellation_remaining} Claiming phase open .................. {'Yes' if worklock_agent.is_claiming_available() else 'No'} Economics ====================================================== Min allowed bid ....... {prettify_eth_amount(worklock_agent.minimum_allowed_bid)} ETH Pool .............. {prettify_eth_amount(blockchain.client.get_balance(worklock_agent.contract_address))} ETH Supply ............ {prettify_eth_amount(worklock_agent.get_eth_supply())} Bonus ETH Supply ...... {prettify_eth_amount(worklock_agent.get_bonus_eth_supply())} Number of bidders...... {worklock_agent.get_bidders_population()} Lot Size .............. {NU.from_nunits(worklock_agent.lot_value)} Bonus Lot Size ........ {NU.from_nunits(worklock_agent.get_bonus_lot_value())} Boosting Refund ....... {worklock_agent.contract.functions.boostingRefund().call()} Slowing Refund ........ {worklock_agent.contract.functions.SLOWING_REFUND().call()} Bonus Refund Rate ..... {worklock_agent.get_bonus_refund_rate()} Bonus Deposit Rate .... {worklock_agent.get_bonus_deposit_rate()} """ emitter.echo(payload) return
def create_specific_mock_state(nickname: str = 'Blue Knight Teal Club', symbol: str = '♣', color_hex: str = '#1E65F3', color: str = 'blue', updated: maya.MayaDT = maya.now()): metadata = [(dict(hex=color_hex, color=color), symbol)] # 0 out microseconds since it causes issues converting from rfc2822 and rfc3339 updated = updated.subtract(microseconds=updated.datetime().microsecond) state = MagicMock(nickname=nickname, metadata=metadata, updated=updated) return state
def test_blockchain_client_get_historical_locked_tokens(new_influx_db): mock_influxdb_client = new_influx_db.return_value mock_query_object = MagicMock(spec=ResultSet, autospec=True) mock_influxdb_client.query.return_value = mock_query_object # fake results for 5 days days = 5 start_date = maya.now().subtract(days=days) base_amount = 45000 amount_increment = 10000 results = [] for day in range(0, days): results.append(dict(time=start_date.add(days=day).rfc3339(), sum=base_amount + (day * amount_increment))) mock_query_object.get_points.return_value = results blockchain_db_client = CrawlerInfluxClient(None, None, None) locked_tokens_dict = blockchain_db_client.get_historical_locked_tokens_over_range(days) # check query today = datetime.utcnow() range_end = datetime(year=today.year, month=today.month, day=today.day, hour=0, minute=0, second=0, microsecond=0) + timedelta(days=1) # include today in range range_begin = range_end - timedelta(days=days) expected_in_query = [ "SELECT SUM(locked_stake)", "AS locked_stake", f"FROM {Crawler.NODE_MEASUREMENT} WHERE time >= '{MayaDT.from_datetime(range_begin).rfc3339()}' AND " f"time < '{MayaDT.from_datetime(range_end).rfc3339()}'", "GROUP BY staker_address, time(1d)) GROUP BY time(1d)", ] mock_influxdb_client.query.assert_called_once() mock_query_object.get_points.assert_called_once() call_args_list = mock_influxdb_client.query.call_args_list assert len(call_args_list) == 1 for idx, execute_call in enumerate(call_args_list): query = execute_call[0][0] for statement in expected_in_query: assert statement in query # check results assert len(locked_tokens_dict) == days for idx, key in enumerate(locked_tokens_dict): # use of rfc3339 loses milliseconds precision date = MayaDT.from_rfc3339(start_date.add(days=idx).rfc3339()).datetime() assert key == date locked_tokens = locked_tokens_dict[key] assert locked_tokens == base_amount + (idx * amount_increment) # close must be explicitly called on CrawlerInfluxClient mock_influxdb_client.close.assert_not_called()
def get_historical_locked_tokens_over_range(self, days: int): range_begin, range_end = self._get_range_bookends(days) results = list( self._client.query( f"SELECT SUM(locked_stake) " f"FROM (" f"SELECT staker_address, current_period, " f"LAST(locked_stake) " f"AS locked_stake " f"FROM {Crawler.NODE_MEASUREMENT} " f"WHERE time >= '{MayaDT.from_datetime(range_begin).rfc3339()}' " f"AND " f"time < '{MayaDT.from_datetime(range_end).rfc3339()}' " f"GROUP BY staker_address, time(1d)" f") " f"GROUP BY time(1d)").get_points()) # Note: all days may not have values eg. days before DB started getting populated # As time progresses this should be less of an issue locked_tokens_dict = OrderedDict() for r in results: locked_stake = r['sum'] if locked_stake: # Dash accepts datetime objects for graphs locked_tokens_dict[MayaDT.from_rfc3339( r['time']).datetime()] = locked_stake return locked_tokens_dict
def get_historical_num_stakers_over_range(self, days: int): range_begin, range_end = self._get_range_bookends(days) results = list( self._client.query( f"SELECT COUNT(staker_address) FROM " f"(" f"SELECT staker_address, LAST(locked_stake)" f"FROM {Crawler.NODE_MEASUREMENT} WHERE " f"time >= '{MayaDT.from_datetime(range_begin).rfc3339()}' AND " f"time < '{MayaDT.from_datetime(range_end).rfc3339()}' " f"GROUP BY staker_address, time(1d)" f") " "GROUP BY time(1d)").get_points()) # 1 day measurements # Note: all days may not have values eg. days before DB started getting populated # As time progresses this should be less of an issue num_stakers_dict = OrderedDict() for r in results: locked_stake = r['count'] if locked_stake: # Dash accepts datetime objects for graphs num_stakers_dict[MayaDT.from_rfc3339( r['time']).datetime()] = locked_stake return num_stakers_dict
def get_previous_states_metadata(self, limit: int = 20) -> List[Dict]: # dash threading means that connection needs to be established in same thread as use db_conn = sqlite3.connect(self._db_filepath) states_dict_list = [] try: result = db_conn.execute( f"SELECT * FROM {CrawlerNodeStorage.STATE_DB_NAME} " f"ORDER BY datetime(updated) DESC LIMIT {limit}") # TODO use `pandas` package instead to automatically get dict? column_names = [ description[0] for description in result.description ] for row in result: state_info = dict() for idx, value in enumerate(row): column_name = column_names[idx] if column_name == 'updated': # convert column from rfc3339 (for sorting) back to rfc2822 # TODO does this matter for displaying? - it doesn't, but rfc2822 is easier on the eyes state_info[column_name] = MayaDT.from_rfc3339( row[idx]).rfc2822() else: state_info[column_name] = row[idx] states_dict_list.append(state_info) return states_dict_list finally: db_conn.close()
def get_historical_locked_tokens_over_range(self, days: int): today = datetime.utcnow() range_end = datetime(year=today.year, month=today.month, day=today.day, hour=0, minute=0, second=0, microsecond=0) + timedelta(days=1) # include today range_begin = range_end - timedelta(days=days) results = list(self._client.query(f"SELECT SUM(locked_stake) " f"FROM (" f"SELECT staker_address, current_period, " f"LAST(locked_stake) " f"AS locked_stake " f"FROM moe_network_info " f"WHERE time >= '{MayaDT.from_datetime(range_begin).rfc3339()}' " f"AND " f"time < '{MayaDT.from_datetime(range_end).rfc3339()}' " f"GROUP BY staker_address, time(1d)" f") " f"GROUP BY time(1d)").get_points()) # Note: all days may not have values eg. days before DB started getting populated # As time progresses this should be less of an issue locked_tokens_dict = OrderedDict() for r in results: locked_stake = r['sum'] if locked_stake: # Dash accepts datetime objects for graphs locked_tokens_dict[MayaDT.from_rfc3339(r['time']).datetime()] = locked_stake return locked_tokens_dict
def confirm_staged_grant(emitter, grant_request: Dict, federated: bool, seconds_per_period=None) -> None: pretty_request = grant_request.copy() # WARNING: Do not mutate if federated: # Boring table = [[field.capitalize(), value] for field, value in pretty_request.items()] emitter.echo(tabulate(table, tablefmt="simple")) return period_rate = Web3.fromWei(pretty_request['n'] * pretty_request['rate'], 'gwei') pretty_request['rate'] = f"{pretty_request['rate']} wei/period * {pretty_request['n']} nodes" expiration = pretty_request['expiration'] periods = calculate_period_duration(future_time=MayaDT.from_datetime(expiration), seconds_per_period=seconds_per_period) periods += 1 # current period is always included pretty_request['expiration'] = f"{pretty_request['expiration']} ({periods} periods)" # M of N pretty_request['Threshold Shares'] = f"{pretty_request['m']} of {pretty_request['n']}" del pretty_request['m'] del pretty_request['n'] def prettify_field(field): field_words = [word.capitalize() for word in field.split('_')] field = ' '.join(field_words) return field table = [[prettify_field(field), value] for field, value in pretty_request.items()] table.append(['Period Rate', f'{period_rate} gwei']) table.append(['Policy Value', f'{period_rate * periods} gwei']) emitter.echo("\nSuccessfully staged grant, Please review the details:\n", color='green') emitter.echo(tabulate(table, tablefmt="simple")) click.confirm('\nGrant access and sign transaction?', abort=True)
class TreasureMap(DatastoreRecord): # Ideally this is a `policy.collections.TreasureMap`, but it causes a huge # circular import due to `Bob` and `Character` in `policy.collections`. # TODO #2126 _treasure_map = RecordField(bytes) _expiration = RecordField( MayaDT, encode=lambda maya_date: maya_date.iso8601().encode(), decode=lambda maya_bytes: MayaDT.from_iso8601(maya_bytes.decode()))
def maya_dt(self): """ :rtype: MayaDT """ maya_dt = MayaDT.from_datetime(self.datetime) return maya_dt
def __init__(self, r): self._get = r self._position = r['position'] self._trainer_id = r['id'] self._trainer_username = r['username'] self._user_id = r['user_id'] self._xp = int(r['xp']) self._time = MayaDT.from_iso8601(r['last_updated']).datetime() self._level = int(r['level']) self._faction = r['faction']
def get_last_seen(node_info): try: slang_last_seen = MayaDT.from_rfc3339(node_info['last_seen']).slang_time() except ParserError: # Show whatever we have anyways slang_last_seen = str(node_info['last_seen']) if slang_last_seen == NO_CONNECTION_TO_NODE: slang_last_seen = NOT_YET_CONNECTED_TO_NODE return slang_last_seen
def get_all_trips(username): """Function to get a trip document with a given trip_id.""" result = list(trips.find({'username': username})) # Include a 'slang time' such as '1 day ago' in the response for trip in result: trip['_id'] = str(trip['_id']) trip['slang_time'] = MayaDT(trip["start_time"]).slang_time() return result
def parse_time(string: str) -> MayaDT: ''' Convert a string into a time. If it's not valid (i.e., not on the hour or has no timezone), raise a ValueError. ''' time = MayaDT.from_iso8601(string) if any(t != 0 for t in (time.minute, time.second, time.microsecond)): raise ValueError(string) if time.timezone is None: raise ValueError(string) return time
class PolicyArrangement(DatastoreRecord): _arrangement_id = RecordField(bytes) _expiration = RecordField(MayaDT, encode=lambda maya_date: maya_date.iso8601().encode(), decode=lambda maya_bytes: MayaDT.from_iso8601(maya_bytes.decode())) _kfrag = RecordField(KFrag, encode=lambda kfrag: kfrag.to_bytes(), decode=KFrag.from_bytes) _alice_verifying_key = RecordField(UmbralPublicKey, encode=bytes, decode=UmbralPublicKey.from_bytes)
def paint_worklock_status(emitter, registry: BaseContractRegistry): from maya import MayaDT worklock_agent = ContractAgency.get_agent(WorkLockAgent, registry=registry) blockchain = worklock_agent.blockchain # Agency token_agent = ContractAgency.get_agent(NucypherTokenAgent, registry=registry) # Time start = MayaDT(worklock_agent.contract.functions.startBidDate().call()) end = MayaDT(worklock_agent.contract.functions.endBidDate().call()) duration = end - start remaining = end - maya.now() # TODO: Include calculated refund and deposit rates payload = f""" Time ====================================================== Start Date ........ {start} End Date .......... {end} Duration .......... {duration} Time Remaining .... {remaining} Economics ====================================================== ETH Pool .......... {blockchain.client.get_balance(worklock_agent.contract_address)} ETH Supply ........ {worklock_agent.get_eth_supply()} Lot Size .......... {NU.from_nunits(worklock_agent.lot_value)} Unclaimed Tokens .. {worklock_agent.get_unclaimed_tokens()} Boosting Refund ... {worklock_agent.contract.functions.boostingRefund().call()} Slowing Refund .... {worklock_agent.contract.functions.SLOWING_REFUND().call()} Refund Rate ....... {worklock_agent.get_refund_rate()} Deposit Rate ...... {worklock_agent.get_deposit_rate()} """ emitter.message(payload) return
def execute(self, query, hunk_size=10000, stringify=False, unit_ids=None, since=0, until=0): """ This method executes a SQL query and returns a pymssql cursor """ params = {} if unit_ids: params['unit_ids'] = [i for i in unit_ids if i] since = until = 0 else: params['unit_ids'] = [0] params['since'] = MayaDT(since).datetime().strftime( '%Y-%m-%d %H:%M:%S') params['until'] = MayaDT(until).datetime().strftime( '%Y-%m-%d %H:%M:%S') self.cursor.execute(query, params) return self.cursor
def generate_node_table_components(node_info: dict, registry) -> dict: identity = html.Td(children=html.Div([ html.A(node_info['nickname'], href=f'https://{node_info["rest_url"]}/status', target='_blank') ])) # Fleet State fleet_state_div = [] fleet_state_icon = node_info['fleet_state_icon'] if fleet_state_icon is not UNKNOWN_FLEET_STATE: icon_list = node_info['fleet_state_icon'] fleet_state_div = icon_list fleet_state = html.Td(children=html.Div(fleet_state_div)) staker_address = node_info['staker_address'] # Blockchainy (TODO) staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=registry) current_period = staking_agent.get_current_period() last_confirmed_period = staking_agent.get_last_active_period( staker_address) status = get_node_status(staking_agent, staker_address, current_period, last_confirmed_period) etherscan_url = f'https://goerli.etherscan.io/address/{node_info["staker_address"]}' try: slang_last_seen = MayaDT.from_rfc3339( node_info['last_seen']).slang_time() except ParserError: slang_last_seen = node_info['last_seen'] components = { 'Status': status, 'Checksum': html.Td( html.A(f'{node_info["staker_address"][:10]}...', href=etherscan_url, target='_blank')), 'Nickname': identity, 'Launched': html.Td(node_info['timestamp']), 'Last Seen': html.Td([slang_last_seen, f" | Period {last_confirmed_period}"]), 'Fleet State': fleet_state } return components
def _get_rows_from_xml(filepath: str, creation_date_start: MayaDT): """Parse the comments xml file and yield all row elements after the given creation date.""" parser = iter(ElementTree.iterparse(filepath, events=['start', 'end'])) _, root = next(parser) month = 0 for event, elem in parser: if event == 'end' and elem.tag == 'row': cd = MayaDT.from_rfc3339(elem.attrib['CreationDate']) if cd.month != month: month = cd.month if creation_date_start is None or creation_date_start <= cd: yield elem root.clear()
def time_remaining(n): tomorrow = datetime.utcnow() + timedelta(days=1) midnight = datetime(year=tomorrow.year, month=tomorrow.month, day=tomorrow.day, hour=0, minute=0, second=0, microsecond=0) seconds_remaining = MayaDT.from_datetime(midnight).slang_time() return html.Div( [html.H4("Next Period"), html.H5(seconds_remaining)])
def store_state_metadata(self, state: dict): # TODO Limit the size of this table - no reason to store really old state values db_row = ( state['nickname'], state['symbol'], state['color_hex'], state['color_name'], # convert to rfc3339 for ease of sqlite3 sorting; we lose millisecond precision, but meh! MayaDT.from_rfc2822(state['updated']).rfc3339()) sql = f'REPLACE INTO {self.STATE_DB_NAME} VALUES(?,?,?,?,?)' with self.db_conn: self.db_conn.execute(sql, db_row)
def _post_xml_row_to_model(elem, question_ids: Set[int] = None, target_post_type: PostType = PostType.QUESTION): """Convert an xml row from the Posts.xml file to a model. Text is sanitized before conversion. question_ids is only applicable if the target post type is PostType.ANSWER. An answer is only added if its parent_id is contained in question_ids. """ try: post_type = PostType(int(elem.attrib['PostTypeId'])) except ValueError: # was not a question or answer return None # early returns if target_post_type != post_type: return None if target_post_type == PostType.ANSWER and int( elem.attrib['ParentId']) not in question_ids: return None try: sanitized = sanitize_post(elem.attrib['Body']) except ValueError: LOGGER.error( f"Sanitization failed for Post with Id={elem.attrib['Id']}") return None date = MayaDT.from_rfc3339(elem.attrib['CreationDate']).date if post_type == PostType.ANSWER: title = None tags = None parent_id = elem.attrib['ParentId'] else: # is question title = elem.attrib['Title'] tags = elem.attrib['Tags'] parent_id = None post = Post(id=elem.attrib['Id'], creation_date=date, post_type_id=post_type.value, title=title, text=sanitized, tags=tags, parent_id=parent_id) return post
def get_trip_detail(): """Endpoint to get a trip's details.""" # Get POST information from request api_key = request.values.get('api_key', None) trip_id = request.values.get('trip_id', None) # Checks that all required information to begin a trip has been provided if not all([api_key, trip_id]): return jsonify({ "ok": False, "message": "API Key and trip ID must be provided." }) # Gets the user with the supplied API Key user = database.verify_api_key(api_key) # If no user is found, an error message is passed back to the client if not user: return jsonify({ "ok": False, "message": "API Key provided is not valid." }) # Gets the trip object with the supplied trip ID trip = database.get_trip(trip_id) # If the trip_id supplied doesn't represent a real trip, an error message is returned if not trip: return jsonify({ "ok": False, "message": "Trip ID provided is not valid." }) # If the user making the request doesn't own the trip, an error message is returned if not database.does_user_own_trip(user['username'], trip_id): return jsonify({ "ok": False, "message": "Trip does not belong to you." }) # Include a 'slang time' such as '1 day ago' in the response slang_time = MayaDT(trip["start_time"]).slang_time() return jsonify(dict(ok=True, slang_time=slang_time, **trip))
def get_historical_work_orders_over_range(self, days: int): range_begin, range_end = self._get_range_bookends(days) results = list( self._client.query( f"SELECT SUM(work_orders) FROM " f"(" f"SELECT staker_address, LAST(work_orders)" f"FROM {Crawler.NODE_MEASUREMENT} WHERE " f"time >= '{MayaDT.from_datetime(range_begin).rfc3339()}' AND " f"time < '{MayaDT.from_datetime(range_end).rfc3339()}' " f"GROUP BY staker_address, time(1d)" f") " "GROUP BY time(1d)").get_points()) # 1 day measurements work_orders_dict = OrderedDict() for r in results: num_work_orders = r['sum'] work_orders_dict[MayaDT.from_rfc3339(r['time']).datetime( )] = num_work_orders if num_work_orders else 0 return work_orders_dict
def guild_info_parser(bot, update): message = update.message text = message.text if is_guild_info(text): group_id = message.chat_id timestamp = MayaDT.from_datetime( message.forward_date).datetime().replace(tzinfo=tzlocal()) try: parse_guild_info(group_id, text, timestamp=timestamp) except GuildExistError: message.reply_text( "sorry, can't proccess the data. this group belongs to other guild." ) # print(group_id) # print(message.forward_from) # print(message.date) # print(message.forward_date) # bot.send_message(chat_id=message.chat_id, text="ok") else: bot.send_message(chat_id=group_id, text="something is wrong", parse_mode=telegram.ParseMode.MARKDOWN)
def _comment_xml_row_to_model(elem, post_ids: Set[int]): """Convert an xml row from the Comments.xml file to a model. Text is sanitized before conversion. Return None if the post_id is not contained in post_ids. """ post_id = int(elem.attrib['PostId']) if post_id not in post_ids: return None try: sanitized = sanitize_comment(elem.attrib['Text']) except Exception as e: LOGGER.error( f"Sanitization failed for Comment with Id={elem.attrib['Id']}\n" f"{type(e).__name__}\n{str(e)}") return None date = MayaDT.from_rfc3339(elem.attrib['CreationDate']).date comment = Comment(id=elem.attrib['Id'], creation_date=date, text=sanitized, post_id=post_id) return comment
def to_maya(commit): return MayaDT.from_rfc3339(commit['timestamp'])
os.getenv('NUCYPHER_CONFIG_ROOT', default=APP_DIR.user_data_dir)) USER_LOG_DIR = Path( os.getenv('NUCYPHER_USER_LOG_DIR', default=APP_DIR.user_log_dir)) DEFAULT_LOG_FILENAME = "nucypher.log" DEFAULT_JSON_LOG_FILENAME = "nucypher.json" # Static Seednodes SeednodeMetadata = namedtuple('seednode', ['checksum_address', 'rest_host', 'rest_port']) SEEDNODES = tuple() # Sentry (Add your public key and user ID below) NUCYPHER_SENTRY_PUBLIC_KEY = "" NUCYPHER_SENTRY_USER_ID = "" NUCYPHER_SENTRY_ENDPOINT = f"https://{NUCYPHER_SENTRY_PUBLIC_KEY}@sentry.io/{NUCYPHER_SENTRY_USER_ID}" # Web CLI_ROOT = NUCYPHER_PACKAGE / 'network' / 'templates' TEMPLATES_DIR = CLI_ROOT / 'templates' MAX_UPLOAD_CONTENT_LENGTH = 1024 * 50 # Dev Mode TEMPORARY_DOMAIN = ":temporary-domain:" # for use with `--dev` node runtimes # Event Blocks Throttling NUCYPHER_EVENTS_THROTTLE_MAX_BLOCKS = 'NUCYPHER_EVENTS_THROTTLE_MAX_BLOCKS' # Probationary period END_OF_POLICIES_PROBATIONARY_PERIOD = MayaDT.from_iso8601( '2022-3-17T23:59:59.0Z')