Skip to content

The Version object

Source code in madonna/version.py
 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
113
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
163
164
165
166
167
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
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
class Version:
    def __init__(
        self,
        major: int,
        minor: int,
        patch: int,
        prerelease: str | None = None,
        buildmetadata: str | None = None,
    ) -> None:
        """
        A data container for a semantic version.

        Args:
            major (int): The major version, to be incremented when making
                backwards incompatible (breaking) changes.
            minor (int): The minor version, to be incremented when introducing
                backwards compatible features.
            patch (int): The patch version, to be incremented when making
                backwards compatible bug fixes.
            prerelease (Optional[str], optional): Any pre-release tags
                e.g. 'rc.1'. Defaults to None.
            buildmetadata (Optional[str], optional): Any build meta tags
                e.g. 'build.123'. Defaults to None.

        Raises:
            ValueError: If any numeric version part < 0.
        """
        self.major = major
        self.minor = minor
        self.patch = patch
        self.prerelease = prerelease
        self.buildmetadata = buildmetadata

        if any(part < 0 for part in (self.major, self.minor, self.patch)):
            raise ValueError(
                f"Version {self!r} is invalid. Parts cannot be less than 0."
            )

    __slots__ = ("major", "minor", "patch", "prerelease", "buildmetadata")

    def __repr__(self) -> str:
        return (
            self.__class__.__qualname__
            + f"(major={self.major!r}, minor={self.minor!r}, patch={self.patch!r}, "
            + f"prerelease={self.prerelease!r}, buildmetadata={self.buildmetadata!r})"
        )

    def __str__(self) -> str:
        ver = f"v{self.major}.{self.minor}.{self.patch}"

        if self.prerelease:
            ver += f"-{self.prerelease}"

        if self.buildmetadata:
            ver += f"+{self.buildmetadata}"

        return ver

    def __eq__(self, other: object) -> bool:
        if not isinstance(other, Version):
            raise TypeError(f"Cannot compare object of type Version and {type(other)}")

        return (
            self.major,
            self.minor,
            self.patch,
            self.prerelease,
            self.buildmetadata,
        ) == (
            other.major,
            other.minor,
            other.patch,
            other.prerelease,
            other.buildmetadata,
        )

    def __lt__(self, other: object) -> bool:
        if not isinstance(other, Version):
            raise TypeError(f"Cannot compare object of type Version and {type(other)}")

        if (self.major, self.minor, self.patch) < (
            other.major,
            other.minor,
            other.patch,
        ):
            return True

        pre_release_comp = self._compare_prerelease(other)
        if pre_release_comp == -1:
            return True

        build_comp = self._compare_build(other)
        if build_comp == -1:
            return True

        return False

    def __gt__(self, other: object) -> bool:
        if not isinstance(other, Version):
            raise TypeError(f"Cannot compare object of type Version and {type(other)}")

        if (self.major, self.minor, self.patch) > (
            other.major,
            other.minor,
            other.patch,
        ):
            return True

        pre_release_comp = self._compare_prerelease(other)
        if pre_release_comp == 1:
            return True

        build_comp = self._compare_build(other)
        if build_comp == 1:
            return True

        return False

    def __le__(self, other: object) -> bool:
        if not isinstance(other, Version):
            raise TypeError(f"Cannot compare object of type Version and {type(other)}")

        if self == other:
            return True

        if self < other:
            return True

        return False

    def __ge__(self, other: object) -> bool:
        if not isinstance(other, Version):
            raise TypeError(f"Cannot compare object of type Version and {type(other)}")

        if self == other:
            return True

        if self > other:
            return True

        return False

    def __hash__(self) -> int:
        return hash(self.to_tuple())

    def _compare_prerelease(self, other: Version) -> int:
        """
        Helper to try and compare the pre-release versions.

        It will check for string equality, whether or not
        the different versions have pre-releases, check
        for integers in the text and compare based on them,
        and if none of this works will raise a ValueError.

        Note: This is only called if the numeric version
        is equal.
        """
        if self.prerelease == other.prerelease:
            # The pre release strings are equal
            return 0
        elif self.prerelease and not other.prerelease:
            # Ours has a pre-release but the other doesn't
            # meaning ours is less
            return -1
        elif not self.prerelease and other.prerelease:
            # Ours doesn't have a pre-release but the other
            # does meaning ours is greater
            return 1

        # Try and extract a number to compare
        if self.prerelease and other.prerelease:
            ours = re.findall(pattern=r"\d+", string=self.prerelease)
            others = re.findall(pattern=r"\d+", string=other.prerelease)

            if not ours or not others:
                raise ValueError("Could not parse comparable pre-release version info.")

            if len(ours) > 1 or len(others) > 1:
                raise ValueError("Multiple integers found in pre-release version.")

            our_version = int(ours.pop())
            other_version = int(others.pop())

            if our_version == other_version:
                return 0
            elif our_version > other_version:
                return 1
            elif our_version < other_version:
                return -1

        # If we get here, we couldn't parse the pre-release
        raise ValueError(
            f"Could not compare {self.prerelease} and {other.prerelease}"
        )  # pragma: no cover

    def _compare_build(self, other: Version) -> int:
        """
        Helper to try and compare the build metadata versions.

        It will check for string equality, whether or not
        the different versions have pre-releases, check
        for integers in the text and compare based on them,
        and if none of this works will raise a ValueError.

        Note: This is only called if both the numeric version
        and the pre-release strings are equal.
        """
        if self.buildmetadata == other.buildmetadata:
            # The pre release strings are equal
            return 0
        elif self.buildmetadata and not other.buildmetadata:
            # Ours has a pre-release but the other doesn't
            # meaning ours is less
            return -1
        elif not self.buildmetadata and other.buildmetadata:
            # Ours doesn't have a pre-release but the other
            # does meaning ours is greater
            return 1

        # Try and extract a number to compare
        if self.buildmetadata and other.buildmetadata:
            ours = re.findall(pattern=r"\d+", string=self.buildmetadata)
            others = re.findall(pattern=r"\d+", string=other.buildmetadata)

            if not ours or not others:
                raise ValueError(
                    "Could not parse comparable build metadata version info."
                )

            if len(ours) > 1 or len(others) > 1:
                raise ValueError("Multiple integers found in build metadata version.")

            our_version = int(ours.pop())
            other_version = int(others.pop())

            if our_version == other_version:
                return 0
            elif our_version > other_version:
                return 1
            elif our_version < other_version:
                return -1

        # If we get here, we couldn't parse the pre-release
        raise ValueError(
            f"Could not compare {self.buildmetadata} and {other.buildmetadata}"
        )  # pragma: no cover

    def is_valid(self) -> bool:
        """
        Checks the `Version` against the official
        semver regex pattern and reports whether or not it
        is a valid semver.

        Returns:
            bool: True if `Version` is valid, else False

        Examples:

        ```python
        >>> v = Version(1, 2, 4)
        >>> v.is_valid()
        True

        ```

        ```python
        >>> v = Version(1, 2, 4, "blah198y_+-2-", "build---19790")
        >>> v.is_valid()
        False

        ```
        """
        return bool(_SEMVER_REGEX.match(self.to_string()))

    def bump_major(self) -> Version:
        """
        Return a new `Version` with the major version
        number bumped.

        Returns:
            Version: New bumped version.

        Examples:

        ```python
        >>> v1 = Version(1, 2, 4)
        >>> v1.bump_major()
        Version(major=2, minor=0, patch=0, prerelease=None, buildmetadata=None)

        ```

        ```python
        >>> v1 = Version(0, 7, 6, "rc.1", "build.123")
        >>> v1.bump_major()
        Version(major=1, minor=0, patch=0, prerelease=None, buildmetadata=None)

        ```
        """
        return Version(self.major + 1, 0, 0)

    def bump_minor(self) -> Version:
        """
        Return a new `Version` with the minor version
        number bumped.

        Returns:
            Version: New bumped version.

        Examples:

        ```python
        >>> v1 = Version(1, 2, 4)
        >>> v1.bump_minor()
        Version(major=1, minor=3, patch=0, prerelease=None, buildmetadata=None)

        ```

        ```python
        >>> v1 = Version(0, 7, 6, "rc.1", "build.123")
        >>> v1.bump_major()
        Version(major=1, minor=0, patch=0, prerelease=None, buildmetadata=None)

        ```
        """
        return Version(self.major, self.minor + 1, 0)

    def bump_patch(self) -> Version:
        """
        Return a new `Version` with the patch version
        number bumped.

        Returns:
            Version: New bumped version.

        Examples:

        ```python
        >>> v1 = Version(1, 2, 4)
        >>> v1.bump_patch()
        Version(major=1, minor=2, patch=5, prerelease=None, buildmetadata=None)

        ```

        ```python
        >>> v1 = Version(0, 7, 6, "rc.1", "build.123")
        >>> v1.bump_major()
        Version(major=1, minor=0, patch=0, prerelease=None, buildmetadata=None)

        ```
        """
        return Version(self.major, self.minor, self.patch + 1)

    def to_string(self) -> str:
        """
        Generate a string representation of the
        `Version`.

        Returns:
            str: Version string.

        Examples:

        ```python
        >>> v = Version(1, 2, 4)
        >>> v.to_string()
        'v1.2.4'

        ```

        ```python
        >>> v = Version(1, 2, 4, "rc.2", "build.6")
        >>> v.to_string()
        'v1.2.4-rc.2+build.6'

        ```
        """
        return str(self)

    def to_tuple(self) -> VersionTuple:
        """
        Return the `Version` as a tuple of it's
        fields.

        Returns:
            VersionTuple: The Version tuple.

        Examples:

        ```python
        >>> v = Version(1, 2, 4)
        >>> v.to_tuple()
        (1, 2, 4, None, None)

        ```

        ```python
        >>> v = Version(1, 2, 4, "rc.2", "build.6")
        >>> v.to_tuple()
        (1, 2, 4, 'rc.2', 'build.6')

        ```
        """
        return (self.major, self.minor, self.patch, self.prerelease, self.buildmetadata)

    def to_dict(self) -> VersionDict:
        """
        Return the `Version` as a dictionary.

        Returns:
            VersionDict: The Version dictionary.

        Examples:

        ```python
        >>> v = Version(1, 2, 4)
        >>> v.to_dict()
        {'major': 1, 'minor': 2, 'patch': 4, 'prerelease': None, 'buildmetadata': None}

        ```

        ```python
        >>> v = Version(1, 2, 4, "rc.1", "build.2")
        >>> v.to_dict()
        {'major': 1, 'minor': 2, 'patch': 4, 'prerelease': 'rc.1', 'buildmetadata': 'build.2'}

        ```
        """
        return {
            "major": self.major,
            "minor": self.minor,
            "patch": self.patch,
            "prerelease": self.prerelease,
            "buildmetadata": self.buildmetadata,
        }

    def to_json(self) -> str:
        """
        Return the `Version` as a JSON string.

        Returns:
            str: The Version JSON string.

        Examples:

        ```python
        >>> v = Version(1, 2, 4)
        >>> v.to_json()
        '{"major": 1, "minor": 2, "patch": 4, "prerelease": null, "buildmetadata": null}'

        ```

        ```python
        >>> v = Version(1, 2, 4, "rc.1", "build.2")
        >>> v.to_json()
        '{"major": 1, "minor": 2, "patch": 4, "prerelease": "rc.1", "buildmetadata": "build.2"}'

        ```
        """
        return json.dumps(self.to_dict())

    @classmethod
    def from_dict(cls, version_dict: VersionDict) -> Version:
        """
        Construct and return a `Version` from a dictionary
        of it's parts.

        Expects a dictionary with keys: `major`, `minor`, `patch`,
        `prerelease` and `buildmetadata`.

        Args:
            version_dict (VersionDict): Version as a dictionary of it's
                parts.

        Returns:
            Version: Constructed Version.

        Raises:
            TypeError: If the passed dictionary does not
                have keys matching the required parts.

        Examples:

        ```python
        >>> v = {"major": 1, "minor": 2, "patch": 4}
        >>> Version.from_dict(v)
        Version(major=1, minor=2, patch=4, prerelease=None, buildmetadata=None)

        ```

        ```python
        >>> v = {"major": 1, "minor": 2, "patch": 4, "prerelease": "rc.1", "buildmetadata": "build.123"}
        >>> Version.from_dict(v)
        Version(major=1, minor=2, patch=4, prerelease='rc.1', buildmetadata='build.123')

        ```
        """
        return Version(**version_dict)

    @classmethod
    def from_string(cls, string: str) -> Version:
        """
        Construct and return a `Version` from a valid semver
        string.

        Args:
            string (str): The semver string.

        Raises:
            ValueError: If the semver string does not
                pass the official semver regex.

        Returns:
            Version: The constructed Version.

        Examples:

        ```python
        >>> Version.from_string("v1.2.4")
        Version(major=1, minor=2, patch=4, prerelease=None, buildmetadata=None)

        ```

        ```python
        >>> Version.from_string("v1.2.4-rc.1+build.123")
        Version(major=1, minor=2, patch=4, prerelease='rc.1', buildmetadata='build.123')

        ```
        """
        match = _SEMVER_REGEX.match(string)
        if not match:
            raise ValueError(f"{string!r} is not a valid semver string.")

        return Version.from_dict(
            VersionDict(
                major=int(match.group("major")),
                minor=int(match.group("minor")),
                patch=int(match.group("patch")),
                prerelease=match.group("prerelease"),
                buildmetadata=match.group("buildmetadata"),
            )
        )

    @classmethod
    def from_tuple(cls, tup: VersionTuple) -> Version:
        """
        Construct and return a `Version` from a tuple of it's
        parts.

        Args:
            tup (VersionTuple): The tuple to construct the Version
                from.

        Returns:
            Version: The constructed Version.

        Examples:

        ```python
        >>> v = (1, 2, 4)
        >>> Version.from_tuple(v)
        Version(major=1, minor=2, patch=4, prerelease=None, buildmetadata=None)

        ```

        ```python
        >>> v = (1, 2, 4, "rc.1", "build.123")
        >>> Version.from_tuple(v)
        Version(major=1, minor=2, patch=4, prerelease='rc.1', buildmetadata='build.123')

        ```
        """
        return Version(*tup)

    @classmethod
    def from_json(cls, json_string: str) -> Version:
        """
        Construct and return a `Version` from a json string
        of it's parts.

        Args:
            json_string (str): The json string.

        Returns:
            Version: The constructed Version.

        Examples:

        ```python
        >>> v = '{"major": 1, "minor": 2, "patch": 4}'
        >>> Version.from_json(v)
        Version(major=1, minor=2, patch=4, prerelease=None, buildmetadata=None)

        ```

        ```python
        >>> v = '{"major": 1, "minor": 2, "patch": 4, "prerelease": "rc.1", "buildmetadata": "build.123"}'
        >>> Version.from_json(v)
        Version(major=1, minor=2, patch=4, prerelease='rc.1', buildmetadata='build.123')

        ```
        """
        data: VersionDict = json.loads(json_string)
        return Version(**data)

