예제 #1
0
def parse(root_path, data):
    """
    Creates and returns a RepositoryDefinition object.

    :param root_path: Reports descriptor root path.
    :type root_path: str
    :param data: Reports descriptor content.
    :type data: dict
    :returns: A repository definition object.
    :rtype: RepositoryDefinition
    """
    reports = data.pop('reports')
    reports_definitions = []
    for report in reports:
        parameters_definitions = []
        for param in report.pop('parameters'):
            cls = ChoicesParameterDefinition if 'choices' in param else ParameterDefinition
            parameters_definitions.append(cls(**param))

        if report['report_spec'] == '1':
            default_renderer = DEFAULT_RENDERER_ID
            template = report.pop('template')
            start_row = report.pop('start_row')
            start_col = report.pop('start_col')
            renderers_definitions = [
                RendererDefinition(root_path=root_path,
                                   id=default_renderer,
                                   type='xlsx',
                                   description='Render report to Excel.',
                                   default=True,
                                   template=template,
                                   args={
                                       'start_row': start_row,
                                       'start_col': start_col,
                                   }),
            ]
        if report['report_spec'] == '2':
            renderers_definitions = [
                RendererDefinition(root_path=root_path, **renderer)
                for renderer in report.pop('renderers')
            ]

        reports_definitions.append(
            ReportDefinition(
                root_path=root_path,
                parameters=parameters_definitions,
                renderers=renderers_definitions,
                **report,
            ), )

    return RepositoryDefinition(
        root_path=root_path,
        reports=reports_definitions,
        **data,
    )
def test_report_get_renderers_multiple(mocker, report_v2_json, renderer_json):
    report_json = report_v2_json()
    xls_renderer = RendererDefinition(
        root_path='root_path',
        **renderer_json(id='xlsx_renderer', default=False),
    )
    json_renderer = RendererDefinition(
        root_path='root_path',
        **renderer_json(
            id='json_renderer',
            type='json',
            default=True,
            description='Json renderer',
        ),
    )
    csv_renderer = RendererDefinition(
        root_path='root_path',
        **renderer_json(
            id='csv_renderer',
            type='csv',
            default=False,
            description='Csv renderer',
        ),
    )
    pdf_renderer = RendererDefinition(
        root_path='root_path',
        **renderer_json(
            id='pdf_renderer',
            type='pdf',
            default=False,
            description='Pdf renderer',
            template='template.j2',
            args={
                'key1': 'value1',
                'key2': 'value2'
            },
        ),
    )
    report_json['renderers'] = [
        xls_renderer, json_renderer, csv_renderer, pdf_renderer
    ]
    defs = ReportDefinition(root_path='root_path', **report_json)

    data = defs.get_renderers()

    assert isinstance(data, list)
    assert len(data) == 4
    assert data[0]['id'] == 'xlsx_renderer'

    for renderer in data:
        if renderer['default']:
            assert renderer['id'] == 'json_renderer'
def test_validator_renderer_unknown_type(param_json, renderer_type):
    report_dict = {
        'name': 'Report',
        'readme_file': 'readme.md',
        'entrypoint': 'reports.report_package.entrypoint',
        'audience': ['vendor', 'provider'],
        'parameters': [param_json()],
        'report_spec': '2',
    }

    tmp_fs = _get_tmpfs_with_readme_and_entry(report_dict['entrypoint'])

    renderer_dict = {
        'root_path': tmp_fs.root_path,
        'id': '123',
        'type': renderer_type,
        'default': True,
        'description': 'Renderer',
    }
    renderer = RendererDefinition(**renderer_dict)

    errors = _validate_renderer('report_one', renderer)
    if renderer_type == 'json':
        assert len(errors) == 0
    else:
        assert len(errors) != 0
        assert 'not known' in errors[0]
        assert 'report_one' in errors[0]
