def combine_platforms_and_since(annotated_obj): parent = annotated_obj.parent obj = annotated_obj.api_obj result = [] platforms = None since = DEFAULT_SINCE if dict_has_non_empty_member(obj, "platforms"): platforms = obj["platforms"] # Method/property/event can't have more platforms than the types they belong to. if (platforms is None or isinstance(annotated_obj, AnnotatedMethod) or isinstance(annotated_obj, AnnotatedProperty) or isinstance(annotated_obj, AnnotatedEvent)): if parent is not None: if dict_has_non_empty_member(parent.api_obj, "platforms"): if platforms is None or len(parent.api_obj["platforms"]) < len(platforms): platforms = parent.api_obj["platforms"] # Last resort is the default list of platforms if platforms is None: platforms = DEFAULT_PLATFORMS if "since" in obj and len(obj["since"]) > 0: since = obj["since"] else: # If a method/event/property we can check type's "since" if (isinstance(annotated_obj, AnnotatedMethod) or isinstance(annotated_obj, AnnotatedProperty) or isinstance(annotated_obj, AnnotatedEvent)): if (parent is not None and dict_has_non_empty_member(parent.api_obj, "since")): since = parent.api_obj["since"] since_is_dict = isinstance(since, dict) for name in platforms: one_platform = {"name": name, "pretty_name": pretty_platform_name(name)} min_since = first_version_for_platform(one_platform["name"]) if not since_is_dict: one_platform["since"] = since if min_since is not None: if StrictVersion(since) < StrictVersion(min_since): one_platform["since"] = min_since else: if name in since: one_platform["since"] = since[name] else: if min_since is not None: one_platform["since"] = min_since else: one_platform["since"] = DEFAULT_SINCE result.append(one_platform) # Be sure no "since" is _before_ a parent object since. if parent and parent.platforms: for entry in result: platform_name = entry["name"] version_parts = entry["since"].split(".") for parent_entry in parent.platforms: if parent_entry["name"] == platform_name: parent_version_parts = parent_entry["since"].split(".") if parent_version_parts > version_parts: entry["since"] = parent_entry["since"] break return result
def is_new_api(annotated_obj, this_version): global platform_list # Checking for none here lets us call is_new_api(find_supertype_member(foo)) without additional checking if annotated_obj is None: return None obj = annotated_obj.api_obj if hasattr(annotated_obj, "platforms") and len(annotated_obj.platforms) > 0: since = annotated_obj.platforms else: return None support_str = "" new_for_platform = [] since_for_platform = {} existing_api = False # if we have both a superclass and a parent object, we only consider the since versions # for platforms shared by *both* parent object and superclass, i.e., a property defined # for all platforms in Ti.Proxy only needs to be supported on Android in a Ti.Android object. # Our platforms list is already constrained by the parent object, so we iterate through # it and check whether it's similarly defined in the supertype... Whew! super_platforms = None if not annotated_obj.typestr in [ "module", "proxy" ]: super = find_supertype_member(annotated_obj) if super is not None and super.platforms is not None: super_platforms = platforms_list_to_dict(super.platforms) for platform_since in since: platform_name = platform_since["name"] # Omit platforms that are new this release if platform_name not in platform_list: continue platform_version = normalize_version(platform_since["since"]) if platform_version == this_version: if super_platforms is not None and platform_name in super_platforms and super_platforms[platform_name] == this_version: existing_api = True else: new_for_platform.append(pretty_platform_name(platform_since["name"])) elif platform_version < this_version: existing_api = True num_platforms = len(new_for_platform) if (num_platforms >= 1): if existing_api: support_str = "Added support for %s" % new_for_platform[0] else: support_str = "New API, supported on %s" % new_for_platform[0] for i in range(1, num_platforms): if (i == num_platforms-1): support_str += " and %s" % new_for_platform[i] else: support_str += ", %s" % new_for_platform[i] if support_str: return { "new": not existing_api, "notes": support_str }
def generate(raw_apis, annotated_apis, options): global all_annotated_apis, apis all_annotated_apis = annotated_apis apis = raw_apis if options is not None and (not hasattr(options, "output") or options.output is None or len(options.output) == 0): log.error ("'output' option not provided") sys.exit(1) if options is not None and (not hasattr(options, "version") or options.version is None or len(options.version) == 0): log.error ("'version' option not provided") sys.exit(1) if options is not None and not os.path.exists(options.output): os.makedirs(options.output) outfile = "api_parity.html" log.info("Generating %s" % outfile) # Build the output text if options is not None: log.info("Creating %s in %s" % (outfile, options.output)) output = open(os.path.join(options.output, outfile), "w") html = "" html += textwrap.dedent('''\ <style> html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { background: transparent; border: 0; font-size: 100%; margin: 0; outline: 0; padding: 0; vertical-align: baseline; } body { line-height: 1; font-family: Helvetica, Arial, sans-serif; margin: 20px; font-size: 12px; } ol, ul { list-style: none; } blockquote, q { quotes: none; } :focus { outline: 0; } ins { text-decoration: none; } del { text-decoration: line-through; } table { border-collapse: collapse; border-spacing: 0; clear: both; } a { text-decoration: none; } a:hover { text-decoration: underline; } th { padding: 5px 10px; background: #CCC; } td { border: 1px solid #CCC; padding: 5px; } .yes { background-color:#007700; color: #FFF; text-align: center; font-weight: bold; } .no { background-color:#770000; color:#FFF; text-align: center; font-weight: bold; } .module_parent_title { font-weight: bold; } .module_child_title { padding-left: 20px; } div.options { float: left; margin: 0px 20px 10px 0px; } .stats_description { font-weight: normal; } </style> <style type="text/css" id="table_row_style"> .module_child { display: table-row; } .pseudo_type { display: none; } </style> <script type="text/javascript"> function toggleShowClass(clsName) { var showPseudo = document.getElementById('pseudo_type_checkbox').checked, showChildren = document.getElementById('module_members_checkbox').checked, rowCSS; if (showPseudo && showChildren) { rowCSS = ".pseudo_type { display: table-row; } .module_child { display: table-row; }"; } else if (!showPseudo && showChildren) { rowCSS = ".module_child { display: table-row; } .pseudo_type { display: none; }"; } else if (showPseudo && !showChildren) { rowCSS = ".pseudo_type { display: table-row; } .module_child { display: none; }"; } else if (!showPseudo && !showChildren) { rowCSS = ".pseudo_type { display: none; } .module_child { display: none; }"; } document.getElementById('table_row_style').innerHTML = rowCSS; } </script> <div id="options"> <div class="option"> Show Pseudotypes: <input type="checkbox" id="pseudo_type_checkbox" onclick="toggleShowClass()"> </div> <div class="option"> Show Members: <input type="checkbox" id="module_members_checkbox" onclick="toggleShowClass()" checked=true> </div> </div> ''') html += textwrap.dedent('''\ <table> <tr> <th></th> ''') for platform in DEFAULT_PLATFORMS: html += "\t<th>%s</th>\n" % pretty_platform_name(platform) html += "</tr>\n" api_names = annotated_apis.keys() api_names.sort() rows_html = "" for name in api_names: annotated_obj = annotated_apis[name] pseudo_text = "" class_type = "normal_type" if annotated_obj.is_pseudotype and not is_special_toplevel_type(raw_apis[name]): pseudo_text = "(<i>pseudotype</i>)" class_type = "pseudo_type" rows_html += "<tr class=\"%s module_parent\" element_type=\"%s\">\n" % (class_type, class_type) rows_html += "\t<td class=\"module_parent_title\" class=\"%s\">%s %s</td>\n" % (class_type, annotated_obj.name, pseudo_text) rows_html += get_platforms_available(annotated_obj.platforms) rows_html += "</tr>\n" attribute_names = { "properties":"property", "methods":"method", "events":"event" } for attr in ("properties", "methods", "events"): p = getattr(annotated_obj, attr) for k in p: rows_html += "<tr class=\"%s module_child\" module_child=\"true\" element_type=\"%s\">\n" % (class_type, class_type) rows_html += "\t<td class=\"module_child_title\">%s.%s (<i>%s</i>)</td>\n" % (k.parent.name, k.name, attribute_names[attr]) rows_html += get_platforms_available(k.platforms) rows_html += "</tr>\n" keep_stats(k) html += "<tr>\n" html += "\t<th class=\"stats_description\">API coverage of the platform excluding APIs namespaced under a platform --></th>\n" html += get_stats() html += "</tr>\n" html += rows_html html += "</table>\n" # Write the output files output.write(html); output.close()
def combine_platforms_and_since(annotated_obj): parent = annotated_obj.parent obj = annotated_obj.api_obj result = [] platforms = None since = DEFAULT_SINCE if dict_has_non_empty_member(obj, "platforms"): platforms = obj["platforms"] # Method/property/event can't have more platforms than the types they belong to. if (platforms is None or isinstance(annotated_obj, AnnotatedMethod) or isinstance(annotated_obj, AnnotatedProperty) or isinstance(annotated_obj, AnnotatedEvent)): if parent is not None: if dict_has_non_empty_member(parent.api_obj, "platforms"): if platforms is None or len( parent.api_obj["platforms"]) < len(platforms): platforms = parent.api_obj["platforms"] # Last resort is the default list of platforms if platforms is None: platforms = DEFAULT_PLATFORMS if "since" in obj and len(obj["since"]) > 0: since = obj["since"] else: # If a method/event/property we can check type's "since" if (isinstance(annotated_obj, AnnotatedMethod) or isinstance(annotated_obj, AnnotatedProperty) or isinstance(annotated_obj, AnnotatedEvent)): if (parent is not None and dict_has_non_empty_member(parent.api_obj, "since")): since = parent.api_obj["since"] since_is_dict = isinstance(since, dict) for name in platforms: one_platform = { "name": name, "pretty_name": pretty_platform_name(name) } min_since = first_version_for_platform(one_platform["name"]) if not since_is_dict: one_platform["since"] = since if min_since is not None: if StrictVersion(since) < StrictVersion(min_since): one_platform["since"] = min_since else: if name in since: one_platform["since"] = since[name] else: if min_since is not None: one_platform["since"] = min_since else: one_platform["since"] = DEFAULT_SINCE result.append(one_platform) # Be sure no "since" is _before_ a parent object since. if parent and parent.platforms: for entry in result: platform_name = entry["name"] version_parts = entry["since"].split(".") for parent_entry in parent.platforms: if parent_entry["name"] == platform_name: parent_version_parts = parent_entry["since"].split(".") if parent_version_parts > version_parts: entry["since"] = parent_entry["since"] break return result
def generate(raw_apis, annotated_apis, options): global all_annotated_apis, apis all_annotated_apis = annotated_apis apis = raw_apis if options is not None and (not hasattr(options, "output") or options.output is None or len(options.output) == 0): log.error("'output' option not provided") sys.exit(1) if options is not None and (not hasattr(options, "version") or options.version is None or len(options.version) == 0): log.error("'version' option not provided") sys.exit(1) if options is not None and not os.path.exists(options.output): os.makedirs(options.output) outfile = "api_parity.html" log.info("Generating %s" % outfile) # Build the output text if options is not None: log.info("Creating %s in %s" % (outfile, options.output)) output = open(os.path.join(options.output, outfile), "w") html = "" html += textwrap.dedent('''\ <style> html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { background: transparent; border: 0; font-size: 100%; margin: 0; outline: 0; padding: 0; vertical-align: baseline; } body { line-height: 1; font-family: Helvetica, Arial, sans-serif; margin: 20px; font-size: 12px; } ol, ul { list-style: none; } blockquote, q { quotes: none; } :focus { outline: 0; } ins { text-decoration: none; } del { text-decoration: line-through; } table { border-collapse: collapse; border-spacing: 0; clear: both; } a { text-decoration: none; } a:hover { text-decoration: underline; } th { padding: 5px 10px; background: #CCC; } td { border: 1px solid #CCC; padding: 5px; } .yes { background-color:#007700; color: #FFF; text-align: center; font-weight: bold; } .no { background-color:#770000; color:#FFF; text-align: center; font-weight: bold; } .module_parent_title { font-weight: bold; } .module_child_title { padding-left: 20px; } div.options { float: left; margin: 0px 20px 10px 0px; } .stats_description { font-weight: normal; } </style> <style type="text/css" id="table_row_style"> .module_child { display: table-row; } .pseudo_type { display: none; } </style> <script type="text/javascript"> function toggleShowClass(clsName) { var showPseudo = document.getElementById('pseudo_type_checkbox').checked, showChildren = document.getElementById('module_members_checkbox').checked, rowCSS; if (showPseudo && showChildren) { rowCSS = ".pseudo_type { display: table-row; } .module_child { display: table-row; }"; } else if (!showPseudo && showChildren) { rowCSS = ".module_child { display: table-row; } .pseudo_type { display: none; }"; } else if (showPseudo && !showChildren) { rowCSS = ".pseudo_type { display: table-row; } .module_child { display: none; }"; } else if (!showPseudo && !showChildren) { rowCSS = ".pseudo_type { display: none; } .module_child { display: none; }"; } document.getElementById('table_row_style').innerHTML = rowCSS; } </script> <div id="options"> <div class="option"> Show Pseudotypes: <input type="checkbox" id="pseudo_type_checkbox" onclick="toggleShowClass()"> </div> <div class="option"> Show Members: <input type="checkbox" id="module_members_checkbox" onclick="toggleShowClass()" checked=true> </div> </div> ''') html += textwrap.dedent('''\ <table> <tr> <th></th> ''') for platform in DEFAULT_PLATFORMS: html += "\t<th>%s</th>\n" % pretty_platform_name(platform) html += "</tr>\n" api_names = annotated_apis.keys() api_names.sort() rows_html = "" for name in api_names: annotated_obj = annotated_apis[name] pseudo_text = "" class_type = "normal_type" if annotated_obj.is_pseudotype and not is_special_toplevel_type( raw_apis[name]): pseudo_text = "(<i>pseudotype</i>)" class_type = "pseudo_type" rows_html += "<tr class=\"%s module_parent\" element_type=\"%s\">\n" % ( class_type, class_type) rows_html += "\t<td class=\"module_parent_title\" class=\"%s\">%s %s</td>\n" % ( class_type, annotated_obj.name, pseudo_text) rows_html += get_platforms_available(annotated_obj.platforms) rows_html += "</tr>\n" attribute_names = { "properties": "property", "methods": "method", "events": "event" } for attr in ("properties", "methods", "events"): p = getattr(annotated_obj, attr) for k in p: rows_html += "<tr class=\"%s module_child\" module_child=\"true\" element_type=\"%s\">\n" % ( class_type, class_type) rows_html += "\t<td class=\"module_child_title\">%s.%s (<i>%s</i>)</td>\n" % ( k.parent.name, k.name, attribute_names[attr]) rows_html += get_platforms_available(k.platforms) rows_html += "</tr>\n" keep_stats(k) html += "<tr>\n" html += "\t<th class=\"stats_description\">API coverage of the platform excluding APIs namespaced under a platform --></th>\n" html += get_stats() html += "</tr>\n" html += rows_html html += "</table>\n" # Write the output files output.write(html) output.close()
def is_new_api(annotated_obj, this_version): global platform_list # Checking for none here lets us call is_new_api(find_supertype_member(foo)) without additional checking if annotated_obj is None: return None obj = annotated_obj.api_obj if hasattr(annotated_obj, "platforms") and len(annotated_obj.platforms) > 0: since = annotated_obj.platforms else: return None support_str = "" new_for_platform = [] since_for_platform = {} existing_api = False # if we have both a superclass and a parent object, we only consider the since versions # for platforms shared by *both* parent object and superclass, i.e., a property defined # for all platforms in Ti.Proxy only needs to be supported on Android in a Ti.Android object. # Our platforms list is already constrained by the parent object, so we iterate through # it and check whether it's similarly defined in the supertype... Whew! super_platforms = None if not annotated_obj.typestr in ["module", "proxy"]: super = find_supertype_member(annotated_obj) if super is not None and super.platforms is not None: super_platforms = platforms_list_to_dict(super.platforms) for platform_since in since: platform_name = platform_since["name"] # Omit platforms that are new this release if platform_name not in platform_list: continue platform_version = normalize_version(platform_since["since"]) if platform_version == this_version: if super_platforms is not None and platform_name in super_platforms and super_platforms[ platform_name] == this_version: existing_api = True else: new_for_platform.append( pretty_platform_name(platform_since["name"])) elif platform_version < this_version: existing_api = True num_platforms = len(new_for_platform) if (num_platforms >= 1): if existing_api: support_str = "Added support for %s" % new_for_platform[0] else: support_str = "New API, supported on %s" % new_for_platform[0] for i in range(1, num_platforms): if (i == num_platforms - 1): support_str += " and %s" % new_for_platform[i] else: support_str += ", %s" % new_for_platform[i] if support_str: return {"new": not existing_api, "notes": support_str}
def generate(raw_apis, annotated_apis, options): global all_annotated_apis, apis all_annotated_apis = annotated_apis apis = raw_apis if options is not None and (not hasattr(options, "output") or options.output is None or len(options.output) == 0): log.error ("'output' option not provided") sys.exit(1) if options is not None and (not hasattr(options, "version") or options.version is None or len(options.version) == 0): log.error ("'version' option not provided") sys.exit(1) if options is not None and not os.path.exists(options.output): os.makedirs(options.output) outfile = "api_parity.html" log.info("Generating %s" % outfile) # Write the output files if options is not None: log.info("Creating %s in %s" % (outfile, options.output)) output = open(os.path.join(options.output, outfile), "w") output.write("<style>\n") output.write("html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td { background: transparent; border: 0; font-size: 100%; margin: 0; outline: 0; padding: 0; vertical-align: baseline; } body { line-height: 1; font-family: Helvetica, Arial, sans-serif; margin: 20px; font-size: 12px; } ol, ul { list-style: none; } blockquote, q { quotes: none; } :focus { outline: 0; } ins { text-decoration: none; } del { text-decoration: line-through; } table { border-collapse: collapse; border-spacing: 0; } a { text-decoration: none; } a:hover { text-decoration: underline; } th { padding: 5px 10px; background: #CCC; } td { border: 1px solid #CCC; padding: 5px; } .yes { background-color:#007700; color: #FFF; text-align: center; font-weight: bold; } .no { background-color:#770000; color:#FFF; text-align: center; font-weight: bold; } .module_parent { font-weight: bold } .module_child { padding-left: 20px }\n") output.write("</style>\n") output.write("<table>\n") output.write("<tr>\n") output.write("<th></th>\n") for platform in DEFAULT_PLATFORMS: output.write("\t<th>%s</th>\n" % pretty_platform_name(platform)) output.write("</tr>\n") api_names = annotated_apis.keys() api_names.sort() for name in api_names: annotated_obj = annotated_apis[name] pseudo_text = "" class_type = "normal_type" if annotated_obj.is_pseudotype and not is_special_toplevel_type(raw_apis[name]): pseudo_text = "(<i>pseudotype</i>)" class_type = "pseudo_type" output.write("<tr>\n") output.write("\t<td class=\"module_parent\" class=\"%s\">%s %s</td>\n" % (class_type, annotated_obj.name, pseudo_text)) output.write( get_platforms_available(annotated_obj.platforms) ) output.write("</tr>\n") attribute_names = { "properties":"property", "methods":"method", "events":"event" } for attr in ("properties", "methods", "events"): p = getattr(annotated_obj, attr) for k in p: output.write("<tr>\n") output.write("\t<td class=\"module_child\">%s.%s (<i>%s</i>)</td>\n" % (k.parent.name, k.name, attribute_names[attr])) output.write( get_platforms_available(annotated_obj.platforms) ) output.write("</tr>\n") output.write("</table>\n") output.close()