__init__(major, minor, patch, prerelease=None, buildmetadata=None)

A data container for a semantic version.

Parameters:

Name Type Description Default
major int

The major version, to be incremented when making backwards incompatible (breaking) changes.

required
minor int

The minor version, to be incremented when introducing backwards compatible features.

required
patch int

The patch version, to be incremented when making backwards compatible bug fixes.

required
prerelease Optional[str]

Any pre-release tags e.g. 'rc.1'. Defaults to None.

None
buildmetadata Optional[str]

Any build meta tags e.g. 'build.123'. Defaults to None.

None

Raises:

Type Description
ValueError

If any numeric version part < 0.

Source code in madonna/version.py
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
def __init__(
    self,
    major: int,
    minor: int,
    patch: int,
    prerelease: str | None = None,
    buildmetadata: str | None = None,
) -> None:
    """
    A data container for a semantic version.

    Args:
        major (int): The major version, to be incremented when making
            backwards incompatible (breaking) changes.
        minor (int): The minor version, to be incremented when introducing
            backwards compatible features.
        patch (int): The patch version, to be incremented when making
            backwards compatible bug fixes.
        prerelease (Optional[str], optional): Any pre-release tags
            e.g. 'rc.1'. Defaults to None.
        buildmetadata (Optional[str], optional): Any build meta tags
            e.g. 'build.123'. Defaults to None.

    Raises:
        ValueError: If any numeric version part < 0.
    """
    self.major = major
    self.minor = minor
    self.patch = patch
    self.prerelease = prerelease
    self.buildmetadata = buildmetadata

    if any(part < 0 for part in (self.major, self.minor, self.patch)):
        raise ValueError(
            f"Version {self!r} is invalid. Parts cannot be less than 0."
        )