def test_validator_empty_parameter_list(param_json):
    report_dict = {
        'name': 'Report',
        'readme_file': 'readme.md',
        'entrypoint': 'reports.report_package.entrypoint',
        'audience': ['vendor', 'provider'],
        'report_spec': '2',
    }
    tmp_fs = _get_tmpfs_with_readme_and_entry(report_dict['entrypoint'])
    renderer_csv_dict = {
        'root_path': tmp_fs.root_path,
        'id': '123',
        'type': 'csv',
        'description': 'CSV Renderer',
        'default': True,
    }
    csv_renderer = RendererDefinition(**renderer_csv_dict)
    report = ReportDefinition(
        root_path=tmp_fs.root_path,
        **report_dict,
        parameters=[],
        renderers=[csv_renderer],
    )
    errors = _validate_report(report)

    assert len(errors) == 0
def test_validator_repo_readme_file_missing(param_json):
    report_dict = {
        'name': 'Report',
        'readme_file': 'readme.md',
        'entrypoint': 'reports.report_package.entrypoint',
        'audience': ['vendor', 'provider'],
        'report_spec': '2',
    }
    renderer_csv_dict = {
        'root_path': 'root_path',
        'id': '123',
        'type': 'csv',
        'description': 'CSV Renderer',
        'default': True,
    }
    csv_renderer = RendererDefinition(**renderer_csv_dict)
    parameter = ParameterDefinition(**param_json())
    report = ReportDefinition(
        root_path='root_path',
        **report_dict,
        renderers=[csv_renderer],
        parameters=[parameter],
    )
    repo_dict = {
        'name': 'Reports Repository',
        'readme_file': 'readme.md',
        'version': '1.0.0',
        'language': 'python',
        'reports': [report],
    }
    repo = RepositoryDefinition(root_path='root_path', **repo_dict)
    errors = validate(repo)

    assert len(errors) != 0
    assert 'repository property `readme_file` cannot be resolved' in errors[0]
예제 #6
0
def test_execute_report_invalid_renderer(mocker):
    config = Config()
    config.add_account(
        'VA-000-001',
        'Account 1',
        'ApiKey XXXX:YYYY',
    )
    config.activate('VA-000-001')

    mocker.patch('connect.cli.plugins.report.helpers.load_repo')

    mocker.patch(
        'connect.cli.plugins.report.helpers.get_report_by_id',
        return_value=mocker.MagicMock(
            renderers=[
                RendererDefinition('path', 'pdf', 'pdf', 'test'),
            ],
            audience=['vendor'],
        ),
    )

    with pytest.raises(ClickException) as cv:
        execute_report(config, 'root_dir', 'local_id', 'out_file', 'out_format')

    assert str(cv.value) == 'The format out_format is not available for report local_id'
def test_validator_duplicate_renderers_error(param_json):
    report_dict = {
        'name': 'Report',
        'readme_file': 'readme.md',
        'entrypoint': 'reports.report_package.entrypoint',
        'audience': ['vendor', 'provider'],
        'report_spec': '2',
    }

    tmp_fs = _get_tmpfs_with_readme_and_entry(report_dict['entrypoint'])

    renderer_dict = {
        'root_path': tmp_fs.root_path,
        'id': '123',
        'type': 'csv',
        'description': 'CSV Renderer',
        'default': True,
    }
    renderer = RendererDefinition(**renderer_dict)
    parameter = ParameterDefinition(**param_json())
    report = ReportDefinition(
        root_path=tmp_fs.root_path,
        **report_dict,
        renderers=[renderer, renderer],
        parameters=[parameter],
    )
    errors = _validate_report(report)

    assert len(errors) != 0
    assert 'duplicated renderer' in errors[0]
def test_validator_entrypoint_bad_directory_structure(report_v2_json,
                                                      param_json):
    tmp_filesystem = TempFS()
    tmp_filesystem.create('readme.md')
    renderer_json_dict = {
        'root_path': tmp_filesystem.root_path,
        'id': '321',
        'type': 'json',
        'description': 'JSON Renderer',
        'default': True,
    }
    renderer = RendererDefinition(**renderer_json_dict)
    parameter = ParameterDefinition(**param_json())
    report_dict = report_v2_json(
        readme_file='readme.md',
        renderers=[renderer],
        parameters=[parameter],
    )
    report = ReportDefinition(
        root_path=tmp_filesystem.root_path,
        **report_dict,
    )
    errors = _validate_report(report)

    assert len(errors) != 0
    assert 'directory structure does not match' in errors[0]
