Skip to content

writer

Citation File Format (CFF) parser and saver.

CFF

Bases: ProjectMetadataWriter

Citation File Format (CFF) parser and saver.

Source code in src/somesy/cff/writer.py
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
class CFF(ProjectMetadataWriter):
    """Citation File Format (CFF) parser and saver."""

    def __init__(
        self,
        path: Path,
        create_if_not_exists: bool = True,
        pass_validation: bool = False,
    ):
        """Citation File Format (CFF) parser.

        See [somesy.core.writer.ProjectMetadataWriter.__init__][].
        """
        self._yaml = YAML()
        self._yaml.preserve_quotes = True
        self._yaml.indent(mapping=2, sequence=4, offset=2)

        mappings: FieldKeyMapping = {
            "name": ["title"],
            "description": ["abstract"],
            "homepage": ["url"],
            "repository": ["repository-code"],
            "documentation": IgnoreKey(),
            "maintainers": ["contact"],
        }
        super().__init__(
            path,
            create_if_not_exists=create_if_not_exists,
            direct_mappings=mappings,
            pass_validation=pass_validation,
        )

    def _init_new_file(self):
        """Initialize new CFF file."""
        self._data = {
            "cff-version": "1.2.0",
            "message": "If you use this software, please cite it using these metadata.",
            "type": "software",
        }
        with open(self.path, "w") as f:
            self._yaml.dump(self._data, f)

    def _load(self):
        """Load the CFF file."""
        with open(self.path) as f:
            self._data = self._yaml.load(f)

    def _validate(self) -> None:
        """Validate the CFF file."""
        if self.pass_validation:
            return
        try:
            citation = create_citation(self.path, None)
            citation.validate()
        except ValueError as e:
            raise ValueError(f"CITATION.cff file is not valid!\n{e}") from e

    def save(self, path: Optional[Path] = None) -> None:
        """Save the CFF object to a file."""
        path = path or self.path
        self._yaml.dump(self._data, path)

    def _sync_authors(self, metadata: ProjectMetadata) -> None:
        """Ensure that publication authors are added all into author list."""
        self.authors = self._sync_person_list(
            self.authors, metadata.publication_authors()
        )

    @staticmethod
    def _from_person(person: Union[Person, Entity]):
        """Convert project metadata person or entity object to cff dict for person format."""
        json_str = person.model_dump_json(
            exclude={
                "contribution",
                "contribution_types",
                "contribution_begin",
                "contribution_end",
                "author",
                "publication_author",
                "maintainer",
            },
            by_alias=True,  # e.g. family_names -> family-names, etc.
        )
        return json.loads(json_str)

    @staticmethod
    def _to_person(person_obj) -> Union[Person, Entity]:
        """Parse CFF Person to a somesy Person or entity."""
        # if the object has key name, it is an entity
        if "name" in person_obj:
            Entity._aliases()
            ret = Entity.make_partial(person_obj)
        else:
            Person._aliases()
            ret = Person.make_partial(person_obj)

        # construct (partial) Person while preserving key order from YAML
        ret.set_key_order(list(person_obj.keys()))
        return ret

__init__

__init__(
    path: Path,
    create_if_not_exists: bool = True,
    pass_validation: bool = False,
)

Citation File Format (CFF) parser.

See somesy.core.writer.ProjectMetadataWriter.init.

Source code in src/somesy/cff/writer.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
def __init__(
    self,
    path: Path,
    create_if_not_exists: bool = True,
    pass_validation: bool = False,
):
    """Citation File Format (CFF) parser.

    See [somesy.core.writer.ProjectMetadataWriter.__init__][].
    """
    self._yaml = YAML()
    self._yaml.preserve_quotes = True
    self._yaml.indent(mapping=2, sequence=4, offset=2)

    mappings: FieldKeyMapping = {
        "name": ["title"],
        "description": ["abstract"],
        "homepage": ["url"],
        "repository": ["repository-code"],
        "documentation": IgnoreKey(),
        "maintainers": ["contact"],
    }
    super().__init__(
        path,
        create_if_not_exists=create_if_not_exists,
        direct_mappings=mappings,
        pass_validation=pass_validation,
    )

save

save(path: Optional[Path] = None) -> None

Save the CFF object to a file.

Source code in src/somesy/cff/writer.py
71
72
73
74
def save(self, path: Optional[Path] = None) -> None:
    """Save the CFF object to a file."""
    path = path or self.path
    self._yaml.dump(self._data, path)