_compare_build(other)

Helper to try and compare the build metadata versions.

It will check for string equality, whether or not the different versions have pre-releases, check for integers in the text and compare based on them, and if none of this works will raise a ValueError.

Note: This is only called if both the numeric version and the pre-release strings are equal.

Source code in madonna/version.py
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
def _compare_build(self, other: Version) -> int:
    """
    Helper to try and compare the build metadata versions.

    It will check for string equality, whether or not
    the different versions have pre-releases, check
    for integers in the text and compare based on them,
    and if none of this works will raise a ValueError.

    Note: This is only called if both the numeric version
    and the pre-release strings are equal.
    """
    if self.buildmetadata == other.buildmetadata:
        # The pre release strings are equal
        return 0
    elif self.buildmetadata and not other.buildmetadata:
        # Ours has a pre-release but the other doesn't
        # meaning ours is less
        return -1
    elif not self.buildmetadata and other.buildmetadata:
        # Ours doesn't have a pre-release but the other
        # does meaning ours is greater
        return 1

    # Try and extract a number to compare
    if self.buildmetadata and other.buildmetadata:
        ours = re.findall(pattern=r"\d+", string=self.buildmetadata)
        others = re.findall(pattern=r"\d+", string=other.buildmetadata)

        if not ours or not others:
            raise ValueError(
                "Could not parse comparable build metadata version info."
            )

        if len(ours) > 1 or len(others) > 1:
            raise ValueError("Multiple integers found in build metadata version.")

        our_version = int(ours.pop())
        other_version = int(others.pop())

        if our_version == other_version:
            return 0
        elif our_version > other_version:
            return 1
        elif our_version < other_version:
            return -1

    # If we get here, we couldn't parse the pre-release
    raise ValueError(
        f"Could not compare {self.buildmetadata} and {other.buildmetadata}"
    )  # pragma: no cover