def test_report_definition_default_renderer(mocker, report_v2_json,
                                            renderer_json):
    report_json = report_v2_json(renderers=[
        RendererDefinition(root_path='root_path', **renderer_json())
    ], )
    defs = ReportDefinition(root_path='root_path', **report_json)
    assert defs.default_renderer == defs.renderers[0].id
예제 #10
0
def parse(root_path, data):
    reports = data.pop('reports')
    reports_definitions = []
    for report in reports:
        parameters_definitions = []
        for param in report.pop('parameters'):
            cls = ChoicesParameterDefinition if 'choices' in param else ParameterDefinition
            parameters_definitions.append(cls(**param))

        if report['report_spec'] == '1':
            default_renderer = 'default_xlsx_renderer'
            template = report.pop('template')
            start_row = report.pop('start_row')
            start_col = report.pop('start_col')
            renderers_definitions = [
                RendererDefinition(
                    root_path=root_path,
                    id=default_renderer,
                    type='xlsx',
                    description='Render report to Excel.',
                    default=True,
                    template=template,
                    args={
                        'start_row': start_row,
                        'start_col': start_col,
                    }),
            ]
        if report['report_spec'] == '2':
            renderers_definitions = [
                RendererDefinition(root_path=root_path, **renderer)
                for renderer in report.pop('renderers')
            ]

        reports_definitions.append(
            ReportDefinition(
                root_path=root_path,
                parameters=parameters_definitions,
                renderers=renderers_definitions,
                **report,
            ),
        )

    return RepositoryDefinition(
        root_path=root_path,
        reports=reports_definitions,
        **data,
    )
def test_validator_repo_duplicated_reports(mocker, param_json):
    mocker.patch(
        'connect.reports.validator._validate_report',
        return_value=[],
    )
    report_dict_1 = {
        'name': 'Report',
        'readme_file': 'readme.md',
        'entrypoint': 'reports.report_package.entrypoint',
        'audience': ['vendor', 'provider'],
        'parameters': [param_json()],
        'report_spec': '2',
    }
    report_dict_2 = {
        'name': 'Report',
        'readme_file': 'readme.md',
        'entrypoint': 'reports.report_package.entrypoint',
        'audience': ['vendor', 'provider'],
        'parameters': [param_json()],
        'report_spec': '2',
    }
    renderer_csv_dict = {
        'root_path': 'root_path',
        'id': '123',
        'type': 'csv',
        'description': 'CSV Renderer',
        'default': True,
    }
    csv_renderer = RendererDefinition(**renderer_csv_dict)
    report_1 = ReportDefinition(
        root_path='root_path',
        **report_dict_1,
        renderers=[csv_renderer],
    )
    report_2 = ReportDefinition(
        root_path='root_path',
        **report_dict_2,
        renderers=[csv_renderer],
    )
    tmp_filesystem = TempFS()
    tmp_filesystem.create('readme.md')
    repo_dict = {
        'name': 'Reports Repository',
        'readme_file': 'readme.md',
        'version': '1.0.0',
        'language': 'python',
        'reports': [report_1, report_2],
    }
    repo = RepositoryDefinition(
        root_path=tmp_filesystem.root_path,
        **repo_dict,
    )

    errors = validate(repo)

    assert len(errors) != 0
    assert 'Multiple reports within single module found' in errors[0]
예제 #12
0
def test_validate_ok():
    defs = RendererDefinition(
        root_path='root_path',
        id='renderer_id',
        type='json',
        description='description',
    )

    assert BaseRenderer.validate(defs) == []
예제 #13
0
def test_validate_no_template():
    defs = RendererDefinition(
        root_path='root_path',
        id='renderer_id',
        type='xlsx',
        description='description',
    )

    assert XLSXRenderer.validate(defs) == [
        '`template` is required for xlsx renderer.'
    ]
