def test_override_template_md_options() -> None:
    """Test init GenerationConfiguration with default values"""

    # add new new_property key
    config = GenerationConfiguration(template_md_options={
        "new_property": True,
    })
    assert config.template_md_options == {
        "new_property": True,
        "badge_as_image": False,
        "show_heading_numbers": True,
        "show_array_restrictions": True,
    }

    # override badge_as_image key
    config = GenerationConfiguration(
        deprecated_from_description=True,
        template_name="md",
        template_md_options={"badge_as_image": "test"})
    assert config.template_md_options["badge_as_image"] == "test"

    # override badge_as_image key
    config = GenerationConfiguration(
        deprecated_from_description=True,
        template_name="md",
        template_md_options={"badge_as_image": True})
    assert config.template_md_options["badge_as_image"] == True
Ejemplo n.º 2
0
def schema(output_file, output_format, data_type, url, database):
    print_messages = _log.isEnabledFor(logging.ERROR)
    if output_file:
        stream = output_file
    else:
        stream = sys.stdout
    schema_data = edb_schemas[data_type]
    if output_format == "json":
        json.dump(schema_data, stream, indent=2)
    else:
        if output_format == "markdown":
            tmpl = "md"
        elif output_format == "html":
            tmpl = "flat"
        elif output_format == "html-js":
            tmpl = "js"
        config = GenerationConfiguration(template_name=tmpl)
        with tempfile.TemporaryDirectory() as tmpdir_name:
            schema_path = pathlib.Path(tmpdir_name) / "schema.json"
            with schema_path.open("w+", encoding="utf-8") as schema_file:
                json.dump(schema_data, schema_file)
                schema_file.seek(0)
                schema_gen.generate_from_file_object(schema_file,
                                                     stream,
                                                     config=config)
def test_with_yaml_examples() -> None:
    soup = generate_case("with_examples",
                         GenerationConfiguration(examples_as_yaml=True))

    examples_label = soup.find_all("div", class_=["badge", "badge-secondary"])
    examples_label_text = [ex.text for ex in examples_label]
    assert examples_label_text == [
        "Examples:", "Example:", "Example:", "Example:"
    ]

    examples_content = soup.find_all("div", class_="examples")
    examples_content_text = [
        ex.findChildren()[0].text for ex in examples_content
    ]
    assert examples_content_text == [
        "Guido\n...\n",
        "BDFL\n...\n",
        "Van Rossum\n...\n",
        "64\n...\n",
        "birthplace: Haarlem, Netherlands\nfavorite_emoji: 🐍\n"
        "motto: Beautiful is better than ugly.\\nExplicit is better than implicit.\\nSimple is\n"
        "  better than complex.\\nComplex is better than complicated.\\nFlat is better than nested.\\nSparse\n"
        "  is better than dense.\\nReadability counts.\\nSpecial cases aren't special enough\n"
        "  to break the rules.\\nAlthough practicality beats purity.\\nErrors should never pass\n"
        "  silently.\\nUnless explicitly silenced.\\nIn the face of ambiguity, refuse the temptation\n"
        "  to guess.\\nThere should be one-- and preferably only one --obvious way to do it.\\nAlthough\n"
        "  that way may not be obvious at first unless you're Dutch.\\nNow is better than never.\\nAlthough\n"
        "  never is often better than *right* now.\\nIf the implementation is hard to explain,\n"
        "  it's a bad idea.\\nIf the implementation is easy to explain, it may be a good idea.\\nNamespaces\n"
        "  are one honking great idea -- let's do more of those!\n",
    ]
def test_deprecated_not_in_description() -> None:
    """Test that the deprecated badge does not get added if the option to get deprecated from description is disabled"""
    soup = generate_case(
        "deprecated",
        GenerationConfiguration(deprecated_from_description=False))

    tests.html_schema_doc_asserts.assert_deprecated(soup, [False] * 3)
