Exemple #1
0
def test_citation_string_serializer_records_list(
    running_app,
    client,
    es_clear,
    minimal_record,
    superuser_identity,
):
    """Test Citation String Serializer for a list of records."""
    service = current_rdm_records.records_service
    default_style = StringCitationSerializer._default_style
    default_locale = StringCitationSerializer._default_locale
    headers = {"Accept": "text/x-bibliography"}

    expected_data = []
    for _ in range(3):
        draft = service.create(superuser_identity, minimal_record)
        record = service.publish(draft.id, superuser_identity)
        expected_record_data = get_citation_string(
            CSLJSONSchema().dump(record),
            record.id,
            locale=default_locale,
            style=get_style_filepath(default_style),
        )
        expected_data.append(expected_record_data)

    RDMRecord.index.refresh()

    response = client.get("/records", headers=headers)
    response_data = response.get_data(as_text=True)

    assert response.status_code == 200
    assert response.headers["content-type"] == "text/plain"

    for citation in expected_data:
        assert citation in response_data
Exemple #2
0
def format_bibliography(json_data):
    """ Format CSL-JSON to HTML APA format """
    json_data = _uniqueify(_flatten(json_data))
    bib_source = CiteProcJSON(json_data)
    style_path = get_style_filepath('apa')
    bib_style = CitationStylesStyle(style_path, validate=False)

    # Create the citeproc-py bibliography, passing it the:
    # * CitationStylesStyle,
    # * BibliographySource (CiteProcJSON in this case), and
    # * a formatter (plain, html, or you can write a custom formatter)

    bibliography = CitationStylesBibliography(bib_style, bib_source,
                                              formatter.html)

    # Processing citations in a document needs to be done in two passes as for
    # some CSL styles, a citation can depend on the order of citations in the
    # bibliography and thus on citations following the current one.
    # For this reason, we first need to register all citations with the
    # CitationStylesBibliography.

    for c in json_data:
        bibliography.register(Citation([CitationItem(c['id'])]))

    items = []
    for item in bibliography.bibliography():
        items.append(str(item))

    return items
def test_style_filepath():
    """Test style filepath retrieval."""
    filepath = get_style_filepath('apa')
    assert os.path.exists(filepath)
    assert 'styles/apa.csl' in filepath

    filepath = get_style_filepath('nature-digest')
    assert os.path.exists(filepath)
    assert 'styles/nature.csl' in filepath

    filepath = get_style_filepath('nature-digest', resolve_dependencies=False)
    assert os.path.exists(filepath)
    assert 'styles/dependent/nature-digest.csl' in filepath

    with pytest.raises(StyleNotFoundError):
        filepath = get_style_filepath('non-existent-style')
Exemple #4
0
def retrieve_csl_style(style=CSL_STYLE):
    """Returns file path to CSL style definition for ``style``.

    This function searches for the CSL definition file in the ``csl``
    subdirectory of the ``BASE_DIR`` defined in the projects ``settings.py``
    file and then in the ``csl`` subdirectory of the application directory
    (i.e., ``cv``).

    If a file with the style name cannot be found in one of those two
    directories, the function will use the ``get_style_filepath()``
    method from the :mod:`citeproc_styles` module. The method will return
    a ``StyleNotFoundError`` if no match exists in the
    :mod:`citeproc_styles` style repository.

    """

    file_locations = [
        os.path.abspath(settings.BASE_DIR),
        os.path.abspath(apps.get_app_config('cv').path)
    ]
    for file_location in file_locations:
        style_path = Path(
            os.path.join(file_location, "csl", "{}.csl".format(style)))
        if style_path.is_file():
            return (style_path)
    return get_style_filepath(style)
def get_style_location(style):
    """Return the path to the CSL style if exists or throw."""
    try:
        return get_style_filepath(style.lower())
    except StyleNotFoundError as ex:
        current_app.logger.warning(f"CSL style {style} not found.")
        raise ex