def test_report_get_renderers(mocker, report_v2_json, renderer_json):
    report_json = report_v2_json()
    renderer = RendererDefinition(root_path='root_path', **renderer_json())
    report_json['renderers'] = [renderer]
    defs = ReportDefinition(root_path='root_path', **report_json)

    data = defs.get_renderers()

    assert data[0]['id'] == renderer.id
    assert data[0]['type'] == renderer.type
    assert data[0]['description'] == renderer.description
    assert 'root_path' not in data[0]
예제 #15
0
def test_validate_invalid_args(mocker, args, error):
    tmp_fs = TempFS()
    defs = RendererDefinition(
        root_path=tmp_fs.root_path,
        id='renderer_id',
        type='xlsx',
        description='description',
        template='template.xlsx',
        args=args,
    )
    _create_xlsx_doc(f'{tmp_fs.root_path}/{defs.template}')

    assert XLSXRenderer.validate(defs) == [error]
예제 #16
0
def test_validate_ok(mocker):
    mocker.patch('connect.reports.renderers.j2.os.path.isfile',
                 return_value=True)

    defs = RendererDefinition(
        root_path='root_path',
        id='renderer_id',
        type='jinja2',
        description='description',
        template='template.csv.j2',
    )

    assert Jinja2Renderer.validate(defs) == []
def test_validator_multiple_default_renderer(param_json):
    report_dict = {
        'name': 'Report',
        'readme_file': 'readme.md',
        'entrypoint': 'reports.report_package.entrypoint',
        'audience': ['vendor', 'provider'],
        'report_spec': '2',
    }

    tmp_fs = _get_tmpfs_with_readme_and_entry(report_dict['entrypoint'])

    renderer_json_dict = {
        'root_path': tmp_fs.root_path,
        'id': '321',
        'type': 'json',
        'description': 'JSON Renderer',
        'default': True,
    }
    renderer_csv_dict = {
        'root_path': tmp_fs.root_path,
        'id': '123',
        'type': 'csv',
        'description': 'CSV Renderer',
        'default': True,
    }
    csv_renderer = RendererDefinition(**renderer_csv_dict)
    json_renderer = RendererDefinition(**renderer_json_dict)
    parameter = ParameterDefinition(**param_json())
    report = ReportDefinition(
        root_path=tmp_fs.root_path,
        **report_dict,
        renderers=[csv_renderer, json_renderer],
        parameters=[parameter],
    )
    errors = _validate_report(report)
    assert len(errors) != 0
    assert f'report {report.local_id} has multiple default renderers:' in errors[
        0]
예제 #18
0
def test_validate_template_not_found(mocker):
    mocker.patch('connect.reports.renderers.xlsx.os.path.isfile',
                 return_value=False)
    defs = RendererDefinition(
        root_path='root_path',
        id='renderer_id',
        type='xlsx',
        description='description',
        template='template.xlsx',
    )

    assert XLSXRenderer.validate(defs) == [
        'template `template.xlsx` not found.'
    ]
예제 #19
0
def test_validate_tempfs_ok():
    tmp_fs = TempFS()
    tmplate_filename = 'template.csv.j2'
    tmp_fs.create(tmplate_filename)

    defs = RendererDefinition(
        root_path=tmp_fs.root_path,
        id='renderer_id',
        type='jinja2',
        description='description',
        template=tmplate_filename,
    )

    assert Jinja2Renderer.validate(defs) == []
예제 #20
0
def test_validate_ok(mocker, args):
    mocker.patch('connect.reports.renderers.pdf.os.path.isfile',
                 return_value=True)

    defs = RendererDefinition(
        root_path='root_path',
        id='renderer_id',
        type='pdf',
        description='description',
        template='template.html.j2',
        args=args,
    )

    assert PDFRenderer.validate(defs) == []
예제 #21
0
def test_validate_tmpfs_css_missing():
    tmp_fs = TempFS()
    tmp_fs.makedirs('package/report')
    tmp_fs.create('package/report/template.html.j2')
    definition = RendererDefinition(
        root_path=tmp_fs.root_path,
        id='renderer_id',
        type='pdf',
        description='description',
        template='package/report/template.html.j2',
        args={'css_file': 'package/report/css_file.css'},
    )
    errors = PDFRenderer.validate(definition)

    assert f"css_file `{definition.args['css_file']}` not found." == errors[0]
