App   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 107
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 107
rs 10
c 0
b 0
f 0
wmc 17

10 Methods

Rating   Name   Duplication   Size   Complexity  
A ev_KEYUP() 0 2 1
A ev_MOUSEMOTION() 0 2 1
A ev_MOUSEUP() 0 2 1
A ev_MOUSEDOWN() 0 2 1
A ev_KEYDOWN() 0 2 1
A ev_QUIT() 0 4 1
A update() 0 15 1
B run_once() 0 24 6
A suspend() 0 9 1
A run() 0 13 3
1
"""
2
    This module handles user input.
3
4
    To handle user input you will likely want to use the :any:`event.get`
5
    function or create a subclass of :any:`event.App`.
6
7
    - :any:`tdl.event.get` iterates over recent events.
8
    - :any:`tdl.event.App` passes events to the overridable methods: ``ev_*``
9
      and ``key_*``.
10
11
    But there are other options such as :any:`event.key_wait` and
12
    :any:`event.is_window_closed`.
13
14
    A few event attributes are actually string constants.
15
    Here's a reference for those:
16
17
    - :any:`Event.type`:
18
      'QUIT', 'KEYDOWN', 'KEYUP', 'MOUSEDOWN', 'MOUSEUP', or 'MOUSEMOTION.'
19
    - :any:`MouseButtonEvent.button` (found in :any:`MouseDown` and
20
      :any:`MouseUp` events):
21
      'LEFT', 'MIDDLE', 'RIGHT', 'SCROLLUP', 'SCROLLDOWN'
22
    - :any:`KeyEvent.key` (found in :any:`KeyDown` and :any:`KeyUp` events):
23
      'NONE', 'ESCAPE', 'BACKSPACE', 'TAB', 'ENTER', 'SHIFT', 'CONTROL',
24
      'ALT', 'PAUSE', 'CAPSLOCK', 'PAGEUP', 'PAGEDOWN', 'END', 'HOME', 'UP',
25
      'LEFT', 'RIGHT', 'DOWN', 'PRINTSCREEN', 'INSERT', 'DELETE', 'LWIN',
26
      'RWIN', 'APPS', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
27
      'KP0', 'KP1', 'KP2', 'KP3', 'KP4', 'KP5', 'KP6', 'KP7', 'KP8', 'KP9',
28
      'KPADD', 'KPSUB', 'KPDIV', 'KPMUL', 'KPDEC', 'KPENTER', 'F1', 'F2',
29
      'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12',
30
      'NUMLOCK', 'SCROLLLOCK', 'SPACE', 'CHAR'
31
"""
32
33
import time as _time
34
35
from tcod import ffi as _ffi
36
from tcod import lib as _lib
37
38
import tdl as _tdl
39
from . import style as _style
40
41
_eventQueue = []
0 ignored issues
show
Coding Style Naming introduced by
The name _eventQueue does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
42
_pushedEvents = []
0 ignored issues
show
Coding Style Naming introduced by
The name _pushedEvents does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
43
_eventsflushed = False
0 ignored issues
show
Coding Style Naming introduced by
The name _eventsflushed does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
44
45
_mousel = 0
0 ignored issues
show
Coding Style Naming introduced by
The name _mousel does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
46
_mousem = 0
0 ignored issues
show
Coding Style Naming introduced by
The name _mousem does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
47
_mouser = 0
0 ignored issues
show
Coding Style Naming introduced by
The name _mouser does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
48
49
# this interprets the constants from libtcod and makes a key -> keyname dictionary
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
50
def _parseKeyNames(lib):
0 ignored issues
show
Coding Style Naming introduced by
The name _parseKeyNames does not conform to the function naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
51
    """
52
    returns a dictionary mapping of human readable key names to their keycodes
53
    this parses constants with the names of K_* and makes code=name pairs
54
    this is for KeyEvent.key variable and that enables things like:
55
    if (event.key == 'PAGEUP'):
56
    """
57
    _keyNames = {}
0 ignored issues
show
Comprehensibility Bug introduced by
_keyNames is re-defining a name which is already available in the outer-scope (previously defined on line 63).

It is generally a bad practice to shadow variables from the outer-scope. In most cases, this is done unintentionally and might lead to unexpected behavior:

param = 5

class Foo:
    def __init__(self, param):   # "param" would be flagged here
        self.param = param
