rendercanvas 2.2.0__tar.gz → 2.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/PKG-INFO +1 -1
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/_loop.py +1 -1
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/_scheduler.py +21 -8
- rendercanvas-2.2.1/rendercanvas/_version.py +194 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/base.py +13 -2
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/glfw.py +12 -18
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/qt.py +0 -2
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/raw.py +1 -0
- rendercanvas-2.2.0/rendercanvas/_version.py +0 -113
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/LICENSE +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/README.md +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/pyproject.toml +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/__init__.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/__pyinstaller/__init__.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/__pyinstaller/conftest.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/__pyinstaller/hook-rendercanvas.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/__pyinstaller/test_rendercanvas.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/_context.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/_coreutils.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/_events.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/asyncio.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/auto.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/jupyter.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/offscreen.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/pyqt5.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/pyqt6.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/pyside2.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/pyside6.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/stub.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/trio.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/utils/__init__.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/utils/asyncadapter.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/utils/asyncs.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/utils/bitmappresentadapter.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/utils/bitmaprenderingcontext.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/utils/cube.py +0 -0
- {rendercanvas-2.2.0 → rendercanvas-2.2.1}/rendercanvas/wx.py +0 -0
|
@@ -372,7 +372,7 @@ class BaseLoop:
|
|
|
372
372
|
This method is optional. A subclass must either implement ``_rc_add_task`` or ``_rc_call_later``.
|
|
373
373
|
|
|
374
374
|
* If you implememt this, make ``_rc_add_task()`` call ``super()._rc_add_task()``.
|
|
375
|
-
* If delay is zero, this should behave like "
|
|
375
|
+
* If delay is zero, this should behave like "call_soon".
|
|
376
376
|
* No need to catch errors from the callback; that's dealt with internally.
|
|
377
377
|
* Return None.
|
|
378
378
|
"""
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
The scheduler class/loop.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
import sys
|
|
5
6
|
import time
|
|
6
7
|
import weakref
|
|
7
8
|
|
|
@@ -9,6 +10,9 @@ from ._coreutils import BaseEnum
|
|
|
9
10
|
from .utils.asyncs import sleep, Event
|
|
10
11
|
|
|
11
12
|
|
|
13
|
+
IS_WIN = sys.platform.startswith("win")
|
|
14
|
+
|
|
15
|
+
|
|
12
16
|
class UpdateMode(BaseEnum):
|
|
13
17
|
"""The UpdateMode enum specifies the different modes to schedule draws for the canvas."""
|
|
14
18
|
|
|
@@ -123,14 +127,23 @@ class Scheduler:
|
|
|
123
127
|
delay = 1 / self._max_fps
|
|
124
128
|
delay = 0 if delay < 0 else delay # 0 means cannot keep up
|
|
125
129
|
|
|
126
|
-
#
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
130
|
+
# Determine amount of sleep
|
|
131
|
+
sleep_time = delay - (time.perf_counter() - last_tick_time)
|
|
132
|
+
|
|
133
|
+
if IS_WIN:
|
|
134
|
+
# On Windows OS-level timers have an in accuracy of 15.6 ms.
|
|
135
|
+
# This can cause sleep to take longer than intended. So we sleep
|
|
136
|
+
# less, and then do a few small sync-sleeps that have high accuracy.
|
|
137
|
+
await sleep(max(0, sleep_time - 0.0156))
|
|
138
|
+
sleep_time = delay - (time.perf_counter() - last_tick_time)
|
|
139
|
+
while sleep_time > 0:
|
|
140
|
+
time.sleep(min(sleep_time, 0.001)) # sleep hard for at most 1ms
|
|
141
|
+
await sleep(0) # Allow other tasks to run but don't wait
|
|
142
|
+
sleep_time = delay - (time.perf_counter() - last_tick_time)
|
|
143
|
+
else:
|
|
144
|
+
# Wait. Even if delay is zero, it gives control back to the loop,
|
|
145
|
+
# allowing other tasks to do work.
|
|
146
|
+
await sleep(max(0, sleep_time))
|
|
134
147
|
|
|
135
148
|
# Below is the "tick"
|
|
136
149
|
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"""
|
|
2
|
+
_version.py v1.4
|
|
3
|
+
|
|
4
|
+
Simple version string management, using a hard-coded version string
|
|
5
|
+
for simplicity and compatibility, while adding git info at runtime.
|
|
6
|
+
See https://github.com/pygfx/_version for more info.
|
|
7
|
+
This code is subject to The Unlicense (public domain).
|
|
8
|
+
|
|
9
|
+
Any updates to this file should be done in https://github.com/pygfx/_version
|
|
10
|
+
|
|
11
|
+
Usage in short:
|
|
12
|
+
|
|
13
|
+
* Add this file to the root of your library (next to the `__init__.py`).
|
|
14
|
+
* On a new release, you just update the __version__.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
# ruff: noqa: RUF100, S310, PLR2004, D212, D400, D415, S603, BLE001, COM812
|
|
18
|
+
|
|
19
|
+
import logging
|
|
20
|
+
import subprocess
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
|
|
23
|
+
# This is the base version number, to be bumped before each release.
|
|
24
|
+
# The build system detects this definition when building a distribution.
|
|
25
|
+
__version__ = "2.2.1"
|
|
26
|
+
|
|
27
|
+
# Set this to your library name
|
|
28
|
+
project_name = "rendercanvas"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
logger = logging.getLogger(project_name)
|
|
32
|
+
|
|
33
|
+
# Get whether this is a repo. If so, repo_dir is the path, otherwise None.
|
|
34
|
+
# .git is a dir in a normal repo and a file when in a submodule.
|
|
35
|
+
repo_dir = Path(__file__).parents[1]
|
|
36
|
+
repo_dir = repo_dir if repo_dir.joinpath(".git").exists() else None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def get_version() -> str:
|
|
40
|
+
"""Get the version string."""
|
|
41
|
+
if repo_dir:
|
|
42
|
+
return get_extended_version()
|
|
43
|
+
return __version__
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def get_extended_version() -> str:
|
|
47
|
+
"""Get an extended version string with information from git."""
|
|
48
|
+
release, post, labels = get_version_info_from_git()
|
|
49
|
+
|
|
50
|
+
# Sample first 3 parts of __version__
|
|
51
|
+
base_release = ".".join(__version__.split(".")[:3])
|
|
52
|
+
|
|
53
|
+
# Check release
|
|
54
|
+
if not release:
|
|
55
|
+
release = base_release
|
|
56
|
+
elif release != base_release:
|
|
57
|
+
warning(
|
|
58
|
+
f"{project_name} version from git ({release})"
|
|
59
|
+
f" and __version__ ({base_release}) don't match."
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Build the total version
|
|
63
|
+
version = release
|
|
64
|
+
if post and post != "0":
|
|
65
|
+
version += f".post{post}"
|
|
66
|
+
if labels:
|
|
67
|
+
version += "+" + ".".join(labels)
|
|
68
|
+
elif labels and labels[-1] == "dirty":
|
|
69
|
+
version += "+" + ".".join(labels)
|
|
70
|
+
|
|
71
|
+
return version
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def get_version_info_from_git() -> str:
|
|
75
|
+
"""
|
|
76
|
+
Get (release, post, labels) from Git.
|
|
77
|
+
|
|
78
|
+
With `release` the version number from the latest tag, `post` the
|
|
79
|
+
number of commits since that tag, and `labels` a tuple with the
|
|
80
|
+
git-hash and optionally a dirty flag.
|
|
81
|
+
"""
|
|
82
|
+
# Call out to Git
|
|
83
|
+
command = [
|
|
84
|
+
"git",
|
|
85
|
+
"describe",
|
|
86
|
+
"--long",
|
|
87
|
+
"--always",
|
|
88
|
+
"--tags",
|
|
89
|
+
"--dirty",
|
|
90
|
+
"--first-parent",
|
|
91
|
+
]
|
|
92
|
+
try:
|
|
93
|
+
p = subprocess.run(command, check=False, cwd=repo_dir, capture_output=True)
|
|
94
|
+
except Exception as e:
|
|
95
|
+
warning(f"Could not get {project_name} version: {e}")
|
|
96
|
+
p = None
|
|
97
|
+
|
|
98
|
+
# Parse the result into parts
|
|
99
|
+
if p is None:
|
|
100
|
+
parts = (None, None, "unknown")
|
|
101
|
+
else:
|
|
102
|
+
output = p.stdout.decode(errors="ignore")
|
|
103
|
+
if p.returncode:
|
|
104
|
+
stderr = p.stderr.decode(errors="ignore")
|
|
105
|
+
warning(
|
|
106
|
+
f"Could not get {project_name} version.\n\nstdout: "
|
|
107
|
+
+ output
|
|
108
|
+
+ "\n\nstderr: "
|
|
109
|
+
+ stderr
|
|
110
|
+
)
|
|
111
|
+
parts = (None, None, "unknown")
|
|
112
|
+
else:
|
|
113
|
+
parts = output.strip().lstrip("v").split("-")
|
|
114
|
+
if len(parts) <= 2:
|
|
115
|
+
# No tags (and thus no post). Only git hash and maybe 'dirty'.
|
|
116
|
+
parts = (None, None, *parts)
|
|
117
|
+
|
|
118
|
+
# Return unpacked parts
|
|
119
|
+
release, post, *labels = parts
|
|
120
|
+
return release, post, labels
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def version_to_tuple(v: str) -> tuple:
|
|
124
|
+
v = __version__.split("+")[0] # remove hash
|
|
125
|
+
return tuple(int(i) if i.isnumeric() else i for i in v.split("."))
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def prnt(m: str) -> None:
|
|
129
|
+
sys.stdout.write(m + "\n")
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def warning(m: str) -> None:
|
|
133
|
+
logger.warning(m)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
# Apply the versioning
|
|
137
|
+
base_version = __version__
|
|
138
|
+
__version__ = get_version()
|
|
139
|
+
version_info = version_to_tuple(__version__)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
# The CLI part
|
|
143
|
+
|
|
144
|
+
CLI_USAGE = """
|
|
145
|
+
_version.py
|
|
146
|
+
|
|
147
|
+
help - Show this message.
|
|
148
|
+
version - Show the current version.
|
|
149
|
+
bump VERSION - Bump the __version__ to the given VERSION.
|
|
150
|
+
update - Self-update the _version.py module by downloading the
|
|
151
|
+
reference code and replacing version number and project name.
|
|
152
|
+
""".lstrip()
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
import sys
|
|
156
|
+
import urllib.request
|
|
157
|
+
|
|
158
|
+
_, *args = sys.argv
|
|
159
|
+
this_file = Path(__file__)
|
|
160
|
+
|
|
161
|
+
if not args or args[0] == "version":
|
|
162
|
+
prnt(f"{project_name} v{__version__}")
|
|
163
|
+
|
|
164
|
+
elif args[0] == "bump":
|
|
165
|
+
if len(args) != 2:
|
|
166
|
+
sys.exit("Expected a version number to bump to.")
|
|
167
|
+
new_version = args[1].lstrip("v") # allow '1.2.3' and 'v1.2.3'
|
|
168
|
+
if new_version.count(".") != 2:
|
|
169
|
+
sys.exit("Expected two dots in new version string.")
|
|
170
|
+
if not all(s.isnumeric() for s in new_version.split(".")):
|
|
171
|
+
sys.exit("Expected only numbers in new version string.")
|
|
172
|
+
with this_file.open("rb") as f:
|
|
173
|
+
text = ref_text = f.read().decode()
|
|
174
|
+
text = text.replace(base_version, new_version, 1)
|
|
175
|
+
with this_file.open("wb") as f:
|
|
176
|
+
f.write(text.encode())
|
|
177
|
+
prnt(f"Bumped version from '{base_version}' to '{new_version}'.")
|
|
178
|
+
|
|
179
|
+
elif args[0] == "update":
|
|
180
|
+
u = "https://raw.githubusercontent.com/pygfx/_version/main/_version.py"
|
|
181
|
+
with urllib.request.urlopen(u) as f:
|
|
182
|
+
text = ref_text = f.read().decode()
|
|
183
|
+
text = text.replace("0.0.0", base_version, 1)
|
|
184
|
+
text = text.replace("PROJECT_NAME", project_name, 1)
|
|
185
|
+
with this_file.open("wb") as f:
|
|
186
|
+
f.write(text.encode())
|
|
187
|
+
prnt("Updated to the latest _version.py.")
|
|
188
|
+
|
|
189
|
+
elif args[0].lstrip("-") in ["h", "help"]:
|
|
190
|
+
prnt(CLI_USAGE)
|
|
191
|
+
|
|
192
|
+
else:
|
|
193
|
+
prnt(f"Unknown command for _version.py: {args[0]!r}")
|
|
194
|
+
prnt("Use ``python _version.py help`` to see a list of options.")
|
|
@@ -476,11 +476,22 @@ class BaseRenderCanvas:
|
|
|
476
476
|
# %% Primary canvas management methods
|
|
477
477
|
|
|
478
478
|
def get_logical_size(self) -> Tuple[float]:
|
|
479
|
-
"""Get the logical size (width, height) in float pixels.
|
|
479
|
+
"""Get the logical size (width, height) in float pixels.
|
|
480
|
+
|
|
481
|
+
The logical size can be smaller than the physical size, e.g. on HiDPI
|
|
482
|
+
monitors or when the user's system has the display-scale set to e.g. 125%.
|
|
483
|
+
"""
|
|
480
484
|
return self._rc_get_logical_size()
|
|
481
485
|
|
|
482
486
|
def get_pixel_ratio(self) -> float:
|
|
483
|
-
"""Get the float ratio between logical and physical pixels.
|
|
487
|
+
"""Get the float ratio between logical and physical pixels.
|
|
488
|
+
|
|
489
|
+
The pixel ratio is typically 1.0 for normal screens and 2.0 for HiDPI
|
|
490
|
+
screens, but fractional values are also possible if the system
|
|
491
|
+
display-scale is set to e.g. 125%. An HiDPI screen can be assumed if the
|
|
492
|
+
pixel ratio >= 2.0. On MacOS (with a Retina screen) the pixel ratio is
|
|
493
|
+
always 2.0.
|
|
494
|
+
"""
|
|
484
495
|
return self._rc_get_pixel_ratio()
|
|
485
496
|
|
|
486
497
|
def close(self) -> None:
|
|
@@ -25,12 +25,12 @@ if glfw_version_info < (1, 9):
|
|
|
25
25
|
raise ImportError("rendercanvas requires glfw 1.9 or higher.")
|
|
26
26
|
|
|
27
27
|
# Do checks to prevent pitfalls on hybrid Xorg/Wayland systems
|
|
28
|
-
|
|
28
|
+
api_is_wayland = False
|
|
29
29
|
if sys.platform.startswith("linux") and SYSTEM_IS_WAYLAND:
|
|
30
30
|
if not hasattr(glfw, "get_x11_window"):
|
|
31
31
|
# Probably glfw was imported before this module, so we missed our chance
|
|
32
32
|
# to set the env var to make glfw use x11.
|
|
33
|
-
|
|
33
|
+
api_is_wayland = True
|
|
34
34
|
logger.warning("Using GLFW with Wayland, which is experimental.")
|
|
35
35
|
|
|
36
36
|
|
|
@@ -135,7 +135,7 @@ def get_glfw_present_methods(window):
|
|
|
135
135
|
}
|
|
136
136
|
}
|
|
137
137
|
elif sys.platform.startswith("linux"):
|
|
138
|
-
if
|
|
138
|
+
if api_is_wayland:
|
|
139
139
|
return {
|
|
140
140
|
"screen": {
|
|
141
141
|
"platform": "wayland",
|
|
@@ -262,6 +262,8 @@ class GlfwRenderCanvas(BaseRenderCanvas):
|
|
|
262
262
|
def _determine_size(self):
|
|
263
263
|
if self._window is None:
|
|
264
264
|
return
|
|
265
|
+
# Note: On Wayland glfw.get_window_content_scale() produces (1.0, 1.0) regardless of the OS settings.
|
|
266
|
+
|
|
265
267
|
# Because the value of get_window_size is in physical-pixels
|
|
266
268
|
# on some systems and in logical-pixels on other, we use the
|
|
267
269
|
# framebuffer size and pixel ratio to derive the logical size.
|
|
@@ -305,21 +307,13 @@ class GlfwRenderCanvas(BaseRenderCanvas):
|
|
|
305
307
|
psize = glfw.get_framebuffer_size(self._window)
|
|
306
308
|
|
|
307
309
|
# Apply
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
)
|
|
316
|
-
else:
|
|
317
|
-
screen_ratio = ssize[0] / psize[0]
|
|
318
|
-
glfw.set_window_size(
|
|
319
|
-
self._window,
|
|
320
|
-
int(new_logical_size[0] * pixel_ratio * screen_ratio),
|
|
321
|
-
int(new_logical_size[1] * pixel_ratio * screen_ratio),
|
|
322
|
-
)
|
|
310
|
+
screen_ratio = ssize[0] / psize[0]
|
|
311
|
+
glfw.set_window_size(
|
|
312
|
+
self._window,
|
|
313
|
+
int(new_logical_size[0] * pixel_ratio * screen_ratio),
|
|
314
|
+
int(new_logical_size[1] * pixel_ratio * screen_ratio),
|
|
315
|
+
)
|
|
316
|
+
|
|
323
317
|
self._screen_size_is_logical = screen_ratio != 1
|
|
324
318
|
# If this causes the widget size to change, then _on_size_change will
|
|
325
319
|
# be called, but we may want force redetermining the size.
|
|
@@ -31,7 +31,6 @@ if libname:
|
|
|
31
31
|
WA_PaintOnScreen = QtCore.Qt.WidgetAttribute.WA_PaintOnScreen
|
|
32
32
|
WA_DeleteOnClose = QtCore.Qt.WidgetAttribute.WA_DeleteOnClose
|
|
33
33
|
WA_InputMethodEnabled = QtCore.Qt.WidgetAttribute.WA_InputMethodEnabled
|
|
34
|
-
PreciseTimer = QtCore.Qt.TimerType.PreciseTimer
|
|
35
34
|
KeyboardModifiers = QtCore.Qt.KeyboardModifier
|
|
36
35
|
FocusPolicy = QtCore.Qt.FocusPolicy
|
|
37
36
|
CursorShape = QtCore.Qt.CursorShape
|
|
@@ -42,7 +41,6 @@ if libname:
|
|
|
42
41
|
WA_PaintOnScreen = QtCore.Qt.WA_PaintOnScreen
|
|
43
42
|
WA_DeleteOnClose = QtCore.Qt.WA_DeleteOnClose
|
|
44
43
|
WA_InputMethodEnabled = QtCore.Qt.WA_InputMethodEnabled
|
|
45
|
-
PreciseTimer = QtCore.Qt.PreciseTimer
|
|
46
44
|
KeyboardModifiers = QtCore.Qt
|
|
47
45
|
FocusPolicy = QtCore.Qt
|
|
48
46
|
CursorShape = QtCore.Qt
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Versioning: we use a hard-coded version number, because it's simple and always
|
|
3
|
-
works. For dev installs we add extra version info from Git.
|
|
4
|
-
"""
|
|
5
|
-
|
|
6
|
-
import logging
|
|
7
|
-
import subprocess
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
# This is the reference version number, to be bumped before each release.
|
|
12
|
-
# The build system detects this definition when building a distribution.
|
|
13
|
-
__version__ = "2.2.0"
|
|
14
|
-
|
|
15
|
-
# Allow using nearly the same code in different projects
|
|
16
|
-
project_name = "rendercanvas"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
logger = logging.getLogger(project_name.lower())
|
|
20
|
-
|
|
21
|
-
# Get whether this is a repo. If so, repo_dir is the path, otherwise repo_dir is None.
|
|
22
|
-
repo_dir = Path(__file__).parents[1]
|
|
23
|
-
repo_dir = repo_dir if repo_dir.joinpath(".git").is_dir() else None
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def get_version():
|
|
27
|
-
"""Get the version string."""
|
|
28
|
-
if repo_dir:
|
|
29
|
-
return get_extended_version()
|
|
30
|
-
else:
|
|
31
|
-
return __version__
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def get_extended_version():
|
|
35
|
-
"""Get an extended version string with information from git."""
|
|
36
|
-
|
|
37
|
-
release, post, labels = get_version_info_from_git()
|
|
38
|
-
|
|
39
|
-
# Sample first 3 parts of __version__
|
|
40
|
-
base_release = ".".join(__version__.split(".")[:3])
|
|
41
|
-
|
|
42
|
-
# Check release
|
|
43
|
-
if not release:
|
|
44
|
-
release = base_release
|
|
45
|
-
elif release != base_release:
|
|
46
|
-
logger.warning(
|
|
47
|
-
f"{project_name} version from git ({release}) and __version__ ({base_release}) don't match."
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
# Build the total version
|
|
51
|
-
version = release
|
|
52
|
-
if post and post != "0":
|
|
53
|
-
version += f".post{post}"
|
|
54
|
-
if labels:
|
|
55
|
-
version += "+" + ".".join(labels)
|
|
56
|
-
|
|
57
|
-
return version
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def get_version_info_from_git():
|
|
61
|
-
"""Get (release, post, labels) from Git.
|
|
62
|
-
|
|
63
|
-
With `release` the version number from the latest tag, `post` the
|
|
64
|
-
number of commits since that tag, and `labels` a tuple with the
|
|
65
|
-
git-hash and optionally a dirty flag.
|
|
66
|
-
"""
|
|
67
|
-
|
|
68
|
-
# Call out to Git
|
|
69
|
-
command = [
|
|
70
|
-
"git",
|
|
71
|
-
"describe",
|
|
72
|
-
"--long",
|
|
73
|
-
"--always",
|
|
74
|
-
"--tags",
|
|
75
|
-
"--dirty",
|
|
76
|
-
"--first-parent",
|
|
77
|
-
]
|
|
78
|
-
try:
|
|
79
|
-
p = subprocess.run(command, cwd=repo_dir, capture_output=True)
|
|
80
|
-
except Exception as e:
|
|
81
|
-
logger.warning(f"Could not get {project_name} version: {e}")
|
|
82
|
-
p = None
|
|
83
|
-
|
|
84
|
-
# Parse the result into parts
|
|
85
|
-
if p is None:
|
|
86
|
-
parts = (None, None, "unknown")
|
|
87
|
-
else:
|
|
88
|
-
output = p.stdout.decode(errors="ignore")
|
|
89
|
-
if p.returncode:
|
|
90
|
-
stderr = p.stderr.decode(errors="ignore")
|
|
91
|
-
logger.warning(
|
|
92
|
-
f"Could not get {project_name} version.\n\nstdout: "
|
|
93
|
-
+ output
|
|
94
|
-
+ "\n\nstderr: "
|
|
95
|
-
+ stderr
|
|
96
|
-
)
|
|
97
|
-
parts = (None, None, "unknown")
|
|
98
|
-
else:
|
|
99
|
-
parts = output.strip().lstrip("v").split("-")
|
|
100
|
-
if len(parts) <= 2:
|
|
101
|
-
# No tags (and thus also no post). Only git hash and maybe 'dirty'
|
|
102
|
-
parts = (None, None, *parts)
|
|
103
|
-
|
|
104
|
-
# Return unpacked parts
|
|
105
|
-
release, post, *labels = parts
|
|
106
|
-
return release, post, labels
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
__version__ = get_version()
|
|
110
|
-
|
|
111
|
-
version_info = tuple(
|
|
112
|
-
int(i) if i.isnumeric() else i for i in __version__.split("+")[0].split(".")
|
|
113
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|