13
13
# Using file=sys.stderr prints to the error stream (usually prints red)
14
14
print("This game requires Arcade 3.0.0+ to run!", file=sys.stderr)
15
15
16
+ The ``VERSION`` constant in this module will be loaded from a file in the
17
+ same directory. It will contain the following:
16
18
17
- Arcade contributors will benefit from understanding how and why
18
- this file loads and converts the contents of the ``VERSION`` file.
19
+ #. major
20
+ #. minor
21
+ #. point
22
+ #. (Optional) one and _only_ one of:
19
23
20
- After a release build succeeds, GitHub's CI is configured to do
21
- the following:
22
-
23
- #. Push the package files to PyPI
24
- #. Call the ``remorses/bump-version@js`` action to auto-increment
25
- Arcade's version on the development branch
26
-
27
- This is where an edge case arises:
28
-
29
- #. Our CI expects ``3.1.0-dev.1`` for dev preview builds
30
- #. Python expects ``3.1.0.dev1`` for dev preview builds
31
-
32
- The ``VERSION`` file in this file's directory stores the version
33
- in the form the GH Action prefers. This allows it to auto-increment
34
- the version number on the ``development`` branch after we make an
35
- Arcade release to PyPI.
36
-
37
- The auto-bump action is configured by the following file:
38
- https://github.com/pythonarcade/arcade/blob/development/.github/workflows/bump_version.yml
39
-
40
- As an example, the GH action would auto-increment a dev preview's
41
- version after releasing the 5th dev preview of ``3.1.0`` by updating
42
- the ``VERSION`` file from this:
43
-
44
- .. code-block::
45
-
46
- 3.1.0-dev.5
47
-
48
- ...to this:
49
-
50
- .. code-block::
51
-
52
- 3.1.0-dev.6
24
+ * .dev{DEV_PREVIEW_NUMBER}
25
+ * rc{RC_NUMBER}
53
26
54
27
"""
55
28
63
36
_HERE = Path (__file__ ).parent
64
37
65
38
# Grab version numbers + optional dev point preview
66
- # Assumes $MAJOR.$MINOR.$POINT format with optional -dev$DEV_PREVIEW
39
+ # Assumes:
40
+ # {MAJOR}.{MINOR}.{POINT} format
41
+ # optional: one and ONLY one of:
42
+ # 1. dev{DEV_PREVIEW}
43
+ # 2. rc{RC_NUMBER}
67
44
# Q: Why did you use regex?!
68
45
# A: If the dev_preview field is invalid, the whole match fails instantly
69
- _VERSION_REGEX = re .compile (
46
+ _VERSION_REGEX : Final [ re . Pattern ] = re .compile (
70
47
r"""
71
48
# First three version number fields
72
49
(?P<major>[0-9]+)
73
- \.(?P<minor>[ 0-9]+ )
74
- \.(?P<point>[ 0-9]+ )
75
- # Optional dev preview suffix
50
+ \.(?P<minor>0|[1-9][ 0-9]* )
51
+ \.(?P<point>0|[1-9][ 0-9]* )
52
+ # Optional and mutually exclusive: dev preview or rc number
76
53
(?:
77
- - dev # Dev prefix as a literal
78
- \. # Point
79
- (?P<dev_preview>[ 0-9]+) # Dev preview number
54
+ \.(?P<dev_preview> dev(?:0|[1-9][0-9]*))
55
+ | # XOR: can't be both a preview and an rc
56
+ (?P<rc_number>rc(?:0|[1-9][ 0-9]*))
80
57
)?
81
58
""" ,
82
59
re .X ,
83
60
)
84
61
85
62
86
- def _parse_python_friendly_version (version_for_github_actions : str ) -> str :
87
- """Convert a GitHub CI version string to a Python-friendly one.
63
+ def _parse_python_friendly_version (
64
+ raw_version : str , pattern : re .Pattern [str ] = _VERSION_REGEX
65
+ ) -> str :
66
+ """Read a GitHub CI version string to a Python-friendly one.
88
67
89
68
For example, ``3.1.0-dev.1`` would become ``3.1.0.dev1``.
90
69
91
70
Args:
92
- version_for_github_actions :
71
+ raw_version :
93
72
A raw GitHub CI version string, as read from a file.
94
73
Returns:
95
74
A Python-friendly version string.
96
75
"""
97
76
# Quick preflight check: we don't support tuple format here!
98
- if not isinstance (version_for_github_actions , str ):
99
- raise TypeError (
100
- f"Expected a string of the format MAJOR.MINOR.POINT"
101
- f"or MAJOR.MINOR.POINT-dev.DEV_PREVIEW,"
102
- f"not { version_for_github_actions !r} "
103
- )
104
-
105
- # Attempt to extract our raw data
106
- match = _VERSION_REGEX .fullmatch (version_for_github_actions .strip ())
107
- if match is None :
108
- raise ValueError (
109
- f"String does not appear to be a version number: { version_for_github_actions !r} "
77
+ problem = None
78
+ if not isinstance (raw_version , str ):
79
+ problem = TypeError
80
+ elif (match := pattern .fullmatch (raw_version )) is None :
81
+ problem = ValueError
82
+ if problem :
83
+ raise problem (
84
+ f"{ raw_version = !r} not a str of the format MAJOR.MINOR"
85
+ f"POINT with at most one of dev{{DEV_PREVIEW}} or"
86
+ f"rc{{RC_NUMBER}},"
110
87
)
111
88
112
89
# Build final output, including a dev preview version if present
113
- group_dict = match .groupdict ()
114
- major , minor , point , dev_preview = group_dict .values ()
115
- parts = [major , minor , point ]
116
- if dev_preview is not None :
117
- parts .append (f"dev{ dev_preview } " )
90
+ group_dict : dict [str , str | None ] = match .groupdict () # type: ignore
91
+ parts : list [str ] = [group_dict [k ] for k in ("major" , "minor" , "point" )] # type: ignore
92
+ dev_preview , rc_number = (group_dict [k ] for k in ("dev_preview" , "rc_number" ))
93
+
94
+ if dev_preview and rc_number :
95
+ raise ValueError (f"Can't have both { dev_preview = !r} and { rc_number = !r} " )
96
+ elif dev_preview :
97
+ parts .append (dev_preview )
98
+
118
99
joined = "." .join (parts )
100
+ if rc_number :
101
+ joined += rc_number
119
102
120
103
return joined
121
104
122
105
123
- def _parse_py_version_from_github_ci_file (
106
+ def _parse_py_version_from_file (
124
107
version_path : str | Path = _HERE / "VERSION" , write_errors_to = sys .stderr
125
108
) -> str :
126
- """Parse a Python-friendly version from a ``bump-version``-compatible file .
109
+ """Read & validate the VERSION file as from a limited subset .
127
110
128
111
On failure, it will:
129
112
130
113
#. Print an error to stderr
131
114
#. Return "0.0.0"
115
+ #. (Indirectly) cause any PyPI uploads to fail
132
116
133
117
Args:
134
118
version_path:
@@ -152,7 +136,7 @@ def _parse_py_version_from_github_ci_file(
152
136
return data
153
137
154
138
155
- VERSION : Final [str ] = _parse_py_version_from_github_ci_file ()
139
+ VERSION : Final [str ] = _parse_py_version_from_file ()
156
140
"""A Python-friendly version string.
157
141
158
142
This value is converted from the GitHub-style ``VERSION`` file at the
0 commit comments