def _annotate_first_of_milestones(self, feature_list, version=None): try: omaha_data = util.get_omaha_data() win_versions = omaha_data[0]['versions'] # Find the latest canary major version from the list of windows versions. canary_versions = [x for x in win_versions if x.get('channel') and x.get('channel').startswith('canary')] LATEST_VERSION = int(canary_versions[0].get('version').split('.')[0]) milestones = range(1, LATEST_VERSION + 1) milestones.reverse() versions = [ IMPLEMENTATION_STATUS[NO_ACTIVE_DEV], IMPLEMENTATION_STATUS[PROPOSED], IMPLEMENTATION_STATUS[IN_DEVELOPMENT], ] versions.extend(milestones) versions.append(IMPLEMENTATION_STATUS[NO_LONGER_PURSUING]) first_of_milestone_func = Feature._first_of_milestone if version == 2: first_of_milestone_func = Feature._first_of_milestone_v2 last_good_idx = 0 for i, ver in enumerate(versions): idx = first_of_milestone_func(feature_list, ver, start=last_good_idx) if idx != -1: feature_list[idx]['first_of_milestone'] = True last_good_idx = idx except Exception as e: logging.error(e)
def construct_chrome_channels_details(): omaha_data = util.get_omaha_data() channels = {} win_versions = omaha_data[0]['versions'] for v in win_versions: channel = v['channel'] major_version = int(v['version'].split('.')[0]) channels[channel] = fetch_chrome_release_info(major_version) channels[channel]['version'] = major_version # Adjust for the brief period after a stable release where stable and beta # are on the same major version. if channels['stable']['version'] == channels['beta']['version']: channels['beta'] = channels['dev'] channels['dev'] = channels['canary'] return channels
def construct_chrome_channels_details(): omaha_data = util.get_omaha_data() channels = {} win_versions = omaha_data[0]['versions'] for v in win_versions: channel = v['channel'] major_version = int(v['version'].split('.')[0]) channels[channel] = fetch_chrome_release_info(major_version) channels[channel]['version'] = major_version # Adjust for the brief period after next miletone gets promted to stable/beta # channel and their major versions are the same. if channels['stable']['version'] == channels['beta']['version']: new_beta_version = channels['stable']['version'] + 1 channels['beta'] = fetch_chrome_release_info(new_beta_version) channels['beta']['version'] = new_beta_version new_dev_version = channels['beta']['version'] + 1 channels['dev'] = fetch_chrome_release_info(new_dev_version) channels['dev']['version'] = new_dev_version return channels
def get(self, path, feature_id=None): # Default to features page. # TODO: remove later when we want an index.html if not path: return self.redirect('/features') # Default /metrics to CSS ranking. # TODO: remove later when we want /metrics/index.html if path == 'metrics' or path == 'metrics/css': return self.redirect('/metrics/css/popularity') # Remove trailing slash from URL and redirect. e.g. /metrics/ -> /metrics if feature_id == '': return self.redirect(self.request.path.rstrip('/')) template_data = {} push_urls = [] # URLs to push in this response. template_data['embed'] = self.request.get('embed', None) is not None if path.startswith('features'): if path.endswith('.xml'): # Atom feed request. status = self.request.get('status', None) if status: feature_list = models.Feature.get_all_with_statuses( status.split(',')) else: filterby = None category = self.request.get('category', None) # Support setting larger-than-default Atom feed sizes so that web # crawlers can use this as a full site feed. try: max_items = int( self.request.get('max-items', settings.RSS_FEED_LIMIT)) except TypeError: max_items = settings.RSS_FEED_LIMIT if category is not None: for k, v in models.FEATURE_CATEGORIES.iteritems(): normalized = normalized_name(v) if category == normalized: filterby = ('category =', k) break feature_list = models.Feature.get_all( # Memcached limit=max_items, filterby=filterby, order='-updated') return self.render_atom_feed('Features', feature_list) else: template_data['categories'] = [ (v, normalized_name(v)) for k, v in models.FEATURE_CATEGORIES.iteritems() ] template_data['IMPLEMENTATION_STATUSES'] = json.dumps([{ 'key': k, 'val': v } for k, v in models.IMPLEMENTATION_STATUS.iteritems()]) template_data['VENDOR_VIEWS'] = json.dumps([{ 'key': k, 'val': v } for k, v in models.VENDOR_VIEWS.iteritems()]) template_data['WEB_DEV_VIEWS'] = json.dumps([{ 'key': k, 'val': v } for k, v in models.WEB_DEV_VIEWS.iteritems()]) template_data['STANDARDS_VALS'] = json.dumps([{ 'key': k, 'val': v } for k, v in models.STANDARDIZATION.iteritems()]) push_urls = http2push.use_push_manifest( 'push_manifest_features.json') elif path.startswith('feature'): feature = None try: feature = models.Feature.get_feature(int(feature_id)) except TypeError: pass if feature is None: self.abort(404) was_updated = False if self.request.referer: was_updated = ( self.request.referer.endswith('/admin/features/new') or '/admin/features/edit' in self.request.referer) template_data['feature'] = feature template_data['was_updated'] = was_updated elif path.startswith('metrics/css/timeline'): properties = sorted( models.CssPropertyHistogram.get_all().iteritems(), key=lambda x: x[1]) template_data['CSS_PROPERTY_BUCKETS'] = json.dumps( properties, separators=(',', ':')) elif path.startswith('metrics/feature/timeline'): properties = sorted( models.FeatureObserverHistogram.get_all().iteritems(), key=lambda x: x[1]) template_data['FEATUREOBSERVER_BUCKETS'] = json.dumps( properties, separators=(',', ':')) elif path.startswith('omaha_data'): omaha_data = util.get_omaha_data() return common.JSONHandler.get(self, omaha_data, formatted=True) if path.startswith('metrics/'): push_urls = http2push.use_push_manifest( 'push_manifest_metrics.json') # Add Link rel=preload header for h2 push on .html file requests. if push_urls: self.response.headers.add_header( 'Link', self._generate_link_preload_headers(push_urls)) self.render(data=template_data, template_path=os.path.join(path + '.html'))
def get(self, path, feature_id=None): # Default to features page. # TODO: remove later when we want an index.html if not path: return self.redirect('/features') # Default /metrics to CSS ranking. # TODO: remove later when we want /metrics/index.html if path == 'metrics' or path == 'metrics/css': return self.redirect('/metrics/css/popularity') # Remove trailing slash from URL and redirect. e.g. /metrics/ -> /metrics if feature_id == '': return self.redirect(self.request.path.rstrip('/')) template_data = {} push_urls = [] # URLs to push in this response. template_data['embed'] = self.request.get('embed', None) is not None if path.startswith('features'): if path.endswith('.xml'): # Atom feed request. status = self.request.get('status', None) if status: feature_list = models.Feature.get_all_with_statuses(status.split(',')) else: filterby = None category = self.request.get('category', None) # Support setting larger-than-default Atom feed sizes so that web # crawlers can use this as a full site feed. try: max_items = int(self.request.get('max-items', settings.RSS_FEED_LIMIT)) except TypeError: max_items = settings.RSS_FEED_LIMIT if category is not None: for k,v in models.FEATURE_CATEGORIES.iteritems(): normalized = normalized_name(v) if category == normalized: filterby = ('category =', k) break feature_list = models.Feature.get_all( # Memcached limit=max_items, filterby=filterby, order='-updated') return self.render_atom_feed('Features', feature_list) else: template_data['categories'] = [ (v, normalized_name(v)) for k,v in models.FEATURE_CATEGORIES.iteritems()] template_data['IMPLEMENTATION_STATUSES'] = json.dumps([ {'key': k, 'val': v} for k,v in models.IMPLEMENTATION_STATUS.iteritems()]) template_data['VENDOR_VIEWS'] = json.dumps([ {'key': k, 'val': v} for k,v in models.VENDOR_VIEWS.iteritems()]) template_data['WEB_DEV_VIEWS'] = json.dumps([ {'key': k, 'val': v} for k,v in models.WEB_DEV_VIEWS.iteritems()]) template_data['STANDARDS_VALS'] = json.dumps([ {'key': k, 'val': v} for k,v in models.STANDARDIZATION.iteritems()]) push_urls = http2push.use_push_manifest('push_manifest_features.json') elif path.startswith('feature'): feature = None try: feature = models.Feature.get_feature(int(feature_id)) except TypeError: pass if feature is None: self.abort(404) was_updated = False if self.request.referer: was_updated = (self.request.referer.endswith('/admin/features/new') or '/admin/features/edit' in self.request.referer) template_data['feature'] = feature template_data['was_updated'] = was_updated elif path.startswith('metrics/css/timeline'): properties = sorted( models.CssPropertyHistogram.get_all().iteritems(), key=lambda x:x[1]) template_data['CSS_PROPERTY_BUCKETS'] = json.dumps( properties, separators=(',',':')) elif path.startswith('metrics/feature/timeline'): properties = sorted( models.FeatureObserverHistogram.get_all().iteritems(), key=lambda x:x[1]) template_data['FEATUREOBSERVER_BUCKETS'] = json.dumps( properties, separators=(',',':')) elif path.startswith('omaha_data'): omaha_data = util.get_omaha_data() return common.JSONHandler.get(self, omaha_data, formatted=True) if path.startswith('metrics/'): push_urls = http2push.use_push_manifest('push_manifest_metrics.json') # Add Link rel=preload header for h2 push on .html file requests. if push_urls: self.response.headers.add_header( 'Link', self._generate_link_preload_headers(push_urls)) self.render(data=template_data, template_path=os.path.join(path + '.html'))