def test_override_markdown_options() -> None:
    """Test init GenerationConfiguration with default values"""

    # override break-on-newline key
    config = GenerationConfiguration(markdown_options={
        "break-on-newline": False,
    })
    assert config.markdown_options == {
        "break-on-newline": False,
        "fenced-code-blocks": {
            "cssclass": "highlight jumbotron"
        },
        "tables": None,
    }
    # override fenced-code-blocks key
    config = GenerationConfiguration(markdown_options={
        "fenced-code-blocks": {
            "cssclass": "test"
        },
    })
    assert config.markdown_options == {
        "break-on-newline": True,
        "fenced-code-blocks": {
            "cssclass": "test"
        },
        "tables": None,
    }
    # override tables key
    config = GenerationConfiguration(markdown_options={"tables": ["test"]})
    assert config.markdown_options == {
        "break-on-newline": True,
        "fenced-code-blocks": {
            "cssclass": "highlight jumbotron"
        },
        "tables": ["test"],
    }

    # add a new key
    config = GenerationConfiguration(markdown_options={"newKey": "test"})
    assert config.markdown_options == {
        "break-on-newline": True,
        "fenced-code-blocks": {
            "cssclass": "highlight jumbotron"
        },
        "tables": None,
        "newKey": "test",
    }
def test_description_markdown_with_default_options() -> None:
    """Override default options"""
    soup = generate_case("description_markdown", GenerationConfiguration())

    assert (
        str(soup.find("span", class_="description")) ==
        '<span class="description"><p>DOC<br/> * List 1<br/> * List 2</p> </span>'
    )
def test_description_with_ref_link_to_reused_ref() -> None:
    """Same as "test_description_with_ref", but do not allow reusing references."""
    soup = generate_case("description_with_ref",
                         GenerationConfiguration(link_to_reused_ref=False))

    tests.html_schema_doc_asserts.assert_descriptions(soup, [
        "We should see this", "inner description", "We should see this too",
        "inner description"
    ])
def test_deprecated_in_description() -> None:
    """Test finding whether a property is deprecated from its description"""
    soup = generate_case(
        "deprecated",
        GenerationConfiguration(deprecated_from_description=True))

    tests.html_schema_doc_asserts.assert_property_names(
        soup, ["deprecated1", "deprecated2", "not_deprecated"])
    tests.html_schema_doc_asserts.assert_deprecated(soup, [True, True, False])
def test_default_values() -> None:
    """Test init GenerationConfiguration with default values"""
    config = GenerationConfiguration()
    assert config.markdown_options == {
        "break-on-newline": True,
        "fenced-code-blocks": {
            "cssclass": "highlight jumbotron"
        },
        "tables": None,
    }
    assert config.template_md_options["badge_as_image"] == False
def test_recursive_array() -> None:
    """Test a schema having a recursive definition pointing to array items"""
    soup = generate_case("recursive_array",
                         GenerationConfiguration(link_to_reused_ref=True))

    assert_descriptions(soup, [
        "A list of people", "A human being", "The children they had",
        "A human being"
    ])

    assert_ref_link(soup, "#person_items", "Same definition as person")
def test_long_description(collapse: bool) -> None:
    soup = generate_case(
        "long_description",
        GenerationConfiguration(collapse_long_descriptions=collapse))

    read_more = soup.find("a",
                          href="#collapseDescription_it_s_hard_to_explain")

    if collapse:
        assert read_more
    else:
        assert not read_more
Ejemplo n.º 12
0
def test_generate_from_schema_config_object(tmp_path: Path,
                                            caplog: LogCaptureFixture) -> None:
    config = GenerationConfiguration(minify=False,
                                     default_from_description=True,
                                     copy_css=False,
                                     copy_js=False)

    caplog.set_level(logging.INFO)

    generate_from_schema(get_test_case_path("basic"), config=config)

    _assert_deprecation_message(caplog, False)
    assert_css_and_js_not_copied(tmp_path)
def test_recursive(link_to_reused_ref: bool) -> None:
    """Test a schema having a recursive definition.

    Even if `link_to_reused_ref` is False, a reference will be generated to avoid a RecursionError
    """
    soup = generate_case(
        "recursive",
        GenerationConfiguration(link_to_reused_ref=link_to_reused_ref))

    assert_descriptions(
        soup, ["A human being", "The children they had", "A human being"])

    assert_ref_link(soup, "#person", "Same definition as person")
def test_description_markdown_with_custom_options() -> None:
    """Same as "test_description_markdown_with_default_options" but with option to render list"""
    soup = generate_case(
        "description_markdown",
        GenerationConfiguration(markdown_options={
            "cuddled-lists": True,
        }),
    )

    assert (
        str(soup.find("span", class_="description")) ==
        """<span class="description"><p>DOC </p> <ul> <li>List 1</li> <li>List 2</li> </ul> </span>"""
    )