Exemple #6
0
def test_style_filepath():
    """Test style filepath retrieval."""
    filepath = get_style_filepath('apa')
    assert os.path.exists(filepath)
    assert 'styles/apa.csl' in filepath

    filepath = get_style_filepath('nature-digest')
    assert os.path.exists(filepath)
    assert 'styles/nature.csl' in filepath

    filepath = get_style_filepath('nature-digest', resolve_dependencies=False)
    assert os.path.exists(filepath)
    assert 'styles/dependent/nature-digest.csl' in filepath

    with pytest.raises(StyleNotFoundError):
        filepath = get_style_filepath('non-existent-style')
Exemple #7
0
    def __init__(self, bib_stylename):
        # valid style names: plos, apa, pnas, nature, bmj, harvard1
        # full list is here: https://github.com/citation-style-language/styles

        self.style_path = get_style_filepath(bib_stylename)
        super(EnhancedCitationStyle, self).__init__(self.style_path,
                                                    validate=False)
Exemple #8
0
def test_citation_string_serializer_record(
    running_app,
    vocabulary_clear,
    client,
    es_clear,
    minimal_record,
    superuser_identity,
):
    """Test Citation String Serializer for single records."""
    service = current_rdm_records.records_service
    draft = service.create(superuser_identity, minimal_record)
    record = service.publish(draft.id, superuser_identity)
    _id = record.id
    _url = f"/records/{_id}"
    headers = {"Accept": "text/x-bibliography"}

    default_style = StringCitationSerializer._default_style
    default_locale = StringCitationSerializer._default_locale

    test_cases = [
        (
            f"{_url}?style=3d-printing-in-medicine&locale=es-ES",
            "3d-printing-in-medicine",
            "es-ES",
            200,
        ),
        (f"{_url}?locale=es-ES", default_style, "es-ES", 200),
        (
            f"{_url}?style=3d-printing-in-medicine",
            "3d-printing-in-medicine",
            default_locale,
            200,
        ),
        (f"{_url}", default_style, default_locale, 200),
        (f"{_url}?style=Unknown_style", "Unknown_style", default_locale, 400),
        (f"{_url}?locale=Unknown_locale", default_style, default_locale, 200),
    ]

    for url, expected_style, expected_locale, expected_status in test_cases:
        response = client.get(url, headers=headers)
        assert response.status_code == expected_status

        body = response.get_data(as_text=True)

        if expected_status == 200:
            assert response.headers["content-type"] == "text/plain"
            expected_data = get_citation_string(
                CSLJSONSchema().dump(record),
                _id,
                locale=expected_locale,
                style=get_style_filepath(expected_style),
            )
            assert expected_data == body
        elif expected_status == 400:
            # in case of error, the response is JSON
            assert response.headers["content-type"] == "application/json"
            assert f"Citation string style not found." in body
Exemple #9
0
 def cite(self):
     style_path = get_style_filepath(CSL_STYLE)
     print(style_path)
     bib_style = CitationStylesStyle(style_path, validate=False)
     bibliography = CitationStylesBibliography(bib_style,
                                               CiteProcJSON([self.fields]),
                                               formatter.html)
     citation = Citation([CitationItem(self.instance.slug)])
     bibliography.register(citation)
     return str(bibliography.bibliography()[0])
Exemple #10
0
def bibToCite(bibfile, ID):
    bib_source = BibTeX(bibfile)

    style_path = get_style_filepath('modern-language-association')
    bib_style = CitationStylesStyle(style_path, validate=False)

    bibliography = CitationStylesBibliography(bib_style, bib_source,
                                              formatter.plain)

    citation1 = Citation([CitationItem(ID)])

    bibliography.register(citation1)

    with open('out.txt', 'w') as f:
        for item in bibliography.bibliography():
            print(str(item), file=f)
