1# coding: ascii
2# pygame - Python Game Library
3# Copyright (C) 2000-2001  Pete Shinners
4#
5# This library is free software; you can redistribute it and/or
6# modify it under the terms of the GNU Library General Public
7# License as published by the Free Software Foundation; either
8# version 2 of the License, or (at your option) any later version.
9#
10# This library is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13# Library General Public License for more details.
14#
15# You should have received a copy of the GNU Library General Public
16# License along with this library; if not, write to the Free
17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18#
19# Pete Shinners
20# pete@shinners.org
21"""Pygame is a set of Python modules designed for writing games.
22It is written on top of the excellent SDL library. This allows you
23to create fully featured games and multimedia programs in the python
24language. The package is highly portable, with games running on
25Windows, MacOS, OS X, BeOS, FreeBSD, IRIX, and Linux."""
26
27import sys
28import os
29
30# Choose Windows display driver
31if os.name == 'nt':
32    #pypy does not find the dlls, so we add package folder to PATH.
33    pygame_dir = os.path.split(__file__)[0]
34    os.environ['PATH'] = os.environ['PATH'] + ';' + pygame_dir
35
36# when running under X11, always set the SDL window WM_CLASS to make the
37#   window managers correctly match the pygame window.
38elif 'DISPLAY' in os.environ and 'SDL_VIDEO_X11_WMCLASS' not in os.environ:
39    os.environ['SDL_VIDEO_X11_WMCLASS'] = os.path.basename(sys.argv[0])
40
41
42class MissingModule:
43    _NOT_IMPLEMENTED_ = True
44
45    def __init__(self, name, urgent=0):
46        self.name = name
47        exc_type, exc_msg = sys.exc_info()[:2]
48        self.info = str(exc_msg)
49        self.reason = "%s: %s" % (exc_type.__name__, self.info)
50        self.urgent = urgent
51        if urgent:
52            self.warn()
53
54    def __getattr__(self, var):
55        if not self.urgent:
56            self.warn()
57            self.urgent = 1
58        missing_msg = "%s module not available (%s)" % (self.name, self.reason)
59        raise NotImplementedError(missing_msg)
60
61    def __nonzero__(self):
62        return False
63
64    __bool__ = __nonzero__
65
66    def warn(self):
67        msg_type = 'import' if self.urgent else 'use'
68        message = '%s %s: %s\n(%s)' % (msg_type, self.name, self.info, self.reason)
69        try:
70            import warnings
71            level = 4 if self.urgent else 3
72            warnings.warn(message, RuntimeWarning, level)
73        except ImportError:
74            print(message)
75
76
77# we need to import like this, each at a time. the cleanest way to import
78# our modules is with the import command (not the __import__ function)
79
80# first, the "required" modules
81from pygame.base import * # pylint: disable=wildcard-import; lgtm[py/polluting-import]
82from pygame.constants import *  # now has __all__ pylint: disable=wildcard-import; lgtm[py/polluting-import]
83from pygame.version import * # pylint: disable=wildcard-import; lgtm[py/polluting-import]
84from pygame.rect import Rect
85from pygame.compat import PY_MAJOR_VERSION
86from pygame.rwobject import encode_string, encode_file_path
87import pygame.surflock
88import pygame.color
89Color = color.Color
90import pygame.bufferproxy
91BufferProxy = bufferproxy.BufferProxy
92import pygame.math
93Vector2 = pygame.math.Vector2
94Vector3 = pygame.math.Vector3
95
96__version__ = ver
97
98# next, the "standard" modules
99# we still allow them to be missing for stripped down pygame distributions
100if get_sdl_version() < (2, 0, 0):
101    # cdrom only available for SDL 1.2.X
102    try:
103        import pygame.cdrom
104    except (ImportError, IOError):
105        cdrom = MissingModule("cdrom", urgent=1)
106
107try:
108    import pygame.display
109except (ImportError, IOError):
110    display = MissingModule("display", urgent=1)
111
112try:
113    import pygame.draw
114except (ImportError, IOError):
115    draw = MissingModule("draw", urgent=1)
116
117try:
118    import pygame.event
119except (ImportError, IOError):
120    event = MissingModule("event", urgent=1)
121
122try:
123    import pygame.image
124except (ImportError, IOError):
125    image = MissingModule("image", urgent=1)
126
127try:
128    import pygame.joystick
129except (ImportError, IOError):
130    joystick = MissingModule("joystick", urgent=1)
131
132try:
133    import pygame.key
134except (ImportError, IOError):
135    key = MissingModule("key", urgent=1)
136
137try:
138    import pygame.mouse
139except (ImportError, IOError):
140    mouse = MissingModule("mouse", urgent=1)
141
142try:
143    import pygame.cursors
144    from pygame.cursors import Cursor
145except (ImportError, IOError):
146    cursors = MissingModule("cursors", urgent=1)
147    Cursor = lambda: Missing_Function
148
149try:
150    import pygame.sprite
151except (ImportError, IOError):
152    sprite = MissingModule("sprite", urgent=1)
153
154try:
155    import pygame.threads
156except (ImportError, IOError):
157    threads = MissingModule("threads", urgent=1)
158
159try:
160    import pygame.pixelcopy
161except (ImportError, IOError):
162    pixelcopy = MissingModule("pixelcopy", urgent=1)
163
164
165def warn_unwanted_files():
166    """warn about unneeded old files"""
167
168    # a temporary hack to warn about camera.so and camera.pyd.
169    install_path = os.path.split(pygame.base.__file__)[0]
170    extension_ext = os.path.splitext(pygame.base.__file__)[1]
171
172    # here are the .so/.pyd files we need to ask to remove.
173    ext_to_remove = ["camera"]
174
175    # here are the .py/.pyo/.pyc files we need to ask to remove.
176    py_to_remove = ["color"]
177
178    # Don't warn on Symbian. The color.py is used as a wrapper.
179    if os.name == "e32":
180        py_to_remove = []
181
182    # See if any of the files are there.
183    extension_files = ["%s%s" % (x, extension_ext) for x in ext_to_remove]
184
185    py_files = ["%s%s" % (x, py_ext)
186                for py_ext in [".py", ".pyc", ".pyo"]
187                for x in py_to_remove]
188
189    files = py_files + extension_files
190
191    unwanted_files = []
192    for f in files:
193        unwanted_files.append(os.path.join(install_path, f))
194
195    ask_remove = []
196    for f in unwanted_files:
197        if os.path.exists(f):
198            ask_remove.append(f)
199
200    if ask_remove:
201        message = "Detected old file(s).  Please remove the old files:\n"
202
203        for f in ask_remove:
204            message += "%s " % f
205        message += "\nLeaving them there might break pygame.  Cheers!\n\n"
206
207        try:
208            import warnings
209            level = 4
210            warnings.warn(message, RuntimeWarning, level)
211        except ImportError:
212            print(message)
213
214
215# disable, because we hopefully don't need it.
216# warn_unwanted_files()
217
218
219try:
220    from pygame.surface import Surface, SurfaceType
221except (ImportError, IOError):
222    Surface = lambda: Missing_Function
223
224try:
225    import pygame.mask
226    from pygame.mask import Mask
227except (ImportError, IOError):
228    mask = MissingModule("mask", urgent=0)
229    Mask = lambda: Missing_Function
230
231try:
232    from pygame.pixelarray import PixelArray
233except (ImportError, IOError):
234    PixelArray = lambda: Missing_Function
235
236try:
237    from pygame.overlay import Overlay
238except (ImportError, IOError):
239    Overlay = lambda: Missing_Function
240
241try:
242    import pygame.time
243except (ImportError, IOError):
244    time = MissingModule("time", urgent=1)
245
246try:
247    import pygame.transform
248except (ImportError, IOError):
249    transform = MissingModule("transform", urgent=1)
250
251# lastly, the "optional" pygame modules
252if 'PYGAME_FREETYPE' in os.environ:
253    try:
254        import pygame.ftfont as font
255        sys.modules['pygame.font'] = font
256    except (ImportError, IOError):
257        pass
258try:
259    import pygame.font
260    import pygame.sysfont
261    pygame.font.SysFont = pygame.sysfont.SysFont
262    pygame.font.get_fonts = pygame.sysfont.get_fonts
263    pygame.font.match_font = pygame.sysfont.match_font
264except (ImportError, IOError):
265    font = MissingModule("font", urgent=0)
266
267# try and load pygame.mixer_music before mixer, for py2app...
268try:
269    import pygame.mixer_music
270    #del pygame.mixer_music
271    #print ("NOTE2: failed importing pygame.mixer_music in lib/__init__.py")
272except (ImportError, IOError):
273    pass
274
275try:
276    import pygame.mixer
277except (ImportError, IOError):
278    mixer = MissingModule("mixer", urgent=0)
279
280# always fails, but MissingModule needs an exception to process
281try:
282    import pygame.movie
283except (ImportError, IOError):
284    movie = MissingModule("movie", urgent=0)
285
286try:
287    import pygame.scrap
288except (ImportError, IOError):
289    scrap = MissingModule("scrap", urgent=0)
290
291try:
292    import pygame.surfarray
293except (ImportError, IOError):
294    surfarray = MissingModule("surfarray", urgent=0)
295
296try:
297    import pygame.sndarray
298except (ImportError, IOError):
299    sndarray = MissingModule("sndarray", urgent=0)
300
301try:
302    import pygame.fastevent
303except (ImportError, IOError):
304    fastevent = MissingModule("fastevent", urgent=0)
305
306# there's also a couple "internal" modules not needed
307# by users, but putting them here helps "dependency finder"
308# programs get everything they need (like py2exe)
309try:
310    import pygame.imageext
311    del pygame.imageext
312except (ImportError, IOError):
313    pass
314
315
316def packager_imports():
317    """some additional imports that py2app/py2exe will want to see"""
318    import atexit
319    import numpy
320    import OpenGL.GL
321    import pygame.macosx
322    import pygame.bufferproxy
323    import pygame.colordict
324
325# make Rects pickleable
326if PY_MAJOR_VERSION >= 3:
327    import copyreg as copy_reg
328else:
329    import copy_reg
330
331
332def __rect_constructor(x, y, w, h):
333    return Rect(x, y, w, h)
334
335
336def __rect_reduce(r):
337    assert type(r) == Rect
338    return __rect_constructor, (r.x, r.y, r.w, r.h)
339copy_reg.pickle(Rect, __rect_reduce, __rect_constructor)
340
341
342# make Colors pickleable
343def __color_constructor(r, g, b, a):
344    return Color(r, g, b, a)
345
346
347def __color_reduce(c):
348    assert type(c) == Color
349    return __color_constructor, (c.r, c.g, c.b, c.a)
350copy_reg.pickle(Color, __color_reduce, __color_constructor)
351
352
353# Thanks for supporting pygame. Without support now, there won't be pygame later.
354if 'PYGAME_HIDE_SUPPORT_PROMPT' not in os.environ:
355    print('pygame {} (SDL {}.{}.{}, Python {}.{}.{})'.format(
356        ver, *get_sdl_version() + sys.version_info[0:3]
357    ))
358    print('Hello from the pygame community. https://www.pygame.org/contribute.html')
359
360
361# cleanup namespace
362del pygame, os, sys, surflock, MissingModule, copy_reg, PY_MAJOR_VERSION
363