Loading history...
Coding Style Naming introduced by
The name _keyNames does not conform to the variable naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
58
    for attr in dir(lib): # from the modules variables
59
        if attr[:6] == 'TCODK_': # get the K_* constants
60
            _keyNames[getattr(lib, attr)] = attr[6:] # and make CODE=NAME pairs
61
    return _keyNames
62
63
_keyNames = _parseKeyNames(_lib)
0 ignored issues
show
Coding Style Naming introduced by
The name _keyNames does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
64
65
class Event(object):
66
    """Base Event class.
67
68
    You can easily subclass this to make your own events.  Be sure to set
69
    the class attribute L{Event.type} for it to be passed to a custom
70
    :any:`App` ev_* method.
71
    """
72
    type = None
73
    """String constant representing the type of event.
74
75
    The :any:`App` ev_* methods depend on this attribute.
76
77
    Can be: 'QUIT', 'KEYDOWN', 'KEYUP', 'MOUSEDOWN', 'MOUSEUP',
78
    or 'MOUSEMOTION.'
79
    """
80
81
    def __repr__(self):
82
        """List an events public attributes when printed.
83
        """
84
        attrdict = {}
85
        for varname in dir(self):
86
            if '_' == varname[0]:
87
                continue
88
            attrdict[varname] = self.__getattribute__(varname)
89
        return '%s Event %s' % (self.__class__.__name__, repr(attrdict))
90
91
class Quit(Event):
92
    """Fired when the window is closed by the user.
93
    """
94
    __slots__ = ()
95
    type = 'QUIT'
96
97
class KeyEvent(Event):
98
    """Base class for key events."""
99
100
    def __init__(self, key='', char='', text='', shift=False,
101
                 left_alt=False, right_alt=False,
102
                 left_control=False, right_control=False,
103
                 left_meta=False, right_meta=False):
104
        # Convert keycodes into string, but use string if passed
105
        self.key = key if isinstance(key, str) else _keyNames[key]
106
        """Text: Human readable names of the key pressed.
107
        Non special characters will show up as 'CHAR'.
108
109
        Can be one of
110
        'NONE', 'ESCAPE', 'BACKSPACE', 'TAB', 'ENTER', 'SHIFT', 'CONTROL',
111
        'ALT', 'PAUSE', 'CAPSLOCK', 'PAGEUP', 'PAGEDOWN', 'END', 'HOME', 'UP',
112
        'LEFT', 'RIGHT', 'DOWN', 'PRINTSCREEN', 'INSERT', 'DELETE', 'LWIN',
113
        'RWIN', 'APPS', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
114
        'KP0', 'KP1', 'KP2', 'KP3', 'KP4', 'KP5', 'KP6', 'KP7', 'KP8', 'KP9',
115
        'KPADD', 'KPSUB', 'KPDIV', 'KPMUL', 'KPDEC', 'KPENTER', 'F1', 'F2',
116
        'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12',
117
        'NUMLOCK', 'SCROLLLOCK', 'SPACE', 'CHAR'
118
119
        For the actual character instead of 'CHAR' use :any:`keychar`.
120
        """
121
        self.char = char.replace('\x00', '') # change null to empty string
122
        """Text: A single character string of the letter or symbol pressed.
123
124
        Special characters like delete and return are not cross-platform.
125
        L{key} or L{keychar} should be used instead for special keys.
126
        Characters are also case sensitive.
127
        """
128
        # get the best out of self.key and self.char
129
        self.keychar = self.char if self.key == 'CHAR' else self.key
130
        """Similar to L{key} but returns a case sensitive letter or symbol
131
        instead of 'CHAR'.
132
133
        This variable makes available the widest variety of symbols and should
134
        be used for key-mappings or anywhere where a narrower sample of keys
135
        isn't needed.
136
        """
137
        self.text = text
138
139
        self.left_alt = self.leftAlt = bool(left_alt)
0 ignored issues
show
Coding Style Naming introduced by
The name leftAlt does not conform to the attribute naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
140
        """bool:"""
141
        self.right_alt = self.rightAlt = bool(right_alt)
0 ignored issues
show
Coding Style Naming introduced by
The name rightAlt does not conform to the attribute naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
142
        """bool:"""
143
        self.left_control = self.leftCtrl = bool(left_control)
