Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Arcade [PyPi Release History](https://pypi.org/project/arcade/#history) page.
## Unreleased

### Fixes
- Fixed the PyInstaller hook bundling Arcade's version file at `arcade/VERSION/VERSION`. Frozen apps printed an error on startup and reported `arcade.VERSION` as `0.0.0`, and builds using `collect_all("arcade")` failed because the hook and `collect_all` put a folder and a file at the same path. The version file is now `arcade/_VERSION`, so it can't be confused with the `arcade.version` module ([#2837](https://github.com/pythonarcade/arcade/issues/2837)).
- Fixed drawing into a texture atlas losing new drawing when the atlas grows during `render_into()`. Nested rendering and exception exits now restore the previous camera and render region.
- Fixed several `arcade.create_text_sprite()` bugs:
- Sprites with the same text shared one image in the texture atlas, so creating a second one (for example in another color or size) changed the first one and drew the second stretched. Each sprite now gets its own image.
Expand Down
2 changes: 1 addition & 1 deletion MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# one-liner to get extensions in package: set([l.split(",")[0].split('.')[-1] for l in open('files.txt').readlines()])

recursive-exclude arcade *.pyc
recursive-include arcade VERSION
recursive-include arcade _VERSION
recursive-include arcade *.typed
recursive-include arcade/resources *.txt *.md *.url
recursive-include arcade/resources *.mp3 *.wav *.ogg
Expand Down
2 changes: 1 addition & 1 deletion RELEASE_CHECKLIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
6. Run `tests/test_examples/run_all_examples.py`
7. Make sure `arcade/examples/asteroid_smasher.py` is playable.
8. Make sure `arcade/examples/platform_tutorial/17_views.py` is playable.
9. Update version number in `arcade/version.py`
9. Update version number in `arcade/_VERSION`
10. Update :ref:`release_notes` with release dates and any additional
info needed.
11. Make sure last check-in ran clean on GitHub actions, viewable on Discord
Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions arcade/__pyinstaller/hook-arcade.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
"./arcade/resources/system",
),
(
arcade_path / "VERSION",
"./arcade/VERSION",
arcade_path / "_VERSION",
"./arcade",
),
]
)
Expand Down
8 changes: 4 additions & 4 deletions arcade/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ def _parse_python_friendly_version(


def _parse_py_version_from_file(
version_path: str | Path = _HERE / "VERSION", write_errors_to=sys.stderr
version_path: str | Path = _HERE / "_VERSION", write_errors_to=sys.stderr
) -> str:
"""Read & validate the VERSION file as from a limited subset.
"""Read and validate the _VERSION file using a limited version syntax.

On failure, it will:

Expand All @@ -114,7 +114,7 @@ def _parse_py_version_from_file(

Args:
version_path:
The VERSION file's path, defaulting to the same directory as
The _VERSION file's path, defaulting to the same directory as
this file.
write_errors_to:
Makes CI simpler by allowing a stream mock to be passed easily.
Expand All @@ -137,6 +137,6 @@ def _parse_py_version_from_file(
VERSION: Final[str] = _parse_py_version_from_file()
"""A Python-friendly version string.

This value is converted from the GitHub-style ``VERSION`` file at the
This value is converted from the GitHub-style ``_VERSION`` file at the
top-level of the arcade module.
"""
2 changes: 1 addition & 1 deletion doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
for k, v in ENV.items():
log.info(f"Env variable {k:{col_width}} : {v!r}")

# _temp_version = (REPO_LOCAL_ROOT / "arcade" / "VERSION").read_text().replace("-",'')
# _temp_version = (REPO_LOCAL_ROOT / "arcade" / "_VERSION").read_text().replace("-",'')

# Don't change to
# from arcade.version import VERSION
Expand Down
30 changes: 30 additions & 0 deletions tests/unit/test_pyinstaller_hook.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import runpy
import sys
from pathlib import Path
from types import ModuleType

import pytest

import arcade


def test_version_data_is_bundled_at_package_root(monkeypatch: pytest.MonkeyPatch):
pyinstaller = ModuleType("PyInstaller")
compat = ModuleType("PyInstaller.compat")
setattr(pyinstaller, "__path__", [])
setattr(pyinstaller, "compat", compat)
setattr(compat, "is_darwin", False)
setattr(compat, "is_unix", True)
setattr(compat, "is_win", False)
monkeypatch.setitem(sys.modules, "PyInstaller", pyinstaller)
monkeypatch.setitem(sys.modules, "PyInstaller.compat", compat)

package_dir = Path(arcade.__file__).parent
hook_globals = runpy.run_path(package_dir / "__pyinstaller" / "hook-arcade.py")
bundled_version_paths = [
Path(destination) / Path(source).name
for source, destination in hook_globals["datas"]
if Path(source).name == "_VERSION"
]

assert bundled_version_paths == [Path("arcade/_VERSION")]
29 changes: 29 additions & 0 deletions tests/unit/test_version.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,41 @@
import sys
import tempfile
from pathlib import Path
from unittest import mock

import pytest

import arcade.version as version_module
from arcade.version import _parse_py_version_from_file, _parse_python_friendly_version


def test_default_version_file_is_loaded():
version_path = Path(version_module.__file__).with_name("_VERSION")

assert version_path.is_file()
assert _parse_py_version_from_file(version_path) == version_module.VERSION


def test_package_data_names_do_not_collide_with_modules_when_casefolded():
package_dir = Path(version_module.__file__).parent
importable_names = {
path.stem.casefold() for path in package_dir.iterdir() if path.suffix == ".py"
}
importable_names.update(
path.name.casefold()
for path in package_dir.iterdir()
if path.is_dir() and (path / "__init__.py").is_file()
)
data_names = {
path.name.casefold()
for path in package_dir.iterdir()
if path.is_file() and path.suffix != ".py"
}

collisions = importable_names & data_names
assert not collisions, f"Case-insensitive package path collisions: {sorted(collisions)}"


@pytest.mark.parametrize(
"value, expected",
[
Expand Down
2 changes: 1 addition & 1 deletion webplayground/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
here = Path(__file__).parent.resolve()

path_arcade = here.parent
version_file_path = path_arcade / "arcade" / "VERSION"
version_file_path = path_arcade / "arcade" / "_VERSION"
VERSION = "unknown"
with open(version_file_path, "r") as version_file:
VERSION = version_file.read().rstrip()
Expand Down
Loading