_compare_prerelease(other)

Helper to try and compare the pre-release versions.

It will check for string equality, whether or not the different versions have pre-releases, check for integers in the text and compare based on them, and if none of this works will raise a ValueError.

Note: This is only called if the numeric version is equal.

Source code in madonna/version.py
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
def _compare_prerelease(self, other: Version) -> int:
    """
    Helper to try and compare the pre-release versions.

    It will check for string equality, whether or not
    the different versions have pre-releases, check
    for integers in the text and compare based on them,
    and if none of this works will raise a ValueError.

    Note: This is only called if the numeric version
    is equal.
    """
    if self.prerelease == other.prerelease:
        # The pre release strings are equal
        return 0
    elif self.prerelease and not other.prerelease:
        # Ours has a pre-release but the other doesn't
        # meaning ours is less
        return -1
    elif not self.prerelease and other.prerelease:
        # Ours doesn't have a pre-release but the other
        # does meaning ours is greater
        return 1

    # Try and extract a number to compare
    if self.prerelease and other.prerelease:
        ours = re.findall(pattern=r"\d+", string=self.prerelease)
        others = re.findall(pattern=r"\d+", string=other.prerelease)

        if not ours or not others:
            raise ValueError("Could not parse comparable pre-release version info.")

        if len(ours) > 1 or len(others) > 1:
            raise ValueError("Multiple integers found in pre-release version.")

        our_version = int(ours.pop())
        other_version = int(others.pop())

        if our_version == other_version:
            return 0
        elif our_version > other_version:
            return 1
        elif our_version < other_version:
            return -1

    # If we get here, we couldn't parse the pre-release
    raise ValueError(
        f"Could not compare {self.prerelease} and {other.prerelease}"
    )  # pragma: no cover

