esper 2.4__zip → 2.5__zip

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.
Files changed (36) hide show
  1. esper-2.4/.github/workflows/python-package.yml → esper-2.5/.github/workflows/unit-tests.yml +9 -8
  2. {esper-2.4 → esper-2.5}/LICENSE.rst +1 -1
  3. {esper-2.4 → esper-2.5}/PKG-INFO +7 -4
  4. {esper-2.4 → esper-2.5}/README.md +6 -3
  5. {esper-2.4 → esper-2.5}/RELEASE_NOTES +20 -0
  6. {esper-2.4 → esper-2.5}/esper/__init__.py +29 -22
  7. {esper-2.4 → esper-2.5}/esper.egg-info/PKG-INFO +7 -4
  8. {esper-2.4 → esper-2.5}/esper.egg-info/SOURCES.txt +1 -2
  9. {esper-2.4 → esper-2.5}/tests/test_world.py +82 -23
  10. esper-2.4/.travis.yml +0 -12
  11. {esper-2.4 → esper-2.5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  12. {esper-2.4 → esper-2.5}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  13. {esper-2.4 → esper-2.5}/.github/ISSUE_TEMPLATE/question-or-comment.md +0 -0
  14. {esper-2.4 → esper-2.5}/.gitignore +0 -0
  15. {esper-2.4 → esper-2.5}/MANIFEST.in +0 -0
  16. {esper-2.4 → esper-2.5}/docs/Makefile +0 -0
  17. {esper-2.4 → esper-2.5}/docs/conf.py +0 -0
  18. {esper-2.4 → esper-2.5}/docs/index.rst +0 -0
  19. {esper-2.4 → esper-2.5}/docs/make.bat +0 -0
  20. {esper-2.4 → esper-2.5}/esper/py.typed +0 -0
  21. {esper-2.4 → esper-2.5}/esper.egg-info/dependency_links.txt +0 -0
  22. {esper-2.4 → esper-2.5}/esper.egg-info/top_level.txt +0 -0
  23. {esper-2.4 → esper-2.5}/examples/benchmark.py +0 -0
  24. {esper-2.4 → esper-2.5}/examples/benchmark_cache.py +0 -0
  25. {esper-2.4 → esper-2.5}/examples/bluesquare.png +0 -0
  26. {esper-2.4 → esper-2.5}/examples/headless_example.py +0 -0
  27. {esper-2.4 → esper-2.5}/examples/pygame_example.py +0 -0
  28. {esper-2.4 → esper-2.5}/examples/pyglet_example.py +0 -0
  29. {esper-2.4 → esper-2.5}/examples/pyglet_example_batch.py +0 -0
  30. {esper-2.4 → esper-2.5}/examples/pysdl2_example.py +0 -0
  31. {esper-2.4 → esper-2.5}/examples/pythonista_ios_example.py +0 -0
  32. {esper-2.4 → esper-2.5}/examples/redsquare.png +0 -0
  33. {esper-2.4 → esper-2.5}/make.py +0 -0
  34. {esper-2.4 → esper-2.5}/setup.cfg +0 -0
  35. {esper-2.4 → esper-2.5}/setup.py +0 -0
  36. {esper-2.4 → esper-2.5}/tests/__init__.py +0 -0
@@ -1,21 +1,22 @@
1
- name: Python Package Tests
1
+ name: unit tests
2
2
 
3
3
  on:
4
4
  push:
5
5
  pull_request:
6
6
 
7
+
7
8
  jobs:
8
- test:
9
- runs-on: ubuntu-20.04
9
+ tests:
10
+ runs-on: ${{ matrix.os }}
10
11
  strategy:
11
12
  matrix:
12
- python-version: ["3.6", "3.7", "3.8", "3.9", "pypy-3.6", "pypy-3.7"]
13
- fail-fast: true
13
+ os: [ 'ubuntu-latest', 'macos-latest', 'windows-latest' ]
14
+ python-version: [ '3.8', '3.9', '3.10', '3.11', '3.12-dev', 'pypy-3.7' ]
14
15
  steps:
15
- - name: Checkout repository
16
- uses: actions/checkout@v2
16
+ - name: Python ${{ matrix.python-version }} ${{ matrix.os }}
17
+ uses: actions/checkout@v3
17
18
  - name: Set up Python ${{ matrix.python-version }}
18
- uses: actions/setup-python@v2
19
+ uses: actions/setup-python@v4
19
20
  with:
20
21
  python-version: ${{ matrix.python-version }}
21
22
  - name: Install test dependencies
@@ -1,6 +1,6 @@
1
1
  The MIT License
2
2
 
3
- Copyright (c) 2020 Benjamin Moran
3
+ Copyright (c) 2015-2023 Benjamin Moran
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: esper
3
- Version: 2.4
3
+ Version: 2.5
4
4
  Summary: esper is a lightweight Entity System (ECS) for Python, with a focus on performance.
5
5
  Home-page: https://github.com/benmoran56/esper
6
6
  Download-URL: https://github.com/benmoran56/esper/releases
@@ -20,8 +20,9 @@ Classifier: Topic :: Games/Entertainment
20
20
  Classifier: Topic :: Software Development :: Libraries
21
21
  License-File: LICENSE.rst
22
22
 
23
- [![CI Status](https://readthedocs.org/projects/esper/badge/?version=latest)](https://travis-ci.org/benmoran56/esper)
24
- [![Documentation Status](https://readthedocs.org/projects/esper/badge/?version=latest)](https://esper.readthedocs.io/?badge=latest)
23
+ [![pypi](https://badge.fury.io/py/esper.svg)](https://pypi.python.org/pypi/esper)
24
+ [![rtd](https://readthedocs.org/projects/esper/badge/?version=latest)](https://esper.readthedocs.io)
25
+ [![PyTest](https://github.com/benmoran56/esper/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/benmoran56/esper/actions/workflows/unit-tests.yml)
25
26
 
26
27
  Esper is a lightweight Entity System module for Python, with a focus on performance
27
28
  ===================================================================================
@@ -393,4 +394,6 @@ Contributions to Esper are always welcome, but there are some specific project g
393
394
  - Avoid bloat as much as possible. New features will be considered if they are commonly useful. Generally speaking, we don't want to add functionality that is better handled in another module or library.
394
395
  - Performance is preferrable to readability.
395
396
 
396
- If you have any questions before contributing, feel free to `open an issue <https://github.com/benmoran56/esper/issues>`_.
397
+ If you have any questions before contributing, feel free to [open an issue].
398
+
399
+ [open an issue]: https://github.com/benmoran56/esper/issues
@@ -1,5 +1,6 @@
1
- [![CI Status](https://readthedocs.org/projects/esper/badge/?version=latest)](https://travis-ci.org/benmoran56/esper)
2
- [![Documentation Status](https://readthedocs.org/projects/esper/badge/?version=latest)](https://esper.readthedocs.io/?badge=latest)
1
+ [![pypi](https://badge.fury.io/py/esper.svg)](https://pypi.python.org/pypi/esper)
2
+ [![rtd](https://readthedocs.org/projects/esper/badge/?version=latest)](https://esper.readthedocs.io)
3
+ [![PyTest](https://github.com/benmoran56/esper/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/benmoran56/esper/actions/workflows/unit-tests.yml)
3
4
 
4
5
  Esper is a lightweight Entity System module for Python, with a focus on performance
5
6
  ===================================================================================
@@ -371,4 +372,6 @@ Contributions to Esper are always welcome, but there are some specific project g
371
372
  - Avoid bloat as much as possible. New features will be considered if they are commonly useful. Generally speaking, we don't want to add functionality that is better handled in another module or library.
372
373
  - Performance is preferrable to readability.
373
374
 
374
- If you have any questions before contributing, feel free to `open an issue <https://github.com/benmoran56/esper/issues>`_.
375
+ If you have any questions before contributing, feel free to [open an issue].
376
+
377
+ [open an issue]: https://github.com/benmoran56/esper/issues
@@ -1,3 +1,23 @@
1
+ esper 2.5
2
+ =========
3
+ Maintenance release
4
+
5
+ Changes
6
+ -------
7
+ - Removing all Components from an Entity will no longer automatically delete the Entity.
8
+ - Typing fixes and additions.
9
+ - Entity DB check and creation is done once when Entity is created, not when adding Components.
10
+
11
+
12
+ esper 2.4
13
+ =========
14
+ Maintenance release
15
+
16
+ Changes
17
+ -------
18
+ - Minor typing changes, and docstring improvement.
19
+
20
+
1
21
  esper 2.3
2
22
  =========
3
23
  Maintenance release
@@ -1,21 +1,21 @@
1
- from __future__ import annotations
2
-
3
1
  import time as _time
4
2
 
5
3
  from types import MethodType as _MethodType
6
4
 
7
- from typing import Iterable as _Iterable
5
+ from typing import Any as _Any
8
6
  from typing import List as _List
9
- from typing import Optional as _Optional
10
- from typing import Tuple as _Tuple
11
7
  from typing import Type as _Type
8
+ from typing import Tuple as _Tuple
12
9
  from typing import TypeVar as _TypeVar
10
+ from typing import Iterable as _Iterable
11
+ from typing import Optional as _Optional
12
+ from typing import overload as _overload
13
13
 
14
14
  from weakref import ref as _ref
15
15
  from weakref import WeakMethod as _WeakMethod
16
16
 
17
17
 
18
- version = '2.4'
18
+ version = '2.5'
19
19
 
20
20
 
21
21
  ###################
@@ -88,6 +88,9 @@ def remove_handler(name: str, func) -> None:
88
88
 
89
89
 
90
90
  _C = _TypeVar('_C')
91
+ _C2 = _TypeVar('_C2')
92
+ _C3 = _TypeVar('_C3')
93
+ _C4 = _TypeVar('_C4')
91
94
 
92
95
 
93
96
  class Processor:
@@ -116,7 +119,7 @@ class Processor:
116
119
  """
117
120
 
118
121
  priority = 0
119
- world: World
122
+ world: "World"
120
123
 
121
124
  def process(self, *args, **kwargs):
122
125
  raise NotImplementedError
@@ -212,6 +215,9 @@ class World:
212
215
 
213
216
  entity = self._next_entity_id
214
217
 
218
+ if entity not in self._entities:
219
+ self._entities[entity] = {}
220
+
215
221
  for component_instance in components:
216
222
 
217
223
  component_type = type(component_instance)
@@ -221,9 +227,6 @@ class World:
221
227
 
222
228
  self._components[component_type].add(entity)
223
229
 
224
- if entity not in self._entities:
225
- self._entities[entity] = {}
226
-
227
230
  self._entities[entity][component_type] = component_instance
228
231
  self.clear_cache()
229
232
 
@@ -311,16 +314,13 @@ class World:
311
314
 
312
315
  self._components[component_type].add(entity)
313
316
 
314
- if entity not in self._entities:
315
- self._entities[entity] = {}
316
-
317
317
  self._entities[entity][component_type] = component_instance
318
318
  self.clear_cache()
319
319
 
320
- def remove_component(self, entity: int, component_type: _Type[_C]) -> int:
320
+ def remove_component(self, entity: int, component_type: _Type[_C]) -> _C:
321
321
  """Remove a Component instance from an Entity, by type.
322
322
 
323
- A Component instance can be removed by providing its type.
323
+ A Component instance can only be removed by providing its type.
324
324
  For example: world.delete_component(enemy_a, Velocity) will remove
325
325
  the Velocity instance from the Entity enemy_a.
326
326
 
@@ -332,13 +332,8 @@ class World:
332
332
  if not self._components[component_type]:
333
333
  del self._components[component_type]
334
334
 
335
- del self._entities[entity][component_type]
336
-
337
- if not self._entities[entity]:
338
- del self._entities[entity]
339
-
340
335
  self.clear_cache()
341
- return entity
336
+ return self._entities[entity].pop(component_type)
342
337
 
343
338
  def _get_component(self, component_type: _Type[_C]) -> _Iterable[_Tuple[int, _C]]:
344
339
  entity_db = self._entities
@@ -365,7 +360,19 @@ class World:
365
360
  component_type, list(self._get_component(component_type))
366
361
  )
367
362
 
368
- def get_components(self, *component_types: _Type[_C]) -> _List[_Tuple[int, _List[_C]]]:
363
+ @_overload
364
+ def get_components(self, __c1: _Type[_C], __c2: _Type[_C2]) -> _List[_Tuple[int, _Tuple[_C, _C2]]]:
365
+ ...
366
+
367
+ @_overload
368
+ def get_components(self, __c1: _Type[_C], __c2: _Type[_C2], __c3: _Type[_C3]) -> _List[_Tuple[int, _Tuple[_C, _C2, _C3]]]:
369
+ ...
370
+
371
+ @_overload
372
+ def get_components(self, __c1: _Type[_C], __c2: _Type[_C2], __c3: _Type[_C3], __c4: _Type[_C4]) -> _List[_Tuple[int, _Tuple[_C, _C2, _C3, _C4]]]:
373
+ ...
374
+
375
+ def get_components(self, *component_types: _Type[_Any]) -> _Iterable[_Tuple[int, _Tuple[_Any, ...]]]:
369
376
  """Get an iterator for Entity and multiple Component sets."""
370
377
  try:
371
378
  return self._get_components_cache[component_types]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: esper
3
- Version: 2.4
3
+ Version: 2.5
4
4
  Summary: esper is a lightweight Entity System (ECS) for Python, with a focus on performance.
5
5
  Home-page: https://github.com/benmoran56/esper
6
6
  Download-URL: https://github.com/benmoran56/esper/releases
@@ -20,8 +20,9 @@ Classifier: Topic :: Games/Entertainment
20
20
  Classifier: Topic :: Software Development :: Libraries
21
21
  License-File: LICENSE.rst
22
22
 
23
- [![CI Status](https://readthedocs.org/projects/esper/badge/?version=latest)](https://travis-ci.org/benmoran56/esper)
24
- [![Documentation Status](https://readthedocs.org/projects/esper/badge/?version=latest)](https://esper.readthedocs.io/?badge=latest)
23
+ [![pypi](https://badge.fury.io/py/esper.svg)](https://pypi.python.org/pypi/esper)
24
+ [![rtd](https://readthedocs.org/projects/esper/badge/?version=latest)](https://esper.readthedocs.io)
25
+ [![PyTest](https://github.com/benmoran56/esper/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/benmoran56/esper/actions/workflows/unit-tests.yml)
25
26
 
26
27
  Esper is a lightweight Entity System module for Python, with a focus on performance
27
28
  ===================================================================================
@@ -393,4 +394,6 @@ Contributions to Esper are always welcome, but there are some specific project g
393
394
  - Avoid bloat as much as possible. New features will be considered if they are commonly useful. Generally speaking, we don't want to add functionality that is better handled in another module or library.
394
395
  - Performance is preferrable to readability.
395
396
 
396
- If you have any questions before contributing, feel free to `open an issue <https://github.com/benmoran56/esper/issues>`_.
397
+ If you have any questions before contributing, feel free to [open an issue].
398
+
399
+ [open an issue]: https://github.com/benmoran56/esper/issues
@@ -1,5 +1,4 @@
1
1
  .gitignore
2
- .travis.yml
3
2
  LICENSE.rst
4
3
  MANIFEST.in
5
4
  README.md
@@ -9,7 +8,7 @@ setup.py
9
8
  .github/ISSUE_TEMPLATE/bug_report.md
10
9
  .github/ISSUE_TEMPLATE/feature_request.md
11
10
  .github/ISSUE_TEMPLATE/question-or-comment.md
12
- .github/workflows/python-package.yml
11
+ .github/workflows/unit-tests.yml
13
12
  docs/Makefile
14
13
  docs/conf.py
15
14
  docs/index.rst
@@ -39,6 +39,11 @@ def test_create_entity_with_components(world):
39
39
  assert world.has_component(entity2, ComponentB) is True
40
40
 
41
41
 
42
+ def test_adding_component_to_not_existing_entity_raises_error(world):
43
+ with pytest.raises(KeyError):
44
+ world.add_component(123, ComponentA())
45
+
46
+
42
47
  def test_create_entity_and_add_components(world):
43
48
  entity1 = world.create_entity()
44
49
  world.add_component(entity1, ComponentA())
@@ -59,18 +64,17 @@ def test_delete_entity(world):
59
64
  world.add_component(entity1, ComponentC())
60
65
  entity2 = world.create_entity()
61
66
  world.add_component(entity2, ComponentD())
62
- entity3 = world.create_entity()
63
- world.add_component(entity3, ComponentE())
64
- entity4 = world.create_entity()
67
+ entity_with_component = world.create_entity()
68
+ world.add_component(entity_with_component, ComponentE())
69
+ empty_entity = world.create_entity()
65
70
 
66
- assert entity3 == 3
67
- world.delete_entity(entity3, immediate=True)
71
+ assert entity_with_component == 3
72
+ world.delete_entity(entity_with_component, immediate=True)
68
73
  with pytest.raises(KeyError):
69
- world.components_for_entity(entity3)
74
+ world.components_for_entity(entity_with_component)
70
75
  with pytest.raises(KeyError):
71
76
  world.delete_entity(999, immediate=True)
72
- with pytest.raises(KeyError):
73
- world.delete_entity(entity4, immediate=True)
77
+ world.delete_entity(empty_entity, immediate=True)
74
78
 
75
79
 
76
80
  def test_component_for_entity(world):
@@ -256,17 +260,71 @@ def test_cache_results(world):
256
260
  assert len(list(query for query in world.get_components(ComponentB, ComponentC))) == 1
257
261
 
258
262
 
259
- def test_entity_exists(world):
260
- dead_entity = world.create_entity(ComponentB())
261
- world.delete_entity(dead_entity)
262
- empty_entity = world.create_entity()
263
- existent_entity = world.create_entity(ComponentA())
264
- future_entity = existent_entity + 1
263
+ class TestEntityExists:
264
+ def test_dead_entity(self, world):
265
+ dead_entity = world.create_entity(ComponentB())
266
+ world.delete_entity(dead_entity)
267
+ assert not world.entity_exists(dead_entity)
268
+
269
+ def test_not_created_entity(self, world):
270
+ assert not world.entity_exists(123)
271
+
272
+ def test_empty_entity(self, world):
273
+ empty_entity = world.create_entity()
274
+ assert world.entity_exists(empty_entity)
275
+
276
+ def test_entity_with_component(self, world):
277
+ entity_with_component = world.create_entity(ComponentA())
278
+ assert world.entity_exists(entity_with_component)
279
+
280
+
281
+ class TestRemoveComponent:
282
+ def test_remove_from_not_existing_entity_raises_key_error(self, world):
283
+ with pytest.raises(KeyError):
284
+ world.remove_component(123, ComponentA)
285
+
286
+ def test_remove_not_existing_component_raises_key_error(self, world):
287
+ entity = world.create_entity(ComponentB())
288
+
289
+ with pytest.raises(KeyError):
290
+ world.remove_component(entity, ComponentA)
265
291
 
266
- assert world.entity_exists(existent_entity)
267
- assert not world.entity_exists(dead_entity)
268
- assert not world.entity_exists(empty_entity)
269
- assert not world.entity_exists(future_entity)
292
+ def test_remove_component_with_object_raises_key_error(self, populated_world):
293
+ entity = 2
294
+ component = ComponentD()
295
+
296
+ assert populated_world.has_component(entity, type(component))
297
+ with pytest.raises(KeyError):
298
+ populated_world.remove_component(entity, component)
299
+
300
+ def test_remove_component_returns_removed_instance(self, world):
301
+ component = ComponentA()
302
+ entity = world.create_entity(component)
303
+
304
+ result = world.remove_component(entity, type(component))
305
+
306
+ assert result is component
307
+
308
+ def test_remove_last_component_leaves_empty_entity(self, world):
309
+ entity = world.create_entity()
310
+ world.add_component(entity, ComponentA())
311
+
312
+ world.remove_component(entity, ComponentA)
313
+
314
+ assert not world.has_component(entity, ComponentA)
315
+ assert world.entity_exists(entity)
316
+
317
+ def test_removing_one_component_leaves_other_intact(self, world):
318
+ component_a = ComponentA()
319
+ component_b = ComponentB()
320
+ component_c = ComponentC()
321
+ entity = world.create_entity(component_a, component_b, component_c)
322
+
323
+ world.remove_component(entity, ComponentB)
324
+
325
+ assert world.component_for_entity(entity, ComponentA) is component_a
326
+ assert not world.has_component(entity, ComponentB)
327
+ assert world.component_for_entity(entity, ComponentC) is component_c
270
328
 
271
329
 
272
330
  def test_event_dispatch_no_handlers():
@@ -301,13 +359,14 @@ def test_set_methoad_as_handler_in_init():
301
359
  def __init__(self):
302
360
  esper.set_handler("foo", self._my_handler)
303
361
 
304
- def _my_handler(self):
362
+ @staticmethod
363
+ def _my_handler():
305
364
  print("OK")
306
365
 
307
366
  def process(self, dt):
308
367
  pass
309
368
 
310
- myclass = MyClass()
369
+ _myclass = MyClass()
311
370
  esper.dispatch_event("foo")
312
371
  esper.event_registry.clear()
313
372
 
@@ -315,7 +374,8 @@ def test_set_methoad_as_handler_in_init():
315
374
  def test_set_instance_methoad_as_handler():
316
375
  class MyClass(esper.Processor):
317
376
 
318
- def my_handler(self):
377
+ @staticmethod
378
+ def my_handler():
319
379
  print("OK")
320
380
 
321
381
  def process(self, dt):
@@ -377,8 +437,7 @@ class ComponentE:
377
437
 
378
438
 
379
439
  class ComponentF:
380
- def __init__(self):
381
- pass
440
+ pass
382
441
 
383
442
 
384
443
  class CorrectProcessorA(esper.Processor):
esper-2.4/.travis.yml DELETED
@@ -1,12 +0,0 @@
1
- dist: xenial
2
- language: python
3
- python:
4
- - "3.7"
5
- - "3.8"
6
- - "3.9"
7
- - "3.10"
8
- - "nightly"
9
- - "pypy3"
10
-
11
- # command to run tests:
12
- script: py.test -v tests
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