Exemple #11
0
    def _get_args(cls, **kwargs):
        """Parse style and locale.

        Argument location precedence: kwargs > view_args > query
        """
        csl_args = {'style': cls._default_style, 'locale': cls._default_locale}

        if has_request_context():
            parser = FlaskParser(locations=('view_args', 'query'))
            csl_args.update(parser.parse(cls._user_args, request))

        csl_args.update(
            {k: kwargs[k]
             for k in ('style', 'locale') if k in kwargs})

        try:
            csl_args['style'] = get_style_filepath(csl_args['style'].lower())
        except StyleNotFoundError:
            if has_request_context():
                raise StyleNotFoundRESTError(csl_args['style'])
            raise
        return csl_args
Exemple #12
0
def citeproc_csl(csl_json: Dict[str, Any],
                 style: str,
                 html: bool = False) -> str:
    """
    Renders a release entity to a styled citation.

    Notable styles include:
    - 'csl-json': special case to JSON encode the structured CSL object (via
      release_to_csl())
    - bibtext: multi-line bibtext format (used with LaTeX)

    Returns a string; if the html flag is set, and the style isn't 'csl-json'
    or 'bibtex', it will be HTML. Otherwise plain text.
    """
    if not csl_json.get("id"):
        csl_json["id"] = "unknown"
    if style == "csl-json":
        return json.dumps(csl_json)
    bib_src = CiteProcJSON([csl_json])
    form = formatter.plain
    if html:
        form = formatter.html
    style_path = get_style_filepath(style)
    bib_style = CitationStylesStyle(style_path, validate=False)
    bib = CitationStylesBibliography(bib_style, bib_src, form)
    bib.register(Citation([CitationItem(csl_json["id"])]))
    lines = bib.bibliography()[0]
    if style == "bibtex":
        out = ""
        for line in lines:
            if line.startswith(" @"):
                out += "@"
            elif line.startswith(" "):
                out += "\n " + line
            else:
                out += line
        return "".join(out)
    else:
        return "".join(lines)
Exemple #13
0
def run_citeproc_releases(args):
    for line in args.json_input:
        line = line.strip()
        if not line:
            continue
        entity = entity_from_json(line, ReleaseEntity, api_client=args.api.api_client)
        csl_json = release_to_csl(entity)
        # XXX:
        csl_json['id'] = "release:" + (entity.ident or "unknown")
        if args.style == "csl-json":
            args.json_output.write(json.dumps(csl_json) + "\n")
            continue
        bib_src = CiteProcJSON([csl_json])
        form = formatter.plain
        if args.html:
            form = formatter.html
        style_path = get_style_filepath(args.style)
        bib_style = CitationStylesStyle(style_path, validate=False)
        bib = CitationStylesBibliography(bib_style, bib_src, form)
        bib.register(Citation([CitationItem(csl_json['id'])]))
        # XXX:
        #args.json_output.write(
        #    json.dumps(release_to_csl(entity)) + '\n')
        lines = bib.bibliography()[0]
        if args.style == "bibtex":
            for l in lines:
                if l.startswith(" @"):
                    args.json_output.write("\n@")
                elif l.startswith(" "):
                    #print("line: START|{}|END".format(l))
                    args.json_output.write("\n  " + l)
                else:
                    args.json_output.write(l)
        else:
            args.json_output.write(''.join(lines) + "\n")
        print()
    def _get_args(cls, **kwargs):
        """Parse style and locale.

        Argument location precedence: kwargs > view_args > query
        """
        csl_args = {
            'style': cls._default_style,
            'locale': cls._default_locale
        }

        if has_request_context():
            parser = FlaskParser(locations=('view_args', 'query'))
            csl_args.update(parser.parse(cls._user_args, request))

        csl_args.update({k: kwargs[k]
                         for k in ('style', 'locale') if k in kwargs})

        try:
            csl_args['style'] = get_style_filepath(csl_args['style'].lower())
        except StyleNotFoundError:
            if has_request_context():
                raise StyleNotFoundRESTError(csl_args['style'])
            raise
        return csl_args