| # This script is used to update the CSS ranking. The CSS ranking will affect |
| # the grouping of CSS properties in Computed Style. |
| # Usage: Run `python update_css_ranking.py` to update the default |
| # CSS ranking file and API. |
| # Run `python update_css_ranking.py <ranking_file>` to update |
| # the ranking to another file with the default ranking API. |
| # Run `python update_css_ranking.py <ranking_file> <ranking_api_link>` |
| # to update the ranking from <ranking_api_link> API to <ranking_file> |
| |
| import urllib2 |
| import json |
| import sys |
| import cluster |
| import json5_generator |
| import math |
| |
| CSS_RANKING_API = "http://www.chromestatus.com/data/csspopularity" |
| CSS_RANKING_FILE = "../../core/css/css_properties_ranking.json5" |
| CSS_PROPERTIES = "../../core/css/css_properties.json5" |
| CONFIG_FILE = "../../core/css/css_group_config.json5" |
| |
| |
| def reformat_properties_name(css_properties): |
| for i in range(len(css_properties)): |
| if css_properties[i][:5] == "alias": |
| css_properties[i] = css_properties[i][5:] |
| if css_properties[i][:6] == "webkit": |
| css_properties[i] = "-" + css_properties[i] |
| |
| |
| def update_css_ranking(css_ranking_file, css_ranking_api): |
| """Create the css_properties_ranking.json5 for uses in Computed Style grouping |
| |
| Args: |
| css_ranking_file: file directory to css_properties_ranking.json5 |
| css_ranking_api: url to CSS ranking api |
| |
| """ |
| css_ranking = json.loads(urllib2.urlopen(css_ranking_api).read()) |
| css_ranking_content = {"properties": {}, "data": []} |
| css_ranking_content["data"] = [ |
| property_["property_name"] for property_ in sorted( |
| css_ranking, key=lambda x: -float(x["day_percentage"])) |
| ] |
| |
| reformat_properties_name(css_ranking_content["data"]) |
| |
| with open(css_ranking_file, "w") as fw: |
| fw.write( |
| "// The popularity ranking of all css properties the first properties is the most\n" |
| ) |
| fw.write( |
| "// used property according to: https://www.chromestatus.com/metrics/css/popularity\n" |
| ) |
| json.dump(css_ranking_content, fw, indent=4, sort_keys=False) |
| |
| |
| def find_partition_rule(css_property_set, |
| all_properties, |
| n_cluster, |
| transform=lambda x: x): |
| """Find partition rule for a set of CSS property based on its popularity |
| |
| Args: |
| css_property_set: list of CSS properties and their popularity of form |
| [(css_property_name, popularity_score)..] |
| n_cluster: number of cluster to divide the set into |
| all_properties: all CSS properties and its score |
| transform: data transform function to transform the popularity score, |
| default value is the identity function |
| |
| Returns: |
| partition rule for css_property_set |
| """ |
| _, cluster_alloc, _ = cluster.k_means( |
| [transform(p[1]) for p in css_property_set], n_cluster=n_cluster) |
| return [ |
| all_properties[css_property_set[i][0]] |
| for i in range(len(cluster_alloc) - 1) |
| if cluster_alloc[i] != cluster_alloc[i + 1] |
| ] + [1.0] |
| |
| |
| def produce_partition_rule(config_file, css_ranking_api): |
| """Find the partition rule for the groups and print them to config_file |
| |
| Args: |
| config_file: the file to write the parameters to |
| css_ranking_api: url to CSS ranking api |
| |
| """ |
| css_ranking = sorted( |
| json.loads(urllib2.urlopen(css_ranking_api).read()), |
| key=lambda x: -x["day_percentage"]) |
| total_css_properties = len(css_ranking) |
| css_ranking_dictionary = dict( |
| [(x["property_name"], x["day_percentage"] * 100) for x in css_ranking]) |
| css_ranking_cdf = dict( |
| zip([x["property_name"] for x in css_ranking], [ |
| float(i) / total_css_properties |
| for i in range(total_css_properties) |
| ])) |
| css_properties = json5_generator.Json5File.load_from_files( |
| [CSS_PROPERTIES]).name_dictionaries |
| |
| rare_non_inherited_properties = sorted( |
| [(x["name"].original, css_ranking_dictionary[x["name"].original]) |
| for x in css_properties |
| if not x["inherited"] and x["field_group"] is not None and "*" in |
| x["field_group"] and x["name"].original in css_ranking_dictionary], |
| key=lambda x: -x[1]) |
| rare_inherited_properties = sorted( |
| [(x["name"].original, css_ranking_dictionary[x["name"].original]) |
| for x in css_properties |
| if x["inherited"] and x["field_group"] is not None and "*" in |
| x["field_group"] and x["name"].original in css_ranking_dictionary], |
| key=lambda x: -x[1]) |
| |
| rni_properties_rule = find_partition_rule( |
| rare_non_inherited_properties, css_ranking_cdf, n_cluster=3) |
| |
| ri_properties_rule = find_partition_rule( |
| rare_inherited_properties, |
| css_ranking_cdf, |
| n_cluster=2, |
| transform=lambda x: math.log(x + 10e-6)) |
| |
| with open(config_file, 'w') as fw: |
| fw.write( |
| "// The grouping parameter is a cumulative distribution " \ |
| "over the whole set of ranked\n" |
| ) |
| fw.write("// CSS properties.\n") |
| json.dump({ |
| "parameters": {}, |
| "data": [{ |
| "name": "rare_non_inherited_properties_rule", |
| "cumulative_distribution": rni_properties_rule |
| }, |
| { |
| "name": "rare_inherited_properties_rule", |
| "cumulative_distribution": ri_properties_rule |
| }] |
| }, |
| fw, |
| indent=4) |
| |
| |
| if __name__ == '__main__': |
| assert len(sys.argv) < 4, "Too many parameters" |
| |
| if len(sys.argv) == 1: |
| update_css_ranking(CSS_RANKING_FILE, CSS_RANKING_API) |
| produce_partition_rule(CONFIG_FILE, CSS_RANKING_API) |
| elif len(sys.argv) == 2: |
| update_css_ranking(sys.argv[1], CSS_RANKING_API) |
| produce_partition_rule(CONFIG_FILE, CSS_RANKING_API) |
| elif len(sys.argv) == 3: |
| update_css_ranking(sys.argv[1], sys.argv[2]) |
| produce_partition_rule(CONFIG_FILE, sys.argv[2]) |