예제 #22
0
def test_validate_template_invalid_name(mocker):
    mocker.patch('connect.reports.renderers.j2.os.path.isfile',
                 return_value=True)
    defs = RendererDefinition(
        root_path='root_path',
        id='renderer_id',
        type='jinja2',
        description='description',
        template='template.j3',
    )

    assert Jinja2Renderer.validate(defs) == [
        'invalid template name: `template.j3` '
        '(must be in the form <name>.<ext>.j2).',
    ]
예제 #23
0
def test_validate_tmpfs_template_wrong_name():
    tmp_fs = TempFS()
    tmp_fs.makedirs('package/report')
    tmp_fs.create('package/report/template.html.j3')
    tmp_fs.create('css_file.css')
    definition = RendererDefinition(
        root_path=tmp_fs.root_path,
        id='renderer_id',
        type='pdf',
        description='description',
        template='package/report/template.html.j3',
        args={'css_file': 'css_file.css'},
    )
    errors = PDFRenderer.validate(definition)

    assert f"invalid template name: `{definition.template}`" in errors[0]
예제 #24
0
def test_validate_template_not_valid():

    tmp_filesystem = TempFS()
    tmp_filesystem.create('test.xlsx')

    defs = RendererDefinition(
        root_path=tmp_filesystem.root_path,
        id='renderer_id',
        type='xlsx',
        description='description',
        template='test.xlsx',
    )

    errors = XLSXRenderer.validate(defs)

    assert 'not valid or empty' in errors[0]
예제 #25
0
def test_validate_css_not_found(mocker):
    mocker.patch('connect.reports.renderers.pdf.os.path.isfile',
                 side_effect=[True, False])

    defs = RendererDefinition(
        root_path='root_path',
        id='renderer_id',
        type='pdf',
        description='description',
        template='template.html.j2',
        args={'css_file': 'my/css_file.css'},
    )

    assert PDFRenderer.validate(defs) == [
        'css_file `my/css_file.css` not found.'
    ]
예제 #26
0
def test_validate_tempfs_template_invalid_name():
    tmp_fs = TempFS()
    tmplate_filename = 'template.j3'
    tmp_fs.create(tmplate_filename)

    defs = RendererDefinition(
        root_path=tmp_fs.root_path,
        id='renderer_id',
        type='jinja2',
        description='description',
        template=tmplate_filename,
    )

    assert Jinja2Renderer.validate(defs) == [
        f'invalid template name: `{tmplate_filename}` '
        '(must be in the form <name>.<ext>.j2).',
    ]
def test_validator_readme_file_not_existing(report_v2_json, param_json):
    renderer_json_dict = {
        'root_path': 'root_path',
        'id': '321',
        'type': 'json',
        'description': 'JSON Renderer',
        'default': True,
    }
    renderer = RendererDefinition(**renderer_json_dict)
    parameter = ParameterDefinition(**param_json())
    report_dict = report_v2_json(renderers=[renderer], parameters=[parameter])
    report = ReportDefinition(
        root_path='root_path',
        **report_dict,
    )
    errors = _validate_report(report)

    assert len(errors) != 0
    assert 'property `readme_file` cannot be resolved' in errors[0]
def test_validator_entrypoint_bad_format(report_v2_json):
    tmp_filesystem = TempFS()
    tmp_filesystem.create('readme.md')
    renderer_json_dict = {
        'root_path': tmp_filesystem.root_path,
        'id': '321',
        'type': 'json',
        'description': 'JSON Renderer',
    }
    renderer = RendererDefinition(**renderer_json_dict)
    report_dict = report_v2_json(
        readme_file='readme.md',
        entrypoint='mypackage',
        renderers=[renderer],
    )
    report = ReportDefinition(
        root_path=tmp_filesystem.root_path,
        **report_dict,
    )
    errors = _validate_report(report)

    assert len(errors) != 0
    assert 'does not follow the package structure' in errors[0]