0 ignored issues
show
Coding Style Naming introduced by
The name leftCtrl does not conform to the attribute naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
144
        """bool:"""
145
        self.right_control = self.rightCtrl = bool(right_control)
0 ignored issues
show
Coding Style Naming introduced by
The name rightCtrl does not conform to the attribute naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
146
        """bool:"""
147
        self.shift = bool(shift)
148
        """bool: True if shift was held down during this event."""
149
        self.alt = self.left_alt or self.right_alt
150
        """bool: True if alt was held down during this event."""
151
        self.control = self.left_control or self.right_control
152
        """bool: True if control was held down during this event."""
153
        self.left_meta = bool(left_meta)
154
        self.right_meta = bool(right_meta)
155
        self.meta = self.left_meta or self.right_meta
156
157
    def __repr__(self):
158
        parameters = []
159
        for attr in ('key', 'char', 'text', 'shift',
160
                     'left_alt', 'right_alt',
161
                     'left_control', 'right_control',
162
                     'left_meta', 'right_meta'):
163
            value = getattr(self, attr)
164
            if value:
165
                parameters.append('%s=%r' % (attr, value))
166
        return '%s(%s)' % (self.__class__.__name__, ', '.join(parameters))
167
168
class KeyDown(KeyEvent):
169
    """Fired when the user presses a key on the keyboard or a key repeats.
170
    """
171
    type = 'KEYDOWN'
172
173
class KeyUp(KeyEvent):
174
    """Fired when the user releases a key on the keyboard.
175
    """
176
    type = 'KEYUP'