bump_major()

Return a new Version with the major version number bumped.

Returns:

Name Type Description
Version Version

New bumped version.

Examples:

>>> v1 = Version(1, 2, 4)
>>> v1.bump_major()
Version(major=2, minor=0, patch=0, prerelease=None, buildmetadata=None)
>>> v1 = Version(0, 7, 6, "rc.1", "build.123")
>>> v1.bump_major()
Version(major=1, minor=0, patch=0, prerelease=None, buildmetadata=None)
Source code in madonna/version.py
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
def bump_major(self) -> Version:
    """
    Return a new `Version` with the major version
    number bumped.

    Returns:
        Version: New bumped version.

    Examples:

    ```python
    >>> v1 = Version(1, 2, 4)
    >>> v1.bump_major()
    Version(major=2, minor=0, patch=0, prerelease=None, buildmetadata=None)

    ```

    ```python
    >>> v1 = Version(0, 7, 6, "rc.1", "build.123")
    >>> v1.bump_major()
    Version(major=1, minor=0, patch=0, prerelease=None, buildmetadata=None)

    ```
    """
    return Version(self.major + 1, 0, 0)

bump_minor()

Return a new Version with the minor version number bumped.

Returns:

Name Type Description
Version Version

New bumped version.

Examples:

>>> v1 = Version(1, 2, 4)
>>> v1.bump_minor()
Version(major=1, minor=3, patch=0, prerelease=None, buildmetadata=None)
>>> v1 = Version(0, 7, 6, "rc.1", "build.123")
>>> v1.bump_major()
Version(major=1, minor=0, patch=0, prerelease=None, buildmetadata=None)
Source code in madonna/version.py
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
def bump_minor(self) -> Version:
    """
    Return a new `Version` with the minor version
    number bumped.

    Returns:
        Version: New bumped version.

    Examples:

    ```python
    >>> v1 = Version(1, 2, 4)
    >>> v1.bump_minor()
    Version(major=1, minor=3, patch=0, prerelease=None, buildmetadata=None)

    ```

    ```python
    >>> v1 = Version(0, 7, 6, "rc.1", "build.123")
    >>> v1.bump_major()
    Version(major=1, minor=0, patch=0, prerelease=None, buildmetadata=None)

    ```
    """
    return Version(self.major, self.minor + 1, 0)