def test_defaults_with_merge(link_to_reused_ref: bool) -> None:
    """Test default values being displayed correctly when they come from a common ref"""
    soup = generate_case(
        "defaults",
        GenerationConfiguration(link_to_reused_ref=link_to_reused_ref))

    tests.html_schema_doc_asserts.assert_types(soup,
                                               ["object", "object", "object"])
    tests.html_schema_doc_asserts.assert_descriptions(
        soup, ["Description of a", "A common description"])
    tests.html_schema_doc_asserts.assert_property_names(soup, ["a", "b"])
    tests.html_schema_doc_asserts.assert_default_values(
        soup, ['"Default from a"', '"Default from b"'])
def test_with_special_chars() -> None:
    soup = generate_case(
        "with_special_chars",
        GenerationConfiguration(deprecated_from_description=False))

    tests.html_schema_doc_asserts.assert_property_names(
        soup, ["prénom", "nomDeFamille", "âge", "0 de quoi d'autre"])

    buttons = soup.find_all("button", attrs={"aria-controls": True})
    expected_targets = [
        "#pr_nom", "#nomDeFamille", "#a_ge", "#a0_de_quoi_d_autre"
    ]
    for i, expected_target in enumerate(expected_targets):
        assert buttons[i].attrs["data-target"] == expected_target
Ejemplo n.º 17
0
def generate_docs(schemaName: str, format: str):
    template_name = "js" if format == "html" else "md_nested"
    file_name = "html" if format == "html" else "md"

    outdir = Path(f"output")
    outdir.mkdir(parents=True, exist_ok=True)
    doc = outdir.joinpath(f"{schemaName}.{file_name}")
    schema_file = Path(f"schema/{schemaName}.schema.json")

    config = GenerationConfiguration(
        template_name=template_name,
        show_toc=True,
        link_to_reused_ref=False,
        collapse_long_descriptions=False,
    )
    generate_from_filename(schema_file, doc, config=config)
    print(f"Created {doc}...")
Ejemplo n.º 18
0
def test_generate_no_file_output(tmp_path: Path,
                                 monkeypatch: MonkeyPatch) -> None:
    """Test generating and getting output as a str instead of writing to file"""
    monkeypatch.chdir(tmp_path)

    test_case_name = "basic"
    test_case_file_name = f"{test_case_name}.json"
    test_case_path = get_test_case_path("basic")

    schemas = get_schemas_to_render(test_case_path, None, "md")
    template_renderer = MagicMock(TemplateRenderer)
    template_renderer.render.return_value = ""
    template_renderer.config = GenerationConfiguration()
    generated = generate_schemas_doc(schemas, template_renderer)

    assert list(generated.keys()) == [test_case_file_name]

    # Ensure no file is written to current working directory
    assert len(list(tmp_path.glob("**"))) == 1  # glob("**") returns itself
def test_recursive_parent_in_definition(link_to_reused_ref: bool) -> None:
    """Test a schema having a recursive definition. Moreover, the ref is linked to an attribute in a definition that
    has not been seen in the tree before

    Even if `link_to_reused_ref` is False, a reference will be generated to avoid a RecursionError
    """
    soup = generate_case(
        "recursive_parent_in_definition",
        GenerationConfiguration(link_to_reused_ref=link_to_reused_ref))

    assert_descriptions(
        soup,
        [
            "Relationships between this person and others",
            "A human being",
            "Relationships between this person and others",
            "A human being",
        ],
    )

    assert_ref_link(soup, "#relationships_mother", "Same definition as mother")
Ejemplo n.º 20
0
def test_generate_multiple_path_inputs(tmp_path: Path) -> None:
    """Test generating using the all-purpose "generate" method with multiple Path inputs"""
    test_case1 = "basic"
    test_case2 = "with_default"
    test_case_path1 = get_test_case_path(test_case1)
    test_case_path2 = get_test_case_path(test_case2)

    result_path = tmp_path / "test_generate"
    result_path.mkdir()

    schemas = get_schemas_to_render_from_cli_arguments(test_case_path1,
                                                       result_path, "md")
    schemas += get_schemas_to_render_from_cli_arguments(
        test_case_path2, result_path, "md")

    template_renderer = MagicMock(TemplateRenderer)
    template_renderer.render.return_value = ""
    template_renderer.config = GenerationConfiguration()
    generated = generate_schemas_doc(schemas, template_renderer)

    assert generated is not None