177
178
_mouseNames = {1: 'LEFT', 2: 'MIDDLE', 3: 'RIGHT', 4: 'SCROLLUP', 5: 'SCROLLDOWN'}
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (82/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
Coding Style Naming introduced by
The name _mouseNames does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
179
class MouseButtonEvent(Event):
180
    """Base class for mouse button events."""
181
182
    def __init__(self, button, pos, cell):
183
        self.button = _mouseNames[button]
184
        """Text: Can be one of
185
        'LEFT', 'MIDDLE', 'RIGHT', 'SCROLLUP', 'SCROLLDOWN'
186
        """
187
        self.pos = pos
188
        """Tuple[int, int]: (x, y) position of the mouse on the screen."""
189
        self.cell = cell
190
        """Tuple[int, int]: (x, y) position of the mouse snapped to a cell on
191
        the root console
192
        """
193
194
class MouseDown(MouseButtonEvent):
195
    """Fired when a mouse button is pressed."""
196
    __slots__ = ()
197
    type = 'MOUSEDOWN'
198
199
class MouseUp(MouseButtonEvent):
200
    """Fired when a mouse button is released."""
201
    __slots__ = ()
202
    type = 'MOUSEUP'
203
204
class MouseMotion(Event):
205
    """Fired when the mouse is moved."""
206
    type = 'MOUSEMOTION'
207
208
    def __init__(self, pos, cell, motion, cellmotion):
209
        self.pos = pos
210
        """(x, y) position of the mouse on the screen.
211
        type: (int, int)"""
212
        self.cell = cell
213
        """(x, y) position of the mouse snapped to a cell on the root console.
214
        type: (int, int)"""
215
        self.motion = motion
216
        """(x, y) motion of the mouse on the screen.
217
        type: (int, int)"""
218
        self.cellmotion = cellmotion
219
        """(x, y) mostion of the mouse moving over cells on the root console.
220
        type: (int, int)"""
221
222
class App(object):
223
    """
224
    Application framework.
225
226
     - ev_*: Events are passed to methods based on their :any:`Event.type`
227
       attribute.
228
       If an event type is 'KEYDOWN' the ev_KEYDOWN method will be called
229
       with the event instance as a parameter.
230
231
     - key_*: When a key is pressed another method will be called based on the
232
       :any:`KeyEvent.key` attribute.  For example the 'ENTER' key will call
233
       key_ENTER with the associated :any:`KeyDown` event as its parameter.
234
235
     - :any:`update`: This method is called every loop.  It is passed a single
236
       parameter detailing the time in seconds since the last update
237
       (often known as deltaTime.)
238
239
       You may want to call drawing routines in this method followed by
240
       :any:`tdl.flush`.
241
242
    """
243
    __slots__ = ('__running', '__prevTime')
244
245
    def ev_QUIT(self, event):
0 ignored issues
show
Coding Style Naming introduced by
The name ev_QUIT does not conform to the method naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Unused Code introduced by
The argument event seems to be unused.
Loading history...
Coding Style introduced by
This method could be written as a function/class method.

If a method does not access any attributes of the class, it could also be implemented as a function or static method. This can help improve readability. For example

class Foo:
    def some_method(self, x, y):
        return x + y;

could be written as

class Foo:
    @classmethod
    def some_method(cls, x, y):
        return x + y;
Loading history...
246
        """Unless overridden this method raises a SystemExit exception closing
247
        the program."""
248
        raise SystemExit()
249
250
    def ev_KEYDOWN(self, event):
0 ignored issues
show
Coding Style Naming introduced by
The name ev_KEYDOWN does not conform to the method naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
251
        """Override this method to handle a :any:`KeyDown` event."""
252
253
    def ev_KEYUP(self, event):
0 ignored issues
show
Coding Style Naming introduced by
The name ev_KEYUP does not conform to the method naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
254
        """Override this method to handle a :any:`KeyUp` event."""
255
256
    def ev_MOUSEDOWN(self, event):
0 ignored issues
show
Coding Style Naming introduced by
The name ev_MOUSEDOWN does not conform to the method naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
257
        """Override this method to handle a :any:`MouseDown` event."""
258
259
    def ev_MOUSEUP(self, event):
0 ignored issues
show
Coding Style Naming introduced by
The name ev_MOUSEUP does not conform to the method naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
260
        """Override this method to handle a :any:`MouseUp` event."""
261
262
    def ev_MOUSEMOTION(self, event):
0 ignored issues
show
Coding Style Naming introduced by
The name ev_MOUSEMOTION does not conform to the method naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
263
        """Override this method to handle a :any:`MouseMotion` event."""
264
265
    def update(self, deltaTime):
0 ignored issues
show
Coding Style Naming introduced by
The name deltaTime does not conform to the argument naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
266
        """Override this method to handle per frame logic and drawing.
267
268
        Args:
269
            deltaTime (float):
270
                This parameter tells the amount of time passed since
271
                the last call measured in seconds as a floating point
272
                number.
273
274
                You can use this variable to make your program
275
                frame rate independent.
276
                Use this parameter to adjust the speed of motion,
277
                timers, and other game logic.
278
        """
279
        pass
280
281
    def suspend(self):
282
        """When called the App will begin to return control to where
283
        :any:`App.run` was called.
284
285
        Some further events are processed and the :any:`App.update` method
286
        will be called one last time before exiting
287
        (unless suspended during a call to :any:`App.update`.)
288
        """
289
        self.__running = False
0 ignored issues
show
Coding Style introduced by
The attribute __running was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
290
291
    def run(self):
292
        """Delegate control over to this App instance.  This function will
293
        process all events and send them to the special methods ev_* and key_*.
294
295
        A call to :any:`App.suspend` will return the control flow back to where
296
        this function is called.  And then the App can be run again.
297
        But a single App instance can not be run multiple times simultaneously.
298
        """
299
        if getattr(self, '_App__running', False):
300
            raise _tdl.TDLError('An App can not be run multiple times simultaneously')
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (86/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
301
        self.__running = True
0 ignored issues
show
Coding Style introduced by
The attribute __running was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
302
        while self.__running:
303
            self.runOnce()
304
305
    def run_once(self):
306
        """Pump events to this App instance and then return.
307
308
        This works in the way described in :any:`App.run` except it immediately
309
        returns after the first :any:`update` call.
310
311
        Having multiple :any:`App` instances and selectively calling runOnce on
312
        them is a decent way to create a state machine.
313
        """
314
        if not hasattr(self, '_App__prevTime'):
315
            self.__prevTime = _time.clock() # initiate __prevTime
0 ignored issues
show
Coding Style Naming introduced by
The name __prevTime does not conform to the attribute naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style introduced by
The attribute __prevTime was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
316
        for event in get():
317
            if event.type: # exclude custom events with a blank type variable
318
                # call the ev_* methods
319
                method = 'ev_%s' % event.type # ev_TYPE
320
                getattr(self, method)(event)
321
            if event.type == 'KEYDOWN':
322
                # call the key_* methods
323
                method = 'key_%s' % event.key # key_KEYNAME
324
                if hasattr(self, method): # silently exclude undefined methods
325
                    getattr(self, method)(event)
326
        newTime = _time.clock()
0 ignored issues
show
Coding Style Naming introduced by
The name newTime does not conform to the variable naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
327
        self.update(newTime - self.__prevTime)
328
        self.__prevTime = newTime
0 ignored issues
show
Coding Style introduced by
The attribute __prevTime was defined outside __init__.

It is generally a good practice to initialize all attributes to default values in the __init__ method:

class Foo:
    def __init__(self, x=None):
        self.x = x
Loading history...
329
        #_tdl.flush()
330
331
def _processEvents():
0 ignored issues
show
Coding Style Naming introduced by
The name _processEvents does not conform to the function naming conventions ([a-z_][a-z0-9_]{2,30}$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
332
    """Flushes the event queue from libtcod into the global list _eventQueue"""
333
    global _mousel, _mousem, _mouser, _eventsflushed, _pushedEvents
0 ignored issues
show
Coding Style Naming introduced by
The name _mousel does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
The name _mousem does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
The name _mouser does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
The name _eventsflushed does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
Coding Style Naming introduced by
The name _pushedEvents does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
334
    _eventsflushed = True
335
    events = _pushedEvents # get events from event.push
336
    _pushedEvents = [] # then clear the pushed events queue
337
338
    mouse = _ffi.new('TCOD_mouse_t *')
339
    libkey = _ffi.new('TCOD_key_t *')
340
    while 1:
341
        libevent = _lib.TCOD_sys_check_for_event(_lib.TCOD_EVENT_ANY, libkey, mouse)
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (84/80).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
342
        if not libevent: # no more events from libtcod
343
            break
344
345
        #if mouse.dx or mouse.dy:
346
        if libevent & _lib.TCOD_EVENT_MOUSE_MOVE:
347
            events.append(MouseMotion((mouse.x, mouse.y),
348
                                      (mouse.cx, mouse.cy),
349
                                      (mouse.dx, mouse.dy),
350
                                      (mouse.dcx, mouse.dcy)))
351
352
        mousepos = ((mouse.x, mouse.y), (mouse.cx, mouse.cy))
353
354
        for oldstate, newstate, released, button in \
355
            zip((_mousel, _mousem, _mouser),
356
                (mouse.lbutton, mouse.mbutton, mouse.rbutton),
357
                (mouse.lbutton_pressed, mouse.mbutton_pressed,
358
                 mouse.rbutton_pressed),
359
                (1, 2, 3)):
360
            if released:
361
                if not oldstate:
362
                    events.append(MouseDown(button, *mousepos))
363
                events.append(MouseUp(button, *mousepos))
364
                if newstate:
365
                    events.append(MouseDown(button, *mousepos))
366
            elif newstate and not oldstate:
367
                events.append(MouseDown(button, *mousepos))
368
369
        if mouse.wheel_up:
370
            events.append(MouseDown(4, *mousepos))
371
        if mouse.wheel_down:
372
            events.append(MouseDown(5, *mousepos))
373
374
        _mousel = mouse.lbutton
375
        _mousem = mouse.mbutton
376
        _mouser = mouse.rbutton
377
378
        if libkey.vk == _lib.TCODK_NONE:
379
            break
380
        if libkey.pressed:
381
            keyevent = KeyDown
382
        else:
383
            keyevent = KeyUp
384
385
        events.append(
386
            keyevent(
387
                libkey.vk,
388
                libkey.c.decode('ascii', errors='ignore'),
389
                _ffi.string(libkey.text).decode('utf-8'),
390
                libkey.shift,
391
                libkey.lalt,
392
                libkey.ralt,
393
                libkey.lctrl,
394
                libkey.rctrl,
395
                libkey.lmeta,
396
                libkey.rmeta,
397
                )
398
            )
399
400
    if _lib.TCOD_console_is_window_closed():
401
        events.append(Quit())
402
403
    _eventQueue.extend(events)
404
405
def get():
406
    """Flushes the event queue and returns the list of events.
407
408
    This function returns :any:`Event` objects that can be identified by their
409
    type attribute or their class.
410
411
    Returns: Iterator[Type[Event]]: An iterable of Events or anything
412
        put in a :any:`push` call.
413
414
        If the iterator is deleted or otherwise interrupted before finishing
415
        the excess items are preserved for the next call.
416
    """
417
    _processEvents()
418
    return _event_generator()
419
420
def _event_generator():
0 ignored issues
show
Coding Style introduced by
This function should have a docstring.

The coding style of this project requires that you add a docstring to this code element. Below, you find an example for methods:

class SomeClass:
    def some_method(self):
        """Do x and return foo."""

If you would like to know more about docstrings, we recommend to read PEP-257: Docstring Conventions.

Loading history...
421
    while _eventQueue:
422
        # if there is an interruption the rest of the events stay untouched
423
        # this means you can break out of a event.get loop without losing
424
        # the leftover events
425
        yield(_eventQueue.pop(0))
0 ignored issues
show
Unused Code Coding Style introduced by
There is an unnecessary parenthesis after yield.
Loading history...
426
    raise StopIteration()
427
428
429
def wait(timeout=None, flush=True):
430
    """Wait for an event.
431
432
    Args:
433
        timeout (Optional[int]): The time in seconds that this function will
434
            wait before giving up and returning None.
435
436
            With the default value of None, this will block forever.
437
        flush (bool): If True a call to :any:`tdl.flush` will be made before
438
            listening for events.
439
440
    Returns: Type[Event]: An event, or None if the function
441
             has timed out.
442
             Anything added via :any:`push` will also be returned.
443
    """
444
    if timeout is not None:
445
        timeout = timeout + _time.clock() # timeout at this time
446
    while True:
447
        if _eventQueue:
448
            return _eventQueue.pop(0)
449
        if flush:
450
            # a full 'round' of events need to be processed before flushing
451
            _tdl.flush()
452
        if timeout and _time.clock() >= timeout:
453
            return None # return None on timeout
454
        _time.sleep(0.001) # sleep 1ms
455
        _processEvents()
456
457
458
def push(event):
459
    """Push an event into the event buffer.
460
461
    Args:
462
        event (Any): This event will be available on the next call to
463
            :any:`event.get`.
464
465
            An event pushed in the middle of a :any:`get` will not show until
466
            the next time :any:`get` called preventing push related
467
            infinite loops.
468
469
            This object should at least have a 'type' attribute.
470
    """
471
    _pushedEvents.append(event)
472
473
def key_wait():
474
    """Waits until the user presses a key.
475
    Then returns a :any:`KeyDown` event.
476
477
    Key events will repeat if held down.
478
479
    A click to close the window will be converted into an Alt+F4 KeyDown event.
480
481
    Returns:
482
        tdl.event.KeyDown: The pressed key.
483
    """
484
    while 1:
485
        for event in get():
486
            if event.type == 'KEYDOWN':
487
                return event
488
            if event.type == 'QUIT':
489
                # convert QUIT into alt+F4
490
                return KeyDown('F4', '', True, False, True, False, False)
491
        _time.sleep(.001)
492
493
def set_key_repeat(delay=500, interval=0):
0 ignored issues
show
Unused Code introduced by
The argument delay seems to be unused.
Loading history...
Unused Code introduced by
The argument interval seems to be unused.
Loading history...
494
    """Does nothing.
495
    """
496
    pass
497
498
def is_window_closed():
499
    """Returns True if the exit button on the window has been clicked and
500
    stays True afterwards.
501
502
    Returns: bool:
503
    """
504
    return _lib.TCOD_console_is_window_closed()
505
506
__all__ = [_var for _var in locals().keys() if _var[0] != '_']
507
508
App.runOnce = _style.backport(App.run_once)
509
keyWait = _style.backport(key_wait)
0 ignored issues
show
Coding Style Naming introduced by
The name keyWait does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
510
setKeyRepeat = _style.backport(set_key_repeat)
0 ignored issues
show
Coding Style Naming introduced by
The name setKeyRepeat does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
511
isWindowClosed = _style.backport(is_window_closed)
0 ignored issues
show
Coding Style Naming introduced by
The name isWindowClosed does not conform to the constant naming conventions ((([A-Z_][A-Z0-9_]*)|(__.*__))$).

This check looks for invalid names for a range of different identifiers.

You can set regular expressions to which the identifiers must conform if the defaults do not match your requirements.

If your project includes a Pylint configuration file, the settings contained in that file take precedence.

To find out more about Pylint, please refer to their site.

Loading history...
512
513