bump_patch()

Return a new Version with the patch version number bumped.

Returns:

Name Type Description
Version Version

New bumped version.

Examples:

>>> v1 = Version(1, 2, 4)
>>> v1.bump_patch()
Version(major=1, minor=2, patch=5, prerelease=None, buildmetadata=None)
>>> v1 = Version(0, 7, 6, "rc.1", "build.123")
>>> v1.bump_major()
Version(major=1, minor=0, patch=0, prerelease=None, buildmetadata=None)
Source code in madonna/version.py
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
def bump_patch(self) -> Version:
    """
    Return a new `Version` with the patch version
    number bumped.

    Returns:
        Version: New bumped version.

    Examples:

    ```python
    >>> v1 = Version(1, 2, 4)
    >>> v1.bump_patch()
    Version(major=1, minor=2, patch=5, prerelease=None, buildmetadata=None)

    ```

    ```python
    >>> v1 = Version(0, 7, 6, "rc.1", "build.123")
    >>> v1.bump_major()
    Version(major=1, minor=0, patch=0, prerelease=None, buildmetadata=None)

    ```
    """
    return Version(self.major, self.minor, self.patch + 1)

from_dict(version_dict) classmethod

Construct and return a Version from a dictionary of it's parts.

Expects a dictionary with keys: major, minor, patch, prerelease and buildmetadata.

Parameters:

Name Type Description Default
version_dict VersionDict

Version as a dictionary of it's parts.

required

Returns:

Name Type Description
Version Version

Constructed Version.

Raises:

Type Description
TypeError

If the passed dictionary does not have keys matching the required parts.

Examples:

>>> v = {"major": 1, "minor": 2, "patch": 4}
>>> Version.from_dict(v)
Version(major=1, minor=2, patch=4, prerelease=None, buildmetadata=None)
>>> v = {"major": 1, "minor": 2, "patch": 4, "prerelease": "rc.1", "buildmetadata": "build.123"}
>>> Version.from_dict(v)
Version(major=1, minor=2, patch=4, prerelease='rc.1', buildmetadata='build.123')
Source code in madonna/version.py
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
@classmethod
def from_dict(cls, version_dict: VersionDict) -> Version:
    """
    Construct and return a `Version` from a dictionary
    of it's parts.

    Expects a dictionary with keys: `major`, `minor`, `patch`,
    `prerelease` and `buildmetadata`.

    Args:
        version_dict (VersionDict): Version as a dictionary of it's
            parts.

    Returns:
        Version: Constructed Version.

    Raises:
        TypeError: If the passed dictionary does not
            have keys matching the required parts.

    Examples:

    ```python
    >>> v = {"major": 1, "minor": 2, "patch": 4}
    >>> Version.from_dict(v)
    Version(major=1, minor=2, patch=4, prerelease=None, buildmetadata=None)

    ```

    ```python
    >>> v = {"major": 1, "minor": 2, "patch": 4, "prerelease": "rc.1", "buildmetadata": "build.123"}
    >>> Version.from_dict(v)
    Version(major=1, minor=2, patch=4, prerelease='rc.1', buildmetadata='build.123')

    ```
    """
    return Version(**version_dict)

from_json(json_string) classmethod

Construct and return a Version from a json string of it's parts.

Parameters:

Name Type Description Default
json_string str

The json string.

required

Returns:

Name Type Description
Version Version

The constructed Version.

Examples:

>>> v = '{"major": 1, "minor": 2, "patch": 4}'
>>> Version.from_json(v)
Version(major=1, minor=2, patch=4, prerelease=None, buildmetadata=None)
>>> v = '{"major": 1, "minor": 2, "patch": 4, "prerelease": "rc.1", "buildmetadata": "build.123"}'
>>> Version.from_json(v)
Version(major=1, minor=2, patch=4, prerelease='rc.1', buildmetadata='build.123')
Source code in madonna/version.py
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
@classmethod
def from_json(cls, json_string: str) -> Version:
    """
    Construct and return a `Version` from a json string
    of it's parts.

    Args:
        json_string (str): The json string.

    Returns:
        Version: The constructed Version.

    Examples:

    ```python
    >>> v = '{"major": 1, "minor": 2, "patch": 4}'
    >>> Version.from_json(v)
    Version(major=1, minor=2, patch=4, prerelease=None, buildmetadata=None)

    ```

    ```python
    >>> v = '{"major": 1, "minor": 2, "patch": 4, "prerelease": "rc.1", "buildmetadata": "build.123"}'
    >>> Version.from_json(v)
    Version(major=1, minor=2, patch=4, prerelease='rc.1', buildmetadata='build.123')

    ```
    """
    data: VersionDict = json.loads(json_string)
    return Version(**data)