def test_recursive_two_files(link_to_reused_ref: bool) -> None:
    """Test rendering a schema with a recursive definition with the same name, but in another file"""
    soup = generate_case(
        "recursive_two_files",
        GenerationConfiguration(link_to_reused_ref=link_to_reused_ref))

    assert_descriptions(
        soup,
        [
            "A human being",
            "The children they had",
            "Person definition from second file. Not the same!",
            "Person definition from second file. Not the same!",
        ],
    )

    if link_to_reused_ref:
        assert_ref_link(soup, "#person_siblings",
                        "Same definition as siblings")
    else:
        assert not get_ref_link(soup, "#person_siblings")
Ejemplo n.º 22
0
def test_recursive_full_schema(link_to_reused_ref: bool) -> None:
    """Test a schema having a recursive definition.

    Even if `link_to_reused_ref` is False, a reference will be generated to avoid a RecursionError
    """
    soup = generate_case(
        "recursive_full_schema",
        GenerationConfiguration(link_to_reused_ref=link_to_reused_ref))

    assert_descriptions(
        soup,
        [
            "Display the issue.",
            "Code property",
            "RecursiveArray property",
            "Display the issue.",
            "DecoratedRecursiveArray property",
            "Display the issue.",
        ],
    )

    assert_ref_link(soup, "#root", "Same definition as Bug")
Ejemplo n.º 23
0
import sys

from json_schema_for_humans.generate import generate_from_filename
from json_schema_for_humans.generation_configuration import GenerationConfiguration

config = GenerationConfiguration(copy_css=True,
                                 expand_buttons=True,
                                 minify=False,
                                 link_to_reused_ref=False,
                                 footer_show_time=False)

schema = sys.argv[1]
source_dir = sys.argv[2]
output_dir = sys.argv[3]

schema_path = source_dir + "/" + schema + ".json"
output_path = output_dir + "/" + schema + ".html"

generate_from_filename(schema_path, output_path, config=config)
    dir_name: str
    config: GenerationConfiguration
    md_example_template: str


CONFIGURATIONS: List[ExampleConfiguration] = [
    {
        "title":
        "JS template",
        "dir_name":
        "examples_js_default",
        "config":
        GenerationConfiguration(
            minify=False,
            template_name="js",
            deprecated_from_description=True,
            expand_buttons=True,
            footer_show_time=False,
        ),
        "md_example_template":
        MD_EXAMPLE_JS_TEMPLATE,
    },
    {
        "title":
        "Flat template",
        "dir_name":
        "examples_flat_default",
        "config":
        GenerationConfiguration(
            minify=False,
            template_name="flat",
Ejemplo n.º 25
0
import os
from typing import List
import pytest
from dataclasses import dataclass
from pathlib import Path

from json_schema_for_humans.generation_configuration import GenerationConfiguration
from tests.md_utils_asserts import MdUtilsAsserts

current_dir = os.path.abspath(os.path.dirname(__file__))
parent_dir = os.path.abspath(os.path.dirname(current_dir))
examples_dir = os.path.join(parent_dir, "docs", "examples")

config_badge = GenerationConfiguration(
    template_name="md",
    template_md_options={"badge_as_image": True},
    deprecated_from_description=True)
config_no_badge = GenerationConfiguration(
    template_name="md",
    template_md_options={"badge_as_image": False},
    deprecated_from_description=True)


@dataclass
class TestCase:
    name: str
    config: GenerationConfiguration

    __test__ = False

def test_basic() -> None:
    intermediate = build_intermediate_representation(
        get_test_case_path("basic"), GenerationConfiguration())

    assert intermediate
Ejemplo n.º 27
0
parent_dir = os.path.abspath(os.path.dirname(current_dir))
sys.path.insert(0, parent_dir)

from json_schema_for_humans.generate import generate_from_filename
from json_schema_for_humans.generation_configuration import GenerationConfiguration

template_names = ["js", "flat", "md", "md_nested"]
template_extension = "html"
if len(sys.argv) >= 2:
    template_names = [sys.argv[1]]


examples_dir = os.path.join(current_dir, "examples")
json_examples_dir = os.path.join(examples_dir, "cases")

config_md = GenerationConfiguration(template_name="md", deprecated_from_description=True)

EXAMPLES_HEADER_TEMPLATE = """
# {title} <!-- {{docsify-ignore-all}} -->

<!-- select:start -->
<!-- select-menu-labels: Schema -->

Here you can browse various example schemas and their rendition with several templates.

"""

CONFIGURATION_HEADER_TEMPLATE = """
# {title} <!-- {{docsify-ignore-all}} -->

<!-- select:start -->
def test_references() -> None:
    intermediate = build_intermediate_representation(
        get_test_case_path("references"), GenerationConfiguration())

    assert intermediate