Skip to content

pyproject

Pyproject module.

Poetry

Bases: PyprojectCommon

Poetry config file handler parsed from pyproject.toml.

Source code in src/somesy/pyproject/writer.py
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
class Poetry(PyprojectCommon):
    """Poetry config file handler parsed from pyproject.toml."""

    def __init__(self, path: Path):
        """Poetry config file handler parsed from pyproject.toml.

        See [somesy.core.writer.ProjectMetadataWriter.__init__][].
        """
        super().__init__(path, section=["tool", "poetry"], model_cls=PoetryConfig)

    @staticmethod
    def _from_person(person: Person):
        """Convert project metadata person object to poetry string for person format "full name <email>."""
        return person.to_name_email_string()

    @staticmethod
    def _to_person(person_obj: str) -> Optional[Person]:
        """Parse poetry person string to a Person."""
        try:
            return Person.from_name_email_string(person_obj)
        except (ValueError, AttributeError):
            logger.warning(f"Cannot convert {person_obj} to Person object.")
            return None

__init__

__init__(path: Path)

Poetry config file handler parsed from pyproject.toml.

See somesy.core.writer.ProjectMetadataWriter.init.

Source code in src/somesy/pyproject/writer.py
92
93
94
95
96
97
def __init__(self, path: Path):
    """Poetry config file handler parsed from pyproject.toml.

    See [somesy.core.writer.ProjectMetadataWriter.__init__][].
    """
    super().__init__(path, section=["tool", "poetry"], model_cls=PoetryConfig)

Pyproject

Bases: ObjectProxy

Class for syncing pyproject file with other metadata files.

Source code in src/somesy/pyproject/writer.py
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
class Pyproject(wrapt.ObjectProxy):
    """Class for syncing pyproject file with other metadata files."""

    __wrapped__: Union[SetupTools, Poetry]

    def __init__(self, path: Path):
        """Pyproject wrapper class. Wraps either setuptools or poetry.

        Args:
            path (Path): Path to pyproject.toml file.

        Raises:
            FileNotFoundError: Raised when pyproject.toml file is not found.
            ValueError: Neither project nor tool.poetry object is found in pyproject.toml file.

        """
        data = None
        if not path.is_file():
            raise FileNotFoundError(f"pyproject file {path} not found")

        with open(path, "r") as f:
            data = load(f)

        # inspect file to pick suitable project metadata writer
        if "project" in data:
            logger.verbose("Found setuptools-based metadata in pyproject.toml")
            self.__wrapped__ = SetupTools(path)
        elif "tool" in data and "poetry" in data["tool"]:
            logger.verbose("Found poetry-based metadata in pyproject.toml")
            self.__wrapped__ = Poetry(path)
        else:
            msg = "The pyproject.toml file is ambiguous, either add a [project] or [tool.poetry] section"
            raise ValueError(msg)

        super().__init__(self.__wrapped__)

__init__

__init__(path: Path)

Pyproject wrapper class. Wraps either setuptools or poetry.

Parameters:

Name Type Description Default
path Path

Path to pyproject.toml file.

required

Raises:

Type Description
FileNotFoundError

Raised when pyproject.toml file is not found.

ValueError

Neither project nor tool.poetry object is found in pyproject.toml file.

Source code in src/somesy/pyproject/writer.py
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
def __init__(self, path: Path):
    """Pyproject wrapper class. Wraps either setuptools or poetry.

    Args:
        path (Path): Path to pyproject.toml file.

    Raises:
        FileNotFoundError: Raised when pyproject.toml file is not found.
        ValueError: Neither project nor tool.poetry object is found in pyproject.toml file.

    """
    data = None
    if not path.is_file():
        raise FileNotFoundError(f"pyproject file {path} not found")

    with open(path, "r") as f:
        data = load(f)

    # inspect file to pick suitable project metadata writer
    if "project" in data:
        logger.verbose("Found setuptools-based metadata in pyproject.toml")
        self.__wrapped__ = SetupTools(path)
    elif "tool" in data and "poetry" in data["tool"]:
        logger.verbose("Found poetry-based metadata in pyproject.toml")
        self.__wrapped__ = Poetry(path)
    else:
        msg = "The pyproject.toml file is ambiguous, either add a [project] or [tool.poetry] section"
        raise ValueError(msg)

    super().__init__(self.__wrapped__)

SetupTools

Bases: PyprojectCommon

Setuptools config file handler parsed from setup.cfg.

Source code in src/somesy/pyproject/writer.py
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
class SetupTools(PyprojectCommon):
    """Setuptools config file handler parsed from setup.cfg."""

    def __init__(self, path: Path):
        """Setuptools config file handler parsed from pyproject.toml.

        See [somesy.core.writer.ProjectMetadataWriter.__init__][].
        """
        section = ["project"]
        mappings = {
            "homepage": ["urls", "homepage"],
            "repository": ["urls", "repository"],
            "documentation": ["urls", "documentation"],
            "license": ["license", "text"],
        }
        super().__init__(
            path, section=section, direct_mappings=mappings, model_cls=SetuptoolsConfig
        )

    @staticmethod
    def _from_person(person: Person):
        """Convert project metadata person object to setuptools dict for person format."""
        return {"name": person.full_name, "email": person.email}

    @staticmethod
    def _to_person(person_obj) -> Person:
        """Parse setuptools person string to a Person."""
        # NOTE: for our purposes, does not matter what are given or family names,
        # we only compare on full_name anyway.
        names = list(map(lambda s: s.strip(), person_obj["name"].split()))
        return Person(
            **{
                "given-names": " ".join(names[:-1]),
                "family-names": names[-1],
                "email": person_obj["email"].strip(),
            }
        )

    def sync(self, metadata: ProjectMetadata) -> None:
        """Sync metadata with pyproject.toml file and fix license field."""
        super().sync(metadata)

        # if license field has both text and file, remove file
        if (
            self._get_property(["license", "file"]) is not None
            and self._get_property(["license", "text"]) is not None
        ):
            # delete license file property
            self._data["project"]["license"].pop("file")

__init__

__init__(path: Path)

Setuptools config file handler parsed from pyproject.toml.

See somesy.core.writer.ProjectMetadataWriter.init.

Source code in src/somesy/pyproject/writer.py
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
def __init__(self, path: Path):
    """Setuptools config file handler parsed from pyproject.toml.

    See [somesy.core.writer.ProjectMetadataWriter.__init__][].
    """
    section = ["project"]
    mappings = {
        "homepage": ["urls", "homepage"],
        "repository": ["urls", "repository"],
        "documentation": ["urls", "documentation"],
        "license": ["license", "text"],
    }
    super().__init__(
        path, section=section, direct_mappings=mappings, model_cls=SetuptoolsConfig
    )

sync

sync(metadata: ProjectMetadata) -> None

Sync metadata with pyproject.toml file and fix license field.

Source code in src/somesy/pyproject/writer.py
152
153
154
155
156
157
158
159
160
161
162
def sync(self, metadata: ProjectMetadata) -> None:
    """Sync metadata with pyproject.toml file and fix license field."""
    super().sync(metadata)

    # if license field has both text and file, remove file
    if (
        self._get_property(["license", "file"]) is not None
        and self._get_property(["license", "text"]) is not None
    ):
        # delete license file property
        self._data["project"]["license"].pop("file")