from_string(string) classmethod

Construct and return a Version from a valid semver string.

Parameters:

Name Type Description Default
string str

The semver string.

required

Raises:

Type Description
ValueError

If the semver string does not pass the official semver regex.

Returns:

Name Type Description
Version Version

The constructed Version.

Examples:

>>> Version.from_string("v1.2.4")
Version(major=1, minor=2, patch=4, prerelease=None, buildmetadata=None)
>>> Version.from_string("v1.2.4-rc.1+build.123")
Version(major=1, minor=2, patch=4, prerelease='rc.1', buildmetadata='build.123')
Source code in madonna/version.py
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
@classmethod
def from_string(cls, string: str) -> Version:
    """
    Construct and return a `Version` from a valid semver
    string.

    Args:
        string (str): The semver string.

    Raises:
        ValueError: If the semver string does not
            pass the official semver regex.

    Returns:
        Version: The constructed Version.

    Examples:

    ```python
    >>> Version.from_string("v1.2.4")
    Version(major=1, minor=2, patch=4, prerelease=None, buildmetadata=None)

    ```

    ```python
    >>> Version.from_string("v1.2.4-rc.1+build.123")
    Version(major=1, minor=2, patch=4, prerelease='rc.1', buildmetadata='build.123')

    ```
    """
    match = _SEMVER_REGEX.match(string)
    if not match:
        raise ValueError(f"{string!r} is not a valid semver string.")

    return Version.from_dict(
        VersionDict(
            major=int(match.group("major")),
            minor=int(match.group("minor")),
            patch=int(match.group("patch")),
            prerelease=match.group("prerelease"),
            buildmetadata=match.group("buildmetadata"),
        )
    )

from_tuple(tup) classmethod

Construct and return a Version from a tuple of it's parts.

Parameters:

Name Type Description Default
tup VersionTuple

The tuple to construct the Version from.

required

Returns:

Name Type Description
Version Version

The constructed Version.

Examples:

>>> v = (1, 2, 4)
>>> Version.from_tuple(v)
Version(major=1, minor=2, patch=4, prerelease=None, buildmetadata=None)
>>> v = (1, 2, 4, "rc.1", "build.123")
>>> Version.from_tuple(v)
Version(major=1, minor=2, patch=4, prerelease='rc.1', buildmetadata='build.123')
Source code in madonna/version.py
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
@classmethod
def from_tuple(cls, tup: VersionTuple) -> Version:
    """
    Construct and return a `Version` from a tuple of it's
    parts.

    Args:
        tup (VersionTuple): The tuple to construct the Version
            from.

    Returns:
        Version: The constructed Version.

    Examples:

    ```python
    >>> v = (1, 2, 4)
    >>> Version.from_tuple(v)
    Version(major=1, minor=2, patch=4, prerelease=None, buildmetadata=None)

    ```

    ```python
    >>> v = (1, 2, 4, "rc.1", "build.123")
    >>> Version.from_tuple(v)
    Version(major=1, minor=2, patch=4, prerelease='rc.1', buildmetadata='build.123')

    ```
    """
    return Version(*tup)

is_valid()

Checks the Version against the official semver regex pattern and reports whether or not it is a valid semver.

Returns:

Name Type Description
bool bool

True if Version is valid, else False

Examples:

>>> v = Version(1, 2, 4)
>>> v.is_valid()
True
>>> v = Version(1, 2, 4, "blah198y_+-2-", "build---19790")
>>> v.is_valid()
False
Source code in madonna/version.py
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
def is_valid(self) -> bool:
    """
    Checks the `Version` against the official
    semver regex pattern and reports whether or not it
    is a valid semver.

    Returns:
        bool: True if `Version` is valid, else False

    Examples:

    ```python
    >>> v = Version(1, 2, 4)
    >>> v.is_valid()
    True

    ```

    ```python
    >>> v = Version(1, 2, 4, "blah198y_+-2-", "build---19790")
    >>> v.is_valid()
    False

    ```
    """
    return bool(_SEMVER_REGEX.match(self.to_string()))

to_dict()

Return the Version as a dictionary.

Returns:

Name Type Description
VersionDict VersionDict

The Version dictionary.

Examples:

>>> v = Version(1, 2, 4)
>>> v.to_dict()
{'major': 1, 'minor': 2, 'patch': 4, 'prerelease': None, 'buildmetadata': None}
>>> v = Version(1, 2, 4, "rc.1", "build.2")
>>> v.to_dict()
{'major': 1, 'minor': 2, 'patch': 4, 'prerelease': 'rc.1', 'buildmetadata': 'build.2'}
Source code in madonna/version.py
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
def to_dict(self) -> VersionDict:
    """
    Return the `Version` as a dictionary.

    Returns:
        VersionDict: The Version dictionary.

    Examples:

    ```python
    >>> v = Version(1, 2, 4)
    >>> v.to_dict()
    {'major': 1, 'minor': 2, 'patch': 4, 'prerelease': None, 'buildmetadata': None}

    ```

    ```python
    >>> v = Version(1, 2, 4, "rc.1", "build.2")
    >>> v.to_dict()
    {'major': 1, 'minor': 2, 'patch': 4, 'prerelease': 'rc.1', 'buildmetadata': 'build.2'}

    ```
    """
    return {
        "major": self.major,
        "minor": self.minor,
        "patch": self.patch,
        "prerelease": self.prerelease,
        "buildmetadata": self.buildmetadata,
    }

to_json()

Return the Version as a JSON string.

Returns:

Name Type Description
str str

The Version JSON string.

Examples:

>>> v = Version(1, 2, 4)
>>> v.to_json()
'{"major": 1, "minor": 2, "patch": 4, "prerelease": null, "buildmetadata": null}'
>>> v = Version(1, 2, 4, "rc.1", "build.2")
>>> v.to_json()
'{"major": 1, "minor": 2, "patch": 4, "prerelease": "rc.1", "buildmetadata": "build.2"}'
Source code in madonna/version.py
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
def to_json(self) -> str:
    """
    Return the `Version` as a JSON string.

    Returns:
        str: The Version JSON string.

    Examples:

    ```python
    >>> v = Version(1, 2, 4)
    >>> v.to_json()
    '{"major": 1, "minor": 2, "patch": 4, "prerelease": null, "buildmetadata": null}'

    ```

    ```python
    >>> v = Version(1, 2, 4, "rc.1", "build.2")
    >>> v.to_json()
    '{"major": 1, "minor": 2, "patch": 4, "prerelease": "rc.1", "buildmetadata": "build.2"}'

    ```
    """
    return json.dumps(self.to_dict())

to_string()

Generate a string representation of the Version.

Returns:

Name Type Description
str str

Version string.

Examples:

>>> v = Version(1, 2, 4)
>>> v.to_string()
'v1.2.4'
>>> v = Version(1, 2, 4, "rc.2", "build.6")
>>> v.to_string()
'v1.2.4-rc.2+build.6'
Source code in madonna/version.py
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
def to_string(self) -> str:
    """
    Generate a string representation of the
    `Version`.

    Returns:
        str: Version string.

    Examples:

    ```python
    >>> v = Version(1, 2, 4)
    >>> v.to_string()
    'v1.2.4'

    ```

    ```python
    >>> v = Version(1, 2, 4, "rc.2", "build.6")
    >>> v.to_string()
    'v1.2.4-rc.2+build.6'

    ```
    """
    return str(self)

to_tuple()

Return the Version as a tuple of it's fields.

Returns:

Name Type Description
VersionTuple VersionTuple

The Version tuple.

Examples:

>>> v = Version(1, 2, 4)
>>> v.to_tuple()
(1, 2, 4, None, None)
>>> v = Version(1, 2, 4, "rc.2", "build.6")
>>> v.to_tuple()
(1, 2, 4, 'rc.2', 'build.6')
Source code in madonna/version.py
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
def to_tuple(self) -> VersionTuple:
    """
    Return the `Version` as a tuple of it's
    fields.

    Returns:
        VersionTuple: The Version tuple.

    Examples:

    ```python
    >>> v = Version(1, 2, 4)
    >>> v.to_tuple()
    (1, 2, 4, None, None)

    ```

    ```python
    >>> v = Version(1, 2, 4, "rc.2", "build.6")
    >>> v.to_tuple()
    (1, 2, 4, 'rc.2', 'build.6')

    ```
    """
    return (self.major, self.minor, self.patch, self.prerelease, self.buildmetadata)