esper 3.2__tar.gz → 3.3__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.
- esper-3.3/.ruff.toml +2 -0
- {esper-3.2 → esper-3.3}/LICENSE +1 -1
- {esper-3.2 → esper-3.3}/PKG-INFO +2 -2
- {esper-3.2 → esper-3.3}/README.md +1 -1
- {esper-3.2 → esper-3.3}/RELEASE_NOTES +11 -0
- {esper-3.2 → esper-3.3}/esper/__init__.py +18 -22
- {esper-3.2 → esper-3.3}/examples/pyglet_example.py +1 -1
- esper-3.2/.ruff.toml +0 -3
- esper-3.2/examples/pyglet_example_batch.py +0 -245
- {esper-3.2 → esper-3.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {esper-3.2 → esper-3.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {esper-3.2 → esper-3.3}/.github/ISSUE_TEMPLATE/question-or-comment.md +0 -0
- {esper-3.2 → esper-3.3}/.github/workflows/type-checking.yml +0 -0
- {esper-3.2 → esper-3.3}/.github/workflows/unit-tests.yml +0 -0
- {esper-3.2 → esper-3.3}/.gitignore +0 -0
- {esper-3.2 → esper-3.3}/.mypy.ini +0 -0
- {esper-3.2 → esper-3.3}/.readthedocs.yaml +0 -0
- {esper-3.2 → esper-3.3}/MANIFEST.in +0 -0
- {esper-3.2 → esper-3.3}/docs/Makefile +0 -0
- {esper-3.2 → esper-3.3}/docs/conf.py +0 -0
- {esper-3.2 → esper-3.3}/docs/index.rst +0 -0
- {esper-3.2 → esper-3.3}/docs/make.bat +0 -0
- {esper-3.2 → esper-3.3}/esper/py.typed +0 -0
- {esper-3.2 → esper-3.3}/examples/benchmark.py +0 -0
- {esper-3.2 → esper-3.3}/examples/benchmark_cache.py +0 -0
- {esper-3.2 → esper-3.3}/examples/bluesquare.png +0 -0
- {esper-3.2 → esper-3.3}/examples/headless_example.py +0 -0
- {esper-3.2 → esper-3.3}/examples/pygame_example.py +0 -0
- {esper-3.2 → esper-3.3}/examples/pysdl2_example.py +0 -0
- {esper-3.2 → esper-3.3}/examples/pythonista_ios_example.py +0 -0
- {esper-3.2 → esper-3.3}/examples/redsquare.png +0 -0
- {esper-3.2 → esper-3.3}/make.py +0 -0
- {esper-3.2 → esper-3.3}/pyproject.toml +0 -0
- {esper-3.2 → esper-3.3}/tests/__init__.py +0 -0
- {esper-3.2 → esper-3.3}/tests/test_world.py +0 -0
esper-3.3/.ruff.toml
ADDED
{esper-3.2 → esper-3.3}/LICENSE
RENAMED
{esper-3.2 → esper-3.3}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: esper
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.3
|
|
4
4
|
Summary: esper is a lightweight Entity System (ECS) for Python, with a focus on performance
|
|
5
5
|
Author-email: Benjamin Moran <benmoran@protonmail.com>
|
|
6
6
|
Requires-Python: >=3.8
|
|
@@ -75,7 +75,7 @@ Design
|
|
|
75
75
|
* World Context
|
|
76
76
|
|
|
77
77
|
Esper uses the concept of "World" contexts. When you first `import esper`, a default context is
|
|
78
|
-
active. You create Entities, assign Components, register
|
|
78
|
+
active. You create Entities, assign Components, register Processors, etc., by calling functions
|
|
79
79
|
on the `esper` module. Entities, Components and Processors can be created, assigned, or deleted
|
|
80
80
|
while your game is running. A simple call to `esper.process()` is all that's needed for each
|
|
81
81
|
iteration of your game loop. Advanced users can switch contexts, which can be useful for
|
|
@@ -65,7 +65,7 @@ Design
|
|
|
65
65
|
* World Context
|
|
66
66
|
|
|
67
67
|
Esper uses the concept of "World" contexts. When you first `import esper`, a default context is
|
|
68
|
-
active. You create Entities, assign Components, register
|
|
68
|
+
active. You create Entities, assign Components, register Processors, etc., by calling functions
|
|
69
69
|
on the `esper` module. Entities, Components and Processors can be created, assigned, or deleted
|
|
70
70
|
while your game is running. A simple call to `esper.process()` is all that's needed for each
|
|
71
71
|
iteration of your game loop. Advanced users can switch contexts, which can be useful for
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
esper 3.3
|
|
2
|
+
=========
|
|
3
|
+
Maintenance release
|
|
4
|
+
|
|
5
|
+
Changes
|
|
6
|
+
-------
|
|
7
|
+
- Fix unreadable `esper.current_world` property. (#100)
|
|
8
|
+
- Minor typing configuration updates.
|
|
9
|
+
- Remove outdated pyglet example. (Another one already exists).
|
|
10
|
+
|
|
11
|
+
|
|
1
12
|
esper 3.2
|
|
2
13
|
=========
|
|
3
14
|
Maintenance release
|
|
@@ -23,7 +23,7 @@ from weakref import WeakMethod as _WeakMethod
|
|
|
23
23
|
|
|
24
24
|
from itertools import count as _count
|
|
25
25
|
|
|
26
|
-
__version__ = version = '3.
|
|
26
|
+
__version__ = version = '3.3'
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
###################
|
|
@@ -131,7 +131,7 @@ class Processor:
|
|
|
131
131
|
# ECS functions
|
|
132
132
|
###################
|
|
133
133
|
|
|
134
|
-
|
|
134
|
+
_current_world: str = "default"
|
|
135
135
|
_entity_count: "_count[int]" = _count(start=1)
|
|
136
136
|
_components: _Dict[_Type[_Any], _Set[_Any]] = {}
|
|
137
137
|
_entities: _Dict[int, _Dict[_Type[_Any], _Any]] = {}
|
|
@@ -141,8 +141,16 @@ _get_components_cache: _Dict[_Tuple[_Type[_Any], ...], _List[_Any]] = {}
|
|
|
141
141
|
_processors: _List[Processor] = []
|
|
142
142
|
process_times: _Dict[str, int] = {}
|
|
143
143
|
event_registry: _Dict[str, _Any] = {}
|
|
144
|
+
current_world: str = "default"
|
|
145
|
+
"""The name of the currently active World context.
|
|
144
146
|
|
|
145
|
-
|
|
147
|
+
This attribute can be checked to confirm the name of the
|
|
148
|
+
currently active World context. Modifying this has no effect;
|
|
149
|
+
to switch Worlds, use the :py:func:`~switch_world` function.
|
|
150
|
+
"""
|
|
151
|
+
|
|
152
|
+
# {context_name: (entity_count, components, entities, dead_entities,
|
|
153
|
+
# comp_cache, comps_cache, processors, process_times, event_registry)}
|
|
146
154
|
_context_map: _Dict[str, _Tuple[
|
|
147
155
|
"_count[int]",
|
|
148
156
|
_Dict[_Type[_Any], _Set[_Any]],
|
|
@@ -387,9 +395,7 @@ def get_component(component_type: _Type[_C]) -> _List[_Tuple[int, _C]]:
|
|
|
387
395
|
try:
|
|
388
396
|
return _get_component_cache[component_type]
|
|
389
397
|
except KeyError:
|
|
390
|
-
return _get_component_cache.setdefault(
|
|
391
|
-
component_type, list(_get_component(component_type))
|
|
392
|
-
)
|
|
398
|
+
return _get_component_cache.setdefault(component_type, list(_get_component(component_type)))
|
|
393
399
|
|
|
394
400
|
|
|
395
401
|
@_overload
|
|
@@ -404,7 +410,7 @@ def get_components(__c1: _Type[_C], __c2: _Type[_C2], __c3: _Type[_C3]) -> _List
|
|
|
404
410
|
|
|
405
411
|
@_overload
|
|
406
412
|
def get_components(__c1: _Type[_C], __c2: _Type[_C2], __c3: _Type[_C3], __c4: _Type[_C4]) -> _List[
|
|
407
|
-
|
|
413
|
+
_Tuple[int, _Tuple[_C, _C2, _C3, _C4]]]:
|
|
408
414
|
...
|
|
409
415
|
|
|
410
416
|
|
|
@@ -413,9 +419,7 @@ def get_components(*component_types: _Type[_Any]) -> _Iterable[_Tuple[int, _Tupl
|
|
|
413
419
|
try:
|
|
414
420
|
return _get_components_cache[component_types]
|
|
415
421
|
except KeyError:
|
|
416
|
-
return _get_components_cache.setdefault(
|
|
417
|
-
component_types, list(_get_components(*component_types))
|
|
418
|
-
)
|
|
422
|
+
return _get_components_cache.setdefault(component_types, list(_get_components(*component_types)))
|
|
419
423
|
|
|
420
424
|
|
|
421
425
|
def try_component(entity: int, component_type: _Type[_C]) -> _Optional[_C]:
|
|
@@ -525,7 +529,7 @@ def delete_world(name: str) -> None:
|
|
|
525
529
|
Raises `PermissionError` if you attempt to delete the currently
|
|
526
530
|
active World context.
|
|
527
531
|
"""
|
|
528
|
-
if
|
|
532
|
+
if _current_world == name:
|
|
529
533
|
raise PermissionError("The active World context cannot be deleted.")
|
|
530
534
|
|
|
531
535
|
del _context_map[name]
|
|
@@ -550,7 +554,7 @@ def switch_world(name: str) -> None:
|
|
|
550
554
|
# Create a new context if the name does not already exist:
|
|
551
555
|
_context_map[name] = (_count(start=1), {}, {}, set(), {}, {}, [], {}, {})
|
|
552
556
|
|
|
553
|
-
global
|
|
557
|
+
global _current_world
|
|
554
558
|
global _entity_count
|
|
555
559
|
global _components
|
|
556
560
|
global _entities
|
|
@@ -560,17 +564,9 @@ def switch_world(name: str) -> None:
|
|
|
560
564
|
global _processors
|
|
561
565
|
global process_times
|
|
562
566
|
global event_registry
|
|
567
|
+
global current_world
|
|
563
568
|
|
|
564
569
|
# switch the references to the objects in the named context_map:
|
|
565
570
|
(_entity_count, _components, _entities, _dead_entities, _get_component_cache,
|
|
566
571
|
_get_components_cache, _processors, process_times, event_registry) = _context_map[name]
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
@property # type: ignore
|
|
571
|
-
def current_world() -> str:
|
|
572
|
-
"""The currently active World context.
|
|
573
|
-
|
|
574
|
-
To switch World contexts, see :py:func:`esper.switch_world`.
|
|
575
|
-
"""
|
|
576
|
-
return _current_context
|
|
572
|
+
_current_world = current_world = name
|
|
@@ -36,7 +36,7 @@ class MovementProcessor:
|
|
|
36
36
|
def process(self, dt):
|
|
37
37
|
# This will iterate over every Entity that has BOTH of these components:
|
|
38
38
|
for ent, (vel, rend) in esper.get_components(Velocity, Renderable):
|
|
39
|
-
# Update the Renderable Component's position by
|
|
39
|
+
# Update the Renderable Component's position by its Velocity:
|
|
40
40
|
# An example of keeping the sprite inside screen boundaries. Basically,
|
|
41
41
|
# adjust the position back inside screen boundaries if it is outside:
|
|
42
42
|
new_x = max(self.minx, rend.sprite.x + vel.x)
|
esper-3.2/.ruff.toml
DELETED
|
@@ -1,245 +0,0 @@
|
|
|
1
|
-
import pyglet
|
|
2
|
-
from pyglet.gl import *
|
|
3
|
-
from pyglet.window import key
|
|
4
|
-
|
|
5
|
-
import esper
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
FPS = 60
|
|
9
|
-
RESOLUTION = 720, 480
|
|
10
|
-
BGCOLOR = (0, 0, 0, 255)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
##################################
|
|
14
|
-
# Define some Components:
|
|
15
|
-
##################################
|
|
16
|
-
class Velocity:
|
|
17
|
-
def __init__(self, x=0.0, y=0.0):
|
|
18
|
-
self.x = x
|
|
19
|
-
self.y = y
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class Renderable:
|
|
23
|
-
def __init__(self, texture, width, height, posx, posy):
|
|
24
|
-
self.texture = texture
|
|
25
|
-
self._x = posx
|
|
26
|
-
self._y = posy
|
|
27
|
-
self.w = width
|
|
28
|
-
self.h = height
|
|
29
|
-
self.group = TextureBindGroup(texture)
|
|
30
|
-
self.vertex_list = None
|
|
31
|
-
self._dirty = True
|
|
32
|
-
|
|
33
|
-
@property
|
|
34
|
-
def x(self):
|
|
35
|
-
return self._x
|
|
36
|
-
|
|
37
|
-
@x.setter
|
|
38
|
-
def x(self, val):
|
|
39
|
-
if val != self._x:
|
|
40
|
-
self._x = val
|
|
41
|
-
self._dirty = True
|
|
42
|
-
|
|
43
|
-
@property
|
|
44
|
-
def y(self):
|
|
45
|
-
return self._y
|
|
46
|
-
|
|
47
|
-
@y.setter
|
|
48
|
-
def y(self, val):
|
|
49
|
-
if val != self._y:
|
|
50
|
-
self._y = val
|
|
51
|
-
self._dirty = True
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
################################
|
|
55
|
-
# Define some Processors:
|
|
56
|
-
################################
|
|
57
|
-
class MovementProcessor:
|
|
58
|
-
def __init__(self, minx, miny, maxx, maxy):
|
|
59
|
-
super().__init__()
|
|
60
|
-
self.minx = minx
|
|
61
|
-
self.miny = miny
|
|
62
|
-
self.maxx = maxx
|
|
63
|
-
self.maxy = maxy
|
|
64
|
-
|
|
65
|
-
def process(self):
|
|
66
|
-
# This will iterate over every Entity that has BOTH of these components:
|
|
67
|
-
for ent, (vel, rend) in esper.get_components(Velocity, Renderable):
|
|
68
|
-
# Update the Renderable Component's position by it's Velocity:
|
|
69
|
-
rend.x += vel.x
|
|
70
|
-
rend.y += vel.y
|
|
71
|
-
# An example of keeping the sprite inside screen boundaries. Basically,
|
|
72
|
-
# adjust the position back inside screen boundaries if it tries to go outside:
|
|
73
|
-
rend.x = max(self.minx, rend.x)
|
|
74
|
-
rend.y = max(self.miny, rend.y)
|
|
75
|
-
rend.x = min(self.maxx - rend.w, rend.x)
|
|
76
|
-
rend.y = min(self.maxy - rend.h, rend.y)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
class TextureRenderProcessor():
|
|
80
|
-
def __init__(self, batch):
|
|
81
|
-
super().__init__()
|
|
82
|
-
self.batch = batch
|
|
83
|
-
|
|
84
|
-
def process(self):
|
|
85
|
-
# This will iterate over every Entity that has this Component, and
|
|
86
|
-
# add the texture associated with the Renderable Component instance
|
|
87
|
-
# and its vertice_list to the render batch. The batch will then be
|
|
88
|
-
# drawn by the 'on_draw' event handler of teh main window:
|
|
89
|
-
for entity, renderable in esper.get_component(Renderable):
|
|
90
|
-
self.draw_texture(renderable)
|
|
91
|
-
|
|
92
|
-
def draw_texture(self, renderable):
|
|
93
|
-
texture = renderable.texture
|
|
94
|
-
|
|
95
|
-
if renderable.vertex_list is None:
|
|
96
|
-
vertex_format = 'v2i/dynamic'
|
|
97
|
-
renderable.vertex_list = self.batch.add(4, GL_QUADS,
|
|
98
|
-
renderable.group,
|
|
99
|
-
vertex_format, 'c4B',
|
|
100
|
-
('t3f', texture.tex_coords))
|
|
101
|
-
|
|
102
|
-
if renderable._dirty:
|
|
103
|
-
x1 = renderable.x - texture.anchor_x
|
|
104
|
-
y1 = renderable.y - texture.anchor_y
|
|
105
|
-
x2 = x1 + texture.width
|
|
106
|
-
y2 = y1 + texture.height
|
|
107
|
-
renderable.vertex_list.vertices[:] = [x1, y1, x2, y1, x2, y2, x1, y2]
|
|
108
|
-
renderable.vertex_list.colors[:] = [255, 255, 255, 255] * 4
|
|
109
|
-
renderable._dirty = False
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
############################################
|
|
113
|
-
# Some pyglet helper classes and functions:
|
|
114
|
-
############################################
|
|
115
|
-
def texture_from_image(image_name):
|
|
116
|
-
"""Create a pyglet Texture from an image file"""
|
|
117
|
-
return pyglet.resource.image(image_name).get_texture()
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
# Code below cobbled together from
|
|
121
|
-
# https://pyglet.readthedocs.org/en/latest/programming_guide/graphics.html#hierarchical-state
|
|
122
|
-
# and pyglet.sprite.SpriteGroup
|
|
123
|
-
|
|
124
|
-
class TextureEnableGroup(pyglet.graphics.Group):
|
|
125
|
-
def set_state(self):
|
|
126
|
-
glEnable(GL_TEXTURE_2D)
|
|
127
|
-
|
|
128
|
-
def unset_state(self):
|
|
129
|
-
glDisable(GL_TEXTURE_2D)
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
texture_enable_group = TextureEnableGroup()
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
class TextureBindGroup(pyglet.graphics.Group):
|
|
136
|
-
def __init__(self, texture):
|
|
137
|
-
super().__init__(parent=texture_enable_group)
|
|
138
|
-
assert texture.target == GL_TEXTURE_2D
|
|
139
|
-
self.texture = texture
|
|
140
|
-
self.blend_src = GL_SRC_ALPHA
|
|
141
|
-
self.blend_dest = GL_ONE_MINUS_SRC_ALPHA
|
|
142
|
-
|
|
143
|
-
def set_state(self):
|
|
144
|
-
glBindTexture(GL_TEXTURE_2D, self.texture.id)
|
|
145
|
-
glPushAttrib(GL_COLOR_BUFFER_BIT)
|
|
146
|
-
glEnable(GL_BLEND)
|
|
147
|
-
glBlendFunc(self.blend_src, self.blend_dest)
|
|
148
|
-
|
|
149
|
-
def unset_state(self):
|
|
150
|
-
glPopAttrib()
|
|
151
|
-
glDisable(self.texture.target)
|
|
152
|
-
|
|
153
|
-
def __eq__(self, other):
|
|
154
|
-
return (other.__class__ is self.__class__ and
|
|
155
|
-
self.parent is other.parent and
|
|
156
|
-
self.texture.target == other.texture.target and
|
|
157
|
-
self.texture.id == other.texture.id and
|
|
158
|
-
self.blend_src == other.blend_src and
|
|
159
|
-
self.blend_dest == other.blend_dest)
|
|
160
|
-
|
|
161
|
-
def __hash__(self):
|
|
162
|
-
return hash((id(self.parent),
|
|
163
|
-
self.texture.id, self.texture.target,
|
|
164
|
-
self.blend_src, self.blend_dest))
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
################################
|
|
168
|
-
# The main core of the program:
|
|
169
|
-
################################
|
|
170
|
-
def run(args=None):
|
|
171
|
-
# Initialize the main window stuff
|
|
172
|
-
window = pyglet.window.Window(width=RESOLUTION[0], height=RESOLUTION[1])
|
|
173
|
-
window.set_caption("Esper pyglet Example")
|
|
174
|
-
pyglet.gl.glClearColor(*BGCOLOR)
|
|
175
|
-
# pyglet graphics batch for efficient rendering
|
|
176
|
-
renderbatch = pyglet.graphics.Batch()
|
|
177
|
-
|
|
178
|
-
# Initialize Esper world, and create a "player" Entity with a few Components.
|
|
179
|
-
player = esper.create_entity()
|
|
180
|
-
esper.add_component(player, Velocity(x=0, y=0))
|
|
181
|
-
redsquare = Renderable(texture=texture_from_image("redsquare.png"),
|
|
182
|
-
width=64,
|
|
183
|
-
height=64,
|
|
184
|
-
posx=100,
|
|
185
|
-
posy=100)
|
|
186
|
-
esper.add_component(player, redsquare)
|
|
187
|
-
|
|
188
|
-
# Another motionless Entity:
|
|
189
|
-
enemy = esper.create_entity()
|
|
190
|
-
bluesquare = Renderable(texture=texture_from_image("bluesquare.png"),
|
|
191
|
-
width=64,
|
|
192
|
-
height=64,
|
|
193
|
-
posx=400,
|
|
194
|
-
posy=250)
|
|
195
|
-
esper.add_component(enemy, bluesquare)
|
|
196
|
-
|
|
197
|
-
# Create some Processor instances, and asign them to be processed.
|
|
198
|
-
render_processor = TextureRenderProcessor(batch=renderbatch)
|
|
199
|
-
movement_processor = MovementProcessor(minx=0, maxx=RESOLUTION[0], miny=0,
|
|
200
|
-
maxy=RESOLUTION[1])
|
|
201
|
-
|
|
202
|
-
@window.event
|
|
203
|
-
def on_key_press(symbol, modifiers):
|
|
204
|
-
if symbol == key.UP:
|
|
205
|
-
# Here is a way to directly access a specific Entity's Velocity
|
|
206
|
-
# Component's attribute (y) without making a temporary variable.
|
|
207
|
-
esper.component_for_entity(player, Velocity).y = 3
|
|
208
|
-
elif symbol == key.DOWN:
|
|
209
|
-
# For clarity, here is an alternate way in which a temporary variable
|
|
210
|
-
# is created and modified. The previous way above is recommended instead.
|
|
211
|
-
player_velocity_component = esper.component_for_entity(player, Velocity)
|
|
212
|
-
player_velocity_component.y = -3
|
|
213
|
-
elif symbol == key.LEFT:
|
|
214
|
-
esper.component_for_entity(player, Velocity).x = -3
|
|
215
|
-
elif symbol == key.RIGHT:
|
|
216
|
-
esper.component_for_entity(player, Velocity).x = 3
|
|
217
|
-
elif symbol == key.ESCAPE:
|
|
218
|
-
pyglet.app.exit()
|
|
219
|
-
|
|
220
|
-
@window.event
|
|
221
|
-
def on_key_release(symbol, modifiers):
|
|
222
|
-
if symbol in (key.UP, key.DOWN):
|
|
223
|
-
esper.component_for_entity(player, Velocity).y = 0
|
|
224
|
-
if symbol in (key.LEFT, key.RIGHT):
|
|
225
|
-
esper.component_for_entity(player, Velocity).x = 0
|
|
226
|
-
|
|
227
|
-
@window.event
|
|
228
|
-
def on_draw():
|
|
229
|
-
# Clear the window:
|
|
230
|
-
window.clear()
|
|
231
|
-
# Draw the batch of Renderables:
|
|
232
|
-
renderbatch.draw()
|
|
233
|
-
|
|
234
|
-
def update(dt):
|
|
235
|
-
# A single call to esper.process() will update all Processors:
|
|
236
|
-
render_processor.process()
|
|
237
|
-
movement_processor.process()
|
|
238
|
-
|
|
239
|
-
pyglet.clock.schedule_interval(update, 1.0 / FPS)
|
|
240
|
-
pyglet.app.run()
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if __name__ == "__main__":
|
|
244
|
-
import sys
|
|
245
|
-
sys.exit(run(sys.argv[1:]) or 0)
|
|
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
|
{esper-3.2 → esper-3.3}/make.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|