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
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')
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
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)
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
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])
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)
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
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)
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