Example #1
0
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()
Example #4
0
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
Example #5
0
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()