initial
This commit is contained in:
commit
a0f3d0edd7
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1 @@
|
||||||
|
*pyc
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
# This file must be used with "source bin/activate" *from bash*
|
||||||
|
# you cannot run it directly
|
||||||
|
|
||||||
|
deactivate () {
|
||||||
|
# reset old environment variables
|
||||||
|
if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
|
||||||
|
PATH="${_OLD_VIRTUAL_PATH:-}"
|
||||||
|
export PATH
|
||||||
|
unset _OLD_VIRTUAL_PATH
|
||||||
|
fi
|
||||||
|
if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
|
||||||
|
PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
|
||||||
|
export PYTHONHOME
|
||||||
|
unset _OLD_VIRTUAL_PYTHONHOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This should detect bash and zsh, which have a hash command that must
|
||||||
|
# be called to get it to forget past commands. Without forgetting
|
||||||
|
# past commands the $PATH changes we made may not be respected
|
||||||
|
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
|
||||||
|
hash -r
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
|
||||||
|
PS1="${_OLD_VIRTUAL_PS1:-}"
|
||||||
|
export PS1
|
||||||
|
unset _OLD_VIRTUAL_PS1
|
||||||
|
fi
|
||||||
|
|
||||||
|
unset VIRTUAL_ENV
|
||||||
|
if [ ! "$1" = "nondestructive" ] ; then
|
||||||
|
# Self destruct!
|
||||||
|
unset -f deactivate
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# unset irrelevant variables
|
||||||
|
deactivate nondestructive
|
||||||
|
|
||||||
|
VIRTUAL_ENV="/home/rusticus/Dokumente/Windmessanlage/Software/Display/.venv"
|
||||||
|
export VIRTUAL_ENV
|
||||||
|
|
||||||
|
_OLD_VIRTUAL_PATH="$PATH"
|
||||||
|
PATH="$VIRTUAL_ENV/bin:$PATH"
|
||||||
|
export PATH
|
||||||
|
|
||||||
|
# unset PYTHONHOME if set
|
||||||
|
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
|
||||||
|
# could use `if (set -u; : $PYTHONHOME) ;` in bash
|
||||||
|
if [ -n "${PYTHONHOME:-}" ] ; then
|
||||||
|
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
|
||||||
|
unset PYTHONHOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
|
||||||
|
_OLD_VIRTUAL_PS1="${PS1:-}"
|
||||||
|
if [ "x(.venv) " != x ] ; then
|
||||||
|
PS1="(.venv) ${PS1:-}"
|
||||||
|
else
|
||||||
|
if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
|
||||||
|
# special case for Aspen magic directories
|
||||||
|
# see http://www.zetadev.com/software/aspen/
|
||||||
|
PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
|
||||||
|
else
|
||||||
|
PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
export PS1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# This should detect bash and zsh, which have a hash command that must
|
||||||
|
# be called to get it to forget past commands. Without forgetting
|
||||||
|
# past commands the $PATH changes we made may not be respected
|
||||||
|
if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
|
||||||
|
hash -r
|
||||||
|
fi
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
# This file must be used with "source bin/activate.csh" *from csh*.
|
||||||
|
# You cannot run it directly.
|
||||||
|
# Created by Davide Di Blasi <davidedb@gmail.com>.
|
||||||
|
# Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
|
||||||
|
|
||||||
|
alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate'
|
||||||
|
|
||||||
|
# Unset irrelevant variables.
|
||||||
|
deactivate nondestructive
|
||||||
|
|
||||||
|
setenv VIRTUAL_ENV "/home/rusticus/Dokumente/Windmessanlage/Software/Display/.venv"
|
||||||
|
|
||||||
|
set _OLD_VIRTUAL_PATH="$PATH"
|
||||||
|
setenv PATH "$VIRTUAL_ENV/bin:$PATH"
|
||||||
|
|
||||||
|
|
||||||
|
set _OLD_VIRTUAL_PROMPT="$prompt"
|
||||||
|
|
||||||
|
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
|
||||||
|
if (".venv" != "") then
|
||||||
|
set env_name = ".venv"
|
||||||
|
else
|
||||||
|
if (`basename "VIRTUAL_ENV"` == "__") then
|
||||||
|
# special case for Aspen magic directories
|
||||||
|
# see http://www.zetadev.com/software/aspen/
|
||||||
|
set env_name = `basename \`dirname "$VIRTUAL_ENV"\``
|
||||||
|
else
|
||||||
|
set env_name = `basename "$VIRTUAL_ENV"`
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
set prompt = "[$env_name] $prompt"
|
||||||
|
unset env_name
|
||||||
|
endif
|
||||||
|
|
||||||
|
alias pydoc python -m pydoc
|
||||||
|
|
||||||
|
rehash
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
# This file must be used with ". bin/activate.fish" *from fish* (http://fishshell.org)
|
||||||
|
# you cannot run it directly
|
||||||
|
|
||||||
|
function deactivate -d "Exit virtualenv and return to normal shell environment"
|
||||||
|
# reset old environment variables
|
||||||
|
if test -n "$_OLD_VIRTUAL_PATH"
|
||||||
|
set -gx PATH $_OLD_VIRTUAL_PATH
|
||||||
|
set -e _OLD_VIRTUAL_PATH
|
||||||
|
end
|
||||||
|
if test -n "$_OLD_VIRTUAL_PYTHONHOME"
|
||||||
|
set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
|
||||||
|
set -e _OLD_VIRTUAL_PYTHONHOME
|
||||||
|
end
|
||||||
|
|
||||||
|
if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
|
||||||
|
functions -e fish_prompt
|
||||||
|
set -e _OLD_FISH_PROMPT_OVERRIDE
|
||||||
|
functions -c _old_fish_prompt fish_prompt
|
||||||
|
functions -e _old_fish_prompt
|
||||||
|
end
|
||||||
|
|
||||||
|
set -e VIRTUAL_ENV
|
||||||
|
if test "$argv[1]" != "nondestructive"
|
||||||
|
# Self destruct!
|
||||||
|
functions -e deactivate
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# unset irrelevant variables
|
||||||
|
deactivate nondestructive
|
||||||
|
|
||||||
|
set -gx VIRTUAL_ENV "/home/rusticus/Dokumente/Windmessanlage/Software/Display/.venv"
|
||||||
|
|
||||||
|
set -gx _OLD_VIRTUAL_PATH $PATH
|
||||||
|
set -gx PATH "$VIRTUAL_ENV/bin" $PATH
|
||||||
|
|
||||||
|
# unset PYTHONHOME if set
|
||||||
|
if set -q PYTHONHOME
|
||||||
|
set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
|
||||||
|
set -e PYTHONHOME
|
||||||
|
end
|
||||||
|
|
||||||
|
if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
|
||||||
|
# fish uses a function instead of an env var to generate the prompt.
|
||||||
|
|
||||||
|
# save the current fish_prompt function as the function _old_fish_prompt
|
||||||
|
functions -c fish_prompt _old_fish_prompt
|
||||||
|
|
||||||
|
# with the original prompt function renamed, we can override with our own.
|
||||||
|
function fish_prompt
|
||||||
|
# Save the return status of the last command
|
||||||
|
set -l old_status $status
|
||||||
|
|
||||||
|
# Prompt override?
|
||||||
|
if test -n "(.venv) "
|
||||||
|
printf "%s%s" "(.venv) " (set_color normal)
|
||||||
|
else
|
||||||
|
# ...Otherwise, prepend env
|
||||||
|
set -l _checkbase (basename "$VIRTUAL_ENV")
|
||||||
|
if test $_checkbase = "__"
|
||||||
|
# special case for Aspen magic directories
|
||||||
|
# see http://www.zetadev.com/software/aspen/
|
||||||
|
printf "%s[%s]%s " (set_color -b blue white) (basename (dirname "$VIRTUAL_ENV")) (set_color normal)
|
||||||
|
else
|
||||||
|
printf "%s(%s)%s" (set_color -b blue white) (basename "$VIRTUAL_ENV") (set_color normal)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Restore the return status of the previous command.
|
||||||
|
echo "exit $old_status" | .
|
||||||
|
_old_fish_prompt
|
||||||
|
end
|
||||||
|
|
||||||
|
set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/home/rusticus/Dokumente/Windmessanlage/Software/Display/.venv/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from setuptools.command.easy_install import main
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(main())
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/home/rusticus/Dokumente/Windmessanlage/Software/Display/.venv/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from setuptools.command.easy_install import main
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(main())
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/home/rusticus/Dokumente/Windmessanlage/Software/Display/.venv/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from pylint import run_epylint
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(run_epylint())
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/home/rusticus/Dokumente/Windmessanlage/Software/Display/.venv/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from isort.main import main
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(main())
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/home/rusticus/Dokumente/Windmessanlage/Software/Display/.venv/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from pip._internal import main
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(main())
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/home/rusticus/Dokumente/Windmessanlage/Software/Display/.venv/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from pip._internal import main
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(main())
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/home/rusticus/Dokumente/Windmessanlage/Software/Display/.venv/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from pip._internal import main
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(main())
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/home/rusticus/Dokumente/Windmessanlage/Software/Display/.venv/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from pylint import run_pylint
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(run_pylint())
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/home/rusticus/Dokumente/Windmessanlage/Software/Display/.venv/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from pylint import run_pyreverse
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(run_pyreverse())
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
python3
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
/usr/bin/python3
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/home/rusticus/Dokumente/Windmessanlage/Software/Display/.venv/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from pylint import run_symilar
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])
|
||||||
|
sys.exit(run_symilar())
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CAMERA_H
|
||||||
|
#define _CAMERA_H
|
||||||
|
|
||||||
|
#include "_pygame.h"
|
||||||
|
#include "camera.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,239 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
Copyright (C) 2000-2001 Pete Shinners
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Pete Shinners
|
||||||
|
pete@shinners.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This will use PYGAMEAPI_EXTERN_SLOTS instead
|
||||||
|
* of PYGAMEAPI_DEFINE_SLOTS for base modules.
|
||||||
|
*/
|
||||||
|
#ifndef _PYGAME_INTERNAL_H
|
||||||
|
#define _PYGAME_INTERNAL_H
|
||||||
|
|
||||||
|
#include "pgplatform.h"
|
||||||
|
#include <Python.h>
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
/* IS_SDLv1 is 1 if SDL 1.x.x, 0 otherwise */
|
||||||
|
/* IS_SDLv2 is 1 if at least SDL 2.0.0, 0 otherwise */
|
||||||
|
#if (SDL_VERSION_ATLEAST(2, 0, 0))
|
||||||
|
#define IS_SDLv2 1
|
||||||
|
#define IS_SDLv1 0
|
||||||
|
#else
|
||||||
|
#define IS_SDLv2 0
|
||||||
|
#define IS_SDLv1 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*#if IS_SDLv1 && PG_MAJOR_VERSION >= 2
|
||||||
|
#error pygame 2 requires SDL 2
|
||||||
|
#endif*/
|
||||||
|
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||||
|
/* SDL 1.2 constants removed from SDL 2 */
|
||||||
|
typedef enum {
|
||||||
|
SDL_HWSURFACE = 0,
|
||||||
|
SDL_RESIZABLE = SDL_WINDOW_RESIZABLE,
|
||||||
|
SDL_ASYNCBLIT = 0,
|
||||||
|
SDL_OPENGL = SDL_WINDOW_OPENGL,
|
||||||
|
SDL_OPENGLBLIT = 0,
|
||||||
|
SDL_ANYFORMAT = 0,
|
||||||
|
SDL_HWPALETTE = 0,
|
||||||
|
SDL_DOUBLEBUF = 0,
|
||||||
|
SDL_FULLSCREEN = SDL_WINDOW_FULLSCREEN,
|
||||||
|
SDL_HWACCEL = 0,
|
||||||
|
SDL_SRCCOLORKEY = 0,
|
||||||
|
SDL_RLEACCELOK = 0,
|
||||||
|
SDL_SRCALPHA = 0,
|
||||||
|
SDL_NOFRAME = SDL_WINDOW_BORDERLESS,
|
||||||
|
SDL_GL_SWAP_CONTROL = 0,
|
||||||
|
TIMER_RESOLUTION = 0
|
||||||
|
} PygameVideoFlags;
|
||||||
|
|
||||||
|
/* the wheel button constants were removed from SDL 2 */
|
||||||
|
typedef enum {
|
||||||
|
PGM_BUTTON_LEFT = SDL_BUTTON_LEFT,
|
||||||
|
PGM_BUTTON_RIGHT = SDL_BUTTON_RIGHT,
|
||||||
|
PGM_BUTTON_MIDDLE = SDL_BUTTON_MIDDLE,
|
||||||
|
PGM_BUTTON_WHEELUP = 4,
|
||||||
|
PGM_BUTTON_WHEELDOWN = 5,
|
||||||
|
PGM_BUTTON_X1 = SDL_BUTTON_X1 + 2,
|
||||||
|
PGM_BUTTON_X2 = SDL_BUTTON_X2 + 2,
|
||||||
|
PGM_BUTTON_KEEP = 0x80
|
||||||
|
} PygameMouseFlags;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* Any SDL_* events here are for backward compatibility. */
|
||||||
|
SDL_NOEVENT = 0,
|
||||||
|
|
||||||
|
/* pygame events */
|
||||||
|
PGE_EVENTBEGIN = SDL_USEREVENT, /* Not an event. Indicates start of pygame events. */
|
||||||
|
SDL_ACTIVEEVENT = PGE_EVENTBEGIN,
|
||||||
|
SDL_VIDEORESIZE,
|
||||||
|
SDL_VIDEOEXPOSE,
|
||||||
|
PGE_KEYREPEAT,
|
||||||
|
PGE_MIDIIN,
|
||||||
|
PGE_MIDIOUT,
|
||||||
|
PGE_EVENTEND, /* Not an event. Indicates end of pygame events. */
|
||||||
|
|
||||||
|
/* User event range. */
|
||||||
|
/* SDL 1.2 allowed for 8 user defined events. */
|
||||||
|
PGE_USEREVENT = PGE_EVENTEND,
|
||||||
|
PG_NUMEVENTS = PGE_USEREVENT + 0x2000 /* Not an event. Indicates end of user events. */
|
||||||
|
} PygameEventCode;
|
||||||
|
|
||||||
|
#define PGE_NUMRESERVED (PGE_EVENTEND - PGE_EVENTBEGIN)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SDL_APPFOCUSMOUSE,
|
||||||
|
SDL_APPINPUTFOCUS,
|
||||||
|
SDL_APPACTIVE
|
||||||
|
} PygameAppCode;
|
||||||
|
|
||||||
|
/* Surface flags: based on SDL 1.2 flags */
|
||||||
|
typedef enum {
|
||||||
|
PGS_SWSURFACE = 0x00000000,
|
||||||
|
PGS_HWSURFACE = 0x00000001,
|
||||||
|
PGS_ASYNCBLIT = 0x00000004,
|
||||||
|
|
||||||
|
PGS_ANYFORMAT = 0x10000000,
|
||||||
|
PGS_HWPALETTE = 0x20000000,
|
||||||
|
PGS_DOUBLEBUF = 0x40000000,
|
||||||
|
PGS_FULLSCREEN = 0x80000000,
|
||||||
|
PGS_SCALED = 0x00000200,
|
||||||
|
|
||||||
|
PGS_OPENGL = 0x00000002,
|
||||||
|
PGS_OPENGLBLIT = 0x0000000A,
|
||||||
|
PGS_RESIZABLE = 0x00000010,
|
||||||
|
PGS_NOFRAME = 0x00000020,
|
||||||
|
PGS_SHOWN = 0x00000040, /* Added from SDL 2 */
|
||||||
|
PGS_HIDDEN = 0x00000080, /* Added from SDL 2 */
|
||||||
|
|
||||||
|
PGS_HWACCEL = 0x00000100,
|
||||||
|
PGS_SRCCOLORKEY = 0x00001000,
|
||||||
|
PGS_RLEACCELOK = 0x00002000,
|
||||||
|
PGS_RLEACCEL = 0x00004000,
|
||||||
|
PGS_SRCALPHA = 0x00010000,
|
||||||
|
PGS_PREALLOC = 0x01000000
|
||||||
|
} PygameSurfaceFlags;
|
||||||
|
#else /* ~SDL_VERSION_ATLEAST(2, 0, 0) */
|
||||||
|
/* To maintain SDL 1.2 build support. */
|
||||||
|
#define PGE_USEREVENT SDL_USEREVENT
|
||||||
|
#define PG_NUMEVENTS SDL_NUMEVENTS
|
||||||
|
/* These midi events were originally defined in midi.py.
|
||||||
|
* Note: They are outside the SDL_USEREVENT/SDL_NUMEVENTS event range for
|
||||||
|
* SDL 1.2. */
|
||||||
|
#define PGE_MIDIIN PGE_USEREVENT + 10
|
||||||
|
#define PGE_MIDIOUT PGE_USEREVENT + 11
|
||||||
|
#endif /* ~SDL_VERSION_ATLEAST(2, 0, 0) */
|
||||||
|
|
||||||
|
#define RAISE(x, y) (PyErr_SetString((x), (y)), (PyObject *)NULL)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialization checks
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define VIDEO_INIT_CHECK() \
|
||||||
|
if (!SDL_WasInit(SDL_INIT_VIDEO)) \
|
||||||
|
return RAISE(pgExc_SDLError, "video system not initialized")
|
||||||
|
|
||||||
|
#define CDROM_INIT_CHECK() \
|
||||||
|
if (!SDL_WasInit(SDL_INIT_CDROM)) \
|
||||||
|
return RAISE(pgExc_SDLError, "cdrom system not initialized")
|
||||||
|
|
||||||
|
#define JOYSTICK_INIT_CHECK() \
|
||||||
|
if (!SDL_WasInit(SDL_INIT_JOYSTICK)) \
|
||||||
|
return RAISE(pgExc_SDLError, "joystick system not initialized")
|
||||||
|
|
||||||
|
/* thread check */
|
||||||
|
#ifdef WITH_THREAD
|
||||||
|
#define PG_CHECK_THREADS() (1)
|
||||||
|
#else /* ~WITH_THREAD */
|
||||||
|
#define PG_CHECK_THREADS() \
|
||||||
|
(RAISE(PyExc_NotImplementedError, \
|
||||||
|
"Python built without thread support"))
|
||||||
|
#endif /* ~WITH_THREAD */
|
||||||
|
|
||||||
|
#define PyType_Init(x) (((x).ob_type) = &PyType_Type)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* event module internals
|
||||||
|
*/
|
||||||
|
struct pgEventObject {
|
||||||
|
PyObject_HEAD int type;
|
||||||
|
PyObject *dict;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* surflock module internals
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD PyObject *surface;
|
||||||
|
PyObject *lockobj;
|
||||||
|
PyObject *weakrefs;
|
||||||
|
} pgLifetimeLockObject;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* surface module internals
|
||||||
|
*/
|
||||||
|
struct pgSubSurface_Data {
|
||||||
|
PyObject *owner;
|
||||||
|
int pixeloffset;
|
||||||
|
int offsetx, offsety;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* color module internals
|
||||||
|
*/
|
||||||
|
struct pgColorObject {
|
||||||
|
PyObject_HEAD
|
||||||
|
Uint8 data[4];
|
||||||
|
Uint8 len;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* include public API
|
||||||
|
*/
|
||||||
|
#include "include/_pygame.h"
|
||||||
|
|
||||||
|
#include "pgimport.h"
|
||||||
|
|
||||||
|
/* Slot counts.
|
||||||
|
* Remember to keep these constants up to date.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PYGAMEAPI_RECT_NUMSLOTS 4
|
||||||
|
#define PYGAMEAPI_JOYSTICK_NUMSLOTS 2
|
||||||
|
#define PYGAMEAPI_DISPLAY_NUMSLOTS 2
|
||||||
|
#define PYGAMEAPI_SURFACE_NUMSLOTS 4
|
||||||
|
#define PYGAMEAPI_SURFLOCK_NUMSLOTS 8
|
||||||
|
#define PYGAMEAPI_RWOBJECT_NUMSLOTS 6
|
||||||
|
#define PYGAMEAPI_PIXELARRAY_NUMSLOTS 2
|
||||||
|
#define PYGAMEAPI_COLOR_NUMSLOTS 5
|
||||||
|
#define PYGAMEAPI_MATH_NUMSLOTS 2
|
||||||
|
#define PYGAMEAPI_CDROM_NUMSLOTS 2
|
||||||
|
|
||||||
|
#if PG_API_VERSION == 1
|
||||||
|
#define PYGAMEAPI_BASE_NUMSLOTS 19
|
||||||
|
#define PYGAMEAPI_EVENT_NUMSLOTS 4
|
||||||
|
#else /* PG_API_VERSION == 2 */
|
||||||
|
#define PYGAMEAPI_BASE_NUMSLOTS 23
|
||||||
|
#define PYGAMEAPI_EVENT_NUMSLOTS 6
|
||||||
|
#endif /* PG_API_VERSION == 2 */
|
||||||
|
|
||||||
|
#endif /* _PYGAME_INTERNAL_H */
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
Copyright (C) 2000-2001 Pete Shinners
|
||||||
|
Copyright (C) 2007 Marcus von Appen
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Pete Shinners
|
||||||
|
pete@shinners.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SURFACE_H
|
||||||
|
#define _SURFACE_H
|
||||||
|
|
||||||
|
#include "_pygame.h"
|
||||||
|
#include "surface.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,205 @@
|
||||||
|
#ifndef CAMERA_H
|
||||||
|
#define CAMERA_H
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pygame.h"
|
||||||
|
#include "doc/camera_doc.h"
|
||||||
|
|
||||||
|
#if defined(__unix__)
|
||||||
|
#include <structmember.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <fcntl.h> /* low-level i/o */
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
/* on freebsd there is no asm/types */
|
||||||
|
#ifdef linux
|
||||||
|
#include <asm/types.h> /* for videodev2.h */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <linux/videodev2.h>
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include <AvailabilityMacros.h>
|
||||||
|
/* We support OSX 10.6 and below. */
|
||||||
|
#if __MAC_OS_X_VERSION_MAX_ALLOWED <= 1060
|
||||||
|
#define PYGAME_MAC_CAMERA_OLD 1
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(PYGAME_MAC_CAMERA_OLD)
|
||||||
|
#include <QuickTime/QuickTime.h>
|
||||||
|
#include <QuickTime/Movies.h>
|
||||||
|
#include <QuickTime/ImageCompression.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* some constants used which are not defined on non-v4l machines. */
|
||||||
|
#ifndef V4L2_PIX_FMT_RGB24
|
||||||
|
#define V4L2_PIX_FMT_RGB24 'RGB3'
|
||||||
|
#endif
|
||||||
|
#ifndef V4L2_PIX_FMT_RGB444
|
||||||
|
#define V4L2_PIX_FMT_RGB444 'R444'
|
||||||
|
#endif
|
||||||
|
#ifndef V4L2_PIX_FMT_YUYV
|
||||||
|
#define V4L2_PIX_FMT_YUYV 'YUYV'
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CLEAR(x) memset (&(x), 0, sizeof (x))
|
||||||
|
#define SAT(c) if (c & (~255)) { if (c < 0) c = 0; else c = 255; }
|
||||||
|
#define SAT2(c) ((c) & (~255) ? ((c) < 0 ? 0 : 255) : (c))
|
||||||
|
#define DEFAULT_WIDTH 640
|
||||||
|
#define DEFAULT_HEIGHT 480
|
||||||
|
#define RGB_OUT 1
|
||||||
|
#define YUV_OUT 2
|
||||||
|
#define HSV_OUT 4
|
||||||
|
#define CAM_V4L 1 /* deprecated. the incomplete support in pygame was removed */
|
||||||
|
#define CAM_V4L2 2
|
||||||
|
|
||||||
|
struct buffer {
|
||||||
|
void * start;
|
||||||
|
size_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
#if defined(__unix__)
|
||||||
|
typedef struct pgCameraObject {
|
||||||
|
PyObject_HEAD
|
||||||
|
char* device_name;
|
||||||
|
int camera_type;
|
||||||
|
unsigned long pixelformat;
|
||||||
|
unsigned int color_out;
|
||||||
|
struct buffer* buffers;
|
||||||
|
unsigned int n_buffers;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int size;
|
||||||
|
int hflip;
|
||||||
|
int vflip;
|
||||||
|
int brightness;
|
||||||
|
int fd;
|
||||||
|
} pgCameraObject;
|
||||||
|
#elif defined(PYGAME_MAC_CAMERA_OLD)
|
||||||
|
typedef struct pgCameraObject {
|
||||||
|
PyObject_HEAD
|
||||||
|
char* device_name; /* unique name of the device */
|
||||||
|
OSType pixelformat;
|
||||||
|
unsigned int color_out;
|
||||||
|
SeqGrabComponent component; /* A type used by the Sequence Grabber API */
|
||||||
|
SGChannel channel; /* Channel of the Sequence Grabber */
|
||||||
|
GWorldPtr gworld; /* Pointer to the struct that holds the data of the captured image */
|
||||||
|
Rect boundsRect; /* bounds of the image frame */
|
||||||
|
long size; /* size of the image in our buffer to draw */
|
||||||
|
int hflip;
|
||||||
|
int vflip;
|
||||||
|
short depth;
|
||||||
|
struct buffer pixels;
|
||||||
|
//struct buffer tmp_pixels /* place where the flipped image in temporarily stored if hflip or vflip is true.*/
|
||||||
|
} pgCameraObject;
|
||||||
|
|
||||||
|
#else
|
||||||
|
/* generic definition.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct pgCameraObject {
|
||||||
|
PyObject_HEAD
|
||||||
|
char* device_name;
|
||||||
|
int camera_type;
|
||||||
|
unsigned long pixelformat;
|
||||||
|
unsigned int color_out;
|
||||||
|
struct buffer* buffers;
|
||||||
|
unsigned int n_buffers;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int size;
|
||||||
|
int hflip;
|
||||||
|
int vflip;
|
||||||
|
int brightness;
|
||||||
|
int fd;
|
||||||
|
} pgCameraObject;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* internal functions for colorspace conversion */
|
||||||
|
void colorspace (SDL_Surface *src, SDL_Surface *dst, int cspace);
|
||||||
|
void rgb24_to_rgb (const void* src, void* dst, int length, SDL_PixelFormat* format);
|
||||||
|
void rgb444_to_rgb (const void* src, void* dst, int length, SDL_PixelFormat* format);
|
||||||
|
void rgb_to_yuv (const void* src, void* dst, int length,
|
||||||
|
unsigned long source, SDL_PixelFormat* format);
|
||||||
|
void rgb_to_hsv (const void* src, void* dst, int length,
|
||||||
|
unsigned long source, SDL_PixelFormat* format);
|
||||||
|
void yuyv_to_rgb (const void* src, void* dst, int length, SDL_PixelFormat* format);
|
||||||
|
void yuyv_to_yuv (const void* src, void* dst, int length, SDL_PixelFormat* format);
|
||||||
|
void uyvy_to_rgb (const void* src, void* dst, int length, SDL_PixelFormat* format);
|
||||||
|
void uyvy_to_yuv (const void* src, void* dst, int length, SDL_PixelFormat* format);
|
||||||
|
void sbggr8_to_rgb (const void* src, void* dst, int width, int height,
|
||||||
|
SDL_PixelFormat* format);
|
||||||
|
void yuv420_to_rgb (const void* src, void* dst, int width, int height,
|
||||||
|
SDL_PixelFormat* format);
|
||||||
|
void yuv420_to_yuv (const void* src, void* dst, int width, int height,
|
||||||
|
SDL_PixelFormat* format);
|
||||||
|
|
||||||
|
#if defined(__unix__)
|
||||||
|
/* internal functions specific to v4l2 */
|
||||||
|
char** v4l2_list_cameras (int* num_devices);
|
||||||
|
int v4l2_get_control (int fd, int id, int *value);
|
||||||
|
int v4l2_set_control (int fd, int id, int value);
|
||||||
|
PyObject* v4l2_read_raw (pgCameraObject* self);
|
||||||
|
int v4l2_xioctl (int fd, int request, void *arg);
|
||||||
|
int v4l2_process_image (pgCameraObject* self, const void *image,
|
||||||
|
unsigned int buffer_size, SDL_Surface* surf);
|
||||||
|
int v4l2_query_buffer (pgCameraObject* self);
|
||||||
|
int v4l2_read_frame (pgCameraObject* self, SDL_Surface* surf);
|
||||||
|
int v4l2_stop_capturing (pgCameraObject* self);
|
||||||
|
int v4l2_start_capturing (pgCameraObject* self);
|
||||||
|
int v4l2_uninit_device (pgCameraObject* self);
|
||||||
|
int v4l2_init_mmap (pgCameraObject* self);
|
||||||
|
int v4l2_init_device (pgCameraObject* self);
|
||||||
|
int v4l2_close_device (pgCameraObject* self);
|
||||||
|
int v4l2_open_device (pgCameraObject* self);
|
||||||
|
|
||||||
|
#elif defined(PYGAME_MAC_CAMERA_OLD)
|
||||||
|
/* internal functions specific to mac */
|
||||||
|
char** mac_list_cameras(int* num_devices);
|
||||||
|
int mac_open_device (pgCameraObject* self);
|
||||||
|
int mac_init_device(pgCameraObject* self);
|
||||||
|
int mac_close_device (pgCameraObject* self);
|
||||||
|
int mac_start_capturing(pgCameraObject* self);
|
||||||
|
int mac_stop_capturing (pgCameraObject* self);
|
||||||
|
|
||||||
|
int mac_get_control(pgCameraObject* self, int id, int* value);
|
||||||
|
int mac_set_control(pgCameraObject* self, int id, int value);
|
||||||
|
|
||||||
|
PyObject* mac_read_raw(pgCameraObject *self);
|
||||||
|
int mac_read_frame(pgCameraObject* self, SDL_Surface* surf);
|
||||||
|
int mac_camera_idle(pgCameraObject* self);
|
||||||
|
int mac_copy_gworld_to_surface(pgCameraObject* self, SDL_Surface* surf);
|
||||||
|
|
||||||
|
void flip_image(const void* image, void* flipped_image, int width, int height,
|
||||||
|
short depth, int hflip, int vflip);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* !CAMERA_H */
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef _FASTEVENTS_H_
|
||||||
|
#define _FASTEVENTS_H_
|
||||||
|
/*
|
||||||
|
NET2 is a threaded, event based, network IO library for SDL.
|
||||||
|
Copyright (C) 2002 Bob Pendleton
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public License
|
||||||
|
as published by the Free Software Foundation; either version 2.1
|
||||||
|
of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
02111-1307 USA
|
||||||
|
|
||||||
|
If you do not wish to comply with the terms of the LGPL please
|
||||||
|
contact the author as other terms are available for a fee.
|
||||||
|
|
||||||
|
Bob Pendleton
|
||||||
|
Bob@Pendleton.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SDL.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int FE_Init(void); // Initialize FE
|
||||||
|
void FE_Quit(void); // shutdown FE
|
||||||
|
|
||||||
|
void FE_PumpEvents(void); // replacement for SDL_PumpEvents
|
||||||
|
int FE_PollEvent(SDL_Event *event); // replacement for SDL_PollEvent
|
||||||
|
int FE_WaitEvent(SDL_Event *event); // replacement for SDL_WaitEvent
|
||||||
|
int FE_PushEvent(SDL_Event *event); // replacement for SDL_PushEvent
|
||||||
|
|
||||||
|
char *FE_GetError(void); // get the last error
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef PGFONT_INTERNAL_H
|
||||||
|
#define PGFONT_INTERNAL_H
|
||||||
|
|
||||||
|
#include <SDL_ttf.h>
|
||||||
|
|
||||||
|
/* test font initialization */
|
||||||
|
#define FONT_INIT_CHECK() \
|
||||||
|
if(!(*(int*)PyFONT_C_API[2])) \
|
||||||
|
return RAISE(pgExc_SDLError, "font system not initialized")
|
||||||
|
|
||||||
|
#include "include/pygame_font.h"
|
||||||
|
|
||||||
|
#define PYGAMEAPI_FONT_NUMSLOTS 3
|
||||||
|
|
||||||
|
#endif /* ~PGFONT_INTERNAL_H */
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
Copyright (C) 2009 Vicent Marti
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
#ifndef _PYGAME_FREETYPE_INTERNAL_H_
|
||||||
|
#define _PYGAME_FREETYPE_INTERNAL_H_
|
||||||
|
|
||||||
|
#define PGFT_PYGAME1_COMPAT
|
||||||
|
#define HAVE_PYGAME_SDL_VIDEO
|
||||||
|
#define HAVE_PYGAME_SDL_RWOPS
|
||||||
|
|
||||||
|
#include "pgcompat.h"
|
||||||
|
#include "pgplatform.h"
|
||||||
|
#include <Python.h>
|
||||||
|
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
#include FT_CACHE_H
|
||||||
|
#include FT_XFREE86_H
|
||||||
|
#include FT_TRIGONOMETRY_H
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
* Global module constants
|
||||||
|
**********************************************************/
|
||||||
|
|
||||||
|
/* Render styles */
|
||||||
|
#define FT_STYLE_NORMAL 0x00
|
||||||
|
#define FT_STYLE_STRONG 0x01
|
||||||
|
#define FT_STYLE_OBLIQUE 0x02
|
||||||
|
#define FT_STYLE_UNDERLINE 0x04
|
||||||
|
#define FT_STYLE_WIDE 0x08
|
||||||
|
#define FT_STYLE_DEFAULT 0xFF
|
||||||
|
|
||||||
|
/* Bounding box modes */
|
||||||
|
#define FT_BBOX_EXACT FT_GLYPH_BBOX_SUBPIXELS
|
||||||
|
#define FT_BBOX_EXACT_GRIDFIT FT_GLYPH_BBOX_GRIDFIT
|
||||||
|
#define FT_BBOX_PIXEL FT_GLYPH_BBOX_TRUNCATE
|
||||||
|
#define FT_BBOX_PIXEL_GRIDFIT FT_GLYPH_BBOX_PIXELS
|
||||||
|
|
||||||
|
/* Rendering flags */
|
||||||
|
#define FT_RFLAG_NONE (0)
|
||||||
|
#define FT_RFLAG_ANTIALIAS (1 << 0)
|
||||||
|
#define FT_RFLAG_AUTOHINT (1 << 1)
|
||||||
|
#define FT_RFLAG_VERTICAL (1 << 2)
|
||||||
|
#define FT_RFLAG_HINTED (1 << 3)
|
||||||
|
#define FT_RFLAG_KERNING (1 << 4)
|
||||||
|
#define FT_RFLAG_TRANSFORM (1 << 5)
|
||||||
|
#define FT_RFLAG_PAD (1 << 6)
|
||||||
|
#define FT_RFLAG_ORIGIN (1 << 7)
|
||||||
|
#define FT_RFLAG_UCS4 (1 << 8)
|
||||||
|
#define FT_RFLAG_USE_BITMAP_STRIKES (1 << 9)
|
||||||
|
#define FT_RFLAG_DEFAULTS (FT_RFLAG_HINTED | \
|
||||||
|
FT_RFLAG_USE_BITMAP_STRIKES | \
|
||||||
|
FT_RFLAG_ANTIALIAS)
|
||||||
|
|
||||||
|
|
||||||
|
#define FT_RENDER_NEWBYTEARRAY 0x0
|
||||||
|
#define FT_RENDER_NEWSURFACE 0x1
|
||||||
|
#define FT_RENDER_EXISTINGSURFACE 0x2
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
* Global module types
|
||||||
|
**********************************************************/
|
||||||
|
|
||||||
|
typedef struct _scale_s {
|
||||||
|
FT_UInt x, y;
|
||||||
|
} Scale_t;
|
||||||
|
typedef FT_Angle Angle_t;
|
||||||
|
|
||||||
|
struct fontinternals_;
|
||||||
|
struct freetypeinstance_;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FT_Long font_index;
|
||||||
|
FT_Open_Args open_args;
|
||||||
|
} pgFontId;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
pgFontId id;
|
||||||
|
PyObject *path;
|
||||||
|
int is_scalable;
|
||||||
|
|
||||||
|
Scale_t face_size;
|
||||||
|
FT_Int16 style;
|
||||||
|
FT_Int16 render_flags;
|
||||||
|
double strength;
|
||||||
|
double underline_adjustment;
|
||||||
|
FT_UInt resolution;
|
||||||
|
Angle_t rotation;
|
||||||
|
FT_Matrix transform;
|
||||||
|
FT_Byte fgcolor[4];
|
||||||
|
|
||||||
|
struct freetypeinstance_ *freetype; /* Personal reference */
|
||||||
|
struct fontinternals_ *_internals;
|
||||||
|
} pgFontObject;
|
||||||
|
|
||||||
|
#define pgFont_IS_ALIVE(o) \
|
||||||
|
(((pgFontObject *)(o))->_internals != 0)
|
||||||
|
|
||||||
|
/* import public API */
|
||||||
|
#include "include/pygame_freetype.h"
|
||||||
|
|
||||||
|
#define PYGAMEAPI_FREETYPE_NUMSLOTS 2
|
||||||
|
|
||||||
|
#endif /* ~_PYGAME_FREETYPE_INTERNAL_H_ */
|
||||||
|
|
@ -0,0 +1,632 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
Copyright (C) 2000-2001 Pete Shinners
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Pete Shinners
|
||||||
|
pete@shinners.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PYGAME_H
|
||||||
|
#define _PYGAME_H
|
||||||
|
|
||||||
|
/** This header file includes all the definitions for the
|
||||||
|
** base pygame extensions. This header only requires
|
||||||
|
** Python includes (and SDL.h for functions that use SDL types).
|
||||||
|
** The reason for functions prototyped with #define's is
|
||||||
|
** to allow for maximum Python portability. It also uses
|
||||||
|
** Python as the runtime linker, which allows for late binding.
|
||||||
|
'' For more information on this style of development, read
|
||||||
|
** the Python docs on this subject.
|
||||||
|
** http://www.python.org/doc/current/ext/using-cobjects.html
|
||||||
|
**
|
||||||
|
** If using this to build your own derived extensions,
|
||||||
|
** you'll see that the functions available here are mainly
|
||||||
|
** used to help convert between python objects and SDL objects.
|
||||||
|
** Since this library doesn't add a lot of functionality to
|
||||||
|
** the SDL library, it doesn't need to offer a lot either.
|
||||||
|
**
|
||||||
|
** When initializing your extension module, you must manually
|
||||||
|
** import the modules you want to use. (this is the part about
|
||||||
|
** using python as the runtime linker). Each module has its
|
||||||
|
** own import_xxx() routine. You need to perform this import
|
||||||
|
** after you have initialized your own module, and before
|
||||||
|
** you call any routines from that module. Since every module
|
||||||
|
** in pygame does this, there are plenty of examples.
|
||||||
|
**
|
||||||
|
** The base module does include some useful conversion routines
|
||||||
|
** that you are free to use in your own extension.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include "pgplatform.h"
|
||||||
|
#include <Python.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* version macros (defined since version 1.9.5) */
|
||||||
|
#define PG_MAJOR_VERSION 2
|
||||||
|
#define PG_MINOR_VERSION 0
|
||||||
|
#define PG_PATCH_VERSION 0
|
||||||
|
#define PG_VERSIONNUM(MAJOR, MINOR, PATCH) (1000*(MAJOR) + 100*(MINOR) + (PATCH))
|
||||||
|
#define PG_VERSION_ATLEAST(MAJOR, MINOR, PATCH) \
|
||||||
|
(PG_VERSIONNUM(PG_MAJOR_VERSION, PG_MINOR_VERSION, PG_PATCH_VERSION) >= \
|
||||||
|
PG_VERSIONNUM(MAJOR, MINOR, PATCH))
|
||||||
|
|
||||||
|
/* SDL 1.x/2.x and pygame 1.x/2.x
|
||||||
|
*/
|
||||||
|
#if defined(SDL_VERSION_ATLEAST)
|
||||||
|
#if (SDL_VERSION_ATLEAST(2, 0, 0))
|
||||||
|
#define PG_API_VERSION 2
|
||||||
|
#else /* SDL 1 */
|
||||||
|
/* for now: allow pygame 2 to be compiled with SDL 1. */
|
||||||
|
#define PG_API_VERSION 1
|
||||||
|
#endif /* SDL 1 */
|
||||||
|
#else /* NO SDL */
|
||||||
|
#define PG_API_VERSION ((PG_MAJOR_VERSION == 1) ? 1 : 2)
|
||||||
|
#endif /* NO SDL */
|
||||||
|
|
||||||
|
#include "pgcompat.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Flag indicating a pg_buffer; used for assertions within callbacks */
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define PyBUF_PYGAME 0x4000
|
||||||
|
#endif
|
||||||
|
#define PyBUF_HAS_FLAG(f, F) (((f) & (F)) == (F))
|
||||||
|
|
||||||
|
/* Array information exchange struct C type; inherits from Py_buffer
|
||||||
|
*
|
||||||
|
* Pygame uses its own Py_buffer derived C struct as an internal representation
|
||||||
|
* of an imported array buffer. The extended Py_buffer allows for a
|
||||||
|
* per-instance release callback,
|
||||||
|
*/
|
||||||
|
typedef void (*pybuffer_releaseproc)(Py_buffer *);
|
||||||
|
|
||||||
|
typedef struct pg_bufferinfo_s {
|
||||||
|
Py_buffer view;
|
||||||
|
PyObject *consumer; /* Input: Borrowed reference */
|
||||||
|
pybuffer_releaseproc release_buffer;
|
||||||
|
} pg_buffer;
|
||||||
|
|
||||||
|
#include "pgimport.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BASE module
|
||||||
|
*/
|
||||||
|
#ifndef PYGAMEAPI_BASE_INTERNAL
|
||||||
|
#define pgExc_SDLError \
|
||||||
|
((PyObject *) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 0))
|
||||||
|
|
||||||
|
#define pg_RegisterQuit \
|
||||||
|
(*(void (*)(void (*)(void))) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 1))
|
||||||
|
|
||||||
|
#define pg_IntFromObj \
|
||||||
|
(*(int (*)(PyObject *, int *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 2))
|
||||||
|
|
||||||
|
#define pg_IntFromObjIndex \
|
||||||
|
(*(int (*)(PyObject *, int, int *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 3))
|
||||||
|
|
||||||
|
#define pg_TwoIntsFromObj \
|
||||||
|
(*(int (*)(PyObject *, int *, int *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 4))
|
||||||
|
|
||||||
|
#define pg_FloatFromObj \
|
||||||
|
(*(int (*)(PyObject *, float *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 5))
|
||||||
|
|
||||||
|
#define pg_FloatFromObjIndex \
|
||||||
|
(*(int (*)(PyObject *, int, float *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 6))
|
||||||
|
|
||||||
|
#define pg_TwoFloatsFromObj \
|
||||||
|
(*(int (*)(PyObject *, float *, float *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 7))
|
||||||
|
|
||||||
|
#define pg_UintFromObj \
|
||||||
|
(*(int (*)(PyObject *, Uint32 *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 8))
|
||||||
|
|
||||||
|
#define pg_UintFromObjIndex \
|
||||||
|
(*(int (*)(PyObject *, int, Uint32 *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 9))
|
||||||
|
|
||||||
|
#define pgVideo_AutoQuit \
|
||||||
|
(*(void (*)(void)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 10))
|
||||||
|
|
||||||
|
#define pgVideo_AutoInit \
|
||||||
|
(*(int (*)(void)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 11))
|
||||||
|
|
||||||
|
#define pg_RGBAFromObj \
|
||||||
|
(*(int (*)(PyObject *, Uint8 *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 12))
|
||||||
|
|
||||||
|
#define pgBuffer_AsArrayInterface \
|
||||||
|
(*(PyObject * (*)(Py_buffer *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 13))
|
||||||
|
|
||||||
|
#define pgBuffer_AsArrayStruct \
|
||||||
|
(*(PyObject * (*)(Py_buffer *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 14))
|
||||||
|
|
||||||
|
#define pgObject_GetBuffer \
|
||||||
|
(*(int (*)(PyObject *, pg_buffer *, int)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 15))
|
||||||
|
|
||||||
|
#define pgBuffer_Release \
|
||||||
|
(*(void (*)(pg_buffer *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 16))
|
||||||
|
|
||||||
|
#define pgDict_AsBuffer \
|
||||||
|
(*(int (*)(pg_buffer *, PyObject *, int)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 17))
|
||||||
|
|
||||||
|
#define pgExc_BufferError \
|
||||||
|
((PyObject *) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 18))
|
||||||
|
|
||||||
|
#if PG_API_VERSION == 2
|
||||||
|
#define pg_GetDefaultWindow \
|
||||||
|
(*(SDL_Window * (*)(void)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 19))
|
||||||
|
|
||||||
|
#define pg_SetDefaultWindow \
|
||||||
|
(*(void (*)(SDL_Window *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 20))
|
||||||
|
|
||||||
|
#define pg_GetDefaultWindowSurface \
|
||||||
|
(*(PyObject * (*)(void)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 21))
|
||||||
|
|
||||||
|
#define pg_SetDefaultWindowSurface \
|
||||||
|
(*(void (*)(PyObject *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(base, 22))
|
||||||
|
|
||||||
|
#endif /* PG_API_VERSION == 2 */
|
||||||
|
|
||||||
|
#define import_pygame_base() IMPORT_PYGAME_MODULE(base)
|
||||||
|
#endif /* ~PYGAMEAPI_BASE_INTERNAL */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RECT module
|
||||||
|
*/
|
||||||
|
#if !defined(SDL_VERSION_ATLEAST) || PG_API_VERSION == 1
|
||||||
|
typedef struct {
|
||||||
|
int x, y;
|
||||||
|
int w, h;
|
||||||
|
} GAME_Rect;
|
||||||
|
#else /* SDL 2+ */
|
||||||
|
typedef SDL_Rect GAME_Rect;
|
||||||
|
#endif /* SDL 2+ */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD GAME_Rect r;
|
||||||
|
PyObject *weakreflist;
|
||||||
|
} pgRectObject;
|
||||||
|
|
||||||
|
#define pgRect_AsRect(x) (((pgRectObject *)x)->r)
|
||||||
|
#ifndef PYGAMEAPI_RECT_INTERNAL
|
||||||
|
#define pgRect_Type \
|
||||||
|
(*(PyTypeObject *) \
|
||||||
|
PYGAMEAPI_GET_SLOT(rect, 0))
|
||||||
|
|
||||||
|
#define pgRect_Check(x) \
|
||||||
|
((x)->ob_type == &pgRect_Type)
|
||||||
|
#define pgRect_New \
|
||||||
|
(*(PyObject * (*)(SDL_Rect *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(rect, 1))
|
||||||
|
|
||||||
|
#define pgRect_New4 \
|
||||||
|
(*(PyObject * (*)(int, int, int, int)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(rect, 2))
|
||||||
|
|
||||||
|
#define pgRect_FromObject \
|
||||||
|
(*(GAME_Rect * (*)(PyObject *, GAME_Rect *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(rect, 3))
|
||||||
|
|
||||||
|
#define import_pygame_rect() IMPORT_PYGAME_MODULE(rect)
|
||||||
|
#endif /* ~PYGAMEAPI_RECT_INTERNAL */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CDROM module
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD int id;
|
||||||
|
} pgCDObject;
|
||||||
|
|
||||||
|
#define pgCD_AsID(x) (((pgCDObject *)x)->id)
|
||||||
|
#ifndef PYGAMEAPI_CDROM_INTERNAL
|
||||||
|
#define pgCD_Type \
|
||||||
|
(*(PyTypeObject *) \
|
||||||
|
PYGAMEAPI_GET_SLOT(cdrom, 0))
|
||||||
|
|
||||||
|
#define pgCD_Check(x) \
|
||||||
|
((x)->ob_type == &pgCD_Type)
|
||||||
|
#define pgCD_New \
|
||||||
|
(*(PyObject * (*)(int)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(cdrom, 1))
|
||||||
|
|
||||||
|
#define import_pygame_cd() IMPORT_PYGAME_MODULE(cdrom)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* JOYSTICK module
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD int id;
|
||||||
|
} pgJoystickObject;
|
||||||
|
|
||||||
|
#define pgJoystick_AsID(x) (((pgJoystickObject *)x)->id)
|
||||||
|
|
||||||
|
#ifndef PYGAMEAPI_JOYSTICK_INTERNAL
|
||||||
|
#define pgJoystick_Type \
|
||||||
|
(*(PyTypeObject *) \
|
||||||
|
PYGAMEAPI_GET_SLOT(joystick, 0))
|
||||||
|
|
||||||
|
#define pgJoystick_Check(x) \
|
||||||
|
((x)->ob_type == &pgJoystick_Type)
|
||||||
|
#define pgJoystick_New \
|
||||||
|
(*(PyObject * (*)(int)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(joystick, 1))
|
||||||
|
|
||||||
|
#define import_pygame_joystick() IMPORT_PYGAME_MODULE(joystick)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DISPLAY module
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(SDL_VERSION_ATLEAST)
|
||||||
|
|
||||||
|
#if PG_API_VERSION == 2
|
||||||
|
typedef struct {
|
||||||
|
Uint32 hw_available:1;
|
||||||
|
Uint32 wm_available:1;
|
||||||
|
Uint32 blit_hw:1;
|
||||||
|
Uint32 blit_hw_CC:1;
|
||||||
|
Uint32 blit_hw_A:1;
|
||||||
|
Uint32 blit_sw:1;
|
||||||
|
Uint32 blit_sw_CC:1;
|
||||||
|
Uint32 blit_sw_A:1;
|
||||||
|
Uint32 blit_fill:1;
|
||||||
|
Uint32 video_mem;
|
||||||
|
SDL_PixelFormat *vfmt;
|
||||||
|
SDL_PixelFormat vfmt_data;
|
||||||
|
int current_w;
|
||||||
|
int current_h;
|
||||||
|
} pg_VideoInfo;
|
||||||
|
#endif /* PG_API_VERSION == 2 */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
#if PG_API_VERSION == 1
|
||||||
|
PyObject_HEAD SDL_VideoInfo info;
|
||||||
|
#else
|
||||||
|
PyObject_HEAD pg_VideoInfo info;
|
||||||
|
#endif
|
||||||
|
} pgVidInfoObject;
|
||||||
|
|
||||||
|
#define pgVidInfo_AsVidInfo(x) (((pgVidInfoObject *)x)->info)
|
||||||
|
#endif /* defined(SDL_VERSION_ATLEAST) */
|
||||||
|
|
||||||
|
#ifndef PYGAMEAPI_DISPLAY_INTERNAL
|
||||||
|
#define pgVidInfo_Type \
|
||||||
|
(*(PyTypeObject *) \
|
||||||
|
PYGAMEAPI_GET_SLOT(display, 0))
|
||||||
|
|
||||||
|
#define pgVidInfo_Check(x) \
|
||||||
|
((x)->ob_type == &pgVidInfo_Type)
|
||||||
|
|
||||||
|
#if PG_API_VERSION == 1
|
||||||
|
#define pgVidInfo_New \
|
||||||
|
(*(PyObject * (*)(SDL_VideoInfo *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(display, 1))
|
||||||
|
#else
|
||||||
|
#define pgVidInfo_New \
|
||||||
|
(*(PyObject * (*)(pg_VideoInfo *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(display, 1))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define import_pygame_display() IMPORT_PYGAME_MODULE(display)
|
||||||
|
#endif /* ~PYGAMEAPI_DISPLAY_INTERNAL */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SURFACE module
|
||||||
|
*/
|
||||||
|
struct pgSubSurface_Data;
|
||||||
|
struct SDL_Surface;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD struct SDL_Surface *surf;
|
||||||
|
#if PG_API_VERSION == 2
|
||||||
|
int owner;
|
||||||
|
#endif /* PG_API_VERSION == 2 */
|
||||||
|
struct pgSubSurface_Data *subsurface; /* ptr to subsurface data (if a
|
||||||
|
* subsurface)*/
|
||||||
|
PyObject *weakreflist;
|
||||||
|
PyObject *locklist;
|
||||||
|
PyObject *dependency;
|
||||||
|
} pgSurfaceObject;
|
||||||
|
#define pgSurface_AsSurface(x) (((pgSurfaceObject *)x)->surf)
|
||||||
|
|
||||||
|
#ifndef PYGAMEAPI_SURFACE_INTERNAL
|
||||||
|
#define pgSurface_Type \
|
||||||
|
(*(PyTypeObject *) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surface, 0))
|
||||||
|
|
||||||
|
#define pgSurface_Check(x) \
|
||||||
|
(PyObject_IsInstance((x), (PyObject *) &pgSurface_Type))
|
||||||
|
#if PG_API_VERSION == 1
|
||||||
|
#define pgSurface_New \
|
||||||
|
(*(PyObject * (*)(SDL_Surface *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surface, 1))
|
||||||
|
|
||||||
|
#define pgSurface_SetSurface \
|
||||||
|
(*(int (*)(PyObject *, SDL_Surface *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surface, 3))
|
||||||
|
|
||||||
|
#else /* PG_API_VERSION == 2 */
|
||||||
|
#define pgSurface_New2 \
|
||||||
|
(*(PyObject * (*)(SDL_Surface *, int)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surface, 1))
|
||||||
|
|
||||||
|
#define pgSurface_SetSurface \
|
||||||
|
(*(int (*)(PyObject *, SDL_Surface *, int)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surface, 3))
|
||||||
|
|
||||||
|
#endif /* PG_API_VERSION == 2 */
|
||||||
|
#define pgSurface_Blit \
|
||||||
|
(*(int (*)(PyObject *, PyObject *, GAME_Rect *, GAME_Rect *, int)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surface, 2))
|
||||||
|
|
||||||
|
#define import_pygame_surface() \
|
||||||
|
do { \
|
||||||
|
IMPORT_PYGAME_MODULE(surface); \
|
||||||
|
if (PyErr_Occurred() != NULL) \
|
||||||
|
break; \
|
||||||
|
IMPORT_PYGAME_MODULE(surflock); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#if PG_API_VERSION == 2
|
||||||
|
#define pgSurface_New(surface) pgSurface_New2((surface), 1)
|
||||||
|
#define pgSurface_NewNoOwn(surface) pgSurface_New2((surface), 0)
|
||||||
|
#endif /* PG_API_VERSION == 2 */
|
||||||
|
|
||||||
|
#endif /* ~PYGAMEAPI_SURFACE_INTERNAL */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SURFLOCK module
|
||||||
|
* auto imported/initialized by surface
|
||||||
|
*/
|
||||||
|
#ifndef PYGAMEAPI_SURFLOCK_INTERNAL
|
||||||
|
#define pgLifetimeLock_Type \
|
||||||
|
(*(PyTypeObject *) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surflock, 0))
|
||||||
|
|
||||||
|
#define pgLifetimeLock_Check(x) \
|
||||||
|
((x)->ob_type == &pgLifetimeLock_Type)
|
||||||
|
|
||||||
|
#define pgSurface_Prep(x) \
|
||||||
|
if (((pgSurfaceObject *)x)->subsurface) \
|
||||||
|
(*(*(void (*)(PyObject *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surflock, 1)))(x)
|
||||||
|
|
||||||
|
#define pgSurface_Unprep(x) \
|
||||||
|
if (((pgSurfaceObject *)x)->subsurface) \
|
||||||
|
(*(*(void (*)(PyObject *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surflock, 2)))(x)
|
||||||
|
|
||||||
|
#define pgSurface_Lock \
|
||||||
|
(*(int (*)(PyObject *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surflock, 3))
|
||||||
|
|
||||||
|
#define pgSurface_Unlock \
|
||||||
|
(*(int (*)(PyObject *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surflock, 4))
|
||||||
|
|
||||||
|
#define pgSurface_LockBy \
|
||||||
|
(*(int (*)(PyObject *, PyObject *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surflock, 5))
|
||||||
|
|
||||||
|
#define pgSurface_UnlockBy \
|
||||||
|
(*(int (*)(PyObject *, PyObject *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surflock, 6))
|
||||||
|
|
||||||
|
#define pgSurface_LockLifetime \
|
||||||
|
(*(PyObject * (*)(PyObject *, PyObject *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(surflock, 7))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVENT module
|
||||||
|
*/
|
||||||
|
typedef struct pgEventObject pgEventObject;
|
||||||
|
|
||||||
|
#ifndef PYGAMEAPI_EVENT_INTERNAL
|
||||||
|
#define pgEvent_Type \
|
||||||
|
(*(PyTypeObject *) \
|
||||||
|
PYGAMEAPI_GET_SLOT(event, 0))
|
||||||
|
|
||||||
|
#define pgEvent_Check(x) \
|
||||||
|
((x)->ob_type == &pgEvent_Type)
|
||||||
|
|
||||||
|
#define pgEvent_New \
|
||||||
|
(*(PyObject * (*)(SDL_Event *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(event, 1))
|
||||||
|
|
||||||
|
#define pgEvent_New2 \
|
||||||
|
(*(PyObject * (*)(int, PyObject *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(event, 2))
|
||||||
|
|
||||||
|
#define pgEvent_FillUserEvent \
|
||||||
|
(*(int (*)(pgEventObject *, SDL_Event *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(event, 3))
|
||||||
|
|
||||||
|
#if PG_API_VERSION == 2
|
||||||
|
#define pg_EnableKeyRepeat \
|
||||||
|
(*(int (*)(int, int)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(event, 4))
|
||||||
|
|
||||||
|
#define pg_GetKeyRepeat \
|
||||||
|
(*(void (*)(int *, int *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(event, 5))
|
||||||
|
#endif /* PG_API_VERSION == 2 */
|
||||||
|
|
||||||
|
#define import_pygame_event() IMPORT_PYGAME_MODULE(event)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RWOBJECT module
|
||||||
|
* the rwobject are only needed for C side work, not accessable from python.
|
||||||
|
*/
|
||||||
|
#ifndef PYGAMEAPI_RWOBJECT_INTERNAL
|
||||||
|
#define pgRWops_FromObject \
|
||||||
|
(*(SDL_RWops * (*)(PyObject *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(rwobject, 0))
|
||||||
|
|
||||||
|
#define pgRWops_IsFileObject \
|
||||||
|
(*(int (*)(SDL_RWops *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(rwobject, 1))
|
||||||
|
|
||||||
|
#define pg_EncodeFilePath \
|
||||||
|
(*(PyObject * (*)(PyObject *, PyObject *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(rwobject, 2))
|
||||||
|
|
||||||
|
#define pg_EncodeString \
|
||||||
|
(*(PyObject * (*)(PyObject *, const char *, const char *, PyObject *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(rwobject, 3))
|
||||||
|
|
||||||
|
#define pgRWops_FromFileObject \
|
||||||
|
(*(SDL_RWops * (*)(PyObject *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(rwobject, 4))
|
||||||
|
|
||||||
|
#define pgRWops_ReleaseObject \
|
||||||
|
(*(int (*)(SDL_RWops *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(rwobject, 5))
|
||||||
|
|
||||||
|
#define import_pygame_rwobject() IMPORT_PYGAME_MODULE(rwobject)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PixelArray module
|
||||||
|
*/
|
||||||
|
#ifndef PYGAMEAPI_PIXELARRAY_INTERNAL
|
||||||
|
#define PyPixelArray_Type \
|
||||||
|
((PyTypeObject *) \
|
||||||
|
PYGAMEAPI_GET_SLOT(pixelarray, 0))
|
||||||
|
|
||||||
|
#define PyPixelArray_Check(x) \
|
||||||
|
((x)->ob_type == &PyPixelArray_Type)
|
||||||
|
#define PyPixelArray_New \
|
||||||
|
(*(PyObject * (*)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(pixelarray, 1))
|
||||||
|
|
||||||
|
#define import_pygame_pixelarray() IMPORT_PYGAME_MODULE(pixelarray)
|
||||||
|
#endif /* PYGAMEAPI_PIXELARRAY_INTERNAL */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Color module
|
||||||
|
*/
|
||||||
|
typedef struct pgColorObject pgColorObject;
|
||||||
|
|
||||||
|
#ifndef PYGAMEAPI_COLOR_INTERNAL
|
||||||
|
#define pgColor_Type (*(PyObject *) \
|
||||||
|
PYGAMEAPI_GET_SLOT(color, 0))
|
||||||
|
|
||||||
|
#define pgColor_Check(x) \
|
||||||
|
((x)->ob_type == &pgColor_Type)
|
||||||
|
#define pgColor_New \
|
||||||
|
(*(PyObject * (*)(Uint8 *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(color, 1))
|
||||||
|
|
||||||
|
#define pgColor_NewLength \
|
||||||
|
(*(PyObject * (*)(Uint8 *, Uint8)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(color, 3))
|
||||||
|
|
||||||
|
#define pg_RGBAFromColorObj \
|
||||||
|
(*(int (*)(PyObject *, Uint8 *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(color, 2))
|
||||||
|
|
||||||
|
#define pg_RGBAFromFuzzyColorObj \
|
||||||
|
(*(int (*)(PyObject *, Uint8 *)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(color, 4))
|
||||||
|
|
||||||
|
#define pgColor_AsArray(x) (((pgColorObject *)x)->data)
|
||||||
|
#define pgColor_NumComponents(x) (((pgColorObject *)x)->len)
|
||||||
|
|
||||||
|
|
||||||
|
#define import_pygame_color() IMPORT_PYGAME_MODULE(color)
|
||||||
|
#endif /* PYGAMEAPI_COLOR_INTERNAL */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Math module
|
||||||
|
*/
|
||||||
|
#ifndef PYGAMEAPI_MATH_INTERNAL
|
||||||
|
#define pgVector2_Check(x) \
|
||||||
|
((x)->ob_type == (PyTypeObject *) \
|
||||||
|
PYGAMEAPI_GET_SLOT(math, 0))
|
||||||
|
|
||||||
|
#define pgVector3_Check(x) \
|
||||||
|
((x)->ob_type == (PyTypeObject *) \
|
||||||
|
PYGAMEAPI_GET_SLOT(math, 1))
|
||||||
|
/*
|
||||||
|
#define pgVector2_New \
|
||||||
|
(*(PyObject*(*)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(PyGAME_C_API, 1))
|
||||||
|
*/
|
||||||
|
#define import_pygame_math() IMPORT_PYGAME_MODULE(math)
|
||||||
|
#endif /* PYGAMEAPI_MATH_INTERNAL */
|
||||||
|
|
||||||
|
#define IMPORT_PYGAME_MODULE _IMPORT_PYGAME_MODULE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* base pygame API slots
|
||||||
|
* disable slots with NO_PYGAME_C_API
|
||||||
|
*/
|
||||||
|
#ifdef PYGAME_H
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(base);
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(rect);
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(cdrom);
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(joystick);
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(display);
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(surface);
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(surflock);
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(event);
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(rwobject);
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(pixelarray);
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(color);
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(math);
|
||||||
|
#else /* ~PYGAME_H */
|
||||||
|
PYGAMEAPI_EXTERN_SLOTS(base);
|
||||||
|
PYGAMEAPI_EXTERN_SLOTS(rect);
|
||||||
|
PYGAMEAPI_EXTERN_SLOTS(cdrom);
|
||||||
|
PYGAMEAPI_EXTERN_SLOTS(joystick);
|
||||||
|
PYGAMEAPI_EXTERN_SLOTS(display);
|
||||||
|
PYGAMEAPI_EXTERN_SLOTS(surface);
|
||||||
|
PYGAMEAPI_EXTERN_SLOTS(surflock);
|
||||||
|
PYGAMEAPI_EXTERN_SLOTS(event);
|
||||||
|
PYGAMEAPI_EXTERN_SLOTS(rwobject);
|
||||||
|
PYGAMEAPI_EXTERN_SLOTS(pixelarray);
|
||||||
|
PYGAMEAPI_EXTERN_SLOTS(color);
|
||||||
|
PYGAMEAPI_EXTERN_SLOTS(math);
|
||||||
|
#endif /* ~PYGAME_H */
|
||||||
|
|
||||||
|
#endif /* PYGAME_H */
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
Bitmask 1.7 - A pixel-perfect collision detection library.
|
||||||
|
|
||||||
|
Copyright (C) 2002-2005 Ulf Ekstrom except for the bitcount
|
||||||
|
function which is copyright (C) Donald W. Gillies, 1992.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
#ifndef BITMASK_H
|
||||||
|
#define BITMASK_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
/* Define INLINE for different compilers. If your compiler does not
|
||||||
|
support inlining then there might be a performance hit in
|
||||||
|
bitmask_overlap_area().
|
||||||
|
*/
|
||||||
|
#ifndef INLINE
|
||||||
|
# ifdef __GNUC__
|
||||||
|
# define INLINE inline
|
||||||
|
# else
|
||||||
|
# ifdef _MSC_VER
|
||||||
|
# define INLINE __inline
|
||||||
|
# else
|
||||||
|
# define INLINE
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define BITMASK_W unsigned long int
|
||||||
|
#define BITMASK_W_LEN (sizeof(BITMASK_W)*CHAR_BIT)
|
||||||
|
#define BITMASK_W_MASK (BITMASK_W_LEN - 1)
|
||||||
|
#define BITMASK_N(n) ((BITMASK_W)1 << (n))
|
||||||
|
|
||||||
|
typedef struct bitmask
|
||||||
|
{
|
||||||
|
int w,h;
|
||||||
|
BITMASK_W bits[1];
|
||||||
|
} bitmask_t;
|
||||||
|
|
||||||
|
/* Creates a bitmask of width w and height h, where
|
||||||
|
w and h must both be greater than or equal to 0.
|
||||||
|
The mask is automatically cleared when created.
|
||||||
|
*/
|
||||||
|
bitmask_t *bitmask_create(int w, int h);
|
||||||
|
|
||||||
|
/* Frees all the memory allocated by bitmask_create for m. */
|
||||||
|
void bitmask_free(bitmask_t *m);
|
||||||
|
|
||||||
|
/* Create a copy of the given bitmask. */
|
||||||
|
bitmask_t *bitmask_copy(bitmask_t *m);
|
||||||
|
|
||||||
|
/* Clears all bits in the mask */
|
||||||
|
void bitmask_clear(bitmask_t *m);
|
||||||
|
|
||||||
|
/* Sets all bits in the mask */
|
||||||
|
void bitmask_fill(bitmask_t *m);
|
||||||
|
|
||||||
|
/* Flips all bits in the mask */
|
||||||
|
void bitmask_invert(bitmask_t *m);
|
||||||
|
|
||||||
|
/* Counts the bits in the mask */
|
||||||
|
unsigned int bitmask_count(bitmask_t *m);
|
||||||
|
|
||||||
|
/* Returns nonzero if the bit at (x,y) is set. Coordinates start at
|
||||||
|
(0,0) */
|
||||||
|
static INLINE int bitmask_getbit(const bitmask_t *m, int x, int y)
|
||||||
|
{
|
||||||
|
return (m->bits[x/BITMASK_W_LEN*m->h + y] & BITMASK_N(x & BITMASK_W_MASK)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sets the bit at (x,y) */
|
||||||
|
static INLINE void bitmask_setbit(bitmask_t *m, int x, int y)
|
||||||
|
{
|
||||||
|
m->bits[x/BITMASK_W_LEN*m->h + y] |= BITMASK_N(x & BITMASK_W_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clears the bit at (x,y) */
|
||||||
|
static INLINE void bitmask_clearbit(bitmask_t *m, int x, int y)
|
||||||
|
{
|
||||||
|
m->bits[x/BITMASK_W_LEN*m->h + y] &= ~BITMASK_N(x & BITMASK_W_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns nonzero if the masks overlap with the given offset.
|
||||||
|
The overlap tests uses the following offsets (which may be negative):
|
||||||
|
|
||||||
|
+----+----------..
|
||||||
|
|A | yoffset
|
||||||
|
| +-+----------..
|
||||||
|
+--|B
|
||||||
|
|xoffset
|
||||||
|
| |
|
||||||
|
: :
|
||||||
|
*/
|
||||||
|
int bitmask_overlap(const bitmask_t *a, const bitmask_t *b, int xoffset, int yoffset);
|
||||||
|
|
||||||
|
/* Like bitmask_overlap(), but will also give a point of intersection.
|
||||||
|
x and y are given in the coordinates of mask a, and are untouched
|
||||||
|
if there is no overlap. */
|
||||||
|
int bitmask_overlap_pos(const bitmask_t *a, const bitmask_t *b,
|
||||||
|
int xoffset, int yoffset, int *x, int *y);
|
||||||
|
|
||||||
|
/* Returns the number of overlapping 'pixels' */
|
||||||
|
int bitmask_overlap_area(const bitmask_t *a, const bitmask_t *b, int xoffset, int yoffset);
|
||||||
|
|
||||||
|
/* Fills a mask with the overlap of two other masks. A bitwise AND. */
|
||||||
|
void bitmask_overlap_mask (const bitmask_t *a, const bitmask_t *b, bitmask_t *c, int xoffset, int yoffset);
|
||||||
|
|
||||||
|
/* Draws mask b onto mask a (bitwise OR). Can be used to compose large
|
||||||
|
(game background?) mask from several submasks, which may speed up
|
||||||
|
the testing. */
|
||||||
|
|
||||||
|
void bitmask_draw(bitmask_t *a, const bitmask_t *b, int xoffset, int yoffset);
|
||||||
|
|
||||||
|
void bitmask_erase(bitmask_t *a, const bitmask_t *b, int xoffset, int yoffset);
|
||||||
|
|
||||||
|
/* Return a new scaled bitmask, with dimensions w*h. The quality of the
|
||||||
|
scaling may not be perfect for all circumstances, but it should
|
||||||
|
be reasonable. If either w or h is 0 a clear 1x1 mask is returned. */
|
||||||
|
bitmask_t *bitmask_scale(const bitmask_t *m, int w, int h);
|
||||||
|
|
||||||
|
/* Convolve b into a, drawing the output into o, shifted by offset. If offset
|
||||||
|
* is 0, then the (x,y) bit will be set if and only if
|
||||||
|
* bitmask_overlap(a, b, x - b->w - 1, y - b->h - 1) returns true.
|
||||||
|
*
|
||||||
|
* Modifies bits o[xoffset ... xoffset + a->w + b->w - 1)
|
||||||
|
* [yoffset ... yoffset + a->h + b->h - 1). */
|
||||||
|
void bitmask_convolve(const bitmask_t *a, const bitmask_t *b, bitmask_t *o, int xoffset, int yoffset);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* End of extern "C" { */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,180 @@
|
||||||
|
/* Python 2.x/3.x and SDL compatibility tools
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(PGCOMPAT_H)
|
||||||
|
#define PGCOMPAT_H
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
|
||||||
|
/* Cobjects vanish in Python 3.2; so we will code as though we use capsules */
|
||||||
|
#if defined(Py_CAPSULE_H)
|
||||||
|
#define PG_HAVE_CAPSULE 1
|
||||||
|
#else
|
||||||
|
#define PG_HAVE_CAPSULE 0
|
||||||
|
#endif
|
||||||
|
#if defined(Py_COBJECT_H)
|
||||||
|
#define PG_HAVE_COBJECT 1
|
||||||
|
#else
|
||||||
|
#define PG_HAVE_COBJECT 0
|
||||||
|
#endif
|
||||||
|
#if !PG_HAVE_CAPSULE
|
||||||
|
#define PyCapsule_New(ptr, n, dfn) PyCObject_FromVoidPtr(ptr, dfn)
|
||||||
|
#define PyCapsule_GetPointer(obj, n) PyCObject_AsVoidPtr(obj)
|
||||||
|
#define PyCapsule_CheckExact(obj) PyCObject_Check(obj)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Pygame uses Py_buffer (PEP 3118) to exchange array information internally;
|
||||||
|
* define here as needed.
|
||||||
|
*/
|
||||||
|
#if !defined(PyBUF_SIMPLE)
|
||||||
|
typedef struct bufferinfo {
|
||||||
|
void *buf;
|
||||||
|
PyObject *obj;
|
||||||
|
Py_ssize_t len;
|
||||||
|
Py_ssize_t itemsize;
|
||||||
|
int readonly;
|
||||||
|
int ndim;
|
||||||
|
char *format;
|
||||||
|
Py_ssize_t *shape;
|
||||||
|
Py_ssize_t *strides;
|
||||||
|
Py_ssize_t *suboffsets;
|
||||||
|
void *internal;
|
||||||
|
} Py_buffer;
|
||||||
|
|
||||||
|
/* Flags for getting buffers */
|
||||||
|
#define PyBUF_SIMPLE 0
|
||||||
|
#define PyBUF_WRITABLE 0x0001
|
||||||
|
/* we used to include an E, backwards compatible alias */
|
||||||
|
#define PyBUF_WRITEABLE PyBUF_WRITABLE
|
||||||
|
#define PyBUF_FORMAT 0x0004
|
||||||
|
#define PyBUF_ND 0x0008
|
||||||
|
#define PyBUF_STRIDES (0x0010 | PyBUF_ND)
|
||||||
|
#define PyBUF_C_CONTIGUOUS (0x0020 | PyBUF_STRIDES)
|
||||||
|
#define PyBUF_F_CONTIGUOUS (0x0040 | PyBUF_STRIDES)
|
||||||
|
#define PyBUF_ANY_CONTIGUOUS (0x0080 | PyBUF_STRIDES)
|
||||||
|
#define PyBUF_INDIRECT (0x0100 | PyBUF_STRIDES)
|
||||||
|
|
||||||
|
#define PyBUF_CONTIG (PyBUF_ND | PyBUF_WRITABLE)
|
||||||
|
#define PyBUF_CONTIG_RO (PyBUF_ND)
|
||||||
|
|
||||||
|
#define PyBUF_STRIDED (PyBUF_STRIDES | PyBUF_WRITABLE)
|
||||||
|
#define PyBUF_STRIDED_RO (PyBUF_STRIDES)
|
||||||
|
|
||||||
|
#define PyBUF_RECORDS (PyBUF_STRIDES | PyBUF_WRITABLE | PyBUF_FORMAT)
|
||||||
|
#define PyBUF_RECORDS_RO (PyBUF_STRIDES | PyBUF_FORMAT)
|
||||||
|
|
||||||
|
#define PyBUF_FULL (PyBUF_INDIRECT | PyBUF_WRITABLE | PyBUF_FORMAT)
|
||||||
|
#define PyBUF_FULL_RO (PyBUF_INDIRECT | PyBUF_FORMAT)
|
||||||
|
|
||||||
|
#define PyBUF_READ 0x100
|
||||||
|
#define PyBUF_WRITE 0x200
|
||||||
|
#define PyBUF_SHADOW 0x400
|
||||||
|
|
||||||
|
typedef int(*getbufferproc)(PyObject *, Py_buffer *, int);
|
||||||
|
typedef void(*releasebufferproc)(Py_buffer *);
|
||||||
|
#endif /* ~defined(PyBUF_SIMPLE) */
|
||||||
|
|
||||||
|
/* define common types where SDL is not included */
|
||||||
|
#ifndef SDL_VERSION_ATLEAST
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
typedef unsigned __int8 uint8_t;
|
||||||
|
typedef unsigned __int32 uint32_t;
|
||||||
|
#else
|
||||||
|
#include <stdint.h>
|
||||||
|
#endif
|
||||||
|
typedef uint32_t Uint32;
|
||||||
|
typedef uint8_t Uint8;
|
||||||
|
#endif /* no SDL */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(SDL_VERSION_ATLEAST)
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_VULKAN
|
||||||
|
#define SDL_WINDOW_VULKAN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_ALWAYS_ON_TOP
|
||||||
|
#define SDL_WINDOW_ALWAYS_ON_TOP 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_SKIP_TASKBAR
|
||||||
|
#define SDL_WINDOW_SKIP_TASKBAR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_UTILITY
|
||||||
|
#define SDL_WINDOW_UTILITY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_TOOLTIP
|
||||||
|
#define SDL_WINDOW_TOOLTIP 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_POPUP_MENU
|
||||||
|
#define SDL_WINDOW_POPUP_MENU 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_INPUT_GRABBED
|
||||||
|
#define SDL_WINDOW_INPUT_GRABBED 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_INPUT_FOCUS
|
||||||
|
#define SDL_WINDOW_INPUT_FOCUS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_MOUSE_FOCUS
|
||||||
|
#define SDL_WINDOW_MOUSE_FOCUS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_FOREIGN
|
||||||
|
#define SDL_WINDOW_FOREIGN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_ALLOW_HIGHDPI
|
||||||
|
#define SDL_WINDOW_ALLOW_HIGHDPI 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_MOUSE_CAPTURE
|
||||||
|
#define SDL_WINDOW_MOUSE_CAPTURE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_ALWAYS_ON_TOP
|
||||||
|
#define SDL_WINDOW_ALWAYS_ON_TOP 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_SKIP_TASKBAR
|
||||||
|
#define SDL_WINDOW_SKIP_TASKBAR 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_UTILITY
|
||||||
|
#define SDL_WINDOW_UTILITY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_TOOLTIP
|
||||||
|
#define SDL_WINDOW_TOOLTIP 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_WINDOW_POPUP_MENU
|
||||||
|
#define SDL_WINDOW_POPUP_MENU 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 4)
|
||||||
|
/* To control the use of:
|
||||||
|
* SDL_AUDIODEVICEADDED
|
||||||
|
* SDL_AUDIODEVICEREMOVED
|
||||||
|
*
|
||||||
|
* Ref: https://wiki.libsdl.org/SDL_EventType
|
||||||
|
* Ref: https://wiki.libsdl.org/SDL_AudioDeviceEvent
|
||||||
|
*/
|
||||||
|
#define SDL2_AUDIODEVICE_SUPPORTED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SDL_MOUSEWHEEL_FLIPPED
|
||||||
|
#define NO_SDL_MOUSEWHEEL_FLIPPED
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* defined(SDL_VERSION_ATLEAST) */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ~defined(PGCOMPAT_H) */
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
#ifndef PGIMPORT_H
|
||||||
|
#define PGIMPORT_H
|
||||||
|
|
||||||
|
/* Prefix when initializing module */
|
||||||
|
#define MODPREFIX ""
|
||||||
|
/* Prefix when importing module */
|
||||||
|
#define IMPPREFIX "pygame."
|
||||||
|
|
||||||
|
#ifdef __SYMBIAN32__
|
||||||
|
|
||||||
|
/* On Symbian there is no pygame package. The extensions are built-in or in
|
||||||
|
* sys\bin. */
|
||||||
|
#undef MODPREFIX
|
||||||
|
#undef IMPPREFIX
|
||||||
|
#define MODPREFIX "pygame_"
|
||||||
|
#define IMPPREFIX "pygame_"
|
||||||
|
|
||||||
|
#endif /* __SYMBIAN32__ */
|
||||||
|
|
||||||
|
#include "pgcompat.h"
|
||||||
|
|
||||||
|
#define PYGAMEAPI_LOCAL_ENTRY "_PYGAME_C_API"
|
||||||
|
#define PG_CAPSULE_NAME(m) (IMPPREFIX m "." PYGAMEAPI_LOCAL_ENTRY)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fill API slots defined by PYGAMEAPI_DEFINE_SLOTS/PYGAMEAPI_EXTERN_SLOTS
|
||||||
|
*/
|
||||||
|
#define _IMPORT_PYGAME_MODULE(module) \
|
||||||
|
{ \
|
||||||
|
PyObject *_module = PyImport_ImportModule(IMPPREFIX #module); \
|
||||||
|
\
|
||||||
|
if (_module != NULL) { \
|
||||||
|
PyObject *_c_api = \
|
||||||
|
PyObject_GetAttrString(_module, PYGAMEAPI_LOCAL_ENTRY); \
|
||||||
|
\
|
||||||
|
Py_DECREF(_module); \
|
||||||
|
if (_c_api != NULL && PyCapsule_CheckExact(_c_api)) { \
|
||||||
|
void **localptr = (void **)PyCapsule_GetPointer( \
|
||||||
|
_c_api, PG_CAPSULE_NAME(#module)); \
|
||||||
|
_PGSLOTS_ ## module = localptr; \
|
||||||
|
} \
|
||||||
|
Py_XDECREF(_c_api); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PYGAMEAPI_IS_IMPORTED(module) (_PGSLOTS_ ## module != NULL)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* source file must include one of these in order to use _IMPORT_PYGAME_MODULE.
|
||||||
|
* this is set by import_pygame_*() functions.
|
||||||
|
* disable with NO_PYGAME_C_API
|
||||||
|
*/
|
||||||
|
#define PYGAMEAPI_DEFINE_SLOTS(module) \
|
||||||
|
void ** _PGSLOTS_ ## module = NULL
|
||||||
|
#define PYGAMEAPI_EXTERN_SLOTS(module) \
|
||||||
|
extern void **_PGSLOTS_ ## module
|
||||||
|
#define PYGAMEAPI_GET_SLOT(module, index) \
|
||||||
|
_PGSLOTS_ ## module [(index)]
|
||||||
|
|
||||||
|
/*
|
||||||
|
* disabled API with NO_PYGAME_C_API; do nothing instead
|
||||||
|
*/
|
||||||
|
#ifdef NO_PYGAME_C_API
|
||||||
|
|
||||||
|
#undef PYGAMEAPI_DEFINE_SLOTS
|
||||||
|
#undef PYGAMEAPI_EXTERN_SLOTS
|
||||||
|
|
||||||
|
#define PYGAMEAPI_DEFINE_SLOTS(module)
|
||||||
|
#define PYGAMEAPI_EXTERN_SLOTS(module)
|
||||||
|
|
||||||
|
/* intentionally leave this defined to cause a compiler error *
|
||||||
|
#define PYGAMEAPI_GET_SLOT(api_root, index)
|
||||||
|
#undef PYGAMEAPI_GET_SLOT*/
|
||||||
|
|
||||||
|
#undef _IMPORT_PYGAME_MODULE
|
||||||
|
#define _IMPORT_PYGAME_MODULE(module)
|
||||||
|
|
||||||
|
#endif /* NO_PYGAME_C_API */
|
||||||
|
|
||||||
|
#endif /* ~PGIMPORT_H */
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/* platform/compiler adjustments */
|
||||||
|
#ifndef PG_PLATFORM_H
|
||||||
|
#define PG_PLATFORM_H
|
||||||
|
|
||||||
|
#if defined(HAVE_SNPRINTF) /* defined in python.h (pyerrors.h) and SDL.h \
|
||||||
|
(SDL_config.h) */
|
||||||
|
#undef HAVE_SNPRINTF /* remove GCC redefine warning */
|
||||||
|
#endif /* HAVE_SNPRINTF */
|
||||||
|
|
||||||
|
#ifndef PG_INLINE
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define PG_INLINE __inline__ __attribute__((__unused__))
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define PG_INLINE __inline__
|
||||||
|
#elif defined(_MSC_VER)
|
||||||
|
#define PG_INLINE __inline
|
||||||
|
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||||
|
#define PG_INLINE inline
|
||||||
|
#else
|
||||||
|
#define PG_INLINE
|
||||||
|
#endif
|
||||||
|
#endif /* ~PG_INLINE */
|
||||||
|
|
||||||
|
/* This is unconditionally defined in Python.h */
|
||||||
|
#if defined(_POSIX_C_SOURCE)
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* No signal() */
|
||||||
|
#if defined(__SYMBIAN32__) && defined(HAVE_SIGNAL_H)
|
||||||
|
#undef HAVE_SIGNAL_H
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(HAVE_SNPRINTF)
|
||||||
|
#undef HAVE_SNPRINTF
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* SDL needs WIN32 */
|
||||||
|
#if !defined(WIN32) && \
|
||||||
|
(defined(MS_WIN32) || defined(_WIN32) || \
|
||||||
|
defined(__WIN32) || defined(__WIN32__) || defined(_WINDOWS))
|
||||||
|
#define WIN32
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ~PG_PLATFORM_H */
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
Copyright (C) 2000-2001 Pete Shinners
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Pete Shinners
|
||||||
|
pete@shinners.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* To allow the Pygame C api to be globally shared by all code within an
|
||||||
|
* extension module built from multiple C files, only include the pygame.h
|
||||||
|
* header within the top level C file, the one which calls the
|
||||||
|
* 'import_pygame_*' macros. All other C source files of the module should
|
||||||
|
* include _pygame.h instead.
|
||||||
|
*/
|
||||||
|
#ifndef PYGAME_H
|
||||||
|
#define PYGAME_H
|
||||||
|
|
||||||
|
#include "_pygame.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
Copyright (C) 2000-2001 Pete Shinners
|
||||||
|
Copyright (C) 2007 Rene Dudfield, Richard Goedeken
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Pete Shinners
|
||||||
|
pete@shinners.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Bufferproxy module C api. */
|
||||||
|
#if !defined(PG_BUFPROXY_HEADER)
|
||||||
|
#define PG_BUFPROXY_HEADER
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
|
||||||
|
typedef PyObject *(*_pgbufproxy_new_t)(PyObject *, getbufferproc);
|
||||||
|
typedef PyObject *(*_pgbufproxy_get_obj_t)(PyObject *);
|
||||||
|
typedef int (*_pgbufproxy_trip_t)(PyObject *);
|
||||||
|
|
||||||
|
#ifndef PYGAMEAPI_BUFPROXY_INTERNAL
|
||||||
|
|
||||||
|
#include "pgimport.h"
|
||||||
|
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(bufferproxy);
|
||||||
|
|
||||||
|
#define pgBufproxy_Type (*(PyTypeObject*) \
|
||||||
|
PYGAMEAPI_GET_SLOT(bufferproxy, 0) )
|
||||||
|
|
||||||
|
#define pgBufproxy_Check(x) ((x)->ob_type == &pgBufproxy_Type)
|
||||||
|
|
||||||
|
#define pgBufproxy_New (*(_pgbufproxy_new_t) \
|
||||||
|
PYGAMEAPI_GET_SLOT(bufferproxy, 1))
|
||||||
|
|
||||||
|
#define pgBufproxy_GetParent \
|
||||||
|
(*(_pgbufproxy_get_obj_t) \
|
||||||
|
PYGAMEAPI_GET_SLOT(bufferproxy, 2))
|
||||||
|
|
||||||
|
#define pgBufproxy_Trip (*(_pgbufproxy_trip_t) \
|
||||||
|
PYGAMEAPI_GET_SLOT(bufferproxy, 3))
|
||||||
|
|
||||||
|
#define import_pygame_bufferproxy() _IMPORT_PYGAME_MODULE(bufferproxy)
|
||||||
|
|
||||||
|
#endif /* ~PYGAMEAPI_BUFPROXY_INTERNAL */
|
||||||
|
|
||||||
|
#endif /* ~defined(PG_BUFPROXY_HEADER) */
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
Copyright (C) 2000-2001 Pete Shinners
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Pete Shinners
|
||||||
|
pete@shinners.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
#include "pgplatform.h"
|
||||||
|
|
||||||
|
struct TTF_Font;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
TTF_Font* font;
|
||||||
|
PyObject* weakreflist;
|
||||||
|
} PyFontObject;
|
||||||
|
#define PyFont_AsFont(x) (((PyFontObject*)x)->font)
|
||||||
|
|
||||||
|
#ifndef PYGAMEAPI_FONT_INTERNAL
|
||||||
|
|
||||||
|
#include "pgimport.h"
|
||||||
|
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(font);
|
||||||
|
|
||||||
|
#define PyFont_Type (*(PyTypeObject*) \
|
||||||
|
PYGAMEAPI_GET_SLOT(font, 0))
|
||||||
|
#define PyFont_Check(x) ((x)->ob_type == &PyFont_Type)
|
||||||
|
|
||||||
|
#define PyFont_New (*(PyObject*(*)(TTF_Font*))\
|
||||||
|
PYGAMEAPI_GET_SLOT(font, 1))
|
||||||
|
|
||||||
|
/*slot 2 taken by FONT_INIT_CHECK*/
|
||||||
|
|
||||||
|
#define import_pygame_font() _IMPORT_PYGAME_MODULE(font)
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
Copyright (C) 2009 Vicent Marti
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
#ifndef PYGAME_FREETYPE_H_
|
||||||
|
#define PYGAME_FREETYPE_H_
|
||||||
|
|
||||||
|
#include "pgplatform.h"
|
||||||
|
#include "pgimport.h"
|
||||||
|
#include "pgcompat.h"
|
||||||
|
|
||||||
|
#ifndef PYGAME_FREETYPE_INTERNAL
|
||||||
|
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(_freetype);
|
||||||
|
|
||||||
|
#define pgFont_Type (*(PyTypeObject*) \
|
||||||
|
PYGAMEAPI_GET_SLOT(_freetype, 0))
|
||||||
|
|
||||||
|
#define pgFont_Check(x) ((x)->ob_type == &pgFont_Type)
|
||||||
|
|
||||||
|
#define pgFont_New (*(PyObject*(*)(const char*, long)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(_freetype, 1))
|
||||||
|
|
||||||
|
#define import_pygame_freetype() _IMPORT_PYGAME_MODULE(_freetype)
|
||||||
|
|
||||||
|
#endif /* PYGAME_FREETYPE_INTERNAL */
|
||||||
|
|
||||||
|
#endif /* PYGAME_FREETYPE_H_ */
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PGMASK_H
|
||||||
|
#define PGMASK_H
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
#include "bitmask.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
bitmask_t *mask;
|
||||||
|
void *bufdata;
|
||||||
|
} pgMaskObject;
|
||||||
|
|
||||||
|
#define pgMask_AsBitmap(x) (((pgMaskObject*)x)->mask)
|
||||||
|
|
||||||
|
#ifndef PYGAMEAPI_MASK_INTERNAL
|
||||||
|
|
||||||
|
#include "pgimport.h"
|
||||||
|
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(mask);
|
||||||
|
|
||||||
|
#define pgMask_Type (*(PyTypeObject*) \
|
||||||
|
PYGAMEAPI_GET_SLOT(mask, 0))
|
||||||
|
#define pgMask_Check(x) ((x)->ob_type == &pgMask_Type)
|
||||||
|
|
||||||
|
#define import_pygame_mask() _IMPORT_PYGAME_MODULE(mask)
|
||||||
|
|
||||||
|
#endif /* ~PYGAMEAPI_MASK_INTERNAL */
|
||||||
|
|
||||||
|
#endif /* ~PGMASK_H */
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
Copyright (C) 2000-2001 Pete Shinners
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Pete Shinners
|
||||||
|
pete@shinners.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PGMIXER_H
|
||||||
|
#define PGMIXER_H
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
#include <structmember.h>
|
||||||
|
|
||||||
|
#include "pgcompat.h"
|
||||||
|
|
||||||
|
struct Mix_Chunk;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
Mix_Chunk *chunk;
|
||||||
|
Uint8 *mem;
|
||||||
|
PyObject *weakreflist;
|
||||||
|
} pgSoundObject;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject_HEAD
|
||||||
|
int chan;
|
||||||
|
} pgChannelObject;
|
||||||
|
|
||||||
|
#define pgSound_AsChunk(x) (((pgSoundObject*)x)->chunk)
|
||||||
|
#define pgChannel_AsInt(x) (((pgChannelObject*)x)->chan)
|
||||||
|
|
||||||
|
#include "pgimport.h"
|
||||||
|
|
||||||
|
#ifndef PYGAMEAPI_MIXER_INTERNAL
|
||||||
|
|
||||||
|
PYGAMEAPI_DEFINE_SLOTS(mixer);
|
||||||
|
|
||||||
|
#define pgSound_Type (*(PyTypeObject*) \
|
||||||
|
PYGAMEAPI_GET_SLOT(mixer, 0))
|
||||||
|
|
||||||
|
#define pgSound_Check(x) ((x)->ob_type == &pgSound_Type)
|
||||||
|
|
||||||
|
#define pgSound_New (*(PyObject*(*)(Mix_Chunk*)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(mixer, 1))
|
||||||
|
|
||||||
|
#define pgSound_Play (*(PyObject*(*)(PyObject*, PyObject*)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(mixer, 2))
|
||||||
|
|
||||||
|
#define pgChannel_Type (*(PyTypeObject*) \
|
||||||
|
PYGAMEAPI_GET_SLOT(mixer, 3))
|
||||||
|
#define pgChannel_Check(x) ((x)->ob_type == &pgChannel_Type)
|
||||||
|
|
||||||
|
#define pgChannel_New (*(PyObject*(*)(int)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(mixer, 4))
|
||||||
|
|
||||||
|
#define pgMixer_AutoInit (*(PyObject*(*)(PyObject*, PyObject*)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(mixer, 5))
|
||||||
|
|
||||||
|
#define pgMixer_AutoQuit (*(void(*)(void)) \
|
||||||
|
PYGAMEAPI_GET_SLOT(mixer, 6))
|
||||||
|
|
||||||
|
#define import_pygame_mixer() _IMPORT_PYGAME_MODULE(mixer)
|
||||||
|
|
||||||
|
#endif /* PYGAMEAPI_MIXER_INTERNAL */
|
||||||
|
|
||||||
|
#endif /* ~PGMIXER_H */
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef PGMASK_INTERNAL_H
|
||||||
|
#define PGMASK_INTERNAL_H
|
||||||
|
|
||||||
|
#include "include/pygame_mask.h"
|
||||||
|
#define PYGAMEAPI_MASK_NUMSLOTS 1
|
||||||
|
|
||||||
|
#endif /* ~PGMASK_INTERNAL_H */
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef MIXER_INTERNAL_H
|
||||||
|
#define MIXER_INTERNAL_H
|
||||||
|
|
||||||
|
#include <SDL_mixer.h>
|
||||||
|
|
||||||
|
/* test mixer initializations */
|
||||||
|
#define MIXER_INIT_CHECK() \
|
||||||
|
if(!SDL_WasInit(SDL_INIT_AUDIO)) \
|
||||||
|
return RAISE(pgExc_SDLError, "mixer not initialized")
|
||||||
|
|
||||||
|
#define PYGAMEAPI_MIXER_NUMSLOTS 7
|
||||||
|
#include "include/pygame_mixer.h"
|
||||||
|
|
||||||
|
#endif /* ~MIXER_INTERNAL_H */
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
Copyright (C) 2000-2001 Pete Shinners
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Pete Shinners
|
||||||
|
pete@shinners.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PALETTE_H
|
||||||
|
#define PALETTE_H
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
|
/* SDL 2 does not assign a default palette color scheme to a new 8 bit
|
||||||
|
* surface. Instead, the palette is set all white. This defines the SDL 1.2
|
||||||
|
* default palette.
|
||||||
|
*/
|
||||||
|
static const SDL_Color default_palette_colors[] = {
|
||||||
|
{0, 0, 0, 255}, {0, 0, 85, 255}, {0, 0, 170, 255},
|
||||||
|
{0, 0, 255, 255}, {0, 36, 0, 255}, {0, 36, 85, 255},
|
||||||
|
{0, 36, 170, 255}, {0, 36, 255, 255}, {0, 73, 0, 255},
|
||||||
|
{0, 73, 85, 255}, {0, 73, 170, 255}, {0, 73, 255, 255},
|
||||||
|
{0, 109, 0, 255}, {0, 109, 85, 255}, {0, 109, 170, 255},
|
||||||
|
{0, 109, 255, 255}, {0, 146, 0, 255}, {0, 146, 85, 255},
|
||||||
|
{0, 146, 170, 255}, {0, 146, 255, 255}, {0, 182, 0, 255},
|
||||||
|
{0, 182, 85, 255}, {0, 182, 170, 255}, {0, 182, 255, 255},
|
||||||
|
{0, 219, 0, 255}, {0, 219, 85, 255}, {0, 219, 170, 255},
|
||||||
|
{0, 219, 255, 255}, {0, 255, 0, 255}, {0, 255, 85, 255},
|
||||||
|
{0, 255, 170, 255}, {0, 255, 255, 255}, {85, 0, 0, 255},
|
||||||
|
{85, 0, 85, 255}, {85, 0, 170, 255}, {85, 0, 255, 255},
|
||||||
|
{85, 36, 0, 255}, {85, 36, 85, 255}, {85, 36, 170, 255},
|
||||||
|
{85, 36, 255, 255}, {85, 73, 0, 255}, {85, 73, 85, 255},
|
||||||
|
{85, 73, 170, 255}, {85, 73, 255, 255}, {85, 109, 0, 255},
|
||||||
|
{85, 109, 85, 255}, {85, 109, 170, 255}, {85, 109, 255, 255},
|
||||||
|
{85, 146, 0, 255}, {85, 146, 85, 255}, {85, 146, 170, 255},
|
||||||
|
{85, 146, 255, 255}, {85, 182, 0, 255}, {85, 182, 85, 255},
|
||||||
|
{85, 182, 170, 255}, {85, 182, 255, 255}, {85, 219, 0, 255},
|
||||||
|
{85, 219, 85, 255}, {85, 219, 170, 255}, {85, 219, 255, 255},
|
||||||
|
{85, 255, 0, 255}, {85, 255, 85, 255}, {85, 255, 170, 255},
|
||||||
|
{85, 255, 255, 255}, {170, 0, 0, 255}, {170, 0, 85, 255},
|
||||||
|
{170, 0, 170, 255}, {170, 0, 255, 255}, {170, 36, 0, 255},
|
||||||
|
{170, 36, 85, 255}, {170, 36, 170, 255}, {170, 36, 255, 255},
|
||||||
|
{170, 73, 0, 255}, {170, 73, 85, 255}, {170, 73, 170, 255},
|
||||||
|
{170, 73, 255, 255}, {170, 109, 0, 255}, {170, 109, 85, 255},
|
||||||
|
{170, 109, 170, 255}, {170, 109, 255, 255}, {170, 146, 0, 255},
|
||||||
|
{170, 146, 85, 255}, {170, 146, 170, 255}, {170, 146, 255, 255},
|
||||||
|
{170, 182, 0, 255}, {170, 182, 85, 255}, {170, 182, 170, 255},
|
||||||
|
{170, 182, 255, 255}, {170, 219, 0, 255}, {170, 219, 85, 255},
|
||||||
|
{170, 219, 170, 255}, {170, 219, 255, 255}, {170, 255, 0, 255},
|
||||||
|
{170, 255, 85, 255}, {170, 255, 170, 255}, {170, 255, 255, 255},
|
||||||
|
{255, 0, 0, 255}, {255, 0, 85, 255}, {255, 0, 170, 255},
|
||||||
|
{255, 0, 255, 255}, {255, 36, 0, 255}, {255, 36, 85, 255},
|
||||||
|
{255, 36, 170, 255}, {255, 36, 255, 255}, {255, 73, 0, 255},
|
||||||
|
{255, 73, 85, 255}, {255, 73, 170, 255}, {255, 73, 255, 255},
|
||||||
|
{255, 109, 0, 255}, {255, 109, 85, 255}, {255, 109, 170, 255},
|
||||||
|
{255, 109, 255, 255}, {255, 146, 0, 255}, {255, 146, 85, 255},
|
||||||
|
{255, 146, 170, 255}, {255, 146, 255, 255}, {255, 182, 0, 255},
|
||||||
|
{255, 182, 85, 255}, {255, 182, 170, 255}, {255, 182, 255, 255},
|
||||||
|
{255, 219, 0, 255}, {255, 219, 85, 255}, {255, 219, 170, 255},
|
||||||
|
{255, 219, 255, 255}, {255, 255, 0, 255}, {255, 255, 85, 255},
|
||||||
|
{255, 255, 170, 255}, {255, 255, 255, 255}, {0, 0, 0, 255},
|
||||||
|
{0, 0, 85, 255}, {0, 0, 170, 255}, {0, 0, 255, 255},
|
||||||
|
{0, 36, 0, 255}, {0, 36, 85, 255}, {0, 36, 170, 255},
|
||||||
|
{0, 36, 255, 255}, {0, 73, 0, 255}, {0, 73, 85, 255},
|
||||||
|
{0, 73, 170, 255}, {0, 73, 255, 255}, {0, 109, 0, 255},
|
||||||
|
{0, 109, 85, 255}, {0, 109, 170, 255}, {0, 109, 255, 255},
|
||||||
|
{0, 146, 0, 255}, {0, 146, 85, 255}, {0, 146, 170, 255},
|
||||||
|
{0, 146, 255, 255}, {0, 182, 0, 255}, {0, 182, 85, 255},
|
||||||
|
{0, 182, 170, 255}, {0, 182, 255, 255}, {0, 219, 0, 255},
|
||||||
|
{0, 219, 85, 255}, {0, 219, 170, 255}, {0, 219, 255, 255},
|
||||||
|
{0, 255, 0, 255}, {0, 255, 85, 255}, {0, 255, 170, 255},
|
||||||
|
{0, 255, 255, 255}, {85, 0, 0, 255}, {85, 0, 85, 255},
|
||||||
|
{85, 0, 170, 255}, {85, 0, 255, 255}, {85, 36, 0, 255},
|
||||||
|
{85, 36, 85, 255}, {85, 36, 170, 255}, {85, 36, 255, 255},
|
||||||
|
{85, 73, 0, 255}, {85, 73, 85, 255}, {85, 73, 170, 255},
|
||||||
|
{85, 73, 255, 255}, {85, 109, 0, 255}, {85, 109, 85, 255},
|
||||||
|
{85, 109, 170, 255}, {85, 109, 255, 255}, {85, 146, 0, 255},
|
||||||
|
{85, 146, 85, 255}, {85, 146, 170, 255}, {85, 146, 255, 255},
|
||||||
|
{85, 182, 0, 255}, {85, 182, 85, 255}, {85, 182, 170, 255},
|
||||||
|
{85, 182, 255, 255}, {85, 219, 0, 255}, {85, 219, 85, 255},
|
||||||
|
{85, 219, 170, 255}, {85, 219, 255, 255}, {85, 255, 0, 255},
|
||||||
|
{85, 255, 85, 255}, {85, 255, 170, 255}, {85, 255, 255, 255},
|
||||||
|
{170, 0, 0, 255}, {170, 0, 85, 255}, {170, 0, 170, 255},
|
||||||
|
{170, 0, 255, 255}, {170, 36, 0, 255}, {170, 36, 85, 255},
|
||||||
|
{170, 36, 170, 255}, {170, 36, 255, 255}, {170, 73, 0, 255},
|
||||||
|
{170, 73, 85, 255}, {170, 73, 170, 255}, {170, 73, 255, 255},
|
||||||
|
{170, 109, 0, 255}, {170, 109, 85, 255}, {170, 109, 170, 255},
|
||||||
|
{170, 109, 255, 255}, {170, 146, 0, 255}, {170, 146, 85, 255},
|
||||||
|
{170, 146, 170, 255}, {170, 146, 255, 255}, {170, 182, 0, 255},
|
||||||
|
{170, 182, 85, 255}, {170, 182, 170, 255}, {170, 182, 255, 255},
|
||||||
|
{170, 219, 0, 255}, {170, 219, 85, 255}, {170, 219, 170, 255},
|
||||||
|
{170, 219, 255, 255}, {170, 255, 0, 255}, {170, 255, 85, 255},
|
||||||
|
{170, 255, 170, 255}, {170, 255, 255, 255}, {255, 0, 0, 255},
|
||||||
|
{255, 0, 85, 255}, {255, 0, 170, 255}, {255, 0, 255, 255},
|
||||||
|
{255, 36, 0, 255}, {255, 36, 85, 255}, {255, 36, 170, 255},
|
||||||
|
{255, 36, 255, 255}, {255, 73, 0, 255}, {255, 73, 85, 255},
|
||||||
|
{255, 73, 170, 255}, {255, 73, 255, 255}, {255, 109, 0, 255},
|
||||||
|
{255, 109, 85, 255}, {255, 109, 170, 255}, {255, 109, 255, 255},
|
||||||
|
{255, 146, 0, 255}, {255, 146, 85, 255}, {255, 146, 170, 255},
|
||||||
|
{255, 146, 255, 255}, {255, 182, 0, 255}, {255, 182, 85, 255},
|
||||||
|
{255, 182, 170, 255}, {255, 182, 255, 255}, {255, 219, 0, 255},
|
||||||
|
{255, 219, 85, 255}, {255, 219, 170, 255}, {255, 219, 255, 255},
|
||||||
|
{255, 255, 0, 255}, {255, 255, 85, 255}, {255, 255, 170, 255},
|
||||||
|
{255, 255, 255, 255}};
|
||||||
|
|
||||||
|
static const int default_palette_size =
|
||||||
|
(int)(sizeof(default_palette_colors) / sizeof(SDL_Color));
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* array structure interface version 3 declarations */
|
||||||
|
|
||||||
|
#if !defined(PG_ARRAYINTER_HEADER)
|
||||||
|
#define PG_ARRAYINTER_HEADER
|
||||||
|
|
||||||
|
static const int PAI_CONTIGUOUS = 0x01;
|
||||||
|
static const int PAI_FORTRAN = 0x02;
|
||||||
|
static const int PAI_ALIGNED = 0x100;
|
||||||
|
static const int PAI_NOTSWAPPED = 0x200;
|
||||||
|
static const int PAI_WRITEABLE = 0x400;
|
||||||
|
static const int PAI_ARR_HAS_DESCR = 0x800;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int two; /* contains the integer 2 -- simple sanity check */
|
||||||
|
int nd; /* number of dimensions */
|
||||||
|
char typekind; /* kind in array -- character code of typestr */
|
||||||
|
int itemsize; /* size of each element */
|
||||||
|
int flags; /* flags indicating how the data should be */
|
||||||
|
/* interpreted */
|
||||||
|
Py_intptr_t *shape; /* A length-nd array of shape information */
|
||||||
|
Py_intptr_t *strides; /* A length-nd array of stride information */
|
||||||
|
void *data; /* A pointer to the first element of the array */
|
||||||
|
PyObject *descr; /* NULL or a data-description */
|
||||||
|
} PyArrayInterface;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
#ifndef PG_BUFPROXY_INTERNAL_H
|
||||||
|
#define PG_BUFPROXY_INTERNAL_H
|
||||||
|
|
||||||
|
#include "include/pygame_bufferproxy.h"
|
||||||
|
#define PYGAMEAPI_BUFPROXY_NUMSLOTS 4
|
||||||
|
|
||||||
|
#endif /* ~PG_BUFPROXY_INTERNAL_H */
|
||||||
|
|
@ -0,0 +1,214 @@
|
||||||
|
/* Python 2.x/3.x compatibility tools (internal)
|
||||||
|
*/
|
||||||
|
#ifndef PGCOMPAT_INTERNAL_H
|
||||||
|
#define PGCOMPAT_INTERNAL_H
|
||||||
|
|
||||||
|
#include "include/pgcompat.h"
|
||||||
|
|
||||||
|
#if PY_MAJOR_VERSION >= 3
|
||||||
|
|
||||||
|
#define PY3 1
|
||||||
|
|
||||||
|
/* Define some aliases for the removed PyInt_* functions */
|
||||||
|
#define PyInt_Check(op) PyLong_Check(op)
|
||||||
|
#define PyInt_FromString PyLong_FromString
|
||||||
|
#define PyInt_FromUnicode PyLong_FromUnicode
|
||||||
|
#define PyInt_FromLong PyLong_FromLong
|
||||||
|
#define PyInt_FromSize_t PyLong_FromSize_t
|
||||||
|
#define PyInt_FromSsize_t PyLong_FromSsize_t
|
||||||
|
#define PyInt_AsLong PyLong_AsLong
|
||||||
|
#define PyInt_AsSsize_t PyLong_AsSsize_t
|
||||||
|
#define PyInt_AsUnsignedLongMask PyLong_AsUnsignedLongMask
|
||||||
|
#define PyInt_AsUnsignedLongLongMask PyLong_AsUnsignedLongLongMask
|
||||||
|
#define PyInt_AS_LONG PyLong_AS_LONG
|
||||||
|
#define PyNumber_Int PyNumber_Long
|
||||||
|
|
||||||
|
/* Weakrefs flags changed in 3.x */
|
||||||
|
#define Py_TPFLAGS_HAVE_WEAKREFS 0
|
||||||
|
|
||||||
|
/* Module init function returns new module instance. */
|
||||||
|
#define MODINIT_RETURN(x) return x
|
||||||
|
#define MODINIT_DEFINE(mod_name) PyMODINIT_FUNC PyInit_##mod_name (void)
|
||||||
|
#define DECREF_MOD(mod) Py_DECREF (mod)
|
||||||
|
|
||||||
|
/* Type header differs. */
|
||||||
|
#define TYPE_HEAD(x,y) PyVarObject_HEAD_INIT(x,y)
|
||||||
|
|
||||||
|
/* Text interface. Use unicode strings. */
|
||||||
|
#define Text_Type PyUnicode_Type
|
||||||
|
#define Text_Check PyUnicode_Check
|
||||||
|
|
||||||
|
#ifndef PYPY_VERSION
|
||||||
|
#define Text_FromLocale(s) PyUnicode_DecodeLocale((s), "strict")
|
||||||
|
#else /* PYPY_VERSION */
|
||||||
|
/* workaround: missing function for pypy */
|
||||||
|
#define Text_FromLocale PyUnicode_FromString
|
||||||
|
#endif /* PYPY_VERSION */
|
||||||
|
|
||||||
|
#define Text_FromUTF8 PyUnicode_FromString
|
||||||
|
#define Text_FromUTF8AndSize PyUnicode_FromStringAndSize
|
||||||
|
#define Text_FromFormat PyUnicode_FromFormat
|
||||||
|
#define Text_GetSize PyUnicode_GetSize
|
||||||
|
#define Text_GET_SIZE PyUnicode_GET_SIZE
|
||||||
|
|
||||||
|
/* Binary interface. Use bytes. */
|
||||||
|
#define Bytes_Type PyBytes_Type
|
||||||
|
#define Bytes_Check PyBytes_Check
|
||||||
|
#define Bytes_Size PyBytes_Size
|
||||||
|
#define Bytes_AsString PyBytes_AsString
|
||||||
|
#define Bytes_AsStringAndSize PyBytes_AsStringAndSize
|
||||||
|
#define Bytes_FromStringAndSize PyBytes_FromStringAndSize
|
||||||
|
#define Bytes_FromFormat PyBytes_FromFormat
|
||||||
|
#define Bytes_AS_STRING PyBytes_AS_STRING
|
||||||
|
#define Bytes_GET_SIZE PyBytes_GET_SIZE
|
||||||
|
#define Bytes_AsDecodeObject PyBytes_AsDecodedObject
|
||||||
|
|
||||||
|
#define Object_Unicode PyObject_Str
|
||||||
|
|
||||||
|
#define IsTextObj(x) (PyUnicode_Check(x) || PyBytes_Check(x))
|
||||||
|
|
||||||
|
/* Renamed builtins */
|
||||||
|
#define BUILTINS_MODULE "builtins"
|
||||||
|
#define BUILTINS_UNICODE "str"
|
||||||
|
#define BUILTINS_UNICHR "chr"
|
||||||
|
|
||||||
|
/* Defaults for unicode file path encoding */
|
||||||
|
#define UNICODE_DEF_FS_CODEC Py_FileSystemDefaultEncoding
|
||||||
|
#if defined(MS_WIN32)
|
||||||
|
#define UNICODE_DEF_FS_ERROR "replace"
|
||||||
|
#else
|
||||||
|
#define UNICODE_DEF_FS_ERROR "surrogateescape"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* #if PY_MAJOR_VERSION >= 3 */
|
||||||
|
|
||||||
|
#define PY3 0
|
||||||
|
|
||||||
|
/* Module init function returns nothing. */
|
||||||
|
#define MODINIT_RETURN(x) return
|
||||||
|
#define MODINIT_DEFINE(mod_name) PyMODINIT_FUNC init##mod_name (void)
|
||||||
|
#define DECREF_MOD(mod)
|
||||||
|
|
||||||
|
/* Type header differs. */
|
||||||
|
#define TYPE_HEAD(x,y) \
|
||||||
|
PyObject_HEAD_INIT(x) \
|
||||||
|
0,
|
||||||
|
|
||||||
|
/* Text interface. Use ascii strings. */
|
||||||
|
#define Text_Type PyString_Type
|
||||||
|
#define Text_Check PyString_Check
|
||||||
|
#define Text_FromLocale PyString_FromString
|
||||||
|
#define Text_FromUTF8 PyString_FromString
|
||||||
|
#define Text_FromUTF8AndSize PyString_FromStringAndSize
|
||||||
|
#define Text_FromFormat PyString_FromFormat
|
||||||
|
#define Text_GetSize PyString_GetSize
|
||||||
|
#define Text_GET_SIZE PyString_GET_SIZE
|
||||||
|
|
||||||
|
/* Binary interface. Use ascii strings. */
|
||||||
|
#define Bytes_Type PyString_Type
|
||||||
|
#define Bytes_Check PyString_Check
|
||||||
|
#define Bytes_Size PyString_Size
|
||||||
|
#define Bytes_AsString PyString_AsString
|
||||||
|
#define Bytes_AsStringAndSize PyString_AsStringAndSize
|
||||||
|
#define Bytes_FromStringAndSize PyString_FromStringAndSize
|
||||||
|
#define Bytes_FromFormat PyString_FromFormat
|
||||||
|
#define Bytes_AS_STRING PyString_AS_STRING
|
||||||
|
#define Bytes_GET_SIZE PyString_GET_SIZE
|
||||||
|
#define Bytes_AsDecodedObject PyString_AsDecodedObject
|
||||||
|
|
||||||
|
#define Object_Unicode PyObject_Unicode
|
||||||
|
|
||||||
|
/* Renamed builtins */
|
||||||
|
#define BUILTINS_MODULE "__builtin__"
|
||||||
|
#define BUILTINS_UNICODE "unicode"
|
||||||
|
#define BUILTINS_UNICHR "unichr"
|
||||||
|
|
||||||
|
/* Defaults for unicode file path encoding */
|
||||||
|
#define UNICODE_DEF_FS_CODEC Py_FileSystemDefaultEncoding
|
||||||
|
#define UNICODE_DEF_FS_ERROR "strict"
|
||||||
|
|
||||||
|
#endif /* #if PY_MAJOR_VERSION >= 3 */
|
||||||
|
|
||||||
|
#define PY2 (!PY3)
|
||||||
|
|
||||||
|
#define MODINIT_ERROR MODINIT_RETURN (NULL)
|
||||||
|
|
||||||
|
/* Module state. These macros are used to define per-module macros.
|
||||||
|
* v - global state variable (Python 2.x)
|
||||||
|
* s - global state structure (Python 3.x)
|
||||||
|
*/
|
||||||
|
#define PY2_GETSTATE(v) (&(v))
|
||||||
|
#define PY3_GETSTATE(s, m) ((struct s *) PyModule_GetState (m))
|
||||||
|
|
||||||
|
/* Pep 3123: Making PyObject_HEAD conform to standard C */
|
||||||
|
#if !defined(Py_TYPE)
|
||||||
|
#define Py_TYPE(o) (((PyObject *)(o))->ob_type)
|
||||||
|
#define Py_REFCNT(o) (((PyObject *)(o))->ob_refcnt)
|
||||||
|
#define Py_SIZE(o) (((PyVarObject *)(o))->ob_size)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Encode a unicode file path */
|
||||||
|
#define Unicode_AsEncodedPath(u) \
|
||||||
|
PyUnicode_AsEncodedString ((u), UNICODE_DEF_FS_CODEC, UNICODE_DEF_FS_ERROR)
|
||||||
|
|
||||||
|
#define RELATIVE_MODULE(m) ("." m)
|
||||||
|
|
||||||
|
#define HAVE_OLD_BUFPROTO PY2
|
||||||
|
|
||||||
|
#if !defined(PG_ENABLE_OLDBUF) /* allow for command line override */
|
||||||
|
#if HAVE_OLD_BUFPROTO
|
||||||
|
#define PG_ENABLE_OLDBUF 1
|
||||||
|
#else
|
||||||
|
#define PG_ENABLE_OLDBUF 0
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Py_TPFLAGS_HAVE_NEWBUFFER
|
||||||
|
#define Py_TPFLAGS_HAVE_NEWBUFFER 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Py_TPFLAGS_HAVE_CLASS
|
||||||
|
#define Py_TPFLAGS_HAVE_CLASS 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef Py_TPFLAGS_CHECKTYPES
|
||||||
|
#define Py_TPFLAGS_CHECKTYPES 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PY_VERSION_HEX >= 0x03020000
|
||||||
|
#define Slice_GET_INDICES_EX(slice, length, start, stop, step, slicelength) \
|
||||||
|
PySlice_GetIndicesEx(slice, length, start, stop, step, slicelength)
|
||||||
|
#else
|
||||||
|
#define Slice_GET_INDICES_EX(slice, length, start, stop, step, slicelength) \
|
||||||
|
PySlice_GetIndicesEx((PySliceObject *)(slice), length, \
|
||||||
|
start, stop, step, slicelength)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Support new buffer protocol? */
|
||||||
|
#if !defined(PG_ENABLE_NEWBUF) /* allow for command line override */
|
||||||
|
#if !defined(PYPY_VERSION)
|
||||||
|
#define PG_ENABLE_NEWBUF 1
|
||||||
|
#else
|
||||||
|
#define PG_ENABLE_NEWBUF 0
|
||||||
|
#endif
|
||||||
|
#endif /* !defined(PG_ENABLE_NEWBUF) */
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(SDL_VERSION_ATLEAST)
|
||||||
|
#if !(SDL_VERSION_ATLEAST(2, 0, 5))
|
||||||
|
/* These functions require SDL 2.0.5 or greater.
|
||||||
|
|
||||||
|
https://wiki.libsdl.org/SDL_SetWindowResizable
|
||||||
|
*/
|
||||||
|
void SDL_SetWindowResizable(SDL_Window *window, SDL_bool resizable);
|
||||||
|
int SDL_GetWindowOpacity(SDL_Window *window, float *opacity);
|
||||||
|
int SDL_SetWindowOpacity(SDL_Window *window, float opacity);
|
||||||
|
int SDL_SetWindowModalFor(SDL_Window *modal_window, SDL_Window *parent_window);
|
||||||
|
int SDL_SetWindowInputFocus(SDL_Window *window);
|
||||||
|
SDL_Surface * SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth,
|
||||||
|
Uint32 format);
|
||||||
|
#endif
|
||||||
|
#endif /* defined(SDL_VERSION_ATLEAST) */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* ~PGCOMPAT_INTERNAL_H */
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
#ifndef PGIMPORT_INTERNAL_H
|
||||||
|
#define PGIMPORT_INTERNAL_H
|
||||||
|
|
||||||
|
#include "include/pgimport.h"
|
||||||
|
|
||||||
|
#if PG_HAVE_CAPSULE
|
||||||
|
#define encapsulate_api(ptr, module) \
|
||||||
|
PyCapsule_New(ptr, PG_CAPSULE_NAME(module), NULL)
|
||||||
|
#else /* ~PG_HAVE_CAPSULE */
|
||||||
|
#define encapsulate_api(ptr, module) PyCObject_FromVoidPtr(ptr, NULL)
|
||||||
|
#endif /* ~PG_HAVE_CAPSULE */
|
||||||
|
|
||||||
|
#endif /* PGIMPORT_INTERNAL_H */
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
#if !defined(PGOPENGL_H)
|
||||||
|
#define PGOPENGL_H
|
||||||
|
|
||||||
|
/** This header includes definitions of Opengl functions as pointer types for
|
||||||
|
** use with the SDL function SDL_GL_GetProcAddress.
|
||||||
|
**/
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define GL_APIENTRY __stdcall
|
||||||
|
#else
|
||||||
|
#define GL_APIENTRY
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef void (GL_APIENTRY *GL_glReadPixels_Func)(int, int, int, int, unsigned int, unsigned int, void*);
|
||||||
|
|
||||||
|
typedef void (GL_APIENTRY *GL_glViewport_Func)(int, int, unsigned int, unsigned int);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* platform/compiler adjustments (internal) */
|
||||||
|
#ifndef PG_PLATFORM_INTERNAL_H
|
||||||
|
#define PG_PLATFORM_INTERNAL_H
|
||||||
|
|
||||||
|
/* This must be before all else */
|
||||||
|
#if defined(__SYMBIAN32__) && defined(OPENC)
|
||||||
|
#include <sys/types.h>
|
||||||
|
#if defined(__WINS__)
|
||||||
|
void *
|
||||||
|
_alloca(size_t size);
|
||||||
|
#define alloca _alloca
|
||||||
|
#endif /* __WINS__ */
|
||||||
|
#endif /* defined(__SYMBIAN32__) && defined(OPENC) */
|
||||||
|
|
||||||
|
#include "include/pgplatform.h"
|
||||||
|
|
||||||
|
#ifndef MIN
|
||||||
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
#ifndef ABS
|
||||||
|
#define ABS(a) (((a) < 0) ? -(a) : (a))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(macintosh) && defined(__MWERKS__) || defined(__SYMBIAN32__)
|
||||||
|
#define PYGAME_EXPORT __declspec(export)
|
||||||
|
#else
|
||||||
|
#define PYGAME_EXPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* warnings */
|
||||||
|
#define PG_STRINGIZE_HELPER(x) #x
|
||||||
|
#define PG_STRINGIZE(x) PG_STRINGIZE_HELPER(x)
|
||||||
|
#define PG_WARN(desc) message(__FILE__ "(" PG_STRINGIZE(__LINE__) "): WARNING: " #desc)
|
||||||
|
|
||||||
|
#endif /* ~PG_PLATFORM_INTERNAL_H */
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
Copyright (C) 2000-2001 Pete Shinners
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Pete Shinners
|
||||||
|
pete@shinners.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This will use PYGAMEAPI_DEFINE_SLOTS instead
|
||||||
|
* of PYGAMEAPI_EXTERN_SLOTS for base modules.
|
||||||
|
*/
|
||||||
|
#ifndef PYGAME_INTERNAL_H
|
||||||
|
#define PYGAME_INTERNAL_H
|
||||||
|
|
||||||
|
#define PYGAME_H
|
||||||
|
#include "_pygame.h"
|
||||||
|
|
||||||
|
#endif /* ~PYGAME_INTERNAL_H */
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
Copyright (C) 2006, 2007 Rene Dudfield, Marcus von Appen
|
||||||
|
|
||||||
|
Originally put in the public domain by Sam Lantinga.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SCRAP_H
|
||||||
|
#define SCRAP_H
|
||||||
|
|
||||||
|
/* This is unconditionally defined in Python.h */
|
||||||
|
#if defined(_POSIX_C_SOURCE)
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
|
||||||
|
/* Handle clipboard text and data in arbitrary formats */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Predefined supported pygame scrap types.
|
||||||
|
*/
|
||||||
|
#define PYGAME_SCRAP_TEXT "text/plain"
|
||||||
|
#define PYGAME_SCRAP_BMP "image/bmp"
|
||||||
|
#define PYGAME_SCRAP_PPM "image/ppm"
|
||||||
|
#define PYGAME_SCRAP_PBM "image/pbm"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The supported scrap clipboard types.
|
||||||
|
*
|
||||||
|
* This is only relevant in a X11 environment, which supports mouse
|
||||||
|
* selections as well. For Win32 and MacOS environments the default
|
||||||
|
* clipboard is used, no matter what value is passed.
|
||||||
|
*/
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SCRAP_CLIPBOARD,
|
||||||
|
SCRAP_SELECTION /* only supported in X11 environments. */
|
||||||
|
} ScrapClipType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Macro for initialization checks.
|
||||||
|
*/
|
||||||
|
#define PYGAME_SCRAP_INIT_CHECK() \
|
||||||
|
if(!pygame_scrap_initialized()) \
|
||||||
|
return (PyErr_SetString (pgExc_SDLError, \
|
||||||
|
"scrap system not initialized."), NULL)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Checks, whether the pygame scrap module was initialized.
|
||||||
|
*
|
||||||
|
* \return 1 if the modules was initialized, 0 otherwise.
|
||||||
|
*/
|
||||||
|
extern int
|
||||||
|
pygame_scrap_initialized (void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Initializes the pygame scrap module internals. Call this before any
|
||||||
|
* other method.
|
||||||
|
*
|
||||||
|
* \return 1 on successful initialization, 0 otherwise.
|
||||||
|
*/
|
||||||
|
extern int
|
||||||
|
pygame_scrap_init (void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Checks, whether the pygame window lost the clipboard focus or not.
|
||||||
|
*
|
||||||
|
* \return 1 if the window lost the focus, 0 otherwise.
|
||||||
|
*/
|
||||||
|
extern int
|
||||||
|
pygame_scrap_lost (void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Places content of a specific type into the clipboard.
|
||||||
|
*
|
||||||
|
* \note For X11 the following notes are important: The following types
|
||||||
|
* are reserved for internal usage and thus will throw an error on
|
||||||
|
* setting them: "TIMESTAMP", "TARGETS", "SDL_SELECTION".
|
||||||
|
* Setting PYGAME_SCRAP_TEXT ("text/plain") will also automatically
|
||||||
|
* set the X11 types "STRING" (XA_STRING), "TEXT" and "UTF8_STRING".
|
||||||
|
*
|
||||||
|
* For Win32 the following notes are important: Setting
|
||||||
|
* PYGAME_SCRAP_TEXT ("text/plain") will also automatically set
|
||||||
|
* the Win32 type "TEXT" (CF_TEXT).
|
||||||
|
*
|
||||||
|
* For QNX the following notes are important: Setting
|
||||||
|
* PYGAME_SCRAP_TEXT ("text/plain") will also automatically set
|
||||||
|
* the QNX type "TEXT" (Ph_CL_TEXT).
|
||||||
|
*
|
||||||
|
* \param type The type of the content.
|
||||||
|
* \param srclen The length of the content.
|
||||||
|
* \param src The NULL terminated content.
|
||||||
|
* \return 1, if the content could be successfully pasted into the clipboard,
|
||||||
|
* 0 otherwise.
|
||||||
|
*/
|
||||||
|
extern int
|
||||||
|
pygame_scrap_put (char *type, int srclen, char *src);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Gets the current content from the clipboard.
|
||||||
|
*
|
||||||
|
* \note The received content does not need to be the content previously
|
||||||
|
* placed in the clipboard using pygame_put_scrap(). See the
|
||||||
|
* pygame_put_scrap() notes for more details.
|
||||||
|
*
|
||||||
|
* \param type The type of the content to receive.
|
||||||
|
* \param count The size of the returned content.
|
||||||
|
* \return The content or NULL in case of an error or if no content of the
|
||||||
|
* specified type was available.
|
||||||
|
*/
|
||||||
|
extern char*
|
||||||
|
pygame_scrap_get (char *type, unsigned long *count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Gets the currently available content types from the clipboard.
|
||||||
|
*
|
||||||
|
* \return The different available content types or NULL in case of an
|
||||||
|
* error or if no content type is available.
|
||||||
|
*/
|
||||||
|
extern char**
|
||||||
|
pygame_scrap_get_types (void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Checks whether content for the specified scrap type is currently
|
||||||
|
* available in the clipboard.
|
||||||
|
*
|
||||||
|
* \param type The type to check for.
|
||||||
|
* \return 1, if there is content and 0 otherwise.
|
||||||
|
*/
|
||||||
|
extern int
|
||||||
|
pygame_scrap_contains (char *type);
|
||||||
|
|
||||||
|
#endif /* SCRAP_H */
|
||||||
|
|
@ -0,0 +1,383 @@
|
||||||
|
/*
|
||||||
|
pygame - Python Game Library
|
||||||
|
Copyright (C) 2000-2001 Pete Shinners
|
||||||
|
Copyright (C) 2007 Marcus von Appen
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Library General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Library General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Library General Public
|
||||||
|
License along with this library; if not, write to the Free
|
||||||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
|
||||||
|
Pete Shinners
|
||||||
|
pete@shinners.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SURFACE_H
|
||||||
|
#define SURFACE_H
|
||||||
|
|
||||||
|
/* This is defined in SDL.h */
|
||||||
|
#if defined(_POSIX_C_SOURCE)
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
#include "pygame.h"
|
||||||
|
|
||||||
|
/* Blend modes */
|
||||||
|
#define PYGAME_BLEND_ADD 0x1
|
||||||
|
#define PYGAME_BLEND_SUB 0x2
|
||||||
|
#define PYGAME_BLEND_MULT 0x3
|
||||||
|
#define PYGAME_BLEND_MIN 0x4
|
||||||
|
#define PYGAME_BLEND_MAX 0x5
|
||||||
|
|
||||||
|
#define PYGAME_BLEND_RGB_ADD 0x1
|
||||||
|
#define PYGAME_BLEND_RGB_SUB 0x2
|
||||||
|
#define PYGAME_BLEND_RGB_MULT 0x3
|
||||||
|
#define PYGAME_BLEND_RGB_MIN 0x4
|
||||||
|
#define PYGAME_BLEND_RGB_MAX 0x5
|
||||||
|
|
||||||
|
#define PYGAME_BLEND_RGBA_ADD 0x6
|
||||||
|
#define PYGAME_BLEND_RGBA_SUB 0x7
|
||||||
|
#define PYGAME_BLEND_RGBA_MULT 0x8
|
||||||
|
#define PYGAME_BLEND_RGBA_MIN 0x9
|
||||||
|
#define PYGAME_BLEND_RGBA_MAX 0x10
|
||||||
|
#define PYGAME_BLEND_PREMULTIPLIED 0x11
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||||
|
#define GET_PIXEL_24(b) (b[0] + (b[1] << 8) + (b[2] << 16))
|
||||||
|
#else
|
||||||
|
#define GET_PIXEL_24(b) (b[2] + (b[1] << 8) + (b[0] << 16))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GET_PIXEL(pxl, bpp, source) \
|
||||||
|
switch (bpp) \
|
||||||
|
{ \
|
||||||
|
case 2: \
|
||||||
|
pxl = *((Uint16 *) (source)); \
|
||||||
|
break; \
|
||||||
|
case 4: \
|
||||||
|
pxl = *((Uint32 *) (source)); \
|
||||||
|
break; \
|
||||||
|
default: \
|
||||||
|
{ \
|
||||||
|
Uint8 *b = (Uint8 *) source; \
|
||||||
|
pxl = GET_PIXEL_24(b); \
|
||||||
|
} \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#if IS_SDLv1
|
||||||
|
#define GET_PIXELVALS(_sR, _sG, _sB, _sA, px, fmt, ppa) \
|
||||||
|
_sR = ((px & fmt->Rmask) >> fmt->Rshift); \
|
||||||
|
_sR = (_sR << fmt->Rloss) + (_sR >> (8 - (fmt->Rloss << 1))); \
|
||||||
|
_sG = ((px & fmt->Gmask) >> fmt->Gshift); \
|
||||||
|
_sG = (_sG << fmt->Gloss) + (_sG >> (8 - (fmt->Gloss << 1))); \
|
||||||
|
_sB = ((px & fmt->Bmask) >> fmt->Bshift); \
|
||||||
|
_sB = (_sB << fmt->Bloss) + (_sB >> (8 - (fmt->Bloss << 1))); \
|
||||||
|
if (ppa) \
|
||||||
|
{ \
|
||||||
|
_sA = ((px & fmt->Amask) >> fmt->Ashift); \
|
||||||
|
_sA = (_sA << fmt->Aloss) + (_sA >> (8 - (fmt->Aloss << 1))); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
_sA = 255; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_PIXELVALS_1(sr, sg, sb, sa, _src, _fmt) \
|
||||||
|
sr = _fmt->palette->colors[*((Uint8 *) (_src))].r; \
|
||||||
|
sg = _fmt->palette->colors[*((Uint8 *) (_src))].g; \
|
||||||
|
sb = _fmt->palette->colors[*((Uint8 *) (_src))].b; \
|
||||||
|
sa = 255;
|
||||||
|
|
||||||
|
/* For 1 byte palette pixels */
|
||||||
|
#define SET_PIXELVAL(px, fmt, _dR, _dG, _dB, _dA) \
|
||||||
|
*(px) = (Uint8) SDL_MapRGB(fmt, _dR, _dG, _dB)
|
||||||
|
#else /* IS_SDLv2 */
|
||||||
|
#define GET_PIXELVALS(_sR, _sG, _sB, _sA, px, fmt, ppa) \
|
||||||
|
SDL_GetRGBA(px, fmt, &(_sR), &(_sG), &(_sB), &(_sA)); \
|
||||||
|
if (!ppa) { \
|
||||||
|
_sA = 255; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GET_PIXELVALS_1(sr, sg, sb, sa, _src, _fmt) \
|
||||||
|
sr = _fmt->palette->colors[*((Uint8 *) (_src))].r; \
|
||||||
|
sg = _fmt->palette->colors[*((Uint8 *) (_src))].g; \
|
||||||
|
sb = _fmt->palette->colors[*((Uint8 *) (_src))].b; \
|
||||||
|
sa = 255;
|
||||||
|
|
||||||
|
/* For 1 byte palette pixels */
|
||||||
|
#define SET_PIXELVAL(px, fmt, _dR, _dG, _dB, _dA) \
|
||||||
|
*(px) = (Uint8) SDL_MapRGBA(fmt, _dR, _dG, _dB, _dA)
|
||||||
|
#endif /* IS_SDLv2 */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||||
|
#define SET_OFFSETS_24(or, og, ob, fmt) \
|
||||||
|
{ \
|
||||||
|
or = (fmt->Rshift == 0 ? 0 : \
|
||||||
|
fmt->Rshift == 8 ? 1 : \
|
||||||
|
2 ); \
|
||||||
|
og = (fmt->Gshift == 0 ? 0 : \
|
||||||
|
fmt->Gshift == 8 ? 1 : \
|
||||||
|
2 ); \
|
||||||
|
ob = (fmt->Bshift == 0 ? 0 : \
|
||||||
|
fmt->Bshift == 8 ? 1 : \
|
||||||
|
2 ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SET_OFFSETS_32(or, og, ob, fmt) \
|
||||||
|
{ \
|
||||||
|
or = (fmt->Rshift == 0 ? 0 : \
|
||||||
|
fmt->Rshift == 8 ? 1 : \
|
||||||
|
fmt->Rshift == 16 ? 2 : \
|
||||||
|
3 ); \
|
||||||
|
og = (fmt->Gshift == 0 ? 0 : \
|
||||||
|
fmt->Gshift == 8 ? 1 : \
|
||||||
|
fmt->Gshift == 16 ? 2 : \
|
||||||
|
3 ); \
|
||||||
|
ob = (fmt->Bshift == 0 ? 0 : \
|
||||||
|
fmt->Bshift == 8 ? 1 : \
|
||||||
|
fmt->Bshift == 16 ? 2 : \
|
||||||
|
3 ); \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define SET_OFFSETS_24(or, og, ob, fmt) \
|
||||||
|
{ \
|
||||||
|
or = (fmt->Rshift == 0 ? 2 : \
|
||||||
|
fmt->Rshift == 8 ? 1 : \
|
||||||
|
0 ); \
|
||||||
|
og = (fmt->Gshift == 0 ? 2 : \
|
||||||
|
fmt->Gshift == 8 ? 1 : \
|
||||||
|
0 ); \
|
||||||
|
ob = (fmt->Bshift == 0 ? 2 : \
|
||||||
|
fmt->Bshift == 8 ? 1 : \
|
||||||
|
0 ); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SET_OFFSETS_32(or, og, ob, fmt) \
|
||||||
|
{ \
|
||||||
|
or = (fmt->Rshift == 0 ? 3 : \
|
||||||
|
fmt->Rshift == 8 ? 2 : \
|
||||||
|
fmt->Rshift == 16 ? 1 : \
|
||||||
|
0 ); \
|
||||||
|
og = (fmt->Gshift == 0 ? 3 : \
|
||||||
|
fmt->Gshift == 8 ? 2 : \
|
||||||
|
fmt->Gshift == 16 ? 1 : \
|
||||||
|
0 ); \
|
||||||
|
ob = (fmt->Bshift == 0 ? 3 : \
|
||||||
|
fmt->Bshift == 8 ? 2 : \
|
||||||
|
fmt->Bshift == 16 ? 1 : \
|
||||||
|
0 ); \
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define CREATE_PIXEL(buf, r, g, b, a, bp, ft) \
|
||||||
|
switch (bp) \
|
||||||
|
{ \
|
||||||
|
case 2: \
|
||||||
|
*((Uint16 *) (buf)) = \
|
||||||
|
((r >> ft->Rloss) << ft->Rshift) | \
|
||||||
|
((g >> ft->Gloss) << ft->Gshift) | \
|
||||||
|
((b >> ft->Bloss) << ft->Bshift) | \
|
||||||
|
((a >> ft->Aloss) << ft->Ashift); \
|
||||||
|
break; \
|
||||||
|
case 4: \
|
||||||
|
*((Uint32 *) (buf)) = \
|
||||||
|
((r >> ft->Rloss) << ft->Rshift) | \
|
||||||
|
((g >> ft->Gloss) << ft->Gshift) | \
|
||||||
|
((b >> ft->Bloss) << ft->Bshift) | \
|
||||||
|
((a >> ft->Aloss) << ft->Ashift); \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pretty good idea from Tom Duff :-). */
|
||||||
|
#define LOOP_UNROLLED4(code, n, width) \
|
||||||
|
n = (width + 3) / 4; \
|
||||||
|
switch (width & 3) \
|
||||||
|
{ \
|
||||||
|
case 0: do { code; \
|
||||||
|
case 3: code; \
|
||||||
|
case 2: code; \
|
||||||
|
case 1: code; \
|
||||||
|
} while (--n > 0); \
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Used in the srcbpp == dstbpp == 1 blend functions */
|
||||||
|
#define REPEAT_3(code) \
|
||||||
|
code; \
|
||||||
|
code; \
|
||||||
|
code;
|
||||||
|
|
||||||
|
#define REPEAT_4(code) \
|
||||||
|
code; \
|
||||||
|
code; \
|
||||||
|
code; \
|
||||||
|
code;
|
||||||
|
|
||||||
|
|
||||||
|
#define BLEND_ADD(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||||
|
tmp = dR + sR; dR = (tmp <= 255 ? tmp : 255); \
|
||||||
|
tmp = dG + sG; dG = (tmp <= 255 ? tmp : 255); \
|
||||||
|
tmp = dB + sB; dB = (tmp <= 255 ? tmp : 255);
|
||||||
|
|
||||||
|
#define BLEND_SUB(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||||
|
tmp = dR - sR; dR = (tmp >= 0 ? tmp : 0); \
|
||||||
|
tmp = dG - sG; dG = (tmp >= 0 ? tmp : 0); \
|
||||||
|
tmp = dB - sB; dB = (tmp >= 0 ? tmp : 0);
|
||||||
|
|
||||||
|
#define BLEND_MULT(sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||||
|
dR = (dR && sR) ? (dR * sR) >> 8 : 0; \
|
||||||
|
dG = (dG && sG) ? (dG * sG) >> 8 : 0; \
|
||||||
|
dB = (dB && sB) ? (dB * sB) >> 8 : 0;
|
||||||
|
|
||||||
|
#define BLEND_MIN(sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||||
|
if(sR < dR) { dR = sR; } \
|
||||||
|
if(sG < dG) { dG = sG; } \
|
||||||
|
if(sB < dB) { dB = sB; }
|
||||||
|
|
||||||
|
#define BLEND_MAX(sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||||
|
if(sR > dR) { dR = sR; } \
|
||||||
|
if(sG > dG) { dG = sG; } \
|
||||||
|
if(sB > dB) { dB = sB; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define BLEND_RGBA_ADD(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||||
|
tmp = dR + sR; dR = (tmp <= 255 ? tmp : 255); \
|
||||||
|
tmp = dG + sG; dG = (tmp <= 255 ? tmp : 255); \
|
||||||
|
tmp = dB + sB; dB = (tmp <= 255 ? tmp : 255); \
|
||||||
|
tmp = dA + sA; dA = (tmp <= 255 ? tmp : 255);
|
||||||
|
|
||||||
|
#define BLEND_RGBA_SUB(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||||
|
tmp = dR - sR; dR = (tmp >= 0 ? tmp : 0); \
|
||||||
|
tmp = dG - sG; dG = (tmp >= 0 ? tmp : 0); \
|
||||||
|
tmp = dB - sB; dB = (tmp >= 0 ? tmp : 0); \
|
||||||
|
tmp = dA - sA; dA = (tmp >= 0 ? tmp : 0);
|
||||||
|
|
||||||
|
#define BLEND_RGBA_MULT(sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||||
|
dR = (dR && sR) ? (dR * sR) >> 8 : 0; \
|
||||||
|
dG = (dG && sG) ? (dG * sG) >> 8 : 0; \
|
||||||
|
dB = (dB && sB) ? (dB * sB) >> 8 : 0; \
|
||||||
|
dA = (dA && sA) ? (dA * sA) >> 8 : 0;
|
||||||
|
|
||||||
|
#define BLEND_RGBA_MIN(sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||||
|
if(sR < dR) { dR = sR; } \
|
||||||
|
if(sG < dG) { dG = sG; } \
|
||||||
|
if(sB < dB) { dB = sB; } \
|
||||||
|
if(sA < dA) { dA = sA; }
|
||||||
|
|
||||||
|
#define BLEND_RGBA_MAX(sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||||
|
if(sR > dR) { dR = sR; } \
|
||||||
|
if(sG > dG) { dG = sG; } \
|
||||||
|
if(sB > dB) { dB = sB; } \
|
||||||
|
if(sA > dA) { dA = sA; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
/* Choose an alpha blend equation. If the sign is preserved on a right shift
|
||||||
|
* then use a specialized, faster, equation. Otherwise a more general form,
|
||||||
|
* where all additions are done before the shift, is needed.
|
||||||
|
*/
|
||||||
|
#if (-1 >> 1) < 0
|
||||||
|
#define ALPHA_BLEND_COMP(sC, dC, sA) ((((sC - dC) * sA + sC) >> 8) + dC)
|
||||||
|
#else
|
||||||
|
#define ALPHA_BLEND_COMP(sC, dC, sA) (((dC << 8) + (sC - dC) * sA + sC) >> 8)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||||
|
do { \
|
||||||
|
if (dA) \
|
||||||
|
{ \
|
||||||
|
dR = ALPHA_BLEND_COMP(sR, dR, sA); \
|
||||||
|
dG = ALPHA_BLEND_COMP(sG, dG, sA); \
|
||||||
|
dB = ALPHA_BLEND_COMP(sB, dB, sA); \
|
||||||
|
dA = sA + dA - ((sA * dA) / 255); \
|
||||||
|
} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
dR = sR; \
|
||||||
|
dG = sG; \
|
||||||
|
dB = sB; \
|
||||||
|
dA = sA; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
#define ALPHA_BLEND_PREMULTIPLIED_COMP(sC, dC, sA) (sC + dC - ((dC * sA) >> 8))
|
||||||
|
|
||||||
|
#define ALPHA_BLEND_PREMULTIPLIED(tmp, sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||||
|
do { \
|
||||||
|
tmp = ALPHA_BLEND_PREMULTIPLIED_COMP(sR, dR, sA); dR = (tmp > 255 ? 255 : tmp); \
|
||||||
|
tmp = ALPHA_BLEND_PREMULTIPLIED_COMP(sG, dG, sA); dG = (tmp > 255 ? 255 : tmp); \
|
||||||
|
tmp = ALPHA_BLEND_PREMULTIPLIED_COMP(sB, dB, sA); dB = (tmp > 255 ? 255 : tmp); \
|
||||||
|
dA = sA + dA - ((sA * dA) / 255); \
|
||||||
|
} while(0)
|
||||||
|
#elif 0
|
||||||
|
|
||||||
|
#define ALPHA_BLEND(sR, sG, sB, sA, dR, dG, dB, dA) \
|
||||||
|
do { \
|
||||||
|
if(sA){ \
|
||||||
|
if(dA && sA < 255){ \
|
||||||
|
int dContrib = dA*(255 - sA)/255; \
|
||||||
|
dA = sA+dA - ((sA*dA)/255); \
|
||||||
|
dR = (dR*dContrib + sR*sA)/dA; \
|
||||||
|
dG = (dG*dContrib + sG*sA)/dA; \
|
||||||
|
dB = (dB*dContrib + sB*sA)/dA; \
|
||||||
|
}else{ \
|
||||||
|
dR = sR; \
|
||||||
|
dG = sG; \
|
||||||
|
dB = sB; \
|
||||||
|
dA = sA; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
surface_fill_blend (SDL_Surface *surface, SDL_Rect *rect, Uint32 color,
|
||||||
|
int blendargs);
|
||||||
|
|
||||||
|
void
|
||||||
|
surface_respect_clip_rect (SDL_Surface *surface, SDL_Rect *rect);
|
||||||
|
|
||||||
|
int
|
||||||
|
pygame_AlphaBlit (SDL_Surface * src, SDL_Rect * srcrect,
|
||||||
|
SDL_Surface * dst, SDL_Rect * dstrect, int the_args);
|
||||||
|
|
||||||
|
int
|
||||||
|
pygame_Blit (SDL_Surface * src, SDL_Rect * srcrect,
|
||||||
|
SDL_Surface * dst, SDL_Rect * dstrect, int the_args);
|
||||||
|
|
||||||
|
#endif /* SURFACE_H */
|
||||||
|
|
@ -0,0 +1,339 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
||||||
|
|
@ -0,0 +1,510 @@
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
|
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations
|
||||||
|
below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
not price. Our General Public Licenses are designed to make sure that
|
||||||
|
you have the freedom to distribute copies of free software (and charge
|
||||||
|
for this service if you wish); that you receive source code or can get
|
||||||
|
it if you want it; that you can change the software and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it
|
||||||
|
becomes a de-facto standard. To achieve this, non-free programs must
|
||||||
|
be allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control
|
||||||
|
compilation and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at least
|
||||||
|
three years, to give the same user the materials specified in
|
||||||
|
Subsection 6a, above, for a charge no more than the cost of
|
||||||
|
performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be distributed need not include anything that is
|
||||||
|
normally distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply, and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding those
|
||||||
|
countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser General Public License from time to time.
|
||||||
|
Such new versions will be similar in spirit to the present version,
|
||||||
|
but may differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||||
|
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||||
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||||
|
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Libraries
|
||||||
|
|
||||||
|
If you develop a new library, and you want it to be of the greatest
|
||||||
|
possible use to the public, we recommend making it free software that
|
||||||
|
everyone can redistribute and change. You can do so by permitting
|
||||||
|
redistribution under these terms (or, alternatively, under the terms
|
||||||
|
of the ordinary General Public License).
|
||||||
|
|
||||||
|
To apply these terms, attach the following notices to the library.
|
||||||
|
It is safest to attach them to the start of each source file to most
|
||||||
|
effectively convey the exclusion of warranty; and each file should
|
||||||
|
have at least the "copyright" line and a pointer to where the full
|
||||||
|
notice is found.
|
||||||
|
|
||||||
|
|
||||||
|
<one line to give the library's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or
|
||||||
|
your school, if any, to sign a "copyright disclaimer" for the library,
|
||||||
|
if necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||||
|
library `Frob' (a library for tweaking knobs) written by James
|
||||||
|
Random Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1990
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
That's all there is to it!
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
pip
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
Metadata-Version: 2.1
|
||||||
|
Name: astroid
|
||||||
|
Version: 2.4.2
|
||||||
|
Summary: An abstract syntax tree for Python with inference support.
|
||||||
|
Home-page: https://github.com/PyCQA/astroid
|
||||||
|
Author: Python Code Quality Authority
|
||||||
|
Author-email: code-quality@python.org
|
||||||
|
License: LGPL
|
||||||
|
Platform: UNKNOWN
|
||||||
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
||||||
|
Classifier: Topic :: Software Development :: Quality Assurance
|
||||||
|
Classifier: Programming Language :: Python
|
||||||
|
Classifier: Programming Language :: Python :: 3
|
||||||
|
Classifier: Programming Language :: Python :: 3.5
|
||||||
|
Classifier: Programming Language :: Python :: 3.6
|
||||||
|
Classifier: Programming Language :: Python :: 3.7
|
||||||
|
Classifier: Programming Language :: Python :: 3.8
|
||||||
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
||||||
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
||||||
|
Requires-Python: >=3.5
|
||||||
|
Requires-Dist: lazy-object-proxy (==1.4.*)
|
||||||
|
Requires-Dist: six (~=1.12)
|
||||||
|
Requires-Dist: wrapt (~=1.11)
|
||||||
|
Requires-Dist: typed-ast (<1.5,>=1.4.0) ; implementation_name == "cpython" and python_version < "3.8"
|
||||||
|
|
||||||
|
Astroid
|
||||||
|
=======
|
||||||
|
|
||||||
|
.. image:: https://travis-ci.org/PyCQA/astroid.svg?branch=master
|
||||||
|
:target: https://travis-ci.org/PyCQA/astroid
|
||||||
|
|
||||||
|
.. image:: https://ci.appveyor.com/api/projects/status/co3u42kunguhbh6l/branch/master?svg=true
|
||||||
|
:alt: AppVeyor Build Status
|
||||||
|
:target: https://ci.appveyor.com/project/PCManticore/astroid
|
||||||
|
|
||||||
|
.. image:: https://coveralls.io/repos/github/PyCQA/astroid/badge.svg?branch=master
|
||||||
|
:target: https://coveralls.io/github/PyCQA/astroid?branch=master
|
||||||
|
|
||||||
|
.. image:: https://readthedocs.org/projects/astroid/badge/?version=latest
|
||||||
|
:target: http://astroid.readthedocs.io/en/latest/?badge=latest
|
||||||
|
:alt: Documentation Status
|
||||||
|
|
||||||
|
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||||
|
:target: https://github.com/ambv/black
|
||||||
|
|
||||||
|
.. |tideliftlogo| image:: doc/media/Tidelift_Logos_RGB_Tidelift_Shorthand_On-White_small.png
|
||||||
|
:width: 75
|
||||||
|
:height: 60
|
||||||
|
:alt: Tidelift
|
||||||
|
|
||||||
|
.. list-table::
|
||||||
|
:widths: 10 100
|
||||||
|
|
||||||
|
* - |tideliftlogo|
|
||||||
|
- Professional support for astroid is available as part of the `Tidelift
|
||||||
|
Subscription`_. Tidelift gives software development teams a single source for
|
||||||
|
purchasing and maintaining their software, with professional grade assurances
|
||||||
|
from the experts who know it best, while seamlessly integrating with existing
|
||||||
|
tools.
|
||||||
|
|
||||||
|
.. _Tidelift Subscription: https://tidelift.com/subscription/pkg/pypi-astroid?utm_source=pypi-astroid&utm_medium=referral&utm_campaign=readme
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
What's this?
|
||||||
|
------------
|
||||||
|
|
||||||
|
The aim of this module is to provide a common base representation of
|
||||||
|
python source code. It is currently the library powering pylint's capabilities.
|
||||||
|
|
||||||
|
It provides a compatible representation which comes from the `_ast`
|
||||||
|
module. It rebuilds the tree generated by the builtin _ast module by
|
||||||
|
recursively walking down the AST and building an extended ast. The new
|
||||||
|
node classes have additional methods and attributes for different
|
||||||
|
usages. They include some support for static inference and local name
|
||||||
|
scopes. Furthermore, astroid can also build partial trees by inspecting living
|
||||||
|
objects.
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
Extract the tarball, jump into the created directory and run::
|
||||||
|
|
||||||
|
pip install .
|
||||||
|
|
||||||
|
|
||||||
|
If you want to do an editable installation, you can run::
|
||||||
|
|
||||||
|
pip install -e .
|
||||||
|
|
||||||
|
|
||||||
|
If you have any questions, please mail the code-quality@python.org
|
||||||
|
mailing list for support. See
|
||||||
|
http://mail.python.org/mailman/listinfo/code-quality for subscription
|
||||||
|
information and archives.
|
||||||
|
|
||||||
|
Documentation
|
||||||
|
-------------
|
||||||
|
http://astroid.readthedocs.io/en/latest/
|
||||||
|
|
||||||
|
|
||||||
|
Python Versions
|
||||||
|
---------------
|
||||||
|
|
||||||
|
astroid 2.0 is currently available for Python 3 only. If you want Python 2
|
||||||
|
support, older versions of astroid will still supported until 2020.
|
||||||
|
|
||||||
|
Test
|
||||||
|
----
|
||||||
|
|
||||||
|
Tests are in the 'test' subdirectory. To launch the whole tests suite, you can use
|
||||||
|
either `tox` or `pytest`::
|
||||||
|
|
||||||
|
tox
|
||||||
|
pytest astroid
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,151 @@
|
||||||
|
astroid-2.4.2.dist-info/COPYING,sha256=qxX9UmvY3Rip5368E5ZWv00z6X_HI4zRG_YOK5uGZsY,17987
|
||||||
|
astroid-2.4.2.dist-info/COPYING.LESSER,sha256=qb3eVhbs3R6YC0TzYGAO6Hg7H5m4zIOivrFjoKOQ6GE,26527
|
||||||
|
astroid-2.4.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||||
|
astroid-2.4.2.dist-info/METADATA,sha256=mWlOM8vl6thD_vA7Lzn2yKmQuaX8NukwS72gEpsGM0U,3915
|
||||||
|
astroid-2.4.2.dist-info/RECORD,,
|
||||||
|
astroid-2.4.2.dist-info/WHEEL,sha256=g4nMs7d-Xl9-xC9XovUrsDHGXt-FT0E17Yqo92DEfvY,92
|
||||||
|
astroid-2.4.2.dist-info/top_level.txt,sha256=HsdW4O2x7ZXRj6k-agi3RaQybGLobI3VSE-jt4vQUXM,8
|
||||||
|
astroid/__init__.py,sha256=zZF5EWBTfOtOcFd62WMbhLAtS2b_Fm-3JJW2AVUUMUI,5655
|
||||||
|
astroid/__pkginfo__.py,sha256=G6QlkatrWucF445cQW7Kb2ZSgBzf7TiKLPwqkP0CoQU,2329
|
||||||
|
astroid/__pycache__/__init__.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/__pkginfo__.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/_ast.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/arguments.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/as_string.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/bases.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/builder.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/context.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/decorators.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/exceptions.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/helpers.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/inference.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/manager.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/mixins.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/modutils.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/node_classes.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/nodes.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/objects.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/protocols.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/raw_building.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/rebuilder.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/scoped_nodes.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/test_utils.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/transforms.cpython-37.pyc,,
|
||||||
|
astroid/__pycache__/util.cpython-37.pyc,,
|
||||||
|
astroid/_ast.py,sha256=n1U2HblBNrMhsmrjF84HUfIgEZ3PyHyiJJOrOkgiUFk,3385
|
||||||
|
astroid/arguments.py,sha256=KJcZn7HeEhj2fZICr-9Pi7iueCNDZRQWh0T7O-qb-AE,12558
|
||||||
|
astroid/as_string.py,sha256=8bOZWsGG79TLmlzRzPtmHdanIAqQUFTKiYH873iMhOw,22821
|
||||||
|
astroid/bases.py,sha256=wL9C23mHFaj7vhMqM83DdsU6kfP488aEjoFWaO8p6Cg,19175
|
||||||
|
astroid/brain/__pycache__/brain_argparse.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_attrs.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_boto3.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_builtin_inference.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_collections.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_crypt.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_curses.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_dataclasses.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_dateutil.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_fstrings.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_functools.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_gi.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_hashlib.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_http.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_io.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_mechanize.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_multiprocessing.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_namedtuple_enum.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_nose.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_numpy_core_fromnumeric.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_numpy_core_function_base.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_numpy_core_multiarray.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_numpy_core_numeric.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_numpy_core_numerictypes.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_numpy_core_umath.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_numpy_ndarray.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_numpy_random_mtrand.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_numpy_utils.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_pkg_resources.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_pytest.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_qt.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_random.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_re.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_responses.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_scipy_signal.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_six.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_ssl.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_subprocess.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_threading.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_typing.cpython-37.pyc,,
|
||||||
|
astroid/brain/__pycache__/brain_uuid.cpython-37.pyc,,
|
||||||
|
astroid/brain/brain_argparse.py,sha256=5XqcThekktCIWRlWAMs-R47wkbsOUSnQlsEbLEnRpsY,1041
|
||||||
|
astroid/brain/brain_attrs.py,sha256=k8zJqIXsIbQrncthrzyB5NtdPTktgVi9wG7nyl8xMzs,2208
|
||||||
|
astroid/brain/brain_boto3.py,sha256=nE8Cw_S_Gp___IszRDRkhEGS6WGrKcF_gTOs3GVxH9k,862
|
||||||
|
astroid/brain/brain_builtin_inference.py,sha256=F6_09yM2mmu_u3ad_f9Uumc-q0lDA2CY8v9-PYtUMmA,28793
|
||||||
|
astroid/brain/brain_collections.py,sha256=Uqi4VmpLDl0ndQa9x-5tIXRtVdtI6TlwR9KNHmOqLyw,2724
|
||||||
|
astroid/brain/brain_crypt.py,sha256=gA7Q4GVuAM4viuTGWM6SNTPQXv5Gr_mFapyKMTRcsJ0,875
|
||||||
|
astroid/brain/brain_curses.py,sha256=tDnlCP1bEvleqCMz856yua9mM5um1p_JendFhT4rBFk,3303
|
||||||
|
astroid/brain/brain_dataclasses.py,sha256=5WndOYSY0oi2v-Od6KdPte-FKt00LoNRH2riSB4S1os,1647
|
||||||
|
astroid/brain/brain_dateutil.py,sha256=GwDrgbaUkKbp3ImLAvuUtPuDBeK3lPh0bNI_Wphm2_8,801
|
||||||
|
astroid/brain/brain_fstrings.py,sha256=Jaf-G-wkLecwG4jfjjfR8MDKzgAjjn2mgrrWZQLOAd8,2126
|
||||||
|
astroid/brain/brain_functools.py,sha256=Nljy7o2vu16S2amFot4wdTI0U76Yafq-ujVPHOdGgCE,5481
|
||||||
|
astroid/brain/brain_gi.py,sha256=oraXhBWyCCxmPEAEvRboeTIho0--ORObvckni00_1wY,7554
|
||||||
|
astroid/brain/brain_hashlib.py,sha256=W2cS6-rixdBcre6lPWIuSOqPLCcVji5JBlImdPbV6Qo,2292
|
||||||
|
astroid/brain/brain_http.py,sha256=a_8eIACvZetnR2xI4ZARVMuB1WSjyyqM3rCl2DVltMo,10524
|
||||||
|
astroid/brain/brain_io.py,sha256=wEY3vvTeV23tYxFn8HHQeyjhb7-jqzwgwNI-kl2Yu-c,1476
|
||||||
|
astroid/brain/brain_mechanize.py,sha256=boZxoCxPGSpHC_RccO5U026hyXyhunXR55M9WM1lYTo,895
|
||||||
|
astroid/brain/brain_multiprocessing.py,sha256=9OswtRuVBj-KemJ0yp4prz8mrkJDzOzN6n13u2MgmwM,3096
|
||||||
|
astroid/brain/brain_namedtuple_enum.py,sha256=eZ8IaHPLLHBakywJ3q4Ogtd2Tk0gtNcAgYAloMAKTjM,15966
|
||||||
|
astroid/brain/brain_nose.py,sha256=PSPmme611h7fC8MKuVXbiGw0HZhdmIuoxM6yieZ1OOc,2217
|
||||||
|
astroid/brain/brain_numpy_core_fromnumeric.py,sha256=NxiHbcMyQQ3Gpx4KEA5eAmGrpjlPN5rfXjRLjHPOVkw,621
|
||||||
|
astroid/brain/brain_numpy_core_function_base.py,sha256=7i6Kge_PviqoWXhbeRgB581xwLo0dxvO54_5UB3ppig,1168
|
||||||
|
astroid/brain/brain_numpy_core_multiarray.py,sha256=vr-nBt3EF_z-UmHmcAlJhGorgDXPpQaYX8g4TWu_2Vw,4015
|
||||||
|
astroid/brain/brain_numpy_core_numeric.py,sha256=M0RXOym2YC-DaZfRqGNIpr6s-Oh1KHn1okGr3PtPl0k,1384
|
||||||
|
astroid/brain/brain_numpy_core_numerictypes.py,sha256=ltlZyQprEbVdUJpC_ERGyXyJsYwzFHx7zGYDLheIonA,8013
|
||||||
|
astroid/brain/brain_numpy_core_umath.py,sha256=je6K3ILMen2mgkZseHCOjOgnFV6SaNgAihEi6irhbRk,4436
|
||||||
|
astroid/brain/brain_numpy_ndarray.py,sha256=WZbRG7GgOWZ68sEr4JjZUnJHLfUc91xp2mucHeLMrnw,8463
|
||||||
|
astroid/brain/brain_numpy_random_mtrand.py,sha256=WRy_CStllgZN2B3Dw2qxXbY4SBrCzu-cdaK230VQHaE,3278
|
||||||
|
astroid/brain/brain_numpy_utils.py,sha256=ZYtCVmn1x6P7iwYFohdW3CCrvVT5BCNYe-7jKcz_25s,1875
|
||||||
|
astroid/brain/brain_pkg_resources.py,sha256=S_5UED1Zg8ObEJumRdpYGnjxZzemh_G_NFj3p5NGPfc,2262
|
||||||
|
astroid/brain/brain_pytest.py,sha256=RYp7StKnC22n4vFJkHH5h7DAFWtouIcg-ZCXQ8Oz3xk,2390
|
||||||
|
astroid/brain/brain_qt.py,sha256=m2s4YXFrnOynWDf9omHOBLVqFriBdGJAmvarJCxiffM,2536
|
||||||
|
astroid/brain/brain_random.py,sha256=2RZY-QEXMNWp7E6h0l0-ke-DtjKTOFlTdjiQZi3XdQc,2432
|
||||||
|
astroid/brain/brain_re.py,sha256=le7VJHUAf80HyE_aQCh7_8FyDVK6JwNWA--c9RaMVQ8,1128
|
||||||
|
astroid/brain/brain_responses.py,sha256=GIAGkwMEGEZ9bJHI9uBGs_UmUy3DRBtjI_j_8dLBVsc,1534
|
||||||
|
astroid/brain/brain_scipy_signal.py,sha256=IKNnGXzEH5FKhPHM2hv57pNdo1emThWwZ0ksckdsOeE,2255
|
||||||
|
astroid/brain/brain_six.py,sha256=79aws4au6ZQJuf-YhBT4R-9wuVOwg-u0T42aUhCswK0,6187
|
||||||
|
astroid/brain/brain_ssl.py,sha256=9dMCTQ0JsX2gpdmBkYO7BByw3zN23oXRL8Svo2S1V28,3722
|
||||||
|
astroid/brain/brain_subprocess.py,sha256=yp-HsE69uh7T7C1kZYciAdRMQ48aNT51lI032oDppDk,4688
|
||||||
|
astroid/brain/brain_threading.py,sha256=dY8YwZ-zrB30_CQFYWh4AK3qUVssakgwLVwunQ6yYkU,837
|
||||||
|
astroid/brain/brain_typing.py,sha256=iFw33beNCitCJjJNvccIY6SsFJcdKVDdl-56DxDioh0,2780
|
||||||
|
astroid/brain/brain_uuid.py,sha256=YzfiOXavu515cS1prsKGfY4-12g_KWT0Yr4-5ti0v74,569
|
||||||
|
astroid/builder.py,sha256=72JlHrXRF9sS5zh1mqXlRHGFg88Efc2rm9yRJKDIShA,16891
|
||||||
|
astroid/context.py,sha256=MpwiEzWZ39a4WyqYgbSmePL2nZLqALt1gjrvi3TP35U,5169
|
||||||
|
astroid/decorators.py,sha256=z_wTjsiMlu_ElHtYUUuxaB2F_s4G0Ks7bmtCZS3IQ_Q,4283
|
||||||
|
astroid/exceptions.py,sha256=GLiZo9BdWILJShO-il8ra-tPZqaODMAX987F--LWv2w,6891
|
||||||
|
astroid/helpers.py,sha256=3YoJeVLoS-66T_abDorUNHiP8m2R7-faNnpc5yPJhrc,9448
|
||||||
|
astroid/inference.py,sha256=UiKKPRYqb5JINQIw1lSdBniHhXjCohCGAqycp2GkVI4,34686
|
||||||
|
astroid/interpreter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||||
|
astroid/interpreter/__pycache__/__init__.cpython-37.pyc,,
|
||||||
|
astroid/interpreter/__pycache__/dunder_lookup.cpython-37.pyc,,
|
||||||
|
astroid/interpreter/__pycache__/objectmodel.cpython-37.pyc,,
|
||||||
|
astroid/interpreter/_import/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||||
|
astroid/interpreter/_import/__pycache__/__init__.cpython-37.pyc,,
|
||||||
|
astroid/interpreter/_import/__pycache__/spec.cpython-37.pyc,,
|
||||||
|
astroid/interpreter/_import/__pycache__/util.cpython-37.pyc,,
|
||||||
|
astroid/interpreter/_import/spec.py,sha256=rZ9kX3I0xPo_pFAYWeOk2Xbi4ZIg_5bRsouZgxOXegA,11436
|
||||||
|
astroid/interpreter/_import/util.py,sha256=inubUz6F3_kaMFaeleKUW6E6wCMIPrhU882zvwEZ02I,255
|
||||||
|
astroid/interpreter/dunder_lookup.py,sha256=dP-AZU_aGPNt03b1ttrMglxzeU3NtgnG0MfpSLPH6sg,2155
|
||||||
|
astroid/interpreter/objectmodel.py,sha256=bbPIaamrqrx7WHtG5YNs9dbrlDC00GrJPxPGoSTsnqg,25792
|
||||||
|
astroid/manager.py,sha256=jmEm9uH00mPA2Y68s10xrPNbZaadv_2c-CWluB3SYoE,13701
|
||||||
|
astroid/mixins.py,sha256=F2rv2Ow7AU3YT_2jitVJik95ZWRVK6hpf8BrkkspzUY,5571
|
||||||
|
astroid/modutils.py,sha256=GBW5Z691eqf6VAnPsZzeQ0WYzrl-0GGTHkkZNb_9XRQ,23242
|
||||||
|
astroid/node_classes.py,sha256=cBRkZ_u8ZoRkiXznYWq1L3I7cO-P9nGowNCy8T7Qpzk,142740
|
||||||
|
astroid/nodes.py,sha256=WoyRe22GNVRc2TRHWOUlqdxCdOVD8GKOq9v1LpPhkr8,2978
|
||||||
|
astroid/objects.py,sha256=caKeQPBtrrfqa1q844vkehXwpdMzvph5YJdJJdbD_m8,11035
|
||||||
|
astroid/protocols.py,sha256=m1ZHvKvFQZSZp993na4f9s8V17kqNPRfH-XpQc8gJ7c,27396
|
||||||
|
astroid/raw_building.py,sha256=PI70y2mPQ7JURDVyNZ6deeBFkvjNNaOQBkuo0VPbvQ4,17340
|
||||||
|
astroid/rebuilder.py,sha256=xn82eWlxzGcDd2VACUnNNWCxArfV9HI8g67fUip0XFk,39411
|
||||||
|
astroid/scoped_nodes.py,sha256=fUrmTyltaLCr9-i8RdC2e5dPA9O8w946Mvvft8mgXdM,98203
|
||||||
|
astroid/test_utils.py,sha256=axGB3j6ZEaVspL1ZgPizKgWehNEREb58Z97U7mQ-GA8,2319
|
||||||
|
astroid/transforms.py,sha256=1npwJWcQUSIjcpcWd1pc-dJhtHOyiboQHsETAIQd5co,3377
|
||||||
|
astroid/util.py,sha256=jg5LnqbWSZTZP1KgpxGBuC6Lfwhn9Jb2T2TohXghmC0,4785
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
Wheel-Version: 1.0
|
||||||
|
Generator: bdist_wheel (0.34.2)
|
||||||
|
Root-Is-Purelib: true
|
||||||
|
Tag: py3-none-any
|
||||||
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
astroid
|
||||||
|
|
@ -0,0 +1,168 @@
|
||||||
|
# Copyright (c) 2006-2013, 2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
|
||||||
|
# Copyright (c) 2014 Google, Inc.
|
||||||
|
# Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com>
|
||||||
|
# Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
# Copyright (c) 2016 Derek Gustafson <degustaf@gmail.com>
|
||||||
|
# Copyright (c) 2016 Moises Lopez <moylop260@vauxoo.com>
|
||||||
|
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
|
||||||
|
# Copyright (c) 2019 Nick Drozd <nicholasdrozd@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
"""Python Abstract Syntax Tree New Generation
|
||||||
|
|
||||||
|
The aim of this module is to provide a common base representation of
|
||||||
|
python source code for projects such as pychecker, pyreverse,
|
||||||
|
pylint... Well, actually the development of this library is essentially
|
||||||
|
governed by pylint's needs.
|
||||||
|
|
||||||
|
It extends class defined in the python's _ast module with some
|
||||||
|
additional methods and attributes. Instance attributes are added by a
|
||||||
|
builder object, which can either generate extended ast (let's call
|
||||||
|
them astroid ;) by visiting an existent ast tree or by inspecting living
|
||||||
|
object. Methods are added by monkey patching ast classes.
|
||||||
|
|
||||||
|
Main modules are:
|
||||||
|
|
||||||
|
* nodes and scoped_nodes for more information about methods and
|
||||||
|
attributes added to different node classes
|
||||||
|
|
||||||
|
* the manager contains a high level object to get astroid trees from
|
||||||
|
source files and living objects. It maintains a cache of previously
|
||||||
|
constructed tree for quick access
|
||||||
|
|
||||||
|
* builder contains the class responsible to build astroid trees
|
||||||
|
"""
|
||||||
|
|
||||||
|
import enum
|
||||||
|
import itertools
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import wrapt
|
||||||
|
|
||||||
|
|
||||||
|
_Context = enum.Enum("Context", "Load Store Del")
|
||||||
|
Load = _Context.Load
|
||||||
|
Store = _Context.Store
|
||||||
|
Del = _Context.Del
|
||||||
|
del _Context
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=wrong-import-order,wrong-import-position
|
||||||
|
from .__pkginfo__ import version as __version__
|
||||||
|
|
||||||
|
# WARNING: internal imports order matters !
|
||||||
|
|
||||||
|
# pylint: disable=redefined-builtin
|
||||||
|
|
||||||
|
# make all exception classes accessible from astroid package
|
||||||
|
from astroid.exceptions import *
|
||||||
|
|
||||||
|
# make all node classes accessible from astroid package
|
||||||
|
from astroid.nodes import *
|
||||||
|
|
||||||
|
# trigger extra monkey-patching
|
||||||
|
from astroid import inference
|
||||||
|
|
||||||
|
# more stuff available
|
||||||
|
from astroid import raw_building
|
||||||
|
from astroid.bases import BaseInstance, Instance, BoundMethod, UnboundMethod
|
||||||
|
from astroid.node_classes import are_exclusive, unpack_infer
|
||||||
|
from astroid.scoped_nodes import builtin_lookup
|
||||||
|
from astroid.builder import parse, extract_node
|
||||||
|
from astroid.util import Uninferable
|
||||||
|
|
||||||
|
# make a manager instance (borg) accessible from astroid package
|
||||||
|
from astroid.manager import AstroidManager
|
||||||
|
|
||||||
|
MANAGER = AstroidManager()
|
||||||
|
del AstroidManager
|
||||||
|
|
||||||
|
# transform utilities (filters and decorator)
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=dangerous-default-value
|
||||||
|
@wrapt.decorator
|
||||||
|
def _inference_tip_cached(func, instance, args, kwargs, _cache={}):
|
||||||
|
"""Cache decorator used for inference tips"""
|
||||||
|
node = args[0]
|
||||||
|
try:
|
||||||
|
return iter(_cache[func, node])
|
||||||
|
except KeyError:
|
||||||
|
result = func(*args, **kwargs)
|
||||||
|
# Need to keep an iterator around
|
||||||
|
original, copy = itertools.tee(result)
|
||||||
|
_cache[func, node] = list(copy)
|
||||||
|
return original
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: enable=dangerous-default-value
|
||||||
|
|
||||||
|
|
||||||
|
def inference_tip(infer_function, raise_on_overwrite=False):
|
||||||
|
"""Given an instance specific inference function, return a function to be
|
||||||
|
given to MANAGER.register_transform to set this inference function.
|
||||||
|
|
||||||
|
:param bool raise_on_overwrite: Raise an `InferenceOverwriteError`
|
||||||
|
if the inference tip will overwrite another. Used for debugging
|
||||||
|
|
||||||
|
Typical usage
|
||||||
|
|
||||||
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
MANAGER.register_transform(Call, inference_tip(infer_named_tuple),
|
||||||
|
predicate)
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
|
||||||
|
Using an inference tip will override
|
||||||
|
any previously set inference tip for the given
|
||||||
|
node. Use a predicate in the transform to prevent
|
||||||
|
excess overwrites.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def transform(node, infer_function=infer_function):
|
||||||
|
if (
|
||||||
|
raise_on_overwrite
|
||||||
|
and node._explicit_inference is not None
|
||||||
|
and node._explicit_inference is not infer_function
|
||||||
|
):
|
||||||
|
raise InferenceOverwriteError(
|
||||||
|
"Inference already set to {existing_inference}. "
|
||||||
|
"Trying to overwrite with {new_inference} for {node}".format(
|
||||||
|
existing_inference=infer_function,
|
||||||
|
new_inference=node._explicit_inference,
|
||||||
|
node=node,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# pylint: disable=no-value-for-parameter
|
||||||
|
node._explicit_inference = _inference_tip_cached(infer_function)
|
||||||
|
return node
|
||||||
|
|
||||||
|
return transform
|
||||||
|
|
||||||
|
|
||||||
|
def register_module_extender(manager, module_name, get_extension_mod):
|
||||||
|
def transform(node):
|
||||||
|
extension_module = get_extension_mod()
|
||||||
|
for name, objs in extension_module.locals.items():
|
||||||
|
node.locals[name] = objs
|
||||||
|
for obj in objs:
|
||||||
|
if obj.parent is extension_module:
|
||||||
|
obj.parent = node
|
||||||
|
|
||||||
|
manager.register_transform(Module, transform, lambda n: n.name == module_name)
|
||||||
|
|
||||||
|
|
||||||
|
# load brain plugins
|
||||||
|
BRAIN_MODULES_DIR = os.path.join(os.path.dirname(__file__), "brain")
|
||||||
|
if BRAIN_MODULES_DIR not in sys.path:
|
||||||
|
# add it to the end of the list so user path take precedence
|
||||||
|
sys.path.append(BRAIN_MODULES_DIR)
|
||||||
|
# load modules in this directory
|
||||||
|
for module in os.listdir(BRAIN_MODULES_DIR):
|
||||||
|
if module.endswith(".py"):
|
||||||
|
__import__(module[:-3])
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2006-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
|
||||||
|
# Copyright (c) 2014-2019 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2014 Google, Inc.
|
||||||
|
# Copyright (c) 2015-2017 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
# Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
|
||||||
|
# Copyright (c) 2015 Radosław Ganczarek <radoslaw@ganczarek.in>
|
||||||
|
# Copyright (c) 2016 Moises Lopez <moylop260@vauxoo.com>
|
||||||
|
# Copyright (c) 2017 Hugo <hugovk@users.noreply.github.com>
|
||||||
|
# Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
|
||||||
|
# Copyright (c) 2017 Calen Pennington <cale@edx.org>
|
||||||
|
# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
|
||||||
|
# Copyright (c) 2018 Ashley Whetter <ashley@awhetter.co.uk>
|
||||||
|
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
|
||||||
|
# Copyright (c) 2019 Uilian Ries <uilianries@gmail.com>
|
||||||
|
# Copyright (c) 2019 Thomas Hisch <t.hisch@gmail.com>
|
||||||
|
# Copyright (c) 2020 Michael <michael-k@users.noreply.github.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
"""astroid packaging information"""
|
||||||
|
|
||||||
|
version = "2.4.2"
|
||||||
|
numversion = tuple(int(elem) for elem in version.split(".") if elem.isdigit())
|
||||||
|
|
||||||
|
extras_require = {}
|
||||||
|
install_requires = [
|
||||||
|
"lazy_object_proxy==1.4.*",
|
||||||
|
"six~=1.12",
|
||||||
|
"wrapt~=1.11",
|
||||||
|
'typed-ast>=1.4.0,<1.5;implementation_name== "cpython" and python_version<"3.8"',
|
||||||
|
]
|
||||||
|
|
||||||
|
# pylint: disable=redefined-builtin; why license is a builtin anyway?
|
||||||
|
license = "LGPL"
|
||||||
|
|
||||||
|
author = "Python Code Quality Authority"
|
||||||
|
author_email = "code-quality@python.org"
|
||||||
|
mailinglist = "mailto://%s" % author_email
|
||||||
|
web = "https://github.com/PyCQA/astroid"
|
||||||
|
|
||||||
|
description = "An abstract syntax tree for Python with inference support."
|
||||||
|
|
||||||
|
classifiers = [
|
||||||
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
|
"Topic :: Software Development :: Quality Assurance",
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"Programming Language :: Python :: 3",
|
||||||
|
"Programming Language :: Python :: 3.5",
|
||||||
|
"Programming Language :: Python :: 3.6",
|
||||||
|
"Programming Language :: Python :: 3.7",
|
||||||
|
"Programming Language :: Python :: 3.8",
|
||||||
|
"Programming Language :: Python :: Implementation :: CPython",
|
||||||
|
"Programming Language :: Python :: Implementation :: PyPy",
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
import ast
|
||||||
|
from collections import namedtuple
|
||||||
|
from functools import partial
|
||||||
|
from typing import Optional
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
|
||||||
|
_ast_py3 = None
|
||||||
|
try:
|
||||||
|
import typed_ast.ast3 as _ast_py3
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
PY38 = sys.version_info[:2] >= (3, 8)
|
||||||
|
if PY38:
|
||||||
|
# On Python 3.8, typed_ast was merged back into `ast`
|
||||||
|
_ast_py3 = ast
|
||||||
|
|
||||||
|
|
||||||
|
FunctionType = namedtuple("FunctionType", ["argtypes", "returns"])
|
||||||
|
|
||||||
|
|
||||||
|
class ParserModule(
|
||||||
|
namedtuple(
|
||||||
|
"ParserModule",
|
||||||
|
[
|
||||||
|
"module",
|
||||||
|
"unary_op_classes",
|
||||||
|
"cmp_op_classes",
|
||||||
|
"bool_op_classes",
|
||||||
|
"bin_op_classes",
|
||||||
|
"context_classes",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
):
|
||||||
|
def parse(self, string: str, type_comments=True):
|
||||||
|
if self.module is _ast_py3:
|
||||||
|
if PY38:
|
||||||
|
parse_func = partial(self.module.parse, type_comments=type_comments)
|
||||||
|
else:
|
||||||
|
parse_func = partial(
|
||||||
|
self.module.parse, feature_version=sys.version_info.minor
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
parse_func = self.module.parse
|
||||||
|
return parse_func(string)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_function_type_comment(type_comment: str) -> Optional[FunctionType]:
|
||||||
|
"""Given a correct type comment, obtain a FunctionType object"""
|
||||||
|
if _ast_py3 is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
func_type = _ast_py3.parse(type_comment, "<type_comment>", "func_type")
|
||||||
|
return FunctionType(argtypes=func_type.argtypes, returns=func_type.returns)
|
||||||
|
|
||||||
|
|
||||||
|
def get_parser_module(type_comments=True) -> ParserModule:
|
||||||
|
if not type_comments:
|
||||||
|
parser_module = ast
|
||||||
|
else:
|
||||||
|
parser_module = _ast_py3
|
||||||
|
parser_module = parser_module or ast
|
||||||
|
|
||||||
|
unary_op_classes = _unary_operators_from_module(parser_module)
|
||||||
|
cmp_op_classes = _compare_operators_from_module(parser_module)
|
||||||
|
bool_op_classes = _bool_operators_from_module(parser_module)
|
||||||
|
bin_op_classes = _binary_operators_from_module(parser_module)
|
||||||
|
context_classes = _contexts_from_module(parser_module)
|
||||||
|
|
||||||
|
return ParserModule(
|
||||||
|
parser_module,
|
||||||
|
unary_op_classes,
|
||||||
|
cmp_op_classes,
|
||||||
|
bool_op_classes,
|
||||||
|
bin_op_classes,
|
||||||
|
context_classes,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _unary_operators_from_module(module):
|
||||||
|
return {module.UAdd: "+", module.USub: "-", module.Not: "not", module.Invert: "~"}
|
||||||
|
|
||||||
|
|
||||||
|
def _binary_operators_from_module(module):
|
||||||
|
binary_operators = {
|
||||||
|
module.Add: "+",
|
||||||
|
module.BitAnd: "&",
|
||||||
|
module.BitOr: "|",
|
||||||
|
module.BitXor: "^",
|
||||||
|
module.Div: "/",
|
||||||
|
module.FloorDiv: "//",
|
||||||
|
module.MatMult: "@",
|
||||||
|
module.Mod: "%",
|
||||||
|
module.Mult: "*",
|
||||||
|
module.Pow: "**",
|
||||||
|
module.Sub: "-",
|
||||||
|
module.LShift: "<<",
|
||||||
|
module.RShift: ">>",
|
||||||
|
}
|
||||||
|
return binary_operators
|
||||||
|
|
||||||
|
|
||||||
|
def _bool_operators_from_module(module):
|
||||||
|
return {module.And: "and", module.Or: "or"}
|
||||||
|
|
||||||
|
|
||||||
|
def _compare_operators_from_module(module):
|
||||||
|
return {
|
||||||
|
module.Eq: "==",
|
||||||
|
module.Gt: ">",
|
||||||
|
module.GtE: ">=",
|
||||||
|
module.In: "in",
|
||||||
|
module.Is: "is",
|
||||||
|
module.IsNot: "is not",
|
||||||
|
module.Lt: "<",
|
||||||
|
module.LtE: "<=",
|
||||||
|
module.NotEq: "!=",
|
||||||
|
module.NotIn: "not in",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _contexts_from_module(module):
|
||||||
|
return {
|
||||||
|
module.Load: astroid.Load,
|
||||||
|
module.Store: astroid.Store,
|
||||||
|
module.Del: astroid.Del,
|
||||||
|
module.Param: astroid.Store,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,300 @@
|
||||||
|
# Copyright (c) 2015-2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
|
||||||
|
# Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
|
||||||
|
# Copyright (c) 2018 Anthony Sottile <asottile@umich.edu>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
|
||||||
|
from astroid import bases
|
||||||
|
from astroid import context as contextmod
|
||||||
|
from astroid import exceptions
|
||||||
|
from astroid import nodes
|
||||||
|
from astroid import util
|
||||||
|
|
||||||
|
|
||||||
|
class CallSite:
|
||||||
|
"""Class for understanding arguments passed into a call site
|
||||||
|
|
||||||
|
It needs a call context, which contains the arguments and the
|
||||||
|
keyword arguments that were passed into a given call site.
|
||||||
|
In order to infer what an argument represents, call :meth:`infer_argument`
|
||||||
|
with the corresponding function node and the argument name.
|
||||||
|
|
||||||
|
:param callcontext:
|
||||||
|
An instance of :class:`astroid.context.CallContext`, that holds
|
||||||
|
the arguments for the call site.
|
||||||
|
:param argument_context_map:
|
||||||
|
Additional contexts per node, passed in from :attr:`astroid.context.Context.extra_context`
|
||||||
|
:param context:
|
||||||
|
An instance of :class:`astroid.context.Context`.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, callcontext, argument_context_map=None, context=None):
|
||||||
|
if argument_context_map is None:
|
||||||
|
argument_context_map = {}
|
||||||
|
self.argument_context_map = argument_context_map
|
||||||
|
args = callcontext.args
|
||||||
|
keywords = callcontext.keywords
|
||||||
|
self.duplicated_keywords = set()
|
||||||
|
self._unpacked_args = self._unpack_args(args, context=context)
|
||||||
|
self._unpacked_kwargs = self._unpack_keywords(keywords, context=context)
|
||||||
|
|
||||||
|
self.positional_arguments = [
|
||||||
|
arg for arg in self._unpacked_args if arg is not util.Uninferable
|
||||||
|
]
|
||||||
|
self.keyword_arguments = {
|
||||||
|
key: value
|
||||||
|
for key, value in self._unpacked_kwargs.items()
|
||||||
|
if value is not util.Uninferable
|
||||||
|
}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_call(cls, call_node, context=None):
|
||||||
|
"""Get a CallSite object from the given Call node.
|
||||||
|
|
||||||
|
:param context:
|
||||||
|
An instance of :class:`astroid.context.Context` that will be used
|
||||||
|
to force a single inference path.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Determine the callcontext from the given `context` object if any.
|
||||||
|
context = context or contextmod.InferenceContext()
|
||||||
|
callcontext = contextmod.CallContext(call_node.args, call_node.keywords)
|
||||||
|
return cls(callcontext, context=context)
|
||||||
|
|
||||||
|
def has_invalid_arguments(self):
|
||||||
|
"""Check if in the current CallSite were passed *invalid* arguments
|
||||||
|
|
||||||
|
This can mean multiple things. For instance, if an unpacking
|
||||||
|
of an invalid object was passed, then this method will return True.
|
||||||
|
Other cases can be when the arguments can't be inferred by astroid,
|
||||||
|
for example, by passing objects which aren't known statically.
|
||||||
|
"""
|
||||||
|
return len(self.positional_arguments) != len(self._unpacked_args)
|
||||||
|
|
||||||
|
def has_invalid_keywords(self):
|
||||||
|
"""Check if in the current CallSite were passed *invalid* keyword arguments
|
||||||
|
|
||||||
|
For instance, unpacking a dictionary with integer keys is invalid
|
||||||
|
(**{1:2}), because the keys must be strings, which will make this
|
||||||
|
method to return True. Other cases where this might return True if
|
||||||
|
objects which can't be inferred were passed.
|
||||||
|
"""
|
||||||
|
return len(self.keyword_arguments) != len(self._unpacked_kwargs)
|
||||||
|
|
||||||
|
def _unpack_keywords(self, keywords, context=None):
|
||||||
|
values = {}
|
||||||
|
context = context or contextmod.InferenceContext()
|
||||||
|
context.extra_context = self.argument_context_map
|
||||||
|
for name, value in keywords:
|
||||||
|
if name is None:
|
||||||
|
# Then it's an unpacking operation (**)
|
||||||
|
try:
|
||||||
|
inferred = next(value.infer(context=context))
|
||||||
|
except exceptions.InferenceError:
|
||||||
|
values[name] = util.Uninferable
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not isinstance(inferred, nodes.Dict):
|
||||||
|
# Not something we can work with.
|
||||||
|
values[name] = util.Uninferable
|
||||||
|
continue
|
||||||
|
|
||||||
|
for dict_key, dict_value in inferred.items:
|
||||||
|
try:
|
||||||
|
dict_key = next(dict_key.infer(context=context))
|
||||||
|
except exceptions.InferenceError:
|
||||||
|
values[name] = util.Uninferable
|
||||||
|
continue
|
||||||
|
if not isinstance(dict_key, nodes.Const):
|
||||||
|
values[name] = util.Uninferable
|
||||||
|
continue
|
||||||
|
if not isinstance(dict_key.value, str):
|
||||||
|
values[name] = util.Uninferable
|
||||||
|
continue
|
||||||
|
if dict_key.value in values:
|
||||||
|
# The name is already in the dictionary
|
||||||
|
values[dict_key.value] = util.Uninferable
|
||||||
|
self.duplicated_keywords.add(dict_key.value)
|
||||||
|
continue
|
||||||
|
values[dict_key.value] = dict_value
|
||||||
|
else:
|
||||||
|
values[name] = value
|
||||||
|
return values
|
||||||
|
|
||||||
|
def _unpack_args(self, args, context=None):
|
||||||
|
values = []
|
||||||
|
context = context or contextmod.InferenceContext()
|
||||||
|
context.extra_context = self.argument_context_map
|
||||||
|
for arg in args:
|
||||||
|
if isinstance(arg, nodes.Starred):
|
||||||
|
try:
|
||||||
|
inferred = next(arg.value.infer(context=context))
|
||||||
|
except exceptions.InferenceError:
|
||||||
|
values.append(util.Uninferable)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if inferred is util.Uninferable:
|
||||||
|
values.append(util.Uninferable)
|
||||||
|
continue
|
||||||
|
if not hasattr(inferred, "elts"):
|
||||||
|
values.append(util.Uninferable)
|
||||||
|
continue
|
||||||
|
values.extend(inferred.elts)
|
||||||
|
else:
|
||||||
|
values.append(arg)
|
||||||
|
return values
|
||||||
|
|
||||||
|
def infer_argument(self, funcnode, name, context):
|
||||||
|
"""infer a function argument value according to the call context
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
funcnode: The function being called.
|
||||||
|
name: The name of the argument whose value is being inferred.
|
||||||
|
context: Inference context object
|
||||||
|
"""
|
||||||
|
if name in self.duplicated_keywords:
|
||||||
|
raise exceptions.InferenceError(
|
||||||
|
"The arguments passed to {func!r} " " have duplicate keywords.",
|
||||||
|
call_site=self,
|
||||||
|
func=funcnode,
|
||||||
|
arg=name,
|
||||||
|
context=context,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Look into the keywords first, maybe it's already there.
|
||||||
|
try:
|
||||||
|
return self.keyword_arguments[name].infer(context)
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Too many arguments given and no variable arguments.
|
||||||
|
if len(self.positional_arguments) > len(funcnode.args.args):
|
||||||
|
if not funcnode.args.vararg:
|
||||||
|
raise exceptions.InferenceError(
|
||||||
|
"Too many positional arguments "
|
||||||
|
"passed to {func!r} that does "
|
||||||
|
"not have *args.",
|
||||||
|
call_site=self,
|
||||||
|
func=funcnode,
|
||||||
|
arg=name,
|
||||||
|
context=context,
|
||||||
|
)
|
||||||
|
|
||||||
|
positional = self.positional_arguments[: len(funcnode.args.args)]
|
||||||
|
vararg = self.positional_arguments[len(funcnode.args.args) :]
|
||||||
|
argindex = funcnode.args.find_argname(name)[0]
|
||||||
|
kwonlyargs = {arg.name for arg in funcnode.args.kwonlyargs}
|
||||||
|
kwargs = {
|
||||||
|
key: value
|
||||||
|
for key, value in self.keyword_arguments.items()
|
||||||
|
if key not in kwonlyargs
|
||||||
|
}
|
||||||
|
# If there are too few positionals compared to
|
||||||
|
# what the function expects to receive, check to see
|
||||||
|
# if the missing positional arguments were passed
|
||||||
|
# as keyword arguments and if so, place them into the
|
||||||
|
# positional args list.
|
||||||
|
if len(positional) < len(funcnode.args.args):
|
||||||
|
for func_arg in funcnode.args.args:
|
||||||
|
if func_arg.name in kwargs:
|
||||||
|
arg = kwargs.pop(func_arg.name)
|
||||||
|
positional.append(arg)
|
||||||
|
|
||||||
|
if argindex is not None:
|
||||||
|
# 2. first argument of instance/class method
|
||||||
|
if argindex == 0 and funcnode.type in ("method", "classmethod"):
|
||||||
|
if context.boundnode is not None:
|
||||||
|
boundnode = context.boundnode
|
||||||
|
else:
|
||||||
|
# XXX can do better ?
|
||||||
|
boundnode = funcnode.parent.frame()
|
||||||
|
|
||||||
|
if isinstance(boundnode, nodes.ClassDef):
|
||||||
|
# Verify that we're accessing a method
|
||||||
|
# of the metaclass through a class, as in
|
||||||
|
# `cls.metaclass_method`. In this case, the
|
||||||
|
# first argument is always the class.
|
||||||
|
method_scope = funcnode.parent.scope()
|
||||||
|
if method_scope is boundnode.metaclass():
|
||||||
|
return iter((boundnode,))
|
||||||
|
|
||||||
|
if funcnode.type == "method":
|
||||||
|
if not isinstance(boundnode, bases.Instance):
|
||||||
|
boundnode = boundnode.instantiate_class()
|
||||||
|
return iter((boundnode,))
|
||||||
|
if funcnode.type == "classmethod":
|
||||||
|
return iter((boundnode,))
|
||||||
|
# if we have a method, extract one position
|
||||||
|
# from the index, so we'll take in account
|
||||||
|
# the extra parameter represented by `self` or `cls`
|
||||||
|
if funcnode.type in ("method", "classmethod"):
|
||||||
|
argindex -= 1
|
||||||
|
# 2. search arg index
|
||||||
|
try:
|
||||||
|
return self.positional_arguments[argindex].infer(context)
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
if funcnode.args.kwarg == name:
|
||||||
|
# It wants all the keywords that were passed into
|
||||||
|
# the call site.
|
||||||
|
if self.has_invalid_keywords():
|
||||||
|
raise exceptions.InferenceError(
|
||||||
|
"Inference failed to find values for all keyword arguments "
|
||||||
|
"to {func!r}: {unpacked_kwargs!r} doesn't correspond to "
|
||||||
|
"{keyword_arguments!r}.",
|
||||||
|
keyword_arguments=self.keyword_arguments,
|
||||||
|
unpacked_kwargs=self._unpacked_kwargs,
|
||||||
|
call_site=self,
|
||||||
|
func=funcnode,
|
||||||
|
arg=name,
|
||||||
|
context=context,
|
||||||
|
)
|
||||||
|
kwarg = nodes.Dict(
|
||||||
|
lineno=funcnode.args.lineno,
|
||||||
|
col_offset=funcnode.args.col_offset,
|
||||||
|
parent=funcnode.args,
|
||||||
|
)
|
||||||
|
kwarg.postinit(
|
||||||
|
[(nodes.const_factory(key), value) for key, value in kwargs.items()]
|
||||||
|
)
|
||||||
|
return iter((kwarg,))
|
||||||
|
if funcnode.args.vararg == name:
|
||||||
|
# It wants all the args that were passed into
|
||||||
|
# the call site.
|
||||||
|
if self.has_invalid_arguments():
|
||||||
|
raise exceptions.InferenceError(
|
||||||
|
"Inference failed to find values for all positional "
|
||||||
|
"arguments to {func!r}: {unpacked_args!r} doesn't "
|
||||||
|
"correspond to {positional_arguments!r}.",
|
||||||
|
positional_arguments=self.positional_arguments,
|
||||||
|
unpacked_args=self._unpacked_args,
|
||||||
|
call_site=self,
|
||||||
|
func=funcnode,
|
||||||
|
arg=name,
|
||||||
|
context=context,
|
||||||
|
)
|
||||||
|
args = nodes.Tuple(
|
||||||
|
lineno=funcnode.args.lineno,
|
||||||
|
col_offset=funcnode.args.col_offset,
|
||||||
|
parent=funcnode.args,
|
||||||
|
)
|
||||||
|
args.postinit(vararg)
|
||||||
|
return iter((args,))
|
||||||
|
|
||||||
|
# Check if it's a default parameter.
|
||||||
|
try:
|
||||||
|
return funcnode.args.default_value(name).infer(context)
|
||||||
|
except exceptions.NoDefault:
|
||||||
|
pass
|
||||||
|
raise exceptions.InferenceError(
|
||||||
|
"No value found for argument {name} to " "{func!r}",
|
||||||
|
call_site=self,
|
||||||
|
func=funcnode,
|
||||||
|
arg=name,
|
||||||
|
context=context,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,631 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2009-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
|
||||||
|
# Copyright (c) 2010 Daniel Harding <dharding@gmail.com>
|
||||||
|
# Copyright (c) 2013-2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2013-2014 Google, Inc.
|
||||||
|
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
# Copyright (c) 2016 Jared Garst <jgarst@users.noreply.github.com>
|
||||||
|
# Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
|
||||||
|
# Copyright (c) 2017, 2019 Łukasz Rogalski <rogalski.91@gmail.com>
|
||||||
|
# Copyright (c) 2017 rr- <rr-@sakuya.pl>
|
||||||
|
# Copyright (c) 2018 Serhiy Storchaka <storchaka@gmail.com>
|
||||||
|
# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
|
||||||
|
# Copyright (c) 2018 brendanator <brendan.maginnis@gmail.com>
|
||||||
|
# Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
|
||||||
|
# Copyright (c) 2019 Alex Hall <alex.mojaki@gmail.com>
|
||||||
|
# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
"""This module renders Astroid nodes as string:
|
||||||
|
|
||||||
|
* :func:`to_code` function return equivalent (hopefully valid) python string
|
||||||
|
|
||||||
|
* :func:`dump` function return an internal representation of nodes found
|
||||||
|
in the tree, useful for debugging or understanding the tree structure
|
||||||
|
"""
|
||||||
|
|
||||||
|
# pylint: disable=unused-argument
|
||||||
|
|
||||||
|
DOC_NEWLINE = "\0"
|
||||||
|
|
||||||
|
|
||||||
|
class AsStringVisitor:
|
||||||
|
"""Visitor to render an Astroid node as a valid python code string"""
|
||||||
|
|
||||||
|
def __init__(self, indent):
|
||||||
|
self.indent = indent
|
||||||
|
|
||||||
|
def __call__(self, node):
|
||||||
|
"""Makes this visitor behave as a simple function"""
|
||||||
|
return node.accept(self).replace(DOC_NEWLINE, "\n")
|
||||||
|
|
||||||
|
def _docs_dedent(self, doc):
|
||||||
|
"""Stop newlines in docs being indented by self._stmt_list"""
|
||||||
|
return '\n%s"""%s"""' % (self.indent, doc.replace("\n", DOC_NEWLINE))
|
||||||
|
|
||||||
|
def _stmt_list(self, stmts, indent=True):
|
||||||
|
"""return a list of nodes to string"""
|
||||||
|
stmts = "\n".join(nstr for nstr in [n.accept(self) for n in stmts] if nstr)
|
||||||
|
if indent:
|
||||||
|
return self.indent + stmts.replace("\n", "\n" + self.indent)
|
||||||
|
|
||||||
|
return stmts
|
||||||
|
|
||||||
|
def _precedence_parens(self, node, child, is_left=True):
|
||||||
|
"""Wrap child in parens only if required to keep same semantics"""
|
||||||
|
if self._should_wrap(node, child, is_left):
|
||||||
|
return "(%s)" % child.accept(self)
|
||||||
|
|
||||||
|
return child.accept(self)
|
||||||
|
|
||||||
|
def _should_wrap(self, node, child, is_left):
|
||||||
|
"""Wrap child if:
|
||||||
|
- it has lower precedence
|
||||||
|
- same precedence with position opposite to associativity direction
|
||||||
|
"""
|
||||||
|
node_precedence = node.op_precedence()
|
||||||
|
child_precedence = child.op_precedence()
|
||||||
|
|
||||||
|
if node_precedence > child_precedence:
|
||||||
|
# 3 * (4 + 5)
|
||||||
|
return True
|
||||||
|
|
||||||
|
if (
|
||||||
|
node_precedence == child_precedence
|
||||||
|
and is_left != node.op_left_associative()
|
||||||
|
):
|
||||||
|
# 3 - (4 - 5)
|
||||||
|
# (2**3)**4
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
## visit_<node> methods ###########################################
|
||||||
|
|
||||||
|
def visit_await(self, node):
|
||||||
|
return "await %s" % node.value.accept(self)
|
||||||
|
|
||||||
|
def visit_asyncwith(self, node):
|
||||||
|
return "async %s" % self.visit_with(node)
|
||||||
|
|
||||||
|
def visit_asyncfor(self, node):
|
||||||
|
return "async %s" % self.visit_for(node)
|
||||||
|
|
||||||
|
def visit_arguments(self, node):
|
||||||
|
"""return an astroid.Function node as string"""
|
||||||
|
return node.format_args()
|
||||||
|
|
||||||
|
def visit_assignattr(self, node):
|
||||||
|
"""return an astroid.AssAttr node as string"""
|
||||||
|
return self.visit_attribute(node)
|
||||||
|
|
||||||
|
def visit_assert(self, node):
|
||||||
|
"""return an astroid.Assert node as string"""
|
||||||
|
if node.fail:
|
||||||
|
return "assert %s, %s" % (node.test.accept(self), node.fail.accept(self))
|
||||||
|
return "assert %s" % node.test.accept(self)
|
||||||
|
|
||||||
|
def visit_assignname(self, node):
|
||||||
|
"""return an astroid.AssName node as string"""
|
||||||
|
return node.name
|
||||||
|
|
||||||
|
def visit_assign(self, node):
|
||||||
|
"""return an astroid.Assign node as string"""
|
||||||
|
lhs = " = ".join(n.accept(self) for n in node.targets)
|
||||||
|
return "%s = %s" % (lhs, node.value.accept(self))
|
||||||
|
|
||||||
|
def visit_augassign(self, node):
|
||||||
|
"""return an astroid.AugAssign node as string"""
|
||||||
|
return "%s %s %s" % (node.target.accept(self), node.op, node.value.accept(self))
|
||||||
|
|
||||||
|
def visit_annassign(self, node):
|
||||||
|
"""Return an astroid.AugAssign node as string"""
|
||||||
|
|
||||||
|
target = node.target.accept(self)
|
||||||
|
annotation = node.annotation.accept(self)
|
||||||
|
if node.value is None:
|
||||||
|
return "%s: %s" % (target, annotation)
|
||||||
|
return "%s: %s = %s" % (target, annotation, node.value.accept(self))
|
||||||
|
|
||||||
|
def visit_repr(self, node):
|
||||||
|
"""return an astroid.Repr node as string"""
|
||||||
|
return "`%s`" % node.value.accept(self)
|
||||||
|
|
||||||
|
def visit_binop(self, node):
|
||||||
|
"""return an astroid.BinOp node as string"""
|
||||||
|
left = self._precedence_parens(node, node.left)
|
||||||
|
right = self._precedence_parens(node, node.right, is_left=False)
|
||||||
|
if node.op == "**":
|
||||||
|
return "%s%s%s" % (left, node.op, right)
|
||||||
|
|
||||||
|
return "%s %s %s" % (left, node.op, right)
|
||||||
|
|
||||||
|
def visit_boolop(self, node):
|
||||||
|
"""return an astroid.BoolOp node as string"""
|
||||||
|
values = ["%s" % self._precedence_parens(node, n) for n in node.values]
|
||||||
|
return (" %s " % node.op).join(values)
|
||||||
|
|
||||||
|
def visit_break(self, node):
|
||||||
|
"""return an astroid.Break node as string"""
|
||||||
|
return "break"
|
||||||
|
|
||||||
|
def visit_call(self, node):
|
||||||
|
"""return an astroid.Call node as string"""
|
||||||
|
expr_str = self._precedence_parens(node, node.func)
|
||||||
|
args = [arg.accept(self) for arg in node.args]
|
||||||
|
if node.keywords:
|
||||||
|
keywords = [kwarg.accept(self) for kwarg in node.keywords]
|
||||||
|
else:
|
||||||
|
keywords = []
|
||||||
|
|
||||||
|
args.extend(keywords)
|
||||||
|
return "%s(%s)" % (expr_str, ", ".join(args))
|
||||||
|
|
||||||
|
def visit_classdef(self, node):
|
||||||
|
"""return an astroid.ClassDef node as string"""
|
||||||
|
decorate = node.decorators.accept(self) if node.decorators else ""
|
||||||
|
args = [n.accept(self) for n in node.bases]
|
||||||
|
if node._metaclass and not node.has_metaclass_hack():
|
||||||
|
args.append("metaclass=" + node._metaclass.accept(self))
|
||||||
|
args += [n.accept(self) for n in node.keywords]
|
||||||
|
args = "(%s)" % ", ".join(args) if args else ""
|
||||||
|
docs = self._docs_dedent(node.doc) if node.doc else ""
|
||||||
|
return "\n\n%sclass %s%s:%s\n%s\n" % (
|
||||||
|
decorate,
|
||||||
|
node.name,
|
||||||
|
args,
|
||||||
|
docs,
|
||||||
|
self._stmt_list(node.body),
|
||||||
|
)
|
||||||
|
|
||||||
|
def visit_compare(self, node):
|
||||||
|
"""return an astroid.Compare node as string"""
|
||||||
|
rhs_str = " ".join(
|
||||||
|
[
|
||||||
|
"%s %s" % (op, self._precedence_parens(node, expr, is_left=False))
|
||||||
|
for op, expr in node.ops
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return "%s %s" % (self._precedence_parens(node, node.left), rhs_str)
|
||||||
|
|
||||||
|
def visit_comprehension(self, node):
|
||||||
|
"""return an astroid.Comprehension node as string"""
|
||||||
|
ifs = "".join(" if %s" % n.accept(self) for n in node.ifs)
|
||||||
|
generated = "for %s in %s%s" % (
|
||||||
|
node.target.accept(self),
|
||||||
|
node.iter.accept(self),
|
||||||
|
ifs,
|
||||||
|
)
|
||||||
|
return "%s%s" % ("async " if node.is_async else "", generated)
|
||||||
|
|
||||||
|
def visit_const(self, node):
|
||||||
|
"""return an astroid.Const node as string"""
|
||||||
|
if node.value is Ellipsis:
|
||||||
|
return "..."
|
||||||
|
return repr(node.value)
|
||||||
|
|
||||||
|
def visit_continue(self, node):
|
||||||
|
"""return an astroid.Continue node as string"""
|
||||||
|
return "continue"
|
||||||
|
|
||||||
|
def visit_delete(self, node): # XXX check if correct
|
||||||
|
"""return an astroid.Delete node as string"""
|
||||||
|
return "del %s" % ", ".join(child.accept(self) for child in node.targets)
|
||||||
|
|
||||||
|
def visit_delattr(self, node):
|
||||||
|
"""return an astroid.DelAttr node as string"""
|
||||||
|
return self.visit_attribute(node)
|
||||||
|
|
||||||
|
def visit_delname(self, node):
|
||||||
|
"""return an astroid.DelName node as string"""
|
||||||
|
return node.name
|
||||||
|
|
||||||
|
def visit_decorators(self, node):
|
||||||
|
"""return an astroid.Decorators node as string"""
|
||||||
|
return "@%s\n" % "\n@".join(item.accept(self) for item in node.nodes)
|
||||||
|
|
||||||
|
def visit_dict(self, node):
|
||||||
|
"""return an astroid.Dict node as string"""
|
||||||
|
return "{%s}" % ", ".join(self._visit_dict(node))
|
||||||
|
|
||||||
|
def _visit_dict(self, node):
|
||||||
|
for key, value in node.items:
|
||||||
|
key = key.accept(self)
|
||||||
|
value = value.accept(self)
|
||||||
|
if key == "**":
|
||||||
|
# It can only be a DictUnpack node.
|
||||||
|
yield key + value
|
||||||
|
else:
|
||||||
|
yield "%s: %s" % (key, value)
|
||||||
|
|
||||||
|
def visit_dictunpack(self, node):
|
||||||
|
return "**"
|
||||||
|
|
||||||
|
def visit_dictcomp(self, node):
|
||||||
|
"""return an astroid.DictComp node as string"""
|
||||||
|
return "{%s: %s %s}" % (
|
||||||
|
node.key.accept(self),
|
||||||
|
node.value.accept(self),
|
||||||
|
" ".join(n.accept(self) for n in node.generators),
|
||||||
|
)
|
||||||
|
|
||||||
|
def visit_expr(self, node):
|
||||||
|
"""return an astroid.Discard node as string"""
|
||||||
|
return node.value.accept(self)
|
||||||
|
|
||||||
|
def visit_emptynode(self, node):
|
||||||
|
"""dummy method for visiting an Empty node"""
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def visit_excepthandler(self, node):
|
||||||
|
if node.type:
|
||||||
|
if node.name:
|
||||||
|
excs = "except %s as %s" % (
|
||||||
|
node.type.accept(self),
|
||||||
|
node.name.accept(self),
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
excs = "except %s" % node.type.accept(self)
|
||||||
|
else:
|
||||||
|
excs = "except"
|
||||||
|
return "%s:\n%s" % (excs, self._stmt_list(node.body))
|
||||||
|
|
||||||
|
def visit_ellipsis(self, node):
|
||||||
|
"""return an astroid.Ellipsis node as string"""
|
||||||
|
return "..."
|
||||||
|
|
||||||
|
def visit_empty(self, node):
|
||||||
|
"""return an Empty node as string"""
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def visit_exec(self, node):
|
||||||
|
"""return an astroid.Exec node as string"""
|
||||||
|
if node.locals:
|
||||||
|
return "exec %s in %s, %s" % (
|
||||||
|
node.expr.accept(self),
|
||||||
|
node.locals.accept(self),
|
||||||
|
node.globals.accept(self),
|
||||||
|
)
|
||||||
|
if node.globals:
|
||||||
|
return "exec %s in %s" % (node.expr.accept(self), node.globals.accept(self))
|
||||||
|
return "exec %s" % node.expr.accept(self)
|
||||||
|
|
||||||
|
def visit_extslice(self, node):
|
||||||
|
"""return an astroid.ExtSlice node as string"""
|
||||||
|
return ", ".join(dim.accept(self) for dim in node.dims)
|
||||||
|
|
||||||
|
def visit_for(self, node):
|
||||||
|
"""return an astroid.For node as string"""
|
||||||
|
fors = "for %s in %s:\n%s" % (
|
||||||
|
node.target.accept(self),
|
||||||
|
node.iter.accept(self),
|
||||||
|
self._stmt_list(node.body),
|
||||||
|
)
|
||||||
|
if node.orelse:
|
||||||
|
fors = "%s\nelse:\n%s" % (fors, self._stmt_list(node.orelse))
|
||||||
|
return fors
|
||||||
|
|
||||||
|
def visit_importfrom(self, node):
|
||||||
|
"""return an astroid.ImportFrom node as string"""
|
||||||
|
return "from %s import %s" % (
|
||||||
|
"." * (node.level or 0) + node.modname,
|
||||||
|
_import_string(node.names),
|
||||||
|
)
|
||||||
|
|
||||||
|
def visit_joinedstr(self, node):
|
||||||
|
string = "".join(
|
||||||
|
# Use repr on the string literal parts
|
||||||
|
# to get proper escapes, e.g. \n, \\, \"
|
||||||
|
# But strip the quotes off the ends
|
||||||
|
# (they will always be one character: ' or ")
|
||||||
|
repr(value.value)[1:-1]
|
||||||
|
# Literal braces must be doubled to escape them
|
||||||
|
.replace("{", "{{").replace("}", "}}")
|
||||||
|
# Each value in values is either a string literal (Const)
|
||||||
|
# or a FormattedValue
|
||||||
|
if type(value).__name__ == "Const" else value.accept(self)
|
||||||
|
for value in node.values
|
||||||
|
)
|
||||||
|
|
||||||
|
# Try to find surrounding quotes that don't appear at all in the string.
|
||||||
|
# Because the formatted values inside {} can't contain backslash (\)
|
||||||
|
# using a triple quote is sometimes necessary
|
||||||
|
for quote in ["'", '"', '"""', "'''"]:
|
||||||
|
if quote not in string:
|
||||||
|
break
|
||||||
|
|
||||||
|
return "f" + quote + string + quote
|
||||||
|
|
||||||
|
def visit_formattedvalue(self, node):
|
||||||
|
result = node.value.accept(self)
|
||||||
|
if node.conversion and node.conversion >= 0:
|
||||||
|
# e.g. if node.conversion == 114: result += "!r"
|
||||||
|
result += "!" + chr(node.conversion)
|
||||||
|
if node.format_spec:
|
||||||
|
# The format spec is itself a JoinedString, i.e. an f-string
|
||||||
|
# We strip the f and quotes of the ends
|
||||||
|
result += ":" + node.format_spec.accept(self)[2:-1]
|
||||||
|
return "{%s}" % result
|
||||||
|
|
||||||
|
def handle_functiondef(self, node, keyword):
|
||||||
|
"""return a (possibly async) function definition node as string"""
|
||||||
|
decorate = node.decorators.accept(self) if node.decorators else ""
|
||||||
|
docs = self._docs_dedent(node.doc) if node.doc else ""
|
||||||
|
trailer = ":"
|
||||||
|
if node.returns:
|
||||||
|
return_annotation = " -> " + node.returns.as_string()
|
||||||
|
trailer = return_annotation + ":"
|
||||||
|
def_format = "\n%s%s %s(%s)%s%s\n%s"
|
||||||
|
return def_format % (
|
||||||
|
decorate,
|
||||||
|
keyword,
|
||||||
|
node.name,
|
||||||
|
node.args.accept(self),
|
||||||
|
trailer,
|
||||||
|
docs,
|
||||||
|
self._stmt_list(node.body),
|
||||||
|
)
|
||||||
|
|
||||||
|
def visit_functiondef(self, node):
|
||||||
|
"""return an astroid.FunctionDef node as string"""
|
||||||
|
return self.handle_functiondef(node, "def")
|
||||||
|
|
||||||
|
def visit_asyncfunctiondef(self, node):
|
||||||
|
"""return an astroid.AsyncFunction node as string"""
|
||||||
|
return self.handle_functiondef(node, "async def")
|
||||||
|
|
||||||
|
def visit_generatorexp(self, node):
|
||||||
|
"""return an astroid.GeneratorExp node as string"""
|
||||||
|
return "(%s %s)" % (
|
||||||
|
node.elt.accept(self),
|
||||||
|
" ".join(n.accept(self) for n in node.generators),
|
||||||
|
)
|
||||||
|
|
||||||
|
def visit_attribute(self, node):
|
||||||
|
"""return an astroid.Getattr node as string"""
|
||||||
|
left = self._precedence_parens(node, node.expr)
|
||||||
|
if left.isdigit():
|
||||||
|
left = "(%s)" % left
|
||||||
|
return "%s.%s" % (left, node.attrname)
|
||||||
|
|
||||||
|
def visit_global(self, node):
|
||||||
|
"""return an astroid.Global node as string"""
|
||||||
|
return "global %s" % ", ".join(node.names)
|
||||||
|
|
||||||
|
def visit_if(self, node):
|
||||||
|
"""return an astroid.If node as string"""
|
||||||
|
ifs = ["if %s:\n%s" % (node.test.accept(self), self._stmt_list(node.body))]
|
||||||
|
if node.has_elif_block():
|
||||||
|
ifs.append("el%s" % self._stmt_list(node.orelse, indent=False))
|
||||||
|
elif node.orelse:
|
||||||
|
ifs.append("else:\n%s" % self._stmt_list(node.orelse))
|
||||||
|
return "\n".join(ifs)
|
||||||
|
|
||||||
|
def visit_ifexp(self, node):
|
||||||
|
"""return an astroid.IfExp node as string"""
|
||||||
|
return "%s if %s else %s" % (
|
||||||
|
self._precedence_parens(node, node.body, is_left=True),
|
||||||
|
self._precedence_parens(node, node.test, is_left=True),
|
||||||
|
self._precedence_parens(node, node.orelse, is_left=False),
|
||||||
|
)
|
||||||
|
|
||||||
|
def visit_import(self, node):
|
||||||
|
"""return an astroid.Import node as string"""
|
||||||
|
return "import %s" % _import_string(node.names)
|
||||||
|
|
||||||
|
def visit_keyword(self, node):
|
||||||
|
"""return an astroid.Keyword node as string"""
|
||||||
|
if node.arg is None:
|
||||||
|
return "**%s" % node.value.accept(self)
|
||||||
|
return "%s=%s" % (node.arg, node.value.accept(self))
|
||||||
|
|
||||||
|
def visit_lambda(self, node):
|
||||||
|
"""return an astroid.Lambda node as string"""
|
||||||
|
args = node.args.accept(self)
|
||||||
|
body = node.body.accept(self)
|
||||||
|
if args:
|
||||||
|
return "lambda %s: %s" % (args, body)
|
||||||
|
|
||||||
|
return "lambda: %s" % body
|
||||||
|
|
||||||
|
def visit_list(self, node):
|
||||||
|
"""return an astroid.List node as string"""
|
||||||
|
return "[%s]" % ", ".join(child.accept(self) for child in node.elts)
|
||||||
|
|
||||||
|
def visit_listcomp(self, node):
|
||||||
|
"""return an astroid.ListComp node as string"""
|
||||||
|
return "[%s %s]" % (
|
||||||
|
node.elt.accept(self),
|
||||||
|
" ".join(n.accept(self) for n in node.generators),
|
||||||
|
)
|
||||||
|
|
||||||
|
def visit_module(self, node):
|
||||||
|
"""return an astroid.Module node as string"""
|
||||||
|
docs = '"""%s"""\n\n' % node.doc if node.doc else ""
|
||||||
|
return docs + "\n".join(n.accept(self) for n in node.body) + "\n\n"
|
||||||
|
|
||||||
|
def visit_name(self, node):
|
||||||
|
"""return an astroid.Name node as string"""
|
||||||
|
return node.name
|
||||||
|
|
||||||
|
def visit_namedexpr(self, node):
|
||||||
|
"""Return an assignment expression node as string"""
|
||||||
|
target = node.target.accept(self)
|
||||||
|
value = node.value.accept(self)
|
||||||
|
return "%s := %s" % (target, value)
|
||||||
|
|
||||||
|
def visit_nonlocal(self, node):
|
||||||
|
"""return an astroid.Nonlocal node as string"""
|
||||||
|
return "nonlocal %s" % ", ".join(node.names)
|
||||||
|
|
||||||
|
def visit_pass(self, node):
|
||||||
|
"""return an astroid.Pass node as string"""
|
||||||
|
return "pass"
|
||||||
|
|
||||||
|
def visit_print(self, node):
|
||||||
|
"""return an astroid.Print node as string"""
|
||||||
|
nodes = ", ".join(n.accept(self) for n in node.values)
|
||||||
|
if not node.nl:
|
||||||
|
nodes = "%s," % nodes
|
||||||
|
if node.dest:
|
||||||
|
return "print >> %s, %s" % (node.dest.accept(self), nodes)
|
||||||
|
return "print %s" % nodes
|
||||||
|
|
||||||
|
def visit_raise(self, node):
|
||||||
|
"""return an astroid.Raise node as string"""
|
||||||
|
if node.exc:
|
||||||
|
if node.cause:
|
||||||
|
return "raise %s from %s" % (
|
||||||
|
node.exc.accept(self),
|
||||||
|
node.cause.accept(self),
|
||||||
|
)
|
||||||
|
return "raise %s" % node.exc.accept(self)
|
||||||
|
return "raise"
|
||||||
|
|
||||||
|
def visit_return(self, node):
|
||||||
|
"""return an astroid.Return node as string"""
|
||||||
|
if node.is_tuple_return() and len(node.value.elts) > 1:
|
||||||
|
elts = [child.accept(self) for child in node.value.elts]
|
||||||
|
return "return %s" % ", ".join(elts)
|
||||||
|
|
||||||
|
if node.value:
|
||||||
|
return "return %s" % node.value.accept(self)
|
||||||
|
|
||||||
|
return "return"
|
||||||
|
|
||||||
|
def visit_index(self, node):
|
||||||
|
"""return an astroid.Index node as string"""
|
||||||
|
return node.value.accept(self)
|
||||||
|
|
||||||
|
def visit_set(self, node):
|
||||||
|
"""return an astroid.Set node as string"""
|
||||||
|
return "{%s}" % ", ".join(child.accept(self) for child in node.elts)
|
||||||
|
|
||||||
|
def visit_setcomp(self, node):
|
||||||
|
"""return an astroid.SetComp node as string"""
|
||||||
|
return "{%s %s}" % (
|
||||||
|
node.elt.accept(self),
|
||||||
|
" ".join(n.accept(self) for n in node.generators),
|
||||||
|
)
|
||||||
|
|
||||||
|
def visit_slice(self, node):
|
||||||
|
"""return an astroid.Slice node as string"""
|
||||||
|
lower = node.lower.accept(self) if node.lower else ""
|
||||||
|
upper = node.upper.accept(self) if node.upper else ""
|
||||||
|
step = node.step.accept(self) if node.step else ""
|
||||||
|
if step:
|
||||||
|
return "%s:%s:%s" % (lower, upper, step)
|
||||||
|
return "%s:%s" % (lower, upper)
|
||||||
|
|
||||||
|
def visit_subscript(self, node):
|
||||||
|
"""return an astroid.Subscript node as string"""
|
||||||
|
idx = node.slice
|
||||||
|
if idx.__class__.__name__.lower() == "index":
|
||||||
|
idx = idx.value
|
||||||
|
idxstr = idx.accept(self)
|
||||||
|
if idx.__class__.__name__.lower() == "tuple" and idx.elts:
|
||||||
|
# Remove parenthesis in tuple and extended slice.
|
||||||
|
# a[(::1, 1:)] is not valid syntax.
|
||||||
|
idxstr = idxstr[1:-1]
|
||||||
|
return "%s[%s]" % (self._precedence_parens(node, node.value), idxstr)
|
||||||
|
|
||||||
|
def visit_tryexcept(self, node):
|
||||||
|
"""return an astroid.TryExcept node as string"""
|
||||||
|
trys = ["try:\n%s" % self._stmt_list(node.body)]
|
||||||
|
for handler in node.handlers:
|
||||||
|
trys.append(handler.accept(self))
|
||||||
|
if node.orelse:
|
||||||
|
trys.append("else:\n%s" % self._stmt_list(node.orelse))
|
||||||
|
return "\n".join(trys)
|
||||||
|
|
||||||
|
def visit_tryfinally(self, node):
|
||||||
|
"""return an astroid.TryFinally node as string"""
|
||||||
|
return "try:\n%s\nfinally:\n%s" % (
|
||||||
|
self._stmt_list(node.body),
|
||||||
|
self._stmt_list(node.finalbody),
|
||||||
|
)
|
||||||
|
|
||||||
|
def visit_tuple(self, node):
|
||||||
|
"""return an astroid.Tuple node as string"""
|
||||||
|
if len(node.elts) == 1:
|
||||||
|
return "(%s, )" % node.elts[0].accept(self)
|
||||||
|
return "(%s)" % ", ".join(child.accept(self) for child in node.elts)
|
||||||
|
|
||||||
|
def visit_unaryop(self, node):
|
||||||
|
"""return an astroid.UnaryOp node as string"""
|
||||||
|
if node.op == "not":
|
||||||
|
operator = "not "
|
||||||
|
else:
|
||||||
|
operator = node.op
|
||||||
|
return "%s%s" % (operator, self._precedence_parens(node, node.operand))
|
||||||
|
|
||||||
|
def visit_while(self, node):
|
||||||
|
"""return an astroid.While node as string"""
|
||||||
|
whiles = "while %s:\n%s" % (node.test.accept(self), self._stmt_list(node.body))
|
||||||
|
if node.orelse:
|
||||||
|
whiles = "%s\nelse:\n%s" % (whiles, self._stmt_list(node.orelse))
|
||||||
|
return whiles
|
||||||
|
|
||||||
|
def visit_with(self, node): # 'with' without 'as' is possible
|
||||||
|
"""return an astroid.With node as string"""
|
||||||
|
items = ", ".join(
|
||||||
|
("%s" % expr.accept(self)) + (vars and " as %s" % (vars.accept(self)) or "")
|
||||||
|
for expr, vars in node.items
|
||||||
|
)
|
||||||
|
return "with %s:\n%s" % (items, self._stmt_list(node.body))
|
||||||
|
|
||||||
|
def visit_yield(self, node):
|
||||||
|
"""yield an ast.Yield node as string"""
|
||||||
|
yi_val = (" " + node.value.accept(self)) if node.value else ""
|
||||||
|
expr = "yield" + yi_val
|
||||||
|
if node.parent.is_statement:
|
||||||
|
return expr
|
||||||
|
|
||||||
|
return "(%s)" % (expr,)
|
||||||
|
|
||||||
|
def visit_yieldfrom(self, node):
|
||||||
|
""" Return an astroid.YieldFrom node as string. """
|
||||||
|
yi_val = (" " + node.value.accept(self)) if node.value else ""
|
||||||
|
expr = "yield from" + yi_val
|
||||||
|
if node.parent.is_statement:
|
||||||
|
return expr
|
||||||
|
|
||||||
|
return "(%s)" % (expr,)
|
||||||
|
|
||||||
|
def visit_starred(self, node):
|
||||||
|
"""return Starred node as string"""
|
||||||
|
return "*" + node.value.accept(self)
|
||||||
|
|
||||||
|
# These aren't for real AST nodes, but for inference objects.
|
||||||
|
|
||||||
|
def visit_frozenset(self, node):
|
||||||
|
return node.parent.accept(self)
|
||||||
|
|
||||||
|
def visit_super(self, node):
|
||||||
|
return node.parent.accept(self)
|
||||||
|
|
||||||
|
def visit_uninferable(self, node):
|
||||||
|
return str(node)
|
||||||
|
|
||||||
|
def visit_property(self, node):
|
||||||
|
return node.function.accept(self)
|
||||||
|
|
||||||
|
def visit_evaluatedobject(self, node):
|
||||||
|
return node.original.accept(self)
|
||||||
|
|
||||||
|
|
||||||
|
def _import_string(names):
|
||||||
|
"""return a list of (name, asname) formatted as a string"""
|
||||||
|
_names = []
|
||||||
|
for name, asname in names:
|
||||||
|
if asname is not None:
|
||||||
|
_names.append("%s as %s" % (name, asname))
|
||||||
|
else:
|
||||||
|
_names.append(name)
|
||||||
|
return ", ".join(_names)
|
||||||
|
|
||||||
|
|
||||||
|
# This sets the default indent to 4 spaces.
|
||||||
|
to_code = AsStringVisitor(" ")
|
||||||
|
|
@ -0,0 +1,548 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2009-2011, 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
|
||||||
|
# Copyright (c) 2012 FELD Boris <lothiraldan@gmail.com>
|
||||||
|
# Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2014 Google, Inc.
|
||||||
|
# Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com>
|
||||||
|
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
# Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
|
||||||
|
# Copyright (c) 2016-2017 Derek Gustafson <degustaf@gmail.com>
|
||||||
|
# Copyright (c) 2017 Calen Pennington <calen.pennington@gmail.com>
|
||||||
|
# Copyright (c) 2018-2019 hippo91 <guillaume.peillex@gmail.com>
|
||||||
|
# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
|
||||||
|
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
|
||||||
|
# Copyright (c) 2018 Nick Drozd <nicholasdrozd@gmail.com>
|
||||||
|
# Copyright (c) 2018 Daniel Colascione <dancol@dancol.org>
|
||||||
|
# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
"""This module contains base classes and functions for the nodes and some
|
||||||
|
inference utils.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import builtins
|
||||||
|
import collections
|
||||||
|
|
||||||
|
from astroid import context as contextmod
|
||||||
|
from astroid import exceptions
|
||||||
|
from astroid import util
|
||||||
|
|
||||||
|
objectmodel = util.lazy_import("interpreter.objectmodel")
|
||||||
|
helpers = util.lazy_import("helpers")
|
||||||
|
BUILTINS = builtins.__name__
|
||||||
|
manager = util.lazy_import("manager")
|
||||||
|
MANAGER = manager.AstroidManager()
|
||||||
|
|
||||||
|
# TODO: check if needs special treatment
|
||||||
|
BUILTINS = "builtins"
|
||||||
|
BOOL_SPECIAL_METHOD = "__bool__"
|
||||||
|
|
||||||
|
PROPERTIES = {BUILTINS + ".property", "abc.abstractproperty"}
|
||||||
|
# List of possible property names. We use this list in order
|
||||||
|
# to see if a method is a property or not. This should be
|
||||||
|
# pretty reliable and fast, the alternative being to check each
|
||||||
|
# decorator to see if its a real property-like descriptor, which
|
||||||
|
# can be too complicated.
|
||||||
|
# Also, these aren't qualified, because each project can
|
||||||
|
# define them, we shouldn't expect to know every possible
|
||||||
|
# property-like decorator!
|
||||||
|
POSSIBLE_PROPERTIES = {
|
||||||
|
"cached_property",
|
||||||
|
"cachedproperty",
|
||||||
|
"lazyproperty",
|
||||||
|
"lazy_property",
|
||||||
|
"reify",
|
||||||
|
"lazyattribute",
|
||||||
|
"lazy_attribute",
|
||||||
|
"LazyProperty",
|
||||||
|
"lazy",
|
||||||
|
"cache_readonly",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _is_property(meth, context=None):
|
||||||
|
decoratornames = meth.decoratornames(context=context)
|
||||||
|
if PROPERTIES.intersection(decoratornames):
|
||||||
|
return True
|
||||||
|
stripped = {
|
||||||
|
name.split(".")[-1] for name in decoratornames if name is not util.Uninferable
|
||||||
|
}
|
||||||
|
if any(name in stripped for name in POSSIBLE_PROPERTIES):
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Lookup for subclasses of *property*
|
||||||
|
if not meth.decorators:
|
||||||
|
return False
|
||||||
|
for decorator in meth.decorators.nodes or ():
|
||||||
|
inferred = helpers.safe_infer(decorator, context=context)
|
||||||
|
if inferred is None or inferred is util.Uninferable:
|
||||||
|
continue
|
||||||
|
if inferred.__class__.__name__ == "ClassDef":
|
||||||
|
for base_class in inferred.bases:
|
||||||
|
if base_class.__class__.__name__ != "Name":
|
||||||
|
continue
|
||||||
|
module, _ = base_class.lookup(base_class.name)
|
||||||
|
if module.name == BUILTINS and base_class.name == "property":
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class Proxy:
|
||||||
|
"""a simple proxy object
|
||||||
|
|
||||||
|
Note:
|
||||||
|
|
||||||
|
Subclasses of this object will need a custom __getattr__
|
||||||
|
if new instance attributes are created. See the Const class
|
||||||
|
"""
|
||||||
|
|
||||||
|
_proxied = None # proxied object may be set by class or by instance
|
||||||
|
|
||||||
|
def __init__(self, proxied=None):
|
||||||
|
if proxied is not None:
|
||||||
|
self._proxied = proxied
|
||||||
|
|
||||||
|
def __getattr__(self, name):
|
||||||
|
if name == "_proxied":
|
||||||
|
return getattr(self.__class__, "_proxied")
|
||||||
|
if name in self.__dict__:
|
||||||
|
return self.__dict__[name]
|
||||||
|
return getattr(self._proxied, name)
|
||||||
|
|
||||||
|
def infer(self, context=None):
|
||||||
|
yield self
|
||||||
|
|
||||||
|
|
||||||
|
def _infer_stmts(stmts, context, frame=None):
|
||||||
|
"""Return an iterator on statements inferred by each statement in *stmts*."""
|
||||||
|
inferred = False
|
||||||
|
if context is not None:
|
||||||
|
name = context.lookupname
|
||||||
|
context = context.clone()
|
||||||
|
else:
|
||||||
|
name = None
|
||||||
|
context = contextmod.InferenceContext()
|
||||||
|
|
||||||
|
for stmt in stmts:
|
||||||
|
if stmt is util.Uninferable:
|
||||||
|
yield stmt
|
||||||
|
inferred = True
|
||||||
|
continue
|
||||||
|
context.lookupname = stmt._infer_name(frame, name)
|
||||||
|
try:
|
||||||
|
for inferred in stmt.infer(context=context):
|
||||||
|
yield inferred
|
||||||
|
inferred = True
|
||||||
|
except exceptions.NameInferenceError:
|
||||||
|
continue
|
||||||
|
except exceptions.InferenceError:
|
||||||
|
yield util.Uninferable
|
||||||
|
inferred = True
|
||||||
|
if not inferred:
|
||||||
|
raise exceptions.InferenceError(
|
||||||
|
"Inference failed for all members of {stmts!r}.",
|
||||||
|
stmts=stmts,
|
||||||
|
frame=frame,
|
||||||
|
context=context,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _infer_method_result_truth(instance, method_name, context):
|
||||||
|
# Get the method from the instance and try to infer
|
||||||
|
# its return's truth value.
|
||||||
|
meth = next(instance.igetattr(method_name, context=context), None)
|
||||||
|
if meth and hasattr(meth, "infer_call_result"):
|
||||||
|
if not meth.callable():
|
||||||
|
return util.Uninferable
|
||||||
|
try:
|
||||||
|
for value in meth.infer_call_result(instance, context=context):
|
||||||
|
if value is util.Uninferable:
|
||||||
|
return value
|
||||||
|
|
||||||
|
inferred = next(value.infer(context=context))
|
||||||
|
return inferred.bool_value()
|
||||||
|
except exceptions.InferenceError:
|
||||||
|
pass
|
||||||
|
return util.Uninferable
|
||||||
|
|
||||||
|
|
||||||
|
class BaseInstance(Proxy):
|
||||||
|
"""An instance base class, which provides lookup methods for potential instances."""
|
||||||
|
|
||||||
|
special_attributes = None
|
||||||
|
|
||||||
|
def display_type(self):
|
||||||
|
return "Instance of"
|
||||||
|
|
||||||
|
def getattr(self, name, context=None, lookupclass=True):
|
||||||
|
try:
|
||||||
|
values = self._proxied.instance_attr(name, context)
|
||||||
|
except exceptions.AttributeInferenceError as exc:
|
||||||
|
if self.special_attributes and name in self.special_attributes:
|
||||||
|
return [self.special_attributes.lookup(name)]
|
||||||
|
|
||||||
|
if lookupclass:
|
||||||
|
# Class attributes not available through the instance
|
||||||
|
# unless they are explicitly defined.
|
||||||
|
return self._proxied.getattr(name, context, class_context=False)
|
||||||
|
|
||||||
|
raise exceptions.AttributeInferenceError(
|
||||||
|
target=self, attribute=name, context=context
|
||||||
|
) from exc
|
||||||
|
# since we've no context information, return matching class members as
|
||||||
|
# well
|
||||||
|
if lookupclass:
|
||||||
|
try:
|
||||||
|
return values + self._proxied.getattr(
|
||||||
|
name, context, class_context=False
|
||||||
|
)
|
||||||
|
except exceptions.AttributeInferenceError:
|
||||||
|
pass
|
||||||
|
return values
|
||||||
|
|
||||||
|
def igetattr(self, name, context=None):
|
||||||
|
"""inferred getattr"""
|
||||||
|
if not context:
|
||||||
|
context = contextmod.InferenceContext()
|
||||||
|
try:
|
||||||
|
# avoid recursively inferring the same attr on the same class
|
||||||
|
if context.push((self._proxied, name)):
|
||||||
|
raise exceptions.InferenceError(
|
||||||
|
message="Cannot infer the same attribute again",
|
||||||
|
node=self,
|
||||||
|
context=context,
|
||||||
|
)
|
||||||
|
|
||||||
|
# XXX frame should be self._proxied, or not ?
|
||||||
|
get_attr = self.getattr(name, context, lookupclass=False)
|
||||||
|
yield from _infer_stmts(
|
||||||
|
self._wrap_attr(get_attr, context), context, frame=self
|
||||||
|
)
|
||||||
|
except exceptions.AttributeInferenceError as error:
|
||||||
|
try:
|
||||||
|
# fallback to class.igetattr since it has some logic to handle
|
||||||
|
# descriptors
|
||||||
|
# But only if the _proxied is the Class.
|
||||||
|
if self._proxied.__class__.__name__ != "ClassDef":
|
||||||
|
raise
|
||||||
|
attrs = self._proxied.igetattr(name, context, class_context=False)
|
||||||
|
yield from self._wrap_attr(attrs, context)
|
||||||
|
except exceptions.AttributeInferenceError as error:
|
||||||
|
raise exceptions.InferenceError(**vars(error)) from error
|
||||||
|
|
||||||
|
def _wrap_attr(self, attrs, context=None):
|
||||||
|
"""wrap bound methods of attrs in a InstanceMethod proxies"""
|
||||||
|
for attr in attrs:
|
||||||
|
if isinstance(attr, UnboundMethod):
|
||||||
|
if _is_property(attr):
|
||||||
|
yield from attr.infer_call_result(self, context)
|
||||||
|
else:
|
||||||
|
yield BoundMethod(attr, self)
|
||||||
|
elif hasattr(attr, "name") and attr.name == "<lambda>":
|
||||||
|
if attr.args.arguments and attr.args.arguments[0].name == "self":
|
||||||
|
yield BoundMethod(attr, self)
|
||||||
|
continue
|
||||||
|
yield attr
|
||||||
|
else:
|
||||||
|
yield attr
|
||||||
|
|
||||||
|
def infer_call_result(self, caller, context=None):
|
||||||
|
"""infer what a class instance is returning when called"""
|
||||||
|
context = contextmod.bind_context_to_node(context, self)
|
||||||
|
inferred = False
|
||||||
|
for node in self._proxied.igetattr("__call__", context):
|
||||||
|
if node is util.Uninferable or not node.callable():
|
||||||
|
continue
|
||||||
|
for res in node.infer_call_result(caller, context):
|
||||||
|
inferred = True
|
||||||
|
yield res
|
||||||
|
if not inferred:
|
||||||
|
raise exceptions.InferenceError(node=self, caller=caller, context=context)
|
||||||
|
|
||||||
|
|
||||||
|
class Instance(BaseInstance):
|
||||||
|
"""A special node representing a class instance."""
|
||||||
|
|
||||||
|
# pylint: disable=unnecessary-lambda
|
||||||
|
special_attributes = util.lazy_descriptor(lambda: objectmodel.InstanceModel())
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Instance of %s.%s at 0x%s>" % (
|
||||||
|
self._proxied.root().name,
|
||||||
|
self._proxied.name,
|
||||||
|
id(self),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Instance of %s.%s" % (self._proxied.root().name, self._proxied.name)
|
||||||
|
|
||||||
|
def callable(self):
|
||||||
|
try:
|
||||||
|
self._proxied.getattr("__call__", class_context=False)
|
||||||
|
return True
|
||||||
|
except exceptions.AttributeInferenceError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def pytype(self):
|
||||||
|
return self._proxied.qname()
|
||||||
|
|
||||||
|
def display_type(self):
|
||||||
|
return "Instance of"
|
||||||
|
|
||||||
|
def bool_value(self, context=None):
|
||||||
|
"""Infer the truth value for an Instance
|
||||||
|
|
||||||
|
The truth value of an instance is determined by these conditions:
|
||||||
|
|
||||||
|
* if it implements __bool__ on Python 3 or __nonzero__
|
||||||
|
on Python 2, then its bool value will be determined by
|
||||||
|
calling this special method and checking its result.
|
||||||
|
* when this method is not defined, __len__() is called, if it
|
||||||
|
is defined, and the object is considered true if its result is
|
||||||
|
nonzero. If a class defines neither __len__() nor __bool__(),
|
||||||
|
all its instances are considered true.
|
||||||
|
"""
|
||||||
|
context = context or contextmod.InferenceContext()
|
||||||
|
context.callcontext = contextmod.CallContext(args=[])
|
||||||
|
context.boundnode = self
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = _infer_method_result_truth(self, BOOL_SPECIAL_METHOD, context)
|
||||||
|
except (exceptions.InferenceError, exceptions.AttributeInferenceError):
|
||||||
|
# Fallback to __len__.
|
||||||
|
try:
|
||||||
|
result = _infer_method_result_truth(self, "__len__", context)
|
||||||
|
except (exceptions.AttributeInferenceError, exceptions.InferenceError):
|
||||||
|
return True
|
||||||
|
return result
|
||||||
|
|
||||||
|
# This is set in inference.py.
|
||||||
|
def getitem(self, index, context=None):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class UnboundMethod(Proxy):
|
||||||
|
"""a special node representing a method not bound to an instance"""
|
||||||
|
|
||||||
|
# pylint: disable=unnecessary-lambda
|
||||||
|
special_attributes = util.lazy_descriptor(lambda: objectmodel.UnboundMethodModel())
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
frame = self._proxied.parent.frame()
|
||||||
|
return "<%s %s of %s at 0x%s" % (
|
||||||
|
self.__class__.__name__,
|
||||||
|
self._proxied.name,
|
||||||
|
frame.qname(),
|
||||||
|
id(self),
|
||||||
|
)
|
||||||
|
|
||||||
|
def implicit_parameters(self):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def is_bound(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getattr(self, name, context=None):
|
||||||
|
if name in self.special_attributes:
|
||||||
|
return [self.special_attributes.lookup(name)]
|
||||||
|
return self._proxied.getattr(name, context)
|
||||||
|
|
||||||
|
def igetattr(self, name, context=None):
|
||||||
|
if name in self.special_attributes:
|
||||||
|
return iter((self.special_attributes.lookup(name),))
|
||||||
|
return self._proxied.igetattr(name, context)
|
||||||
|
|
||||||
|
def infer_call_result(self, caller, context):
|
||||||
|
"""
|
||||||
|
The boundnode of the regular context with a function called
|
||||||
|
on ``object.__new__`` will be of type ``object``,
|
||||||
|
which is incorrect for the argument in general.
|
||||||
|
If no context is given the ``object.__new__`` call argument will
|
||||||
|
correctly inferred except when inside a call that requires
|
||||||
|
the additional context (such as a classmethod) of the boundnode
|
||||||
|
to determine which class the method was called from
|
||||||
|
"""
|
||||||
|
|
||||||
|
# If we're unbound method __new__ of builtin object, the result is an
|
||||||
|
# instance of the class given as first argument.
|
||||||
|
if (
|
||||||
|
self._proxied.name == "__new__"
|
||||||
|
and self._proxied.parent.frame().qname() == "%s.object" % BUILTINS
|
||||||
|
):
|
||||||
|
if caller.args:
|
||||||
|
node_context = context.extra_context.get(caller.args[0])
|
||||||
|
infer = caller.args[0].infer(context=node_context)
|
||||||
|
else:
|
||||||
|
infer = []
|
||||||
|
return (Instance(x) if x is not util.Uninferable else x for x in infer)
|
||||||
|
return self._proxied.infer_call_result(caller, context)
|
||||||
|
|
||||||
|
def bool_value(self, context=None):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class BoundMethod(UnboundMethod):
|
||||||
|
"""a special node representing a method bound to an instance"""
|
||||||
|
|
||||||
|
# pylint: disable=unnecessary-lambda
|
||||||
|
special_attributes = util.lazy_descriptor(lambda: objectmodel.BoundMethodModel())
|
||||||
|
|
||||||
|
def __init__(self, proxy, bound):
|
||||||
|
UnboundMethod.__init__(self, proxy)
|
||||||
|
self.bound = bound
|
||||||
|
|
||||||
|
def implicit_parameters(self):
|
||||||
|
if self.name == "__new__":
|
||||||
|
# __new__ acts as a classmethod but the class argument is not implicit.
|
||||||
|
return 0
|
||||||
|
return 1
|
||||||
|
|
||||||
|
def is_bound(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _infer_type_new_call(self, caller, context):
|
||||||
|
"""Try to infer what type.__new__(mcs, name, bases, attrs) returns.
|
||||||
|
|
||||||
|
In order for such call to be valid, the metaclass needs to be
|
||||||
|
a subtype of ``type``, the name needs to be a string, the bases
|
||||||
|
needs to be a tuple of classes
|
||||||
|
"""
|
||||||
|
# pylint: disable=import-outside-toplevel; circular import
|
||||||
|
from astroid import node_classes
|
||||||
|
|
||||||
|
# Verify the metaclass
|
||||||
|
mcs = next(caller.args[0].infer(context=context))
|
||||||
|
if mcs.__class__.__name__ != "ClassDef":
|
||||||
|
# Not a valid first argument.
|
||||||
|
return None
|
||||||
|
if not mcs.is_subtype_of("%s.type" % BUILTINS):
|
||||||
|
# Not a valid metaclass.
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Verify the name
|
||||||
|
name = next(caller.args[1].infer(context=context))
|
||||||
|
if name.__class__.__name__ != "Const":
|
||||||
|
# Not a valid name, needs to be a const.
|
||||||
|
return None
|
||||||
|
if not isinstance(name.value, str):
|
||||||
|
# Needs to be a string.
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Verify the bases
|
||||||
|
bases = next(caller.args[2].infer(context=context))
|
||||||
|
if bases.__class__.__name__ != "Tuple":
|
||||||
|
# Needs to be a tuple.
|
||||||
|
return None
|
||||||
|
inferred_bases = [next(elt.infer(context=context)) for elt in bases.elts]
|
||||||
|
if any(base.__class__.__name__ != "ClassDef" for base in inferred_bases):
|
||||||
|
# All the bases needs to be Classes
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Verify the attributes.
|
||||||
|
attrs = next(caller.args[3].infer(context=context))
|
||||||
|
if attrs.__class__.__name__ != "Dict":
|
||||||
|
# Needs to be a dictionary.
|
||||||
|
return None
|
||||||
|
cls_locals = collections.defaultdict(list)
|
||||||
|
for key, value in attrs.items:
|
||||||
|
key = next(key.infer(context=context))
|
||||||
|
value = next(value.infer(context=context))
|
||||||
|
# Ignore non string keys
|
||||||
|
if key.__class__.__name__ == "Const" and isinstance(key.value, str):
|
||||||
|
cls_locals[key.value].append(value)
|
||||||
|
|
||||||
|
# Build the class from now.
|
||||||
|
cls = mcs.__class__(
|
||||||
|
name=name.value,
|
||||||
|
lineno=caller.lineno,
|
||||||
|
col_offset=caller.col_offset,
|
||||||
|
parent=caller,
|
||||||
|
)
|
||||||
|
empty = node_classes.Pass()
|
||||||
|
cls.postinit(
|
||||||
|
bases=bases.elts,
|
||||||
|
body=[empty],
|
||||||
|
decorators=[],
|
||||||
|
newstyle=True,
|
||||||
|
metaclass=mcs,
|
||||||
|
keywords=[],
|
||||||
|
)
|
||||||
|
cls.locals = cls_locals
|
||||||
|
return cls
|
||||||
|
|
||||||
|
def infer_call_result(self, caller, context=None):
|
||||||
|
context = contextmod.bind_context_to_node(context, self.bound)
|
||||||
|
if (
|
||||||
|
self.bound.__class__.__name__ == "ClassDef"
|
||||||
|
and self.bound.name == "type"
|
||||||
|
and self.name == "__new__"
|
||||||
|
and len(caller.args) == 4
|
||||||
|
):
|
||||||
|
# Check if we have a ``type.__new__(mcs, name, bases, attrs)`` call.
|
||||||
|
new_cls = self._infer_type_new_call(caller, context)
|
||||||
|
if new_cls:
|
||||||
|
return iter((new_cls,))
|
||||||
|
|
||||||
|
return super().infer_call_result(caller, context)
|
||||||
|
|
||||||
|
def bool_value(self, context=None):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
class Generator(BaseInstance):
|
||||||
|
"""a special node representing a generator.
|
||||||
|
|
||||||
|
Proxied class is set once for all in raw_building.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# pylint: disable=unnecessary-lambda
|
||||||
|
special_attributes = util.lazy_descriptor(lambda: objectmodel.GeneratorModel())
|
||||||
|
|
||||||
|
# pylint: disable=super-init-not-called
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
self.parent = parent
|
||||||
|
|
||||||
|
def callable(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def pytype(self):
|
||||||
|
return "%s.generator" % BUILTINS
|
||||||
|
|
||||||
|
def display_type(self):
|
||||||
|
return "Generator"
|
||||||
|
|
||||||
|
def bool_value(self, context=None):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<Generator(%s) l.%s at 0x%s>" % (
|
||||||
|
self._proxied.name,
|
||||||
|
self.lineno,
|
||||||
|
id(self),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Generator(%s)" % (self._proxied.name)
|
||||||
|
|
||||||
|
|
||||||
|
class AsyncGenerator(Generator):
|
||||||
|
"""Special node representing an async generator"""
|
||||||
|
|
||||||
|
def pytype(self):
|
||||||
|
return "%s.async_generator" % BUILTINS
|
||||||
|
|
||||||
|
def display_type(self):
|
||||||
|
return "AsyncGenerator"
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return "<AsyncGenerator(%s) l.%s at 0x%s>" % (
|
||||||
|
self._proxied.name,
|
||||||
|
self.lineno,
|
||||||
|
id(self),
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "AsyncGenerator(%s)" % (self._proxied.name)
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
from astroid import MANAGER, arguments, nodes, inference_tip, UseInferenceDefault
|
||||||
|
|
||||||
|
|
||||||
|
def infer_namespace(node, context=None):
|
||||||
|
callsite = arguments.CallSite.from_call(node, context=context)
|
||||||
|
if not callsite.keyword_arguments:
|
||||||
|
# Cannot make sense of it.
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
|
||||||
|
class_node = nodes.ClassDef("Namespace", "docstring")
|
||||||
|
class_node.parent = node.parent
|
||||||
|
for attr in set(callsite.keyword_arguments):
|
||||||
|
fake_node = nodes.EmptyNode()
|
||||||
|
fake_node.parent = class_node
|
||||||
|
fake_node.attrname = attr
|
||||||
|
class_node.instance_attrs[attr] = [fake_node]
|
||||||
|
return iter((class_node.instantiate_class(),))
|
||||||
|
|
||||||
|
|
||||||
|
def _looks_like_namespace(node):
|
||||||
|
func = node.func
|
||||||
|
if isinstance(func, nodes.Attribute):
|
||||||
|
return (
|
||||||
|
func.attrname == "Namespace"
|
||||||
|
and isinstance(func.expr, nodes.Name)
|
||||||
|
and func.expr.name == "argparse"
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
MANAGER.register_transform(
|
||||||
|
nodes.Call, inference_tip(infer_namespace), _looks_like_namespace
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
"""
|
||||||
|
Astroid hook for the attrs library
|
||||||
|
|
||||||
|
Without this hook pylint reports unsupported-assignment-operation
|
||||||
|
for attrs classes
|
||||||
|
"""
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
from astroid import MANAGER
|
||||||
|
|
||||||
|
|
||||||
|
ATTRIB_NAMES = frozenset(("attr.ib", "attrib", "attr.attrib"))
|
||||||
|
ATTRS_NAMES = frozenset(("attr.s", "attrs", "attr.attrs", "attr.attributes"))
|
||||||
|
|
||||||
|
|
||||||
|
def is_decorated_with_attrs(node, decorator_names=ATTRS_NAMES):
|
||||||
|
"""Return True if a decorated node has
|
||||||
|
an attr decorator applied."""
|
||||||
|
if not node.decorators:
|
||||||
|
return False
|
||||||
|
for decorator_attribute in node.decorators.nodes:
|
||||||
|
if isinstance(decorator_attribute, astroid.Call): # decorator with arguments
|
||||||
|
decorator_attribute = decorator_attribute.func
|
||||||
|
if decorator_attribute.as_string() in decorator_names:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def attr_attributes_transform(node):
|
||||||
|
"""Given that the ClassNode has an attr decorator,
|
||||||
|
rewrite class attributes as instance attributes
|
||||||
|
"""
|
||||||
|
# Astroid can't infer this attribute properly
|
||||||
|
# Prevents https://github.com/PyCQA/pylint/issues/1884
|
||||||
|
node.locals["__attrs_attrs__"] = [astroid.Unknown(parent=node)]
|
||||||
|
|
||||||
|
for cdefbodynode in node.body:
|
||||||
|
if not isinstance(cdefbodynode, (astroid.Assign, astroid.AnnAssign)):
|
||||||
|
continue
|
||||||
|
if isinstance(cdefbodynode.value, astroid.Call):
|
||||||
|
if cdefbodynode.value.func.as_string() not in ATTRIB_NAMES:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
targets = (
|
||||||
|
cdefbodynode.targets
|
||||||
|
if hasattr(cdefbodynode, "targets")
|
||||||
|
else [cdefbodynode.target]
|
||||||
|
)
|
||||||
|
for target in targets:
|
||||||
|
|
||||||
|
rhs_node = astroid.Unknown(
|
||||||
|
lineno=cdefbodynode.lineno,
|
||||||
|
col_offset=cdefbodynode.col_offset,
|
||||||
|
parent=cdefbodynode,
|
||||||
|
)
|
||||||
|
node.locals[target.name] = [rhs_node]
|
||||||
|
node.instance_attrs[target.name] = [rhs_node]
|
||||||
|
|
||||||
|
|
||||||
|
MANAGER.register_transform(
|
||||||
|
astroid.ClassDef, attr_attributes_transform, is_decorated_with_attrs
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
"""Astroid hooks for understanding boto3.ServiceRequest()"""
|
||||||
|
import astroid
|
||||||
|
from astroid import MANAGER, extract_node
|
||||||
|
|
||||||
|
BOTO_SERVICE_FACTORY_QUALIFIED_NAME = "boto3.resources.base.ServiceResource"
|
||||||
|
|
||||||
|
|
||||||
|
def service_request_transform(node):
|
||||||
|
"""Transform ServiceResource to look like dynamic classes"""
|
||||||
|
code = """
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
return 0
|
||||||
|
"""
|
||||||
|
func_getattr = extract_node(code)
|
||||||
|
node.locals["__getattr__"] = [func_getattr]
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
def _looks_like_boto3_service_request(node):
|
||||||
|
return node.qname() == BOTO_SERVICE_FACTORY_QUALIFIED_NAME
|
||||||
|
|
||||||
|
|
||||||
|
MANAGER.register_transform(
|
||||||
|
astroid.ClassDef, service_request_transform, _looks_like_boto3_service_request
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,873 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2014-2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
|
||||||
|
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
# Copyright (c) 2015 Rene Zhang <rz99@cornell.edu>
|
||||||
|
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
|
||||||
|
# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
|
||||||
|
# Copyright (c) 2019 Stanislav Levin <slev@altlinux.org>
|
||||||
|
# Copyright (c) 2019 David Liu <david@cs.toronto.edu>
|
||||||
|
# Copyright (c) 2019 Bryce Guinta <bryce.guinta@protonmail.com>
|
||||||
|
# Copyright (c) 2019 Frédéric Chapoton <fchapoton2@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
"""Astroid hooks for various builtins."""
|
||||||
|
|
||||||
|
from functools import partial
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
|
import six
|
||||||
|
from astroid import (
|
||||||
|
MANAGER,
|
||||||
|
UseInferenceDefault,
|
||||||
|
AttributeInferenceError,
|
||||||
|
inference_tip,
|
||||||
|
InferenceError,
|
||||||
|
NameInferenceError,
|
||||||
|
AstroidTypeError,
|
||||||
|
MroError,
|
||||||
|
)
|
||||||
|
from astroid import arguments
|
||||||
|
from astroid.builder import AstroidBuilder
|
||||||
|
from astroid import helpers
|
||||||
|
from astroid import nodes
|
||||||
|
from astroid import objects
|
||||||
|
from astroid import scoped_nodes
|
||||||
|
from astroid import util
|
||||||
|
|
||||||
|
|
||||||
|
OBJECT_DUNDER_NEW = "object.__new__"
|
||||||
|
|
||||||
|
|
||||||
|
def _extend_str(class_node, rvalue):
|
||||||
|
"""function to extend builtin str/unicode class"""
|
||||||
|
code = dedent(
|
||||||
|
"""
|
||||||
|
class whatever(object):
|
||||||
|
def join(self, iterable):
|
||||||
|
return {rvalue}
|
||||||
|
def replace(self, old, new, count=None):
|
||||||
|
return {rvalue}
|
||||||
|
def format(self, *args, **kwargs):
|
||||||
|
return {rvalue}
|
||||||
|
def encode(self, encoding='ascii', errors=None):
|
||||||
|
return ''
|
||||||
|
def decode(self, encoding='ascii', errors=None):
|
||||||
|
return u''
|
||||||
|
def capitalize(self):
|
||||||
|
return {rvalue}
|
||||||
|
def title(self):
|
||||||
|
return {rvalue}
|
||||||
|
def lower(self):
|
||||||
|
return {rvalue}
|
||||||
|
def upper(self):
|
||||||
|
return {rvalue}
|
||||||
|
def swapcase(self):
|
||||||
|
return {rvalue}
|
||||||
|
def index(self, sub, start=None, end=None):
|
||||||
|
return 0
|
||||||
|
def find(self, sub, start=None, end=None):
|
||||||
|
return 0
|
||||||
|
def count(self, sub, start=None, end=None):
|
||||||
|
return 0
|
||||||
|
def strip(self, chars=None):
|
||||||
|
return {rvalue}
|
||||||
|
def lstrip(self, chars=None):
|
||||||
|
return {rvalue}
|
||||||
|
def rstrip(self, chars=None):
|
||||||
|
return {rvalue}
|
||||||
|
def rjust(self, width, fillchar=None):
|
||||||
|
return {rvalue}
|
||||||
|
def center(self, width, fillchar=None):
|
||||||
|
return {rvalue}
|
||||||
|
def ljust(self, width, fillchar=None):
|
||||||
|
return {rvalue}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
code = code.format(rvalue=rvalue)
|
||||||
|
fake = AstroidBuilder(MANAGER).string_build(code)["whatever"]
|
||||||
|
for method in fake.mymethods():
|
||||||
|
method.parent = class_node
|
||||||
|
method.lineno = None
|
||||||
|
method.col_offset = None
|
||||||
|
if "__class__" in method.locals:
|
||||||
|
method.locals["__class__"] = [class_node]
|
||||||
|
class_node.locals[method.name] = [method]
|
||||||
|
method.parent = class_node
|
||||||
|
|
||||||
|
|
||||||
|
def _extend_builtins(class_transforms):
|
||||||
|
builtin_ast = MANAGER.builtins_module
|
||||||
|
for class_name, transform in class_transforms.items():
|
||||||
|
transform(builtin_ast[class_name])
|
||||||
|
|
||||||
|
|
||||||
|
_extend_builtins(
|
||||||
|
{
|
||||||
|
"bytes": partial(_extend_str, rvalue="b''"),
|
||||||
|
"str": partial(_extend_str, rvalue="''"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _builtin_filter_predicate(node, builtin_name):
|
||||||
|
if isinstance(node.func, nodes.Name) and node.func.name == builtin_name:
|
||||||
|
return True
|
||||||
|
if isinstance(node.func, nodes.Attribute):
|
||||||
|
return (
|
||||||
|
node.func.attrname == "fromkeys"
|
||||||
|
and isinstance(node.func.expr, nodes.Name)
|
||||||
|
and node.func.expr.name == "dict"
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def register_builtin_transform(transform, builtin_name):
|
||||||
|
"""Register a new transform function for the given *builtin_name*.
|
||||||
|
|
||||||
|
The transform function must accept two parameters, a node and
|
||||||
|
an optional context.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _transform_wrapper(node, context=None):
|
||||||
|
result = transform(node, context=context)
|
||||||
|
if result:
|
||||||
|
if not result.parent:
|
||||||
|
# Let the transformation function determine
|
||||||
|
# the parent for its result. Otherwise,
|
||||||
|
# we set it to be the node we transformed from.
|
||||||
|
result.parent = node
|
||||||
|
|
||||||
|
if result.lineno is None:
|
||||||
|
result.lineno = node.lineno
|
||||||
|
if result.col_offset is None:
|
||||||
|
result.col_offset = node.col_offset
|
||||||
|
return iter([result])
|
||||||
|
|
||||||
|
MANAGER.register_transform(
|
||||||
|
nodes.Call,
|
||||||
|
inference_tip(_transform_wrapper),
|
||||||
|
partial(_builtin_filter_predicate, builtin_name=builtin_name),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _container_generic_inference(node, context, node_type, transform):
|
||||||
|
args = node.args
|
||||||
|
if not args:
|
||||||
|
return node_type()
|
||||||
|
if len(node.args) > 1:
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
|
||||||
|
(arg,) = args
|
||||||
|
transformed = transform(arg)
|
||||||
|
if not transformed:
|
||||||
|
try:
|
||||||
|
inferred = next(arg.infer(context=context))
|
||||||
|
except (InferenceError, StopIteration):
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
if inferred is util.Uninferable:
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
transformed = transform(inferred)
|
||||||
|
if not transformed or transformed is util.Uninferable:
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
return transformed
|
||||||
|
|
||||||
|
|
||||||
|
def _container_generic_transform(arg, context, klass, iterables, build_elts):
|
||||||
|
if isinstance(arg, klass):
|
||||||
|
return arg
|
||||||
|
elif isinstance(arg, iterables):
|
||||||
|
if all(isinstance(elt, nodes.Const) for elt in arg.elts):
|
||||||
|
elts = [elt.value for elt in arg.elts]
|
||||||
|
else:
|
||||||
|
# TODO: Does not handle deduplication for sets.
|
||||||
|
elts = []
|
||||||
|
for element in arg.elts:
|
||||||
|
inferred = helpers.safe_infer(element, context=context)
|
||||||
|
if inferred:
|
||||||
|
evaluated_object = nodes.EvaluatedObject(
|
||||||
|
original=element, value=inferred
|
||||||
|
)
|
||||||
|
elts.append(evaluated_object)
|
||||||
|
elif isinstance(arg, nodes.Dict):
|
||||||
|
# Dicts need to have consts as strings already.
|
||||||
|
if not all(isinstance(elt[0], nodes.Const) for elt in arg.items):
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
elts = [item[0].value for item in arg.items]
|
||||||
|
elif isinstance(arg, nodes.Const) and isinstance(
|
||||||
|
arg.value, (six.string_types, six.binary_type)
|
||||||
|
):
|
||||||
|
elts = arg.value
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
return klass.from_elements(elts=build_elts(elts))
|
||||||
|
|
||||||
|
|
||||||
|
def _infer_builtin_container(
|
||||||
|
node, context, klass=None, iterables=None, build_elts=None
|
||||||
|
):
|
||||||
|
transform_func = partial(
|
||||||
|
_container_generic_transform,
|
||||||
|
context=context,
|
||||||
|
klass=klass,
|
||||||
|
iterables=iterables,
|
||||||
|
build_elts=build_elts,
|
||||||
|
)
|
||||||
|
|
||||||
|
return _container_generic_inference(node, context, klass, transform_func)
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=invalid-name
|
||||||
|
infer_tuple = partial(
|
||||||
|
_infer_builtin_container,
|
||||||
|
klass=nodes.Tuple,
|
||||||
|
iterables=(
|
||||||
|
nodes.List,
|
||||||
|
nodes.Set,
|
||||||
|
objects.FrozenSet,
|
||||||
|
objects.DictItems,
|
||||||
|
objects.DictKeys,
|
||||||
|
objects.DictValues,
|
||||||
|
),
|
||||||
|
build_elts=tuple,
|
||||||
|
)
|
||||||
|
|
||||||
|
infer_list = partial(
|
||||||
|
_infer_builtin_container,
|
||||||
|
klass=nodes.List,
|
||||||
|
iterables=(
|
||||||
|
nodes.Tuple,
|
||||||
|
nodes.Set,
|
||||||
|
objects.FrozenSet,
|
||||||
|
objects.DictItems,
|
||||||
|
objects.DictKeys,
|
||||||
|
objects.DictValues,
|
||||||
|
),
|
||||||
|
build_elts=list,
|
||||||
|
)
|
||||||
|
|
||||||
|
infer_set = partial(
|
||||||
|
_infer_builtin_container,
|
||||||
|
klass=nodes.Set,
|
||||||
|
iterables=(nodes.List, nodes.Tuple, objects.FrozenSet, objects.DictKeys),
|
||||||
|
build_elts=set,
|
||||||
|
)
|
||||||
|
|
||||||
|
infer_frozenset = partial(
|
||||||
|
_infer_builtin_container,
|
||||||
|
klass=objects.FrozenSet,
|
||||||
|
iterables=(nodes.List, nodes.Tuple, nodes.Set, objects.FrozenSet, objects.DictKeys),
|
||||||
|
build_elts=frozenset,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_elts(arg, context):
|
||||||
|
is_iterable = lambda n: isinstance(n, (nodes.List, nodes.Tuple, nodes.Set))
|
||||||
|
try:
|
||||||
|
inferred = next(arg.infer(context))
|
||||||
|
except (InferenceError, NameInferenceError):
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
if isinstance(inferred, nodes.Dict):
|
||||||
|
items = inferred.items
|
||||||
|
elif is_iterable(inferred):
|
||||||
|
items = []
|
||||||
|
for elt in inferred.elts:
|
||||||
|
# If an item is not a pair of two items,
|
||||||
|
# then fallback to the default inference.
|
||||||
|
# Also, take in consideration only hashable items,
|
||||||
|
# tuples and consts. We are choosing Names as well.
|
||||||
|
if not is_iterable(elt):
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
if len(elt.elts) != 2:
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
if not isinstance(elt.elts[0], (nodes.Tuple, nodes.Const, nodes.Name)):
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
items.append(tuple(elt.elts))
|
||||||
|
else:
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
return items
|
||||||
|
|
||||||
|
|
||||||
|
def infer_dict(node, context=None):
|
||||||
|
"""Try to infer a dict call to a Dict node.
|
||||||
|
|
||||||
|
The function treats the following cases:
|
||||||
|
|
||||||
|
* dict()
|
||||||
|
* dict(mapping)
|
||||||
|
* dict(iterable)
|
||||||
|
* dict(iterable, **kwargs)
|
||||||
|
* dict(mapping, **kwargs)
|
||||||
|
* dict(**kwargs)
|
||||||
|
|
||||||
|
If a case can't be inferred, we'll fallback to default inference.
|
||||||
|
"""
|
||||||
|
call = arguments.CallSite.from_call(node, context=context)
|
||||||
|
if call.has_invalid_arguments() or call.has_invalid_keywords():
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
args = call.positional_arguments
|
||||||
|
kwargs = list(call.keyword_arguments.items())
|
||||||
|
|
||||||
|
if not args and not kwargs:
|
||||||
|
# dict()
|
||||||
|
return nodes.Dict()
|
||||||
|
elif kwargs and not args:
|
||||||
|
# dict(a=1, b=2, c=4)
|
||||||
|
items = [(nodes.Const(key), value) for key, value in kwargs]
|
||||||
|
elif len(args) == 1 and kwargs:
|
||||||
|
# dict(some_iterable, b=2, c=4)
|
||||||
|
elts = _get_elts(args[0], context)
|
||||||
|
keys = [(nodes.Const(key), value) for key, value in kwargs]
|
||||||
|
items = elts + keys
|
||||||
|
elif len(args) == 1:
|
||||||
|
items = _get_elts(args[0], context)
|
||||||
|
else:
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
|
||||||
|
value = nodes.Dict(
|
||||||
|
col_offset=node.col_offset, lineno=node.lineno, parent=node.parent
|
||||||
|
)
|
||||||
|
value.postinit(items)
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def infer_super(node, context=None):
|
||||||
|
"""Understand super calls.
|
||||||
|
|
||||||
|
There are some restrictions for what can be understood:
|
||||||
|
|
||||||
|
* unbounded super (one argument form) is not understood.
|
||||||
|
|
||||||
|
* if the super call is not inside a function (classmethod or method),
|
||||||
|
then the default inference will be used.
|
||||||
|
|
||||||
|
* if the super arguments can't be inferred, the default inference
|
||||||
|
will be used.
|
||||||
|
"""
|
||||||
|
if len(node.args) == 1:
|
||||||
|
# Ignore unbounded super.
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
scope = node.scope()
|
||||||
|
if not isinstance(scope, nodes.FunctionDef):
|
||||||
|
# Ignore non-method uses of super.
|
||||||
|
raise UseInferenceDefault
|
||||||
|
if scope.type not in ("classmethod", "method"):
|
||||||
|
# Not interested in staticmethods.
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
cls = scoped_nodes.get_wrapping_class(scope)
|
||||||
|
if not len(node.args):
|
||||||
|
mro_pointer = cls
|
||||||
|
# In we are in a classmethod, the interpreter will fill
|
||||||
|
# automatically the class as the second argument, not an instance.
|
||||||
|
if scope.type == "classmethod":
|
||||||
|
mro_type = cls
|
||||||
|
else:
|
||||||
|
mro_type = cls.instantiate_class()
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
mro_pointer = next(node.args[0].infer(context=context))
|
||||||
|
except InferenceError:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
try:
|
||||||
|
mro_type = next(node.args[1].infer(context=context))
|
||||||
|
except InferenceError:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
if mro_pointer is util.Uninferable or mro_type is util.Uninferable:
|
||||||
|
# No way we could understand this.
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
super_obj = objects.Super(
|
||||||
|
mro_pointer=mro_pointer, mro_type=mro_type, self_class=cls, scope=scope
|
||||||
|
)
|
||||||
|
super_obj.parent = node
|
||||||
|
return super_obj
|
||||||
|
|
||||||
|
|
||||||
|
def _infer_getattr_args(node, context):
|
||||||
|
if len(node.args) not in (2, 3):
|
||||||
|
# Not a valid getattr call.
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj = next(node.args[0].infer(context=context))
|
||||||
|
attr = next(node.args[1].infer(context=context))
|
||||||
|
except InferenceError:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
if obj is util.Uninferable or attr is util.Uninferable:
|
||||||
|
# If one of the arguments is something we can't infer,
|
||||||
|
# then also make the result of the getattr call something
|
||||||
|
# which is unknown.
|
||||||
|
return util.Uninferable, util.Uninferable
|
||||||
|
|
||||||
|
is_string = isinstance(attr, nodes.Const) and isinstance(
|
||||||
|
attr.value, six.string_types
|
||||||
|
)
|
||||||
|
if not is_string:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
return obj, attr.value
|
||||||
|
|
||||||
|
|
||||||
|
def infer_getattr(node, context=None):
|
||||||
|
"""Understand getattr calls
|
||||||
|
|
||||||
|
If one of the arguments is an Uninferable object, then the
|
||||||
|
result will be an Uninferable object. Otherwise, the normal attribute
|
||||||
|
lookup will be done.
|
||||||
|
"""
|
||||||
|
obj, attr = _infer_getattr_args(node, context)
|
||||||
|
if (
|
||||||
|
obj is util.Uninferable
|
||||||
|
or attr is util.Uninferable
|
||||||
|
or not hasattr(obj, "igetattr")
|
||||||
|
):
|
||||||
|
return util.Uninferable
|
||||||
|
|
||||||
|
try:
|
||||||
|
return next(obj.igetattr(attr, context=context))
|
||||||
|
except (StopIteration, InferenceError, AttributeInferenceError):
|
||||||
|
if len(node.args) == 3:
|
||||||
|
# Try to infer the default and return it instead.
|
||||||
|
try:
|
||||||
|
return next(node.args[2].infer(context=context))
|
||||||
|
except InferenceError:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
|
||||||
|
def infer_hasattr(node, context=None):
|
||||||
|
"""Understand hasattr calls
|
||||||
|
|
||||||
|
This always guarantees three possible outcomes for calling
|
||||||
|
hasattr: Const(False) when we are sure that the object
|
||||||
|
doesn't have the intended attribute, Const(True) when
|
||||||
|
we know that the object has the attribute and Uninferable
|
||||||
|
when we are unsure of the outcome of the function call.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
obj, attr = _infer_getattr_args(node, context)
|
||||||
|
if (
|
||||||
|
obj is util.Uninferable
|
||||||
|
or attr is util.Uninferable
|
||||||
|
or not hasattr(obj, "getattr")
|
||||||
|
):
|
||||||
|
return util.Uninferable
|
||||||
|
obj.getattr(attr, context=context)
|
||||||
|
except UseInferenceDefault:
|
||||||
|
# Can't infer something from this function call.
|
||||||
|
return util.Uninferable
|
||||||
|
except AttributeInferenceError:
|
||||||
|
# Doesn't have it.
|
||||||
|
return nodes.Const(False)
|
||||||
|
return nodes.Const(True)
|
||||||
|
|
||||||
|
|
||||||
|
def infer_callable(node, context=None):
|
||||||
|
"""Understand callable calls
|
||||||
|
|
||||||
|
This follows Python's semantics, where an object
|
||||||
|
is callable if it provides an attribute __call__,
|
||||||
|
even though that attribute is something which can't be
|
||||||
|
called.
|
||||||
|
"""
|
||||||
|
if len(node.args) != 1:
|
||||||
|
# Invalid callable call.
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
argument = node.args[0]
|
||||||
|
try:
|
||||||
|
inferred = next(argument.infer(context=context))
|
||||||
|
except InferenceError:
|
||||||
|
return util.Uninferable
|
||||||
|
if inferred is util.Uninferable:
|
||||||
|
return util.Uninferable
|
||||||
|
return nodes.Const(inferred.callable())
|
||||||
|
|
||||||
|
|
||||||
|
def infer_property(node, context=None):
|
||||||
|
"""Understand `property` class
|
||||||
|
|
||||||
|
This only infers the output of `property`
|
||||||
|
call, not the arguments themselves.
|
||||||
|
"""
|
||||||
|
if len(node.args) < 1:
|
||||||
|
# Invalid property call.
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
getter = node.args[0]
|
||||||
|
try:
|
||||||
|
inferred = next(getter.infer(context=context))
|
||||||
|
except InferenceError:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
if not isinstance(inferred, (nodes.FunctionDef, nodes.Lambda)):
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
return objects.Property(
|
||||||
|
function=inferred,
|
||||||
|
name=inferred.name,
|
||||||
|
doc=getattr(inferred, "doc", None),
|
||||||
|
lineno=node.lineno,
|
||||||
|
parent=node,
|
||||||
|
col_offset=node.col_offset,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def infer_bool(node, context=None):
|
||||||
|
"""Understand bool calls."""
|
||||||
|
if len(node.args) > 1:
|
||||||
|
# Invalid bool call.
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
if not node.args:
|
||||||
|
return nodes.Const(False)
|
||||||
|
|
||||||
|
argument = node.args[0]
|
||||||
|
try:
|
||||||
|
inferred = next(argument.infer(context=context))
|
||||||
|
except InferenceError:
|
||||||
|
return util.Uninferable
|
||||||
|
if inferred is util.Uninferable:
|
||||||
|
return util.Uninferable
|
||||||
|
|
||||||
|
bool_value = inferred.bool_value(context=context)
|
||||||
|
if bool_value is util.Uninferable:
|
||||||
|
return util.Uninferable
|
||||||
|
return nodes.Const(bool_value)
|
||||||
|
|
||||||
|
|
||||||
|
def infer_type(node, context=None):
|
||||||
|
"""Understand the one-argument form of *type*."""
|
||||||
|
if len(node.args) != 1:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
return helpers.object_type(node.args[0], context)
|
||||||
|
|
||||||
|
|
||||||
|
def infer_slice(node, context=None):
|
||||||
|
"""Understand `slice` calls."""
|
||||||
|
args = node.args
|
||||||
|
if not 0 < len(args) <= 3:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
infer_func = partial(helpers.safe_infer, context=context)
|
||||||
|
args = [infer_func(arg) for arg in args]
|
||||||
|
for arg in args:
|
||||||
|
if not arg or arg is util.Uninferable:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
if not isinstance(arg, nodes.Const):
|
||||||
|
raise UseInferenceDefault
|
||||||
|
if not isinstance(arg.value, (type(None), int)):
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
if len(args) < 3:
|
||||||
|
# Make sure we have 3 arguments.
|
||||||
|
args.extend([None] * (3 - len(args)))
|
||||||
|
|
||||||
|
slice_node = nodes.Slice(
|
||||||
|
lineno=node.lineno, col_offset=node.col_offset, parent=node.parent
|
||||||
|
)
|
||||||
|
slice_node.postinit(*args)
|
||||||
|
return slice_node
|
||||||
|
|
||||||
|
|
||||||
|
def _infer_object__new__decorator(node, context=None):
|
||||||
|
# Instantiate class immediately
|
||||||
|
# since that's what @object.__new__ does
|
||||||
|
return iter((node.instantiate_class(),))
|
||||||
|
|
||||||
|
|
||||||
|
def _infer_object__new__decorator_check(node):
|
||||||
|
"""Predicate before inference_tip
|
||||||
|
|
||||||
|
Check if the given ClassDef has an @object.__new__ decorator
|
||||||
|
"""
|
||||||
|
if not node.decorators:
|
||||||
|
return False
|
||||||
|
|
||||||
|
for decorator in node.decorators.nodes:
|
||||||
|
if isinstance(decorator, nodes.Attribute):
|
||||||
|
if decorator.as_string() == OBJECT_DUNDER_NEW:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def infer_issubclass(callnode, context=None):
|
||||||
|
"""Infer issubclass() calls
|
||||||
|
|
||||||
|
:param nodes.Call callnode: an `issubclass` call
|
||||||
|
:param InferenceContext: the context for the inference
|
||||||
|
:rtype nodes.Const: Boolean Const value of the `issubclass` call
|
||||||
|
:raises UseInferenceDefault: If the node cannot be inferred
|
||||||
|
"""
|
||||||
|
call = arguments.CallSite.from_call(callnode, context=context)
|
||||||
|
if call.keyword_arguments:
|
||||||
|
# issubclass doesn't support keyword arguments
|
||||||
|
raise UseInferenceDefault("TypeError: issubclass() takes no keyword arguments")
|
||||||
|
if len(call.positional_arguments) != 2:
|
||||||
|
raise UseInferenceDefault(
|
||||||
|
"Expected two arguments, got {count}".format(
|
||||||
|
count=len(call.positional_arguments)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# The left hand argument is the obj to be checked
|
||||||
|
obj_node, class_or_tuple_node = call.positional_arguments
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj_type = next(obj_node.infer(context=context))
|
||||||
|
except InferenceError as exc:
|
||||||
|
raise UseInferenceDefault from exc
|
||||||
|
if not isinstance(obj_type, nodes.ClassDef):
|
||||||
|
raise UseInferenceDefault("TypeError: arg 1 must be class")
|
||||||
|
|
||||||
|
# The right hand argument is the class(es) that the given
|
||||||
|
# object is to be checked against.
|
||||||
|
try:
|
||||||
|
class_container = _class_or_tuple_to_container(
|
||||||
|
class_or_tuple_node, context=context
|
||||||
|
)
|
||||||
|
except InferenceError as exc:
|
||||||
|
raise UseInferenceDefault from exc
|
||||||
|
try:
|
||||||
|
issubclass_bool = helpers.object_issubclass(obj_type, class_container, context)
|
||||||
|
except AstroidTypeError as exc:
|
||||||
|
raise UseInferenceDefault("TypeError: " + str(exc)) from exc
|
||||||
|
except MroError as exc:
|
||||||
|
raise UseInferenceDefault from exc
|
||||||
|
return nodes.Const(issubclass_bool)
|
||||||
|
|
||||||
|
|
||||||
|
def infer_isinstance(callnode, context=None):
|
||||||
|
"""Infer isinstance calls
|
||||||
|
|
||||||
|
:param nodes.Call callnode: an isinstance call
|
||||||
|
:param InferenceContext: context for call
|
||||||
|
(currently unused but is a common interface for inference)
|
||||||
|
:rtype nodes.Const: Boolean Const value of isinstance call
|
||||||
|
|
||||||
|
:raises UseInferenceDefault: If the node cannot be inferred
|
||||||
|
"""
|
||||||
|
call = arguments.CallSite.from_call(callnode, context=context)
|
||||||
|
if call.keyword_arguments:
|
||||||
|
# isinstance doesn't support keyword arguments
|
||||||
|
raise UseInferenceDefault("TypeError: isinstance() takes no keyword arguments")
|
||||||
|
if len(call.positional_arguments) != 2:
|
||||||
|
raise UseInferenceDefault(
|
||||||
|
"Expected two arguments, got {count}".format(
|
||||||
|
count=len(call.positional_arguments)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# The left hand argument is the obj to be checked
|
||||||
|
obj_node, class_or_tuple_node = call.positional_arguments
|
||||||
|
# The right hand argument is the class(es) that the given
|
||||||
|
# obj is to be check is an instance of
|
||||||
|
try:
|
||||||
|
class_container = _class_or_tuple_to_container(
|
||||||
|
class_or_tuple_node, context=context
|
||||||
|
)
|
||||||
|
except InferenceError:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
try:
|
||||||
|
isinstance_bool = helpers.object_isinstance(obj_node, class_container, context)
|
||||||
|
except AstroidTypeError as exc:
|
||||||
|
raise UseInferenceDefault("TypeError: " + str(exc))
|
||||||
|
except MroError as exc:
|
||||||
|
raise UseInferenceDefault from exc
|
||||||
|
if isinstance_bool is util.Uninferable:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
return nodes.Const(isinstance_bool)
|
||||||
|
|
||||||
|
|
||||||
|
def _class_or_tuple_to_container(node, context=None):
|
||||||
|
# Move inferences results into container
|
||||||
|
# to simplify later logic
|
||||||
|
# raises InferenceError if any of the inferences fall through
|
||||||
|
node_infer = next(node.infer(context=context))
|
||||||
|
# arg2 MUST be a type or a TUPLE of types
|
||||||
|
# for isinstance
|
||||||
|
if isinstance(node_infer, nodes.Tuple):
|
||||||
|
class_container = [
|
||||||
|
next(node.infer(context=context)) for node in node_infer.elts
|
||||||
|
]
|
||||||
|
class_container = [
|
||||||
|
klass_node for klass_node in class_container if klass_node is not None
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
class_container = [node_infer]
|
||||||
|
return class_container
|
||||||
|
|
||||||
|
|
||||||
|
def infer_len(node, context=None):
|
||||||
|
"""Infer length calls
|
||||||
|
|
||||||
|
:param nodes.Call node: len call to infer
|
||||||
|
:param context.InferenceContext: node context
|
||||||
|
:rtype nodes.Const: a Const node with the inferred length, if possible
|
||||||
|
"""
|
||||||
|
call = arguments.CallSite.from_call(node, context=context)
|
||||||
|
if call.keyword_arguments:
|
||||||
|
raise UseInferenceDefault("TypeError: len() must take no keyword arguments")
|
||||||
|
if len(call.positional_arguments) != 1:
|
||||||
|
raise UseInferenceDefault(
|
||||||
|
"TypeError: len() must take exactly one argument "
|
||||||
|
"({len}) given".format(len=len(call.positional_arguments))
|
||||||
|
)
|
||||||
|
[argument_node] = call.positional_arguments
|
||||||
|
try:
|
||||||
|
return nodes.Const(helpers.object_len(argument_node, context=context))
|
||||||
|
except (AstroidTypeError, InferenceError) as exc:
|
||||||
|
raise UseInferenceDefault(str(exc)) from exc
|
||||||
|
|
||||||
|
|
||||||
|
def infer_str(node, context=None):
|
||||||
|
"""Infer str() calls
|
||||||
|
|
||||||
|
:param nodes.Call node: str() call to infer
|
||||||
|
:param context.InferenceContext: node context
|
||||||
|
:rtype nodes.Const: a Const containing an empty string
|
||||||
|
"""
|
||||||
|
call = arguments.CallSite.from_call(node, context=context)
|
||||||
|
if call.keyword_arguments:
|
||||||
|
raise UseInferenceDefault("TypeError: str() must take no keyword arguments")
|
||||||
|
try:
|
||||||
|
return nodes.Const("")
|
||||||
|
except (AstroidTypeError, InferenceError) as exc:
|
||||||
|
raise UseInferenceDefault(str(exc)) from exc
|
||||||
|
|
||||||
|
|
||||||
|
def infer_int(node, context=None):
|
||||||
|
"""Infer int() calls
|
||||||
|
|
||||||
|
:param nodes.Call node: int() call to infer
|
||||||
|
:param context.InferenceContext: node context
|
||||||
|
:rtype nodes.Const: a Const containing the integer value of the int() call
|
||||||
|
"""
|
||||||
|
call = arguments.CallSite.from_call(node, context=context)
|
||||||
|
if call.keyword_arguments:
|
||||||
|
raise UseInferenceDefault("TypeError: int() must take no keyword arguments")
|
||||||
|
|
||||||
|
if call.positional_arguments:
|
||||||
|
try:
|
||||||
|
first_value = next(call.positional_arguments[0].infer(context=context))
|
||||||
|
except (InferenceError, StopIteration) as exc:
|
||||||
|
raise UseInferenceDefault(str(exc)) from exc
|
||||||
|
|
||||||
|
if first_value is util.Uninferable:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
if isinstance(first_value, nodes.Const) and isinstance(
|
||||||
|
first_value.value, (int, str)
|
||||||
|
):
|
||||||
|
try:
|
||||||
|
actual_value = int(first_value.value)
|
||||||
|
except ValueError:
|
||||||
|
return nodes.Const(0)
|
||||||
|
return nodes.Const(actual_value)
|
||||||
|
|
||||||
|
return nodes.Const(0)
|
||||||
|
|
||||||
|
|
||||||
|
def infer_dict_fromkeys(node, context=None):
|
||||||
|
"""Infer dict.fromkeys
|
||||||
|
|
||||||
|
:param nodes.Call node: dict.fromkeys() call to infer
|
||||||
|
:param context.InferenceContext: node context
|
||||||
|
:rtype nodes.Dict:
|
||||||
|
a Dictionary containing the values that astroid was able to infer.
|
||||||
|
In case the inference failed for any reason, an empty dictionary
|
||||||
|
will be inferred instead.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _build_dict_with_elements(elements):
|
||||||
|
new_node = nodes.Dict(
|
||||||
|
col_offset=node.col_offset, lineno=node.lineno, parent=node.parent
|
||||||
|
)
|
||||||
|
new_node.postinit(elements)
|
||||||
|
return new_node
|
||||||
|
|
||||||
|
call = arguments.CallSite.from_call(node, context=context)
|
||||||
|
if call.keyword_arguments:
|
||||||
|
raise UseInferenceDefault("TypeError: int() must take no keyword arguments")
|
||||||
|
if len(call.positional_arguments) not in {1, 2}:
|
||||||
|
raise UseInferenceDefault(
|
||||||
|
"TypeError: Needs between 1 and 2 positional arguments"
|
||||||
|
)
|
||||||
|
|
||||||
|
default = nodes.Const(None)
|
||||||
|
values = call.positional_arguments[0]
|
||||||
|
try:
|
||||||
|
inferred_values = next(values.infer(context=context))
|
||||||
|
except InferenceError:
|
||||||
|
return _build_dict_with_elements([])
|
||||||
|
if inferred_values is util.Uninferable:
|
||||||
|
return _build_dict_with_elements([])
|
||||||
|
|
||||||
|
# Limit to a couple of potential values, as this can become pretty complicated
|
||||||
|
accepted_iterable_elements = (nodes.Const,)
|
||||||
|
if isinstance(inferred_values, (nodes.List, nodes.Set, nodes.Tuple)):
|
||||||
|
elements = inferred_values.elts
|
||||||
|
for element in elements:
|
||||||
|
if not isinstance(element, accepted_iterable_elements):
|
||||||
|
# Fallback to an empty dict
|
||||||
|
return _build_dict_with_elements([])
|
||||||
|
|
||||||
|
elements_with_value = [(element, default) for element in elements]
|
||||||
|
return _build_dict_with_elements(elements_with_value)
|
||||||
|
|
||||||
|
elif isinstance(inferred_values, nodes.Const) and isinstance(
|
||||||
|
inferred_values.value, (str, bytes)
|
||||||
|
):
|
||||||
|
elements = [
|
||||||
|
(nodes.Const(element), default) for element in inferred_values.value
|
||||||
|
]
|
||||||
|
return _build_dict_with_elements(elements)
|
||||||
|
elif isinstance(inferred_values, nodes.Dict):
|
||||||
|
keys = inferred_values.itered()
|
||||||
|
for key in keys:
|
||||||
|
if not isinstance(key, accepted_iterable_elements):
|
||||||
|
# Fallback to an empty dict
|
||||||
|
return _build_dict_with_elements([])
|
||||||
|
|
||||||
|
elements_with_value = [(element, default) for element in keys]
|
||||||
|
return _build_dict_with_elements(elements_with_value)
|
||||||
|
|
||||||
|
# Fallback to an empty dictionary
|
||||||
|
return _build_dict_with_elements([])
|
||||||
|
|
||||||
|
|
||||||
|
# Builtins inference
|
||||||
|
register_builtin_transform(infer_bool, "bool")
|
||||||
|
register_builtin_transform(infer_super, "super")
|
||||||
|
register_builtin_transform(infer_callable, "callable")
|
||||||
|
register_builtin_transform(infer_property, "property")
|
||||||
|
register_builtin_transform(infer_getattr, "getattr")
|
||||||
|
register_builtin_transform(infer_hasattr, "hasattr")
|
||||||
|
register_builtin_transform(infer_tuple, "tuple")
|
||||||
|
register_builtin_transform(infer_set, "set")
|
||||||
|
register_builtin_transform(infer_list, "list")
|
||||||
|
register_builtin_transform(infer_dict, "dict")
|
||||||
|
register_builtin_transform(infer_frozenset, "frozenset")
|
||||||
|
register_builtin_transform(infer_type, "type")
|
||||||
|
register_builtin_transform(infer_slice, "slice")
|
||||||
|
register_builtin_transform(infer_isinstance, "isinstance")
|
||||||
|
register_builtin_transform(infer_issubclass, "issubclass")
|
||||||
|
register_builtin_transform(infer_len, "len")
|
||||||
|
register_builtin_transform(infer_str, "str")
|
||||||
|
register_builtin_transform(infer_int, "int")
|
||||||
|
register_builtin_transform(infer_dict_fromkeys, "dict.fromkeys")
|
||||||
|
|
||||||
|
|
||||||
|
# Infer object.__new__ calls
|
||||||
|
MANAGER.register_transform(
|
||||||
|
nodes.ClassDef,
|
||||||
|
inference_tip(_infer_object__new__decorator),
|
||||||
|
_infer_object__new__decorator_check,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2016-2017 Łukasz Rogalski <rogalski.91@gmail.com>
|
||||||
|
# Copyright (c) 2017 Derek Gustafson <degustaf@gmail.com>
|
||||||
|
# Copyright (c) 2018 Ioana Tagirta <ioana.tagirta@gmail.com>
|
||||||
|
# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
|
||||||
|
|
||||||
|
def _collections_transform():
|
||||||
|
return astroid.parse(
|
||||||
|
"""
|
||||||
|
class defaultdict(dict):
|
||||||
|
default_factory = None
|
||||||
|
def __missing__(self, key): pass
|
||||||
|
def __getitem__(self, key): return default_factory
|
||||||
|
|
||||||
|
"""
|
||||||
|
+ _deque_mock()
|
||||||
|
+ _ordered_dict_mock()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _deque_mock():
|
||||||
|
base_deque_class = """
|
||||||
|
class deque(object):
|
||||||
|
maxlen = 0
|
||||||
|
def __init__(self, iterable=None, maxlen=None):
|
||||||
|
self.iterable = iterable or []
|
||||||
|
def append(self, x): pass
|
||||||
|
def appendleft(self, x): pass
|
||||||
|
def clear(self): pass
|
||||||
|
def count(self, x): return 0
|
||||||
|
def extend(self, iterable): pass
|
||||||
|
def extendleft(self, iterable): pass
|
||||||
|
def pop(self): return self.iterable[0]
|
||||||
|
def popleft(self): return self.iterable[0]
|
||||||
|
def remove(self, value): pass
|
||||||
|
def reverse(self): return reversed(self.iterable)
|
||||||
|
def rotate(self, n=1): return self
|
||||||
|
def __iter__(self): return self
|
||||||
|
def __reversed__(self): return self.iterable[::-1]
|
||||||
|
def __getitem__(self, index): return self.iterable[index]
|
||||||
|
def __setitem__(self, index, value): pass
|
||||||
|
def __delitem__(self, index): pass
|
||||||
|
def __bool__(self): return bool(self.iterable)
|
||||||
|
def __nonzero__(self): return bool(self.iterable)
|
||||||
|
def __contains__(self, o): return o in self.iterable
|
||||||
|
def __len__(self): return len(self.iterable)
|
||||||
|
def __copy__(self): return deque(self.iterable)
|
||||||
|
def copy(self): return deque(self.iterable)
|
||||||
|
def index(self, x, start=0, end=0): return 0
|
||||||
|
def insert(self, x, i): pass
|
||||||
|
def __add__(self, other): pass
|
||||||
|
def __iadd__(self, other): pass
|
||||||
|
def __mul__(self, other): pass
|
||||||
|
def __imul__(self, other): pass
|
||||||
|
def __rmul__(self, other): pass"""
|
||||||
|
return base_deque_class
|
||||||
|
|
||||||
|
|
||||||
|
def _ordered_dict_mock():
|
||||||
|
base_ordered_dict_class = """
|
||||||
|
class OrderedDict(dict):
|
||||||
|
def __reversed__(self): return self[::-1]
|
||||||
|
def move_to_end(self, key, last=False): pass"""
|
||||||
|
return base_ordered_dict_class
|
||||||
|
|
||||||
|
|
||||||
|
astroid.register_module_extender(astroid.MANAGER, "collections", _collections_transform)
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
import sys
|
||||||
|
import astroid
|
||||||
|
|
||||||
|
PY37 = sys.version_info >= (3, 7)
|
||||||
|
|
||||||
|
if PY37:
|
||||||
|
# Since Python 3.7 Hashing Methods are added
|
||||||
|
# dynamically to globals()
|
||||||
|
|
||||||
|
def _re_transform():
|
||||||
|
return astroid.parse(
|
||||||
|
"""
|
||||||
|
from collections import namedtuple
|
||||||
|
_Method = namedtuple('_Method', 'name ident salt_chars total_size')
|
||||||
|
|
||||||
|
METHOD_SHA512 = _Method('SHA512', '6', 16, 106)
|
||||||
|
METHOD_SHA256 = _Method('SHA256', '5', 16, 63)
|
||||||
|
METHOD_BLOWFISH = _Method('BLOWFISH', 2, 'b', 22)
|
||||||
|
METHOD_MD5 = _Method('MD5', '1', 8, 34)
|
||||||
|
METHOD_CRYPT = _Method('CRYPT', None, 2, 13)
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
astroid.register_module_extender(astroid.MANAGER, "crypt", _re_transform)
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
import astroid
|
||||||
|
|
||||||
|
|
||||||
|
def _curses_transform():
|
||||||
|
return astroid.parse(
|
||||||
|
"""
|
||||||
|
A_ALTCHARSET = 1
|
||||||
|
A_BLINK = 1
|
||||||
|
A_BOLD = 1
|
||||||
|
A_DIM = 1
|
||||||
|
A_INVIS = 1
|
||||||
|
A_ITALIC = 1
|
||||||
|
A_NORMAL = 1
|
||||||
|
A_PROTECT = 1
|
||||||
|
A_REVERSE = 1
|
||||||
|
A_STANDOUT = 1
|
||||||
|
A_UNDERLINE = 1
|
||||||
|
A_HORIZONTAL = 1
|
||||||
|
A_LEFT = 1
|
||||||
|
A_LOW = 1
|
||||||
|
A_RIGHT = 1
|
||||||
|
A_TOP = 1
|
||||||
|
A_VERTICAL = 1
|
||||||
|
A_CHARTEXT = 1
|
||||||
|
A_ATTRIBUTES = 1
|
||||||
|
A_CHARTEXT = 1
|
||||||
|
A_COLOR = 1
|
||||||
|
KEY_MIN = 1
|
||||||
|
KEY_BREAK = 1
|
||||||
|
KEY_DOWN = 1
|
||||||
|
KEY_UP = 1
|
||||||
|
KEY_LEFT = 1
|
||||||
|
KEY_RIGHT = 1
|
||||||
|
KEY_HOME = 1
|
||||||
|
KEY_BACKSPACE = 1
|
||||||
|
KEY_F0 = 1
|
||||||
|
KEY_Fn = 1
|
||||||
|
KEY_DL = 1
|
||||||
|
KEY_IL = 1
|
||||||
|
KEY_DC = 1
|
||||||
|
KEY_IC = 1
|
||||||
|
KEY_EIC = 1
|
||||||
|
KEY_CLEAR = 1
|
||||||
|
KEY_EOS = 1
|
||||||
|
KEY_EOL = 1
|
||||||
|
KEY_SF = 1
|
||||||
|
KEY_SR = 1
|
||||||
|
KEY_NPAGE = 1
|
||||||
|
KEY_PPAGE = 1
|
||||||
|
KEY_STAB = 1
|
||||||
|
KEY_CTAB = 1
|
||||||
|
KEY_CATAB = 1
|
||||||
|
KEY_ENTER = 1
|
||||||
|
KEY_SRESET = 1
|
||||||
|
KEY_RESET = 1
|
||||||
|
KEY_PRINT = 1
|
||||||
|
KEY_LL = 1
|
||||||
|
KEY_A1 = 1
|
||||||
|
KEY_A3 = 1
|
||||||
|
KEY_B2 = 1
|
||||||
|
KEY_C1 = 1
|
||||||
|
KEY_C3 = 1
|
||||||
|
KEY_BTAB = 1
|
||||||
|
KEY_BEG = 1
|
||||||
|
KEY_CANCEL = 1
|
||||||
|
KEY_CLOSE = 1
|
||||||
|
KEY_COMMAND = 1
|
||||||
|
KEY_COPY = 1
|
||||||
|
KEY_CREATE = 1
|
||||||
|
KEY_END = 1
|
||||||
|
KEY_EXIT = 1
|
||||||
|
KEY_FIND = 1
|
||||||
|
KEY_HELP = 1
|
||||||
|
KEY_MARK = 1
|
||||||
|
KEY_MESSAGE = 1
|
||||||
|
KEY_MOVE = 1
|
||||||
|
KEY_NEXT = 1
|
||||||
|
KEY_OPEN = 1
|
||||||
|
KEY_OPTIONS = 1
|
||||||
|
KEY_PREVIOUS = 1
|
||||||
|
KEY_REDO = 1
|
||||||
|
KEY_REFERENCE = 1
|
||||||
|
KEY_REFRESH = 1
|
||||||
|
KEY_REPLACE = 1
|
||||||
|
KEY_RESTART = 1
|
||||||
|
KEY_RESUME = 1
|
||||||
|
KEY_SAVE = 1
|
||||||
|
KEY_SBEG = 1
|
||||||
|
KEY_SCANCEL = 1
|
||||||
|
KEY_SCOMMAND = 1
|
||||||
|
KEY_SCOPY = 1
|
||||||
|
KEY_SCREATE = 1
|
||||||
|
KEY_SDC = 1
|
||||||
|
KEY_SDL = 1
|
||||||
|
KEY_SELECT = 1
|
||||||
|
KEY_SEND = 1
|
||||||
|
KEY_SEOL = 1
|
||||||
|
KEY_SEXIT = 1
|
||||||
|
KEY_SFIND = 1
|
||||||
|
KEY_SHELP = 1
|
||||||
|
KEY_SHOME = 1
|
||||||
|
KEY_SIC = 1
|
||||||
|
KEY_SLEFT = 1
|
||||||
|
KEY_SMESSAGE = 1
|
||||||
|
KEY_SMOVE = 1
|
||||||
|
KEY_SNEXT = 1
|
||||||
|
KEY_SOPTIONS = 1
|
||||||
|
KEY_SPREVIOUS = 1
|
||||||
|
KEY_SPRINT = 1
|
||||||
|
KEY_SREDO = 1
|
||||||
|
KEY_SREPLACE = 1
|
||||||
|
KEY_SRIGHT = 1
|
||||||
|
KEY_SRSUME = 1
|
||||||
|
KEY_SSAVE = 1
|
||||||
|
KEY_SSUSPEND = 1
|
||||||
|
KEY_SUNDO = 1
|
||||||
|
KEY_SUSPEND = 1
|
||||||
|
KEY_UNDO = 1
|
||||||
|
KEY_MOUSE = 1
|
||||||
|
KEY_RESIZE = 1
|
||||||
|
KEY_MAX = 1
|
||||||
|
ACS_BBSS = 1
|
||||||
|
ACS_BLOCK = 1
|
||||||
|
ACS_BOARD = 1
|
||||||
|
ACS_BSBS = 1
|
||||||
|
ACS_BSSB = 1
|
||||||
|
ACS_BSSS = 1
|
||||||
|
ACS_BTEE = 1
|
||||||
|
ACS_BULLET = 1
|
||||||
|
ACS_CKBOARD = 1
|
||||||
|
ACS_DARROW = 1
|
||||||
|
ACS_DEGREE = 1
|
||||||
|
ACS_DIAMOND = 1
|
||||||
|
ACS_GEQUAL = 1
|
||||||
|
ACS_HLINE = 1
|
||||||
|
ACS_LANTERN = 1
|
||||||
|
ACS_LARROW = 1
|
||||||
|
ACS_LEQUAL = 1
|
||||||
|
ACS_LLCORNER = 1
|
||||||
|
ACS_LRCORNER = 1
|
||||||
|
ACS_LTEE = 1
|
||||||
|
ACS_NEQUAL = 1
|
||||||
|
ACS_PI = 1
|
||||||
|
ACS_PLMINUS = 1
|
||||||
|
ACS_PLUS = 1
|
||||||
|
ACS_RARROW = 1
|
||||||
|
ACS_RTEE = 1
|
||||||
|
ACS_S1 = 1
|
||||||
|
ACS_S3 = 1
|
||||||
|
ACS_S7 = 1
|
||||||
|
ACS_S9 = 1
|
||||||
|
ACS_SBBS = 1
|
||||||
|
ACS_SBSB = 1
|
||||||
|
ACS_SBSS = 1
|
||||||
|
ACS_SSBB = 1
|
||||||
|
ACS_SSBS = 1
|
||||||
|
ACS_SSSB = 1
|
||||||
|
ACS_SSSS = 1
|
||||||
|
ACS_STERLING = 1
|
||||||
|
ACS_TTEE = 1
|
||||||
|
ACS_UARROW = 1
|
||||||
|
ACS_ULCORNER = 1
|
||||||
|
ACS_URCORNER = 1
|
||||||
|
ACS_VLINE = 1
|
||||||
|
COLOR_BLACK = 1
|
||||||
|
COLOR_BLUE = 1
|
||||||
|
COLOR_CYAN = 1
|
||||||
|
COLOR_GREEN = 1
|
||||||
|
COLOR_MAGENTA = 1
|
||||||
|
COLOR_RED = 1
|
||||||
|
COLOR_WHITE = 1
|
||||||
|
COLOR_YELLOW = 1
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
astroid.register_module_extender(astroid.MANAGER, "curses", _curses_transform)
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
"""
|
||||||
|
Astroid hook for the dataclasses library
|
||||||
|
"""
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
from astroid import MANAGER
|
||||||
|
|
||||||
|
|
||||||
|
DATACLASSES_DECORATORS = frozenset(("dataclasses.dataclass", "dataclass"))
|
||||||
|
|
||||||
|
|
||||||
|
def is_decorated_with_dataclass(node, decorator_names=DATACLASSES_DECORATORS):
|
||||||
|
"""Return True if a decorated node has a `dataclass` decorator applied."""
|
||||||
|
if not node.decorators:
|
||||||
|
return False
|
||||||
|
for decorator_attribute in node.decorators.nodes:
|
||||||
|
if isinstance(decorator_attribute, astroid.Call): # decorator with arguments
|
||||||
|
decorator_attribute = decorator_attribute.func
|
||||||
|
if decorator_attribute.as_string() in decorator_names:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def dataclass_transform(node):
|
||||||
|
"""Rewrite a dataclass to be easily understood by pylint"""
|
||||||
|
|
||||||
|
for assign_node in node.body:
|
||||||
|
if not isinstance(assign_node, (astroid.AnnAssign, astroid.Assign)):
|
||||||
|
continue
|
||||||
|
|
||||||
|
targets = (
|
||||||
|
assign_node.targets
|
||||||
|
if hasattr(assign_node, "targets")
|
||||||
|
else [assign_node.target]
|
||||||
|
)
|
||||||
|
for target in targets:
|
||||||
|
rhs_node = astroid.Unknown(
|
||||||
|
lineno=assign_node.lineno,
|
||||||
|
col_offset=assign_node.col_offset,
|
||||||
|
parent=assign_node,
|
||||||
|
)
|
||||||
|
node.instance_attrs[target.name] = [rhs_node]
|
||||||
|
node.locals[target.name] = [rhs_node]
|
||||||
|
|
||||||
|
|
||||||
|
MANAGER.register_transform(
|
||||||
|
astroid.ClassDef, dataclass_transform, is_decorated_with_dataclass
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2015 raylu <lurayl@gmail.com>
|
||||||
|
# Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
"""Astroid hooks for dateutil"""
|
||||||
|
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
from astroid import MANAGER, register_module_extender
|
||||||
|
from astroid.builder import AstroidBuilder
|
||||||
|
|
||||||
|
|
||||||
|
def dateutil_transform():
|
||||||
|
return AstroidBuilder(MANAGER).string_build(
|
||||||
|
textwrap.dedent(
|
||||||
|
"""
|
||||||
|
import datetime
|
||||||
|
def parse(timestr, parserinfo=None, **kwargs):
|
||||||
|
return datetime.datetime()
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
register_module_extender(MANAGER, "dateutil.parser", dateutil_transform)
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
# Copyright (c) 2017-2018 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
import collections
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
|
||||||
|
|
||||||
|
def _clone_node_with_lineno(node, parent, lineno):
|
||||||
|
cls = node.__class__
|
||||||
|
other_fields = node._other_fields
|
||||||
|
_astroid_fields = node._astroid_fields
|
||||||
|
init_params = {"lineno": lineno, "col_offset": node.col_offset, "parent": parent}
|
||||||
|
postinit_params = {param: getattr(node, param) for param in _astroid_fields}
|
||||||
|
if other_fields:
|
||||||
|
init_params.update({param: getattr(node, param) for param in other_fields})
|
||||||
|
new_node = cls(**init_params)
|
||||||
|
if hasattr(node, "postinit") and _astroid_fields:
|
||||||
|
for param, child in postinit_params.items():
|
||||||
|
if child and not isinstance(child, collections.Sequence):
|
||||||
|
cloned_child = _clone_node_with_lineno(
|
||||||
|
node=child, lineno=new_node.lineno, parent=new_node
|
||||||
|
)
|
||||||
|
postinit_params[param] = cloned_child
|
||||||
|
new_node.postinit(**postinit_params)
|
||||||
|
return new_node
|
||||||
|
|
||||||
|
|
||||||
|
def _transform_formatted_value(node):
|
||||||
|
if node.value and node.value.lineno == 1:
|
||||||
|
if node.lineno != node.value.lineno:
|
||||||
|
new_node = astroid.FormattedValue(
|
||||||
|
lineno=node.lineno, col_offset=node.col_offset, parent=node.parent
|
||||||
|
)
|
||||||
|
new_value = _clone_node_with_lineno(
|
||||||
|
node=node.value, lineno=node.lineno, parent=new_node
|
||||||
|
)
|
||||||
|
new_node.postinit(value=new_value, format_spec=node.format_spec)
|
||||||
|
return new_node
|
||||||
|
|
||||||
|
|
||||||
|
if sys.version_info[:2] >= (3, 6):
|
||||||
|
# TODO: this fix tries to *patch* http://bugs.python.org/issue29051
|
||||||
|
# The problem is that FormattedValue.value, which is a Name node,
|
||||||
|
# has wrong line numbers, usually 1. This creates problems for pylint,
|
||||||
|
# which expects correct line numbers for things such as message control.
|
||||||
|
astroid.MANAGER.register_transform(
|
||||||
|
astroid.FormattedValue, _transform_formatted_value
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,159 @@
|
||||||
|
# Copyright (c) 2016, 2018-2020 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2018 hippo91 <guillaume.peillex@gmail.com>
|
||||||
|
# Copyright (c) 2018 Bryce Guinta <bryce.paul.guinta@gmail.com>
|
||||||
|
|
||||||
|
"""Astroid hooks for understanding functools library module."""
|
||||||
|
from functools import partial
|
||||||
|
from itertools import chain
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
from astroid import arguments
|
||||||
|
from astroid import BoundMethod
|
||||||
|
from astroid import extract_node
|
||||||
|
from astroid import helpers
|
||||||
|
from astroid.interpreter import objectmodel
|
||||||
|
from astroid import MANAGER
|
||||||
|
from astroid import objects
|
||||||
|
|
||||||
|
|
||||||
|
LRU_CACHE = "functools.lru_cache"
|
||||||
|
|
||||||
|
|
||||||
|
class LruWrappedModel(objectmodel.FunctionModel):
|
||||||
|
"""Special attribute model for functions decorated with functools.lru_cache.
|
||||||
|
|
||||||
|
The said decorators patches at decoration time some functions onto
|
||||||
|
the decorated function.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@property
|
||||||
|
def attr___wrapped__(self):
|
||||||
|
return self._instance
|
||||||
|
|
||||||
|
@property
|
||||||
|
def attr_cache_info(self):
|
||||||
|
cache_info = extract_node(
|
||||||
|
"""
|
||||||
|
from functools import _CacheInfo
|
||||||
|
_CacheInfo(0, 0, 0, 0)
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
class CacheInfoBoundMethod(BoundMethod):
|
||||||
|
def infer_call_result(self, caller, context=None):
|
||||||
|
yield helpers.safe_infer(cache_info)
|
||||||
|
|
||||||
|
return CacheInfoBoundMethod(proxy=self._instance, bound=self._instance)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def attr_cache_clear(self):
|
||||||
|
node = extract_node("""def cache_clear(self): pass""")
|
||||||
|
return BoundMethod(proxy=node, bound=self._instance.parent.scope())
|
||||||
|
|
||||||
|
|
||||||
|
def _transform_lru_cache(node, context=None):
|
||||||
|
# TODO: this is not ideal, since the node should be immutable,
|
||||||
|
# but due to https://github.com/PyCQA/astroid/issues/354,
|
||||||
|
# there's not much we can do now.
|
||||||
|
# Replacing the node would work partially, because,
|
||||||
|
# in pylint, the old node would still be available, leading
|
||||||
|
# to spurious false positives.
|
||||||
|
node.special_attributes = LruWrappedModel()(node)
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
def _functools_partial_inference(node, context=None):
|
||||||
|
call = arguments.CallSite.from_call(node, context=context)
|
||||||
|
number_of_positional = len(call.positional_arguments)
|
||||||
|
if number_of_positional < 1:
|
||||||
|
raise astroid.UseInferenceDefault(
|
||||||
|
"functools.partial takes at least one argument"
|
||||||
|
)
|
||||||
|
if number_of_positional == 1 and not call.keyword_arguments:
|
||||||
|
raise astroid.UseInferenceDefault(
|
||||||
|
"functools.partial needs at least to have some filled arguments"
|
||||||
|
)
|
||||||
|
|
||||||
|
partial_function = call.positional_arguments[0]
|
||||||
|
try:
|
||||||
|
inferred_wrapped_function = next(partial_function.infer(context=context))
|
||||||
|
except astroid.InferenceError as exc:
|
||||||
|
raise astroid.UseInferenceDefault from exc
|
||||||
|
if inferred_wrapped_function is astroid.Uninferable:
|
||||||
|
raise astroid.UseInferenceDefault("Cannot infer the wrapped function")
|
||||||
|
if not isinstance(inferred_wrapped_function, astroid.FunctionDef):
|
||||||
|
raise astroid.UseInferenceDefault("The wrapped function is not a function")
|
||||||
|
|
||||||
|
# Determine if the passed keywords into the callsite are supported
|
||||||
|
# by the wrapped function.
|
||||||
|
function_parameters = chain(
|
||||||
|
inferred_wrapped_function.args.args or (),
|
||||||
|
inferred_wrapped_function.args.posonlyargs or (),
|
||||||
|
inferred_wrapped_function.args.kwonlyargs or (),
|
||||||
|
)
|
||||||
|
parameter_names = set(
|
||||||
|
param.name
|
||||||
|
for param in function_parameters
|
||||||
|
if isinstance(param, astroid.AssignName)
|
||||||
|
)
|
||||||
|
if set(call.keyword_arguments) - parameter_names:
|
||||||
|
raise astroid.UseInferenceDefault(
|
||||||
|
"wrapped function received unknown parameters"
|
||||||
|
)
|
||||||
|
|
||||||
|
partial_function = objects.PartialFunction(
|
||||||
|
call,
|
||||||
|
name=inferred_wrapped_function.name,
|
||||||
|
doc=inferred_wrapped_function.doc,
|
||||||
|
lineno=inferred_wrapped_function.lineno,
|
||||||
|
col_offset=inferred_wrapped_function.col_offset,
|
||||||
|
parent=inferred_wrapped_function.parent,
|
||||||
|
)
|
||||||
|
partial_function.postinit(
|
||||||
|
args=inferred_wrapped_function.args,
|
||||||
|
body=inferred_wrapped_function.body,
|
||||||
|
decorators=inferred_wrapped_function.decorators,
|
||||||
|
returns=inferred_wrapped_function.returns,
|
||||||
|
type_comment_returns=inferred_wrapped_function.type_comment_returns,
|
||||||
|
type_comment_args=inferred_wrapped_function.type_comment_args,
|
||||||
|
)
|
||||||
|
return iter((partial_function,))
|
||||||
|
|
||||||
|
|
||||||
|
def _looks_like_lru_cache(node):
|
||||||
|
"""Check if the given function node is decorated with lru_cache."""
|
||||||
|
if not node.decorators:
|
||||||
|
return False
|
||||||
|
for decorator in node.decorators.nodes:
|
||||||
|
if not isinstance(decorator, astroid.Call):
|
||||||
|
continue
|
||||||
|
if _looks_like_functools_member(decorator, "lru_cache"):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _looks_like_functools_member(node, member):
|
||||||
|
"""Check if the given Call node is a functools.partial call"""
|
||||||
|
if isinstance(node.func, astroid.Name):
|
||||||
|
return node.func.name == member
|
||||||
|
elif isinstance(node.func, astroid.Attribute):
|
||||||
|
return (
|
||||||
|
node.func.attrname == member
|
||||||
|
and isinstance(node.func.expr, astroid.Name)
|
||||||
|
and node.func.expr.name == "functools"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
_looks_like_partial = partial(_looks_like_functools_member, member="partial")
|
||||||
|
|
||||||
|
|
||||||
|
MANAGER.register_transform(
|
||||||
|
astroid.FunctionDef, _transform_lru_cache, _looks_like_lru_cache
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
MANAGER.register_transform(
|
||||||
|
astroid.Call,
|
||||||
|
astroid.inference_tip(_functools_partial_inference),
|
||||||
|
_looks_like_partial,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,253 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2013-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
|
||||||
|
# Copyright (c) 2014 Google, Inc.
|
||||||
|
# Copyright (c) 2014 Cole Robinson <crobinso@redhat.com>
|
||||||
|
# Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
# Copyright (c) 2015 David Shea <dshea@redhat.com>
|
||||||
|
# Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
|
||||||
|
# Copyright (c) 2016 Giuseppe Scrivano <gscrivan@redhat.com>
|
||||||
|
# Copyright (c) 2018 Christoph Reiter <reiter.christoph@gmail.com>
|
||||||
|
# Copyright (c) 2019 Philipp Hörist <philipp@hoerist.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
"""Astroid hooks for the Python 2 GObject introspection bindings.
|
||||||
|
|
||||||
|
Helps with understanding everything imported from 'gi.repository'
|
||||||
|
"""
|
||||||
|
|
||||||
|
import inspect
|
||||||
|
import itertools
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
from astroid import MANAGER, AstroidBuildingError, nodes
|
||||||
|
from astroid.builder import AstroidBuilder
|
||||||
|
|
||||||
|
|
||||||
|
_inspected_modules = {}
|
||||||
|
|
||||||
|
_identifier_re = r"^[A-Za-z_]\w*$"
|
||||||
|
|
||||||
|
_special_methods = frozenset(
|
||||||
|
{
|
||||||
|
"__lt__",
|
||||||
|
"__le__",
|
||||||
|
"__eq__",
|
||||||
|
"__ne__",
|
||||||
|
"__ge__",
|
||||||
|
"__gt__",
|
||||||
|
"__iter__",
|
||||||
|
"__getitem__",
|
||||||
|
"__setitem__",
|
||||||
|
"__delitem__",
|
||||||
|
"__len__",
|
||||||
|
"__bool__",
|
||||||
|
"__nonzero__",
|
||||||
|
"__next__",
|
||||||
|
"__str__",
|
||||||
|
"__len__",
|
||||||
|
"__contains__",
|
||||||
|
"__enter__",
|
||||||
|
"__exit__",
|
||||||
|
"__repr__",
|
||||||
|
"__getattr__",
|
||||||
|
"__setattr__",
|
||||||
|
"__delattr__",
|
||||||
|
"__del__",
|
||||||
|
"__hash__",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _gi_build_stub(parent):
|
||||||
|
"""
|
||||||
|
Inspect the passed module recursively and build stubs for functions,
|
||||||
|
classes, etc.
|
||||||
|
"""
|
||||||
|
classes = {}
|
||||||
|
functions = {}
|
||||||
|
constants = {}
|
||||||
|
methods = {}
|
||||||
|
for name in dir(parent):
|
||||||
|
if name.startswith("__") and name not in _special_methods:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check if this is a valid name in python
|
||||||
|
if not re.match(_identifier_re, name):
|
||||||
|
continue
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj = getattr(parent, name)
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if inspect.isclass(obj):
|
||||||
|
classes[name] = obj
|
||||||
|
elif inspect.isfunction(obj) or inspect.isbuiltin(obj):
|
||||||
|
functions[name] = obj
|
||||||
|
elif inspect.ismethod(obj) or inspect.ismethoddescriptor(obj):
|
||||||
|
methods[name] = obj
|
||||||
|
elif (
|
||||||
|
str(obj).startswith("<flags")
|
||||||
|
or str(obj).startswith("<enum ")
|
||||||
|
or str(obj).startswith("<GType ")
|
||||||
|
or inspect.isdatadescriptor(obj)
|
||||||
|
):
|
||||||
|
constants[name] = 0
|
||||||
|
elif isinstance(obj, (int, str)):
|
||||||
|
constants[name] = obj
|
||||||
|
elif callable(obj):
|
||||||
|
# Fall back to a function for anything callable
|
||||||
|
functions[name] = obj
|
||||||
|
else:
|
||||||
|
# Assume everything else is some manner of constant
|
||||||
|
constants[name] = 0
|
||||||
|
|
||||||
|
ret = ""
|
||||||
|
|
||||||
|
if constants:
|
||||||
|
ret += "# %s constants\n\n" % parent.__name__
|
||||||
|
for name in sorted(constants):
|
||||||
|
if name[0].isdigit():
|
||||||
|
# GDK has some busted constant names like
|
||||||
|
# Gdk.EventType.2BUTTON_PRESS
|
||||||
|
continue
|
||||||
|
|
||||||
|
val = constants[name]
|
||||||
|
|
||||||
|
strval = str(val)
|
||||||
|
if isinstance(val, str):
|
||||||
|
strval = '"%s"' % str(val).replace("\\", "\\\\")
|
||||||
|
ret += "%s = %s\n" % (name, strval)
|
||||||
|
|
||||||
|
if ret:
|
||||||
|
ret += "\n\n"
|
||||||
|
if functions:
|
||||||
|
ret += "# %s functions\n\n" % parent.__name__
|
||||||
|
for name in sorted(functions):
|
||||||
|
ret += "def %s(*args, **kwargs):\n" % name
|
||||||
|
ret += " pass\n"
|
||||||
|
|
||||||
|
if ret:
|
||||||
|
ret += "\n\n"
|
||||||
|
if methods:
|
||||||
|
ret += "# %s methods\n\n" % parent.__name__
|
||||||
|
for name in sorted(methods):
|
||||||
|
ret += "def %s(self, *args, **kwargs):\n" % name
|
||||||
|
ret += " pass\n"
|
||||||
|
|
||||||
|
if ret:
|
||||||
|
ret += "\n\n"
|
||||||
|
if classes:
|
||||||
|
ret += "# %s classes\n\n" % parent.__name__
|
||||||
|
for name, obj in sorted(classes.items()):
|
||||||
|
base = "object"
|
||||||
|
if issubclass(obj, Exception):
|
||||||
|
base = "Exception"
|
||||||
|
ret += "class %s(%s):\n" % (name, base)
|
||||||
|
|
||||||
|
classret = _gi_build_stub(obj)
|
||||||
|
if not classret:
|
||||||
|
classret = "pass\n"
|
||||||
|
|
||||||
|
for line in classret.splitlines():
|
||||||
|
ret += " " + line + "\n"
|
||||||
|
ret += "\n"
|
||||||
|
|
||||||
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
def _import_gi_module(modname):
|
||||||
|
# we only consider gi.repository submodules
|
||||||
|
if not modname.startswith("gi.repository."):
|
||||||
|
raise AstroidBuildingError(modname=modname)
|
||||||
|
# build astroid representation unless we already tried so
|
||||||
|
if modname not in _inspected_modules:
|
||||||
|
modnames = [modname]
|
||||||
|
optional_modnames = []
|
||||||
|
|
||||||
|
# GLib and GObject may have some special case handling
|
||||||
|
# in pygobject that we need to cope with. However at
|
||||||
|
# least as of pygobject3-3.13.91 the _glib module doesn't
|
||||||
|
# exist anymore, so if treat these modules as optional.
|
||||||
|
if modname == "gi.repository.GLib":
|
||||||
|
optional_modnames.append("gi._glib")
|
||||||
|
elif modname == "gi.repository.GObject":
|
||||||
|
optional_modnames.append("gi._gobject")
|
||||||
|
|
||||||
|
try:
|
||||||
|
modcode = ""
|
||||||
|
for m in itertools.chain(modnames, optional_modnames):
|
||||||
|
try:
|
||||||
|
with warnings.catch_warnings():
|
||||||
|
# Just inspecting the code can raise gi deprecation
|
||||||
|
# warnings, so ignore them.
|
||||||
|
try:
|
||||||
|
from gi import PyGIDeprecationWarning, PyGIWarning
|
||||||
|
|
||||||
|
warnings.simplefilter("ignore", PyGIDeprecationWarning)
|
||||||
|
warnings.simplefilter("ignore", PyGIWarning)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
__import__(m)
|
||||||
|
modcode += _gi_build_stub(sys.modules[m])
|
||||||
|
except ImportError:
|
||||||
|
if m not in optional_modnames:
|
||||||
|
raise
|
||||||
|
except ImportError:
|
||||||
|
astng = _inspected_modules[modname] = None
|
||||||
|
else:
|
||||||
|
astng = AstroidBuilder(MANAGER).string_build(modcode, modname)
|
||||||
|
_inspected_modules[modname] = astng
|
||||||
|
else:
|
||||||
|
astng = _inspected_modules[modname]
|
||||||
|
if astng is None:
|
||||||
|
raise AstroidBuildingError(modname=modname)
|
||||||
|
return astng
|
||||||
|
|
||||||
|
|
||||||
|
def _looks_like_require_version(node):
|
||||||
|
# Return whether this looks like a call to gi.require_version(<name>, <version>)
|
||||||
|
# Only accept function calls with two constant arguments
|
||||||
|
if len(node.args) != 2:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not all(isinstance(arg, nodes.Const) for arg in node.args):
|
||||||
|
return False
|
||||||
|
|
||||||
|
func = node.func
|
||||||
|
if isinstance(func, nodes.Attribute):
|
||||||
|
if func.attrname != "require_version":
|
||||||
|
return False
|
||||||
|
if isinstance(func.expr, nodes.Name) and func.expr.name == "gi":
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
if isinstance(func, nodes.Name):
|
||||||
|
return func.name == "require_version"
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def _register_require_version(node):
|
||||||
|
# Load the gi.require_version locally
|
||||||
|
try:
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version(node.args[0].value, node.args[1].value)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
MANAGER.register_failed_import_hook(_import_gi_module)
|
||||||
|
MANAGER.register_transform(
|
||||||
|
nodes.Call, _register_require_version, _looks_like_require_version
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
# Copyright (c) 2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2018 David Poirier <david-poirier-csn@users.noreply.github.com>
|
||||||
|
# Copyright (c) 2018 wgehalo <wgehalo@gmail.com>
|
||||||
|
# Copyright (c) 2018 Ioana Tagirta <ioana.tagirta@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
|
||||||
|
PY36 = sys.version_info >= (3, 6)
|
||||||
|
|
||||||
|
|
||||||
|
def _hashlib_transform():
|
||||||
|
signature = "value=''"
|
||||||
|
template = """
|
||||||
|
class %(name)s(object):
|
||||||
|
def __init__(self, %(signature)s): pass
|
||||||
|
def digest(self):
|
||||||
|
return %(digest)s
|
||||||
|
def copy(self):
|
||||||
|
return self
|
||||||
|
def update(self, value): pass
|
||||||
|
def hexdigest(self):
|
||||||
|
return ''
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return %(name)r
|
||||||
|
@property
|
||||||
|
def block_size(self):
|
||||||
|
return 1
|
||||||
|
@property
|
||||||
|
def digest_size(self):
|
||||||
|
return 1
|
||||||
|
"""
|
||||||
|
algorithms_with_signature = dict.fromkeys(
|
||||||
|
["md5", "sha1", "sha224", "sha256", "sha384", "sha512"], signature
|
||||||
|
)
|
||||||
|
if PY36:
|
||||||
|
blake2b_signature = "data=b'', *, digest_size=64, key=b'', salt=b'', \
|
||||||
|
person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, \
|
||||||
|
node_depth=0, inner_size=0, last_node=False"
|
||||||
|
blake2s_signature = "data=b'', *, digest_size=32, key=b'', salt=b'', \
|
||||||
|
person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, \
|
||||||
|
node_depth=0, inner_size=0, last_node=False"
|
||||||
|
new_algorithms = dict.fromkeys(
|
||||||
|
["sha3_224", "sha3_256", "sha3_384", "sha3_512", "shake_128", "shake_256"],
|
||||||
|
signature,
|
||||||
|
)
|
||||||
|
algorithms_with_signature.update(new_algorithms)
|
||||||
|
algorithms_with_signature.update(
|
||||||
|
{"blake2b": blake2b_signature, "blake2s": blake2s_signature}
|
||||||
|
)
|
||||||
|
classes = "".join(
|
||||||
|
template
|
||||||
|
% {
|
||||||
|
"name": hashfunc,
|
||||||
|
"digest": 'b""' if six.PY3 else '""',
|
||||||
|
"signature": signature,
|
||||||
|
}
|
||||||
|
for hashfunc, signature in algorithms_with_signature.items()
|
||||||
|
)
|
||||||
|
return astroid.parse(classes)
|
||||||
|
|
||||||
|
|
||||||
|
astroid.register_module_extender(astroid.MANAGER, "hashlib", _hashlib_transform)
|
||||||
|
|
@ -0,0 +1,211 @@
|
||||||
|
# Copyright (c) 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
"""Astroid brain hints for some of the `http` module."""
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
from astroid.builder import AstroidBuilder
|
||||||
|
|
||||||
|
|
||||||
|
def _http_transform():
|
||||||
|
code = textwrap.dedent(
|
||||||
|
"""
|
||||||
|
from collections import namedtuple
|
||||||
|
_HTTPStatus = namedtuple('_HTTPStatus', 'value phrase description')
|
||||||
|
|
||||||
|
class HTTPStatus:
|
||||||
|
|
||||||
|
@property
|
||||||
|
def phrase(self):
|
||||||
|
return ""
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return 0
|
||||||
|
@property
|
||||||
|
def description(self):
|
||||||
|
return ""
|
||||||
|
|
||||||
|
# informational
|
||||||
|
CONTINUE = _HTTPStatus(100, 'Continue', 'Request received, please continue')
|
||||||
|
SWITCHING_PROTOCOLS = _HTTPStatus(101, 'Switching Protocols',
|
||||||
|
'Switching to new protocol; obey Upgrade header')
|
||||||
|
PROCESSING = _HTTPStatus(102, 'Processing', '')
|
||||||
|
OK = _HTTPStatus(200, 'OK', 'Request fulfilled, document follows')
|
||||||
|
CREATED = _HTTPStatus(201, 'Created', 'Document created, URL follows')
|
||||||
|
ACCEPTED = _HTTPStatus(202, 'Accepted',
|
||||||
|
'Request accepted, processing continues off-line')
|
||||||
|
NON_AUTHORITATIVE_INFORMATION = _HTTPStatus(203,
|
||||||
|
'Non-Authoritative Information', 'Request fulfilled from cache')
|
||||||
|
NO_CONTENT = _HTTPStatus(204, 'No Content', 'Request fulfilled, nothing follows')
|
||||||
|
RESET_CONTENT =_HTTPStatus(205, 'Reset Content', 'Clear input form for further input')
|
||||||
|
PARTIAL_CONTENT = _HTTPStatus(206, 'Partial Content', 'Partial content follows')
|
||||||
|
MULTI_STATUS = _HTTPStatus(207, 'Multi-Status', '')
|
||||||
|
ALREADY_REPORTED = _HTTPStatus(208, 'Already Reported', '')
|
||||||
|
IM_USED = _HTTPStatus(226, 'IM Used', '')
|
||||||
|
MULTIPLE_CHOICES = _HTTPStatus(300, 'Multiple Choices',
|
||||||
|
'Object has several resources -- see URI list')
|
||||||
|
MOVED_PERMANENTLY = _HTTPStatus(301, 'Moved Permanently',
|
||||||
|
'Object moved permanently -- see URI list')
|
||||||
|
FOUND = _HTTPStatus(302, 'Found', 'Object moved temporarily -- see URI list')
|
||||||
|
SEE_OTHER = _HTTPStatus(303, 'See Other', 'Object moved -- see Method and URL list')
|
||||||
|
NOT_MODIFIED = _HTTPStatus(304, 'Not Modified',
|
||||||
|
'Document has not changed since given time')
|
||||||
|
USE_PROXY = _HTTPStatus(305, 'Use Proxy',
|
||||||
|
'You must use proxy specified in Location to access this resource')
|
||||||
|
TEMPORARY_REDIRECT = _HTTPStatus(307, 'Temporary Redirect',
|
||||||
|
'Object moved temporarily -- see URI list')
|
||||||
|
PERMANENT_REDIRECT = _HTTPStatus(308, 'Permanent Redirect',
|
||||||
|
'Object moved permanently -- see URI list')
|
||||||
|
BAD_REQUEST = _HTTPStatus(400, 'Bad Request',
|
||||||
|
'Bad request syntax or unsupported method')
|
||||||
|
UNAUTHORIZED = _HTTPStatus(401, 'Unauthorized',
|
||||||
|
'No permission -- see authorization schemes')
|
||||||
|
PAYMENT_REQUIRED = _HTTPStatus(402, 'Payment Required',
|
||||||
|
'No payment -- see charging schemes')
|
||||||
|
FORBIDDEN = _HTTPStatus(403, 'Forbidden',
|
||||||
|
'Request forbidden -- authorization will not help')
|
||||||
|
NOT_FOUND = _HTTPStatus(404, 'Not Found',
|
||||||
|
'Nothing matches the given URI')
|
||||||
|
METHOD_NOT_ALLOWED = _HTTPStatus(405, 'Method Not Allowed',
|
||||||
|
'Specified method is invalid for this resource')
|
||||||
|
NOT_ACCEPTABLE = _HTTPStatus(406, 'Not Acceptable',
|
||||||
|
'URI not available in preferred format')
|
||||||
|
PROXY_AUTHENTICATION_REQUIRED = _HTTPStatus(407,
|
||||||
|
'Proxy Authentication Required',
|
||||||
|
'You must authenticate with this proxy before proceeding')
|
||||||
|
REQUEST_TIMEOUT = _HTTPStatus(408, 'Request Timeout',
|
||||||
|
'Request timed out; try again later')
|
||||||
|
CONFLICT = _HTTPStatus(409, 'Conflict', 'Request conflict')
|
||||||
|
GONE = _HTTPStatus(410, 'Gone',
|
||||||
|
'URI no longer exists and has been permanently removed')
|
||||||
|
LENGTH_REQUIRED = _HTTPStatus(411, 'Length Required',
|
||||||
|
'Client must specify Content-Length')
|
||||||
|
PRECONDITION_FAILED = _HTTPStatus(412, 'Precondition Failed',
|
||||||
|
'Precondition in headers is false')
|
||||||
|
REQUEST_ENTITY_TOO_LARGE = _HTTPStatus(413, 'Request Entity Too Large',
|
||||||
|
'Entity is too large')
|
||||||
|
REQUEST_URI_TOO_LONG = _HTTPStatus(414, 'Request-URI Too Long',
|
||||||
|
'URI is too long')
|
||||||
|
UNSUPPORTED_MEDIA_TYPE = _HTTPStatus(415, 'Unsupported Media Type',
|
||||||
|
'Entity body in unsupported format')
|
||||||
|
REQUESTED_RANGE_NOT_SATISFIABLE = _HTTPStatus(416,
|
||||||
|
'Requested Range Not Satisfiable',
|
||||||
|
'Cannot satisfy request range')
|
||||||
|
EXPECTATION_FAILED = _HTTPStatus(417, 'Expectation Failed',
|
||||||
|
'Expect condition could not be satisfied')
|
||||||
|
MISDIRECTED_REQUEST = _HTTPStatus(421, 'Misdirected Request',
|
||||||
|
'Server is not able to produce a response')
|
||||||
|
UNPROCESSABLE_ENTITY = _HTTPStatus(422, 'Unprocessable Entity')
|
||||||
|
LOCKED = _HTTPStatus(423, 'Locked')
|
||||||
|
FAILED_DEPENDENCY = _HTTPStatus(424, 'Failed Dependency')
|
||||||
|
UPGRADE_REQUIRED = _HTTPStatus(426, 'Upgrade Required')
|
||||||
|
PRECONDITION_REQUIRED = _HTTPStatus(428, 'Precondition Required',
|
||||||
|
'The origin server requires the request to be conditional')
|
||||||
|
TOO_MANY_REQUESTS = _HTTPStatus(429, 'Too Many Requests',
|
||||||
|
'The user has sent too many requests in '
|
||||||
|
'a given amount of time ("rate limiting")')
|
||||||
|
REQUEST_HEADER_FIELDS_TOO_LARGE = _HTTPStatus(431,
|
||||||
|
'Request Header Fields Too Large',
|
||||||
|
'The server is unwilling to process the request because its header '
|
||||||
|
'fields are too large')
|
||||||
|
UNAVAILABLE_FOR_LEGAL_REASONS = _HTTPStatus(451,
|
||||||
|
'Unavailable For Legal Reasons',
|
||||||
|
'The server is denying access to the '
|
||||||
|
'resource as a consequence of a legal demand')
|
||||||
|
INTERNAL_SERVER_ERROR = _HTTPStatus(500, 'Internal Server Error',
|
||||||
|
'Server got itself in trouble')
|
||||||
|
NOT_IMPLEMENTED = _HTTPStatus(501, 'Not Implemented',
|
||||||
|
'Server does not support this operation')
|
||||||
|
BAD_GATEWAY = _HTTPStatus(502, 'Bad Gateway',
|
||||||
|
'Invalid responses from another server/proxy')
|
||||||
|
SERVICE_UNAVAILABLE = _HTTPStatus(503, 'Service Unavailable',
|
||||||
|
'The server cannot process the request due to a high load')
|
||||||
|
GATEWAY_TIMEOUT = _HTTPStatus(504, 'Gateway Timeout',
|
||||||
|
'The gateway server did not receive a timely response')
|
||||||
|
HTTP_VERSION_NOT_SUPPORTED = _HTTPStatus(505, 'HTTP Version Not Supported',
|
||||||
|
'Cannot fulfill request')
|
||||||
|
VARIANT_ALSO_NEGOTIATES = _HTTPStatus(506, 'Variant Also Negotiates')
|
||||||
|
INSUFFICIENT_STORAGE = _HTTPStatus(507, 'Insufficient Storage')
|
||||||
|
LOOP_DETECTED = _HTTPStatus(508, 'Loop Detected')
|
||||||
|
NOT_EXTENDED = _HTTPStatus(510, 'Not Extended')
|
||||||
|
NETWORK_AUTHENTICATION_REQUIRED = _HTTPStatus(511,
|
||||||
|
'Network Authentication Required',
|
||||||
|
'The client needs to authenticate to gain network access')
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
return AstroidBuilder(astroid.MANAGER).string_build(code)
|
||||||
|
|
||||||
|
|
||||||
|
def _http_client_transform():
|
||||||
|
return AstroidBuilder(astroid.MANAGER).string_build(
|
||||||
|
textwrap.dedent(
|
||||||
|
"""
|
||||||
|
from http import HTTPStatus
|
||||||
|
|
||||||
|
CONTINUE = HTTPStatus.CONTINUE
|
||||||
|
SWITCHING_PROTOCOLS = HTTPStatus.SWITCHING_PROTOCOLS
|
||||||
|
PROCESSING = HTTPStatus.PROCESSING
|
||||||
|
OK = HTTPStatus.OK
|
||||||
|
CREATED = HTTPStatus.CREATED
|
||||||
|
ACCEPTED = HTTPStatus.ACCEPTED
|
||||||
|
NON_AUTHORITATIVE_INFORMATION = HTTPStatus.NON_AUTHORITATIVE_INFORMATION
|
||||||
|
NO_CONTENT = HTTPStatus.NO_CONTENT
|
||||||
|
RESET_CONTENT = HTTPStatus.RESET_CONTENT
|
||||||
|
PARTIAL_CONTENT = HTTPStatus.PARTIAL_CONTENT
|
||||||
|
MULTI_STATUS = HTTPStatus.MULTI_STATUS
|
||||||
|
ALREADY_REPORTED = HTTPStatus.ALREADY_REPORTED
|
||||||
|
IM_USED = HTTPStatus.IM_USED
|
||||||
|
MULTIPLE_CHOICES = HTTPStatus.MULTIPLE_CHOICES
|
||||||
|
MOVED_PERMANENTLY = HTTPStatus.MOVED_PERMANENTLY
|
||||||
|
FOUND = HTTPStatus.FOUND
|
||||||
|
SEE_OTHER = HTTPStatus.SEE_OTHER
|
||||||
|
NOT_MODIFIED = HTTPStatus.NOT_MODIFIED
|
||||||
|
USE_PROXY = HTTPStatus.USE_PROXY
|
||||||
|
TEMPORARY_REDIRECT = HTTPStatus.TEMPORARY_REDIRECT
|
||||||
|
PERMANENT_REDIRECT = HTTPStatus.PERMANENT_REDIRECT
|
||||||
|
BAD_REQUEST = HTTPStatus.BAD_REQUEST
|
||||||
|
UNAUTHORIZED = HTTPStatus.UNAUTHORIZED
|
||||||
|
PAYMENT_REQUIRED = HTTPStatus.PAYMENT_REQUIRED
|
||||||
|
FORBIDDEN = HTTPStatus.FORBIDDEN
|
||||||
|
NOT_FOUND = HTTPStatus.NOT_FOUND
|
||||||
|
METHOD_NOT_ALLOWED = HTTPStatus.METHOD_NOT_ALLOWED
|
||||||
|
NOT_ACCEPTABLE = HTTPStatus.NOT_ACCEPTABLE
|
||||||
|
PROXY_AUTHENTICATION_REQUIRED = HTTPStatus.PROXY_AUTHENTICATION_REQUIRED
|
||||||
|
REQUEST_TIMEOUT = HTTPStatus.REQUEST_TIMEOUT
|
||||||
|
CONFLICT = HTTPStatus.CONFLICT
|
||||||
|
GONE = HTTPStatus.GONE
|
||||||
|
LENGTH_REQUIRED = HTTPStatus.LENGTH_REQUIRED
|
||||||
|
PRECONDITION_FAILED = HTTPStatus.PRECONDITION_FAILED
|
||||||
|
REQUEST_ENTITY_TOO_LARGE = HTTPStatus.REQUEST_ENTITY_TOO_LARGE
|
||||||
|
REQUEST_URI_TOO_LONG = HTTPStatus.REQUEST_URI_TOO_LONG
|
||||||
|
UNSUPPORTED_MEDIA_TYPE = HTTPStatus.UNSUPPORTED_MEDIA_TYPE
|
||||||
|
REQUESTED_RANGE_NOT_SATISFIABLE = HTTPStatus.REQUESTED_RANGE_NOT_SATISFIABLE
|
||||||
|
EXPECTATION_FAILED = HTTPStatus.EXPECTATION_FAILED
|
||||||
|
UNPROCESSABLE_ENTITY = HTTPStatus.UNPROCESSABLE_ENTITY
|
||||||
|
LOCKED = HTTPStatus.LOCKED
|
||||||
|
FAILED_DEPENDENCY = HTTPStatus.FAILED_DEPENDENCY
|
||||||
|
UPGRADE_REQUIRED = HTTPStatus.UPGRADE_REQUIRED
|
||||||
|
PRECONDITION_REQUIRED = HTTPStatus.PRECONDITION_REQUIRED
|
||||||
|
TOO_MANY_REQUESTS = HTTPStatus.TOO_MANY_REQUESTS
|
||||||
|
REQUEST_HEADER_FIELDS_TOO_LARGE = HTTPStatus.REQUEST_HEADER_FIELDS_TOO_LARGE
|
||||||
|
INTERNAL_SERVER_ERROR = HTTPStatus.INTERNAL_SERVER_ERROR
|
||||||
|
NOT_IMPLEMENTED = HTTPStatus.NOT_IMPLEMENTED
|
||||||
|
BAD_GATEWAY = HTTPStatus.BAD_GATEWAY
|
||||||
|
SERVICE_UNAVAILABLE = HTTPStatus.SERVICE_UNAVAILABLE
|
||||||
|
GATEWAY_TIMEOUT = HTTPStatus.GATEWAY_TIMEOUT
|
||||||
|
HTTP_VERSION_NOT_SUPPORTED = HTTPStatus.HTTP_VERSION_NOT_SUPPORTED
|
||||||
|
VARIANT_ALSO_NEGOTIATES = HTTPStatus.VARIANT_ALSO_NEGOTIATES
|
||||||
|
INSUFFICIENT_STORAGE = HTTPStatus.INSUFFICIENT_STORAGE
|
||||||
|
LOOP_DETECTED = HTTPStatus.LOOP_DETECTED
|
||||||
|
NOT_EXTENDED = HTTPStatus.NOT_EXTENDED
|
||||||
|
NETWORK_AUTHENTICATION_REQUIRED = HTTPStatus.NETWORK_AUTHENTICATION_REQUIRED
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
astroid.register_module_extender(astroid.MANAGER, "http", _http_transform)
|
||||||
|
astroid.register_module_extender(astroid.MANAGER, "http.client", _http_client_transform)
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
# Copyright (c) 2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
"""Astroid brain hints for some of the _io C objects."""
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
|
||||||
|
|
||||||
|
BUFFERED = {"BufferedWriter", "BufferedReader"}
|
||||||
|
TextIOWrapper = "TextIOWrapper"
|
||||||
|
FileIO = "FileIO"
|
||||||
|
BufferedWriter = "BufferedWriter"
|
||||||
|
|
||||||
|
|
||||||
|
def _generic_io_transform(node, name, cls):
|
||||||
|
"""Transform the given name, by adding the given *class* as a member of the node."""
|
||||||
|
|
||||||
|
io_module = astroid.MANAGER.ast_from_module_name("_io")
|
||||||
|
attribute_object = io_module[cls]
|
||||||
|
instance = attribute_object.instantiate_class()
|
||||||
|
node.locals[name] = [instance]
|
||||||
|
|
||||||
|
|
||||||
|
def _transform_text_io_wrapper(node):
|
||||||
|
# This is not always correct, since it can vary with the type of the descriptor,
|
||||||
|
# being stdout, stderr or stdin. But we cannot get access to the name of the
|
||||||
|
# stream, which is why we are using the BufferedWriter class as a default
|
||||||
|
# value
|
||||||
|
return _generic_io_transform(node, name="buffer", cls=BufferedWriter)
|
||||||
|
|
||||||
|
|
||||||
|
def _transform_buffered(node):
|
||||||
|
return _generic_io_transform(node, name="raw", cls=FileIO)
|
||||||
|
|
||||||
|
|
||||||
|
astroid.MANAGER.register_transform(
|
||||||
|
astroid.ClassDef, _transform_buffered, lambda node: node.name in BUFFERED
|
||||||
|
)
|
||||||
|
astroid.MANAGER.register_transform(
|
||||||
|
astroid.ClassDef,
|
||||||
|
_transform_text_io_wrapper,
|
||||||
|
lambda node: node.name == TextIOWrapper,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Copyright (c) 2012-2013 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
|
||||||
|
# Copyright (c) 2014 Google, Inc.
|
||||||
|
# Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
from astroid import MANAGER, register_module_extender
|
||||||
|
from astroid.builder import AstroidBuilder
|
||||||
|
|
||||||
|
|
||||||
|
def mechanize_transform():
|
||||||
|
return AstroidBuilder(MANAGER).string_build(
|
||||||
|
"""
|
||||||
|
|
||||||
|
class Browser(object):
|
||||||
|
def open(self, url, data=None, timeout=None):
|
||||||
|
return None
|
||||||
|
def open_novisit(self, url, data=None, timeout=None):
|
||||||
|
return None
|
||||||
|
def open_local_file(self, filename):
|
||||||
|
return None
|
||||||
|
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
register_module_extender(MANAGER, "mechanize", mechanize_transform)
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
# Copyright (c) 2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2019 Hugo van Kemenade <hugovk@users.noreply.github.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
from astroid import exceptions
|
||||||
|
|
||||||
|
|
||||||
|
def _multiprocessing_transform():
|
||||||
|
module = astroid.parse(
|
||||||
|
"""
|
||||||
|
from multiprocessing.managers import SyncManager
|
||||||
|
def Manager():
|
||||||
|
return SyncManager()
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
# Multiprocessing uses a getattr lookup inside contexts,
|
||||||
|
# in order to get the attributes they need. Since it's extremely
|
||||||
|
# dynamic, we use this approach to fake it.
|
||||||
|
node = astroid.parse(
|
||||||
|
"""
|
||||||
|
from multiprocessing.context import DefaultContext, BaseContext
|
||||||
|
default = DefaultContext()
|
||||||
|
base = BaseContext()
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
context = next(node["default"].infer())
|
||||||
|
base = next(node["base"].infer())
|
||||||
|
except exceptions.InferenceError:
|
||||||
|
return module
|
||||||
|
|
||||||
|
for node in (context, base):
|
||||||
|
for key, value in node.locals.items():
|
||||||
|
if key.startswith("_"):
|
||||||
|
continue
|
||||||
|
|
||||||
|
value = value[0]
|
||||||
|
if isinstance(value, astroid.FunctionDef):
|
||||||
|
# We need to rebound this, since otherwise
|
||||||
|
# it will have an extra argument (self).
|
||||||
|
value = astroid.BoundMethod(value, node)
|
||||||
|
module[key] = value
|
||||||
|
return module
|
||||||
|
|
||||||
|
|
||||||
|
def _multiprocessing_managers_transform():
|
||||||
|
return astroid.parse(
|
||||||
|
"""
|
||||||
|
import array
|
||||||
|
import threading
|
||||||
|
import multiprocessing.pool as pool
|
||||||
|
|
||||||
|
import six
|
||||||
|
|
||||||
|
class Namespace(object):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class Value(object):
|
||||||
|
def __init__(self, typecode, value, lock=True):
|
||||||
|
self._typecode = typecode
|
||||||
|
self._value = value
|
||||||
|
def get(self):
|
||||||
|
return self._value
|
||||||
|
def set(self, value):
|
||||||
|
self._value = value
|
||||||
|
def __repr__(self):
|
||||||
|
return '%s(%r, %r)'%(type(self).__name__, self._typecode, self._value)
|
||||||
|
value = property(get, set)
|
||||||
|
|
||||||
|
def Array(typecode, sequence, lock=True):
|
||||||
|
return array.array(typecode, sequence)
|
||||||
|
|
||||||
|
class SyncManager(object):
|
||||||
|
Queue = JoinableQueue = six.moves.queue.Queue
|
||||||
|
Event = threading.Event
|
||||||
|
RLock = threading.RLock
|
||||||
|
BoundedSemaphore = threading.BoundedSemaphore
|
||||||
|
Condition = threading.Condition
|
||||||
|
Barrier = threading.Barrier
|
||||||
|
Pool = pool.Pool
|
||||||
|
list = list
|
||||||
|
dict = dict
|
||||||
|
Value = Value
|
||||||
|
Array = Array
|
||||||
|
Namespace = Namespace
|
||||||
|
__enter__ = lambda self: self
|
||||||
|
__exit__ = lambda *args: args
|
||||||
|
|
||||||
|
def start(self, initializer=None, initargs=None):
|
||||||
|
pass
|
||||||
|
def shutdown(self):
|
||||||
|
pass
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
astroid.register_module_extender(
|
||||||
|
astroid.MANAGER, "multiprocessing.managers", _multiprocessing_managers_transform
|
||||||
|
)
|
||||||
|
astroid.register_module_extender(
|
||||||
|
astroid.MANAGER, "multiprocessing", _multiprocessing_transform
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,455 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright (c) 2012-2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
|
||||||
|
# Copyright (c) 2013-2014 Google, Inc.
|
||||||
|
# Copyright (c) 2014-2020 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2014 Eevee (Alex Munroe) <amunroe@yelp.com>
|
||||||
|
# Copyright (c) 2015-2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
# Copyright (c) 2015 Dmitry Pribysh <dmand@yandex.ru>
|
||||||
|
# Copyright (c) 2015 David Shea <dshea@redhat.com>
|
||||||
|
# Copyright (c) 2015 Philip Lorenz <philip@bithub.de>
|
||||||
|
# Copyright (c) 2016 Jakub Wilk <jwilk@jwilk.net>
|
||||||
|
# Copyright (c) 2016 Mateusz Bysiek <mb@mbdev.pl>
|
||||||
|
# Copyright (c) 2017 Hugo <hugovk@users.noreply.github.com>
|
||||||
|
# Copyright (c) 2017 Łukasz Rogalski <rogalski.91@gmail.com>
|
||||||
|
# Copyright (c) 2018 Ville Skyttä <ville.skytta@iki.fi>
|
||||||
|
# Copyright (c) 2019 Ashley Whetter <ashley@awhetter.co.uk>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
"""Astroid hooks for the Python standard library."""
|
||||||
|
|
||||||
|
import functools
|
||||||
|
import keyword
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
|
from astroid import MANAGER, UseInferenceDefault, inference_tip, InferenceError
|
||||||
|
from astroid import arguments
|
||||||
|
from astroid import exceptions
|
||||||
|
from astroid import nodes
|
||||||
|
from astroid.builder import AstroidBuilder, extract_node
|
||||||
|
from astroid import util
|
||||||
|
|
||||||
|
|
||||||
|
TYPING_NAMEDTUPLE_BASENAMES = {"NamedTuple", "typing.NamedTuple"}
|
||||||
|
ENUM_BASE_NAMES = {
|
||||||
|
"Enum",
|
||||||
|
"IntEnum",
|
||||||
|
"enum.Enum",
|
||||||
|
"enum.IntEnum",
|
||||||
|
"IntFlag",
|
||||||
|
"enum.IntFlag",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _infer_first(node, context):
|
||||||
|
if node is util.Uninferable:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
try:
|
||||||
|
value = next(node.infer(context=context))
|
||||||
|
if value is util.Uninferable:
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
except StopIteration:
|
||||||
|
raise InferenceError()
|
||||||
|
|
||||||
|
|
||||||
|
def _find_func_form_arguments(node, context):
|
||||||
|
def _extract_namedtuple_arg_or_keyword(position, key_name=None):
|
||||||
|
|
||||||
|
if len(args) > position:
|
||||||
|
return _infer_first(args[position], context)
|
||||||
|
if key_name and key_name in found_keywords:
|
||||||
|
return _infer_first(found_keywords[key_name], context)
|
||||||
|
|
||||||
|
args = node.args
|
||||||
|
keywords = node.keywords
|
||||||
|
found_keywords = (
|
||||||
|
{keyword.arg: keyword.value for keyword in keywords} if keywords else {}
|
||||||
|
)
|
||||||
|
|
||||||
|
name = _extract_namedtuple_arg_or_keyword(position=0, key_name="typename")
|
||||||
|
names = _extract_namedtuple_arg_or_keyword(position=1, key_name="field_names")
|
||||||
|
if name and names:
|
||||||
|
return name.value, names
|
||||||
|
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
|
||||||
|
|
||||||
|
def infer_func_form(node, base_type, context=None, enum=False):
|
||||||
|
"""Specific inference function for namedtuple or Python 3 enum. """
|
||||||
|
# node is a Call node, class name as first argument and generated class
|
||||||
|
# attributes as second argument
|
||||||
|
|
||||||
|
# namedtuple or enums list of attributes can be a list of strings or a
|
||||||
|
# whitespace-separate string
|
||||||
|
try:
|
||||||
|
name, names = _find_func_form_arguments(node, context)
|
||||||
|
try:
|
||||||
|
attributes = names.value.replace(",", " ").split()
|
||||||
|
except AttributeError:
|
||||||
|
if not enum:
|
||||||
|
attributes = [
|
||||||
|
_infer_first(const, context).value for const in names.elts
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
# Enums supports either iterator of (name, value) pairs
|
||||||
|
# or mappings.
|
||||||
|
if hasattr(names, "items") and isinstance(names.items, list):
|
||||||
|
attributes = [
|
||||||
|
_infer_first(const[0], context).value
|
||||||
|
for const in names.items
|
||||||
|
if isinstance(const[0], nodes.Const)
|
||||||
|
]
|
||||||
|
elif hasattr(names, "elts"):
|
||||||
|
# Enums can support either ["a", "b", "c"]
|
||||||
|
# or [("a", 1), ("b", 2), ...], but they can't
|
||||||
|
# be mixed.
|
||||||
|
if all(isinstance(const, nodes.Tuple) for const in names.elts):
|
||||||
|
attributes = [
|
||||||
|
_infer_first(const.elts[0], context).value
|
||||||
|
for const in names.elts
|
||||||
|
if isinstance(const, nodes.Tuple)
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
attributes = [
|
||||||
|
_infer_first(const, context).value for const in names.elts
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
raise AttributeError
|
||||||
|
if not attributes:
|
||||||
|
raise AttributeError
|
||||||
|
except (AttributeError, exceptions.InferenceError):
|
||||||
|
raise UseInferenceDefault()
|
||||||
|
|
||||||
|
attributes = [attr for attr in attributes if " " not in attr]
|
||||||
|
|
||||||
|
# If we can't infer the name of the class, don't crash, up to this point
|
||||||
|
# we know it is a namedtuple anyway.
|
||||||
|
name = name or "Uninferable"
|
||||||
|
# we want to return a Class node instance with proper attributes set
|
||||||
|
class_node = nodes.ClassDef(name, "docstring")
|
||||||
|
class_node.parent = node.parent
|
||||||
|
# set base class=tuple
|
||||||
|
class_node.bases.append(base_type)
|
||||||
|
# XXX add __init__(*attributes) method
|
||||||
|
for attr in attributes:
|
||||||
|
fake_node = nodes.EmptyNode()
|
||||||
|
fake_node.parent = class_node
|
||||||
|
fake_node.attrname = attr
|
||||||
|
class_node.instance_attrs[attr] = [fake_node]
|
||||||
|
return class_node, name, attributes
|
||||||
|
|
||||||
|
|
||||||
|
def _has_namedtuple_base(node):
|
||||||
|
"""Predicate for class inference tip
|
||||||
|
|
||||||
|
:type node: ClassDef
|
||||||
|
:rtype: bool
|
||||||
|
"""
|
||||||
|
return set(node.basenames) & TYPING_NAMEDTUPLE_BASENAMES
|
||||||
|
|
||||||
|
|
||||||
|
def _looks_like(node, name):
|
||||||
|
func = node.func
|
||||||
|
if isinstance(func, nodes.Attribute):
|
||||||
|
return func.attrname == name
|
||||||
|
if isinstance(func, nodes.Name):
|
||||||
|
return func.name == name
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
_looks_like_namedtuple = functools.partial(_looks_like, name="namedtuple")
|
||||||
|
_looks_like_enum = functools.partial(_looks_like, name="Enum")
|
||||||
|
_looks_like_typing_namedtuple = functools.partial(_looks_like, name="NamedTuple")
|
||||||
|
|
||||||
|
|
||||||
|
def infer_named_tuple(node, context=None):
|
||||||
|
"""Specific inference function for namedtuple Call node"""
|
||||||
|
tuple_base_name = nodes.Name(name="tuple", parent=node.root())
|
||||||
|
class_node, name, attributes = infer_func_form(
|
||||||
|
node, tuple_base_name, context=context
|
||||||
|
)
|
||||||
|
call_site = arguments.CallSite.from_call(node, context=context)
|
||||||
|
func = next(extract_node("import collections; collections.namedtuple").infer())
|
||||||
|
try:
|
||||||
|
rename = next(call_site.infer_argument(func, "rename", context)).bool_value()
|
||||||
|
except InferenceError:
|
||||||
|
rename = False
|
||||||
|
|
||||||
|
if rename:
|
||||||
|
attributes = _get_renamed_namedtuple_attributes(attributes)
|
||||||
|
|
||||||
|
replace_args = ", ".join("{arg}=None".format(arg=arg) for arg in attributes)
|
||||||
|
field_def = (
|
||||||
|
" {name} = property(lambda self: self[{index:d}], "
|
||||||
|
"doc='Alias for field number {index:d}')"
|
||||||
|
)
|
||||||
|
field_defs = "\n".join(
|
||||||
|
field_def.format(name=name, index=index)
|
||||||
|
for index, name in enumerate(attributes)
|
||||||
|
)
|
||||||
|
fake = AstroidBuilder(MANAGER).string_build(
|
||||||
|
"""
|
||||||
|
class %(name)s(tuple):
|
||||||
|
__slots__ = ()
|
||||||
|
_fields = %(fields)r
|
||||||
|
def _asdict(self):
|
||||||
|
return self.__dict__
|
||||||
|
@classmethod
|
||||||
|
def _make(cls, iterable, new=tuple.__new__, len=len):
|
||||||
|
return new(cls, iterable)
|
||||||
|
def _replace(self, %(replace_args)s):
|
||||||
|
return self
|
||||||
|
def __getnewargs__(self):
|
||||||
|
return tuple(self)
|
||||||
|
%(field_defs)s
|
||||||
|
"""
|
||||||
|
% {
|
||||||
|
"name": name,
|
||||||
|
"fields": attributes,
|
||||||
|
"field_defs": field_defs,
|
||||||
|
"replace_args": replace_args,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
class_node.locals["_asdict"] = fake.body[0].locals["_asdict"]
|
||||||
|
class_node.locals["_make"] = fake.body[0].locals["_make"]
|
||||||
|
class_node.locals["_replace"] = fake.body[0].locals["_replace"]
|
||||||
|
class_node.locals["_fields"] = fake.body[0].locals["_fields"]
|
||||||
|
for attr in attributes:
|
||||||
|
class_node.locals[attr] = fake.body[0].locals[attr]
|
||||||
|
# we use UseInferenceDefault, we can't be a generator so return an iterator
|
||||||
|
return iter([class_node])
|
||||||
|
|
||||||
|
|
||||||
|
def _get_renamed_namedtuple_attributes(field_names):
|
||||||
|
names = list(field_names)
|
||||||
|
seen = set()
|
||||||
|
for i, name in enumerate(field_names):
|
||||||
|
if (
|
||||||
|
not all(c.isalnum() or c == "_" for c in name)
|
||||||
|
or keyword.iskeyword(name)
|
||||||
|
or not name
|
||||||
|
or name[0].isdigit()
|
||||||
|
or name.startswith("_")
|
||||||
|
or name in seen
|
||||||
|
):
|
||||||
|
names[i] = "_%d" % i
|
||||||
|
seen.add(name)
|
||||||
|
return tuple(names)
|
||||||
|
|
||||||
|
|
||||||
|
def infer_enum(node, context=None):
|
||||||
|
""" Specific inference function for enum Call node. """
|
||||||
|
enum_meta = extract_node(
|
||||||
|
"""
|
||||||
|
class EnumMeta(object):
|
||||||
|
'docstring'
|
||||||
|
def __call__(self, node):
|
||||||
|
class EnumAttribute(object):
|
||||||
|
name = ''
|
||||||
|
value = 0
|
||||||
|
return EnumAttribute()
|
||||||
|
def __iter__(self):
|
||||||
|
class EnumAttribute(object):
|
||||||
|
name = ''
|
||||||
|
value = 0
|
||||||
|
return [EnumAttribute()]
|
||||||
|
def __reversed__(self):
|
||||||
|
class EnumAttribute(object):
|
||||||
|
name = ''
|
||||||
|
value = 0
|
||||||
|
return (EnumAttribute, )
|
||||||
|
def __next__(self):
|
||||||
|
return next(iter(self))
|
||||||
|
def __getitem__(self, attr):
|
||||||
|
class Value(object):
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return ''
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return attr
|
||||||
|
|
||||||
|
return Value()
|
||||||
|
__members__ = ['']
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
class_node = infer_func_form(node, enum_meta, context=context, enum=True)[0]
|
||||||
|
return iter([class_node.instantiate_class()])
|
||||||
|
|
||||||
|
|
||||||
|
INT_FLAG_ADDITION_METHODS = """
|
||||||
|
def __or__(self, other):
|
||||||
|
return {name}(self.value | other.value)
|
||||||
|
def __and__(self, other):
|
||||||
|
return {name}(self.value & other.value)
|
||||||
|
def __xor__(self, other):
|
||||||
|
return {name}(self.value ^ other.value)
|
||||||
|
def __add__(self, other):
|
||||||
|
return {name}(self.value + other.value)
|
||||||
|
def __div__(self, other):
|
||||||
|
return {name}(self.value / other.value)
|
||||||
|
def __invert__(self):
|
||||||
|
return {name}(~self.value)
|
||||||
|
def __mul__(self, other):
|
||||||
|
return {name}(self.value * other.value)
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def infer_enum_class(node):
|
||||||
|
""" Specific inference for enums. """
|
||||||
|
for basename in node.basenames:
|
||||||
|
# TODO: doesn't handle subclasses yet. This implementation
|
||||||
|
# is a hack to support enums.
|
||||||
|
if basename not in ENUM_BASE_NAMES:
|
||||||
|
continue
|
||||||
|
if node.root().name == "enum":
|
||||||
|
# Skip if the class is directly from enum module.
|
||||||
|
break
|
||||||
|
for local, values in node.locals.items():
|
||||||
|
if any(not isinstance(value, nodes.AssignName) for value in values):
|
||||||
|
continue
|
||||||
|
|
||||||
|
targets = []
|
||||||
|
stmt = values[0].statement()
|
||||||
|
if isinstance(stmt, nodes.Assign):
|
||||||
|
if isinstance(stmt.targets[0], nodes.Tuple):
|
||||||
|
targets = stmt.targets[0].itered()
|
||||||
|
else:
|
||||||
|
targets = stmt.targets
|
||||||
|
elif isinstance(stmt, nodes.AnnAssign):
|
||||||
|
targets = [stmt.target]
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
|
||||||
|
inferred_return_value = None
|
||||||
|
if isinstance(stmt, nodes.Assign):
|
||||||
|
if isinstance(stmt.value, nodes.Const):
|
||||||
|
if isinstance(stmt.value.value, str):
|
||||||
|
inferred_return_value = repr(stmt.value.value)
|
||||||
|
else:
|
||||||
|
inferred_return_value = stmt.value.value
|
||||||
|
else:
|
||||||
|
inferred_return_value = stmt.value.as_string()
|
||||||
|
|
||||||
|
new_targets = []
|
||||||
|
for target in targets:
|
||||||
|
# Replace all the assignments with our mocked class.
|
||||||
|
classdef = dedent(
|
||||||
|
"""
|
||||||
|
class {name}({types}):
|
||||||
|
@property
|
||||||
|
def value(self):
|
||||||
|
return {return_value}
|
||||||
|
@property
|
||||||
|
def name(self):
|
||||||
|
return "{name}"
|
||||||
|
""".format(
|
||||||
|
name=target.name,
|
||||||
|
types=", ".join(node.basenames),
|
||||||
|
return_value=inferred_return_value,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if "IntFlag" in basename:
|
||||||
|
# Alright, we need to add some additional methods.
|
||||||
|
# Unfortunately we still can't infer the resulting objects as
|
||||||
|
# Enum members, but once we'll be able to do that, the following
|
||||||
|
# should result in some nice symbolic execution
|
||||||
|
classdef += INT_FLAG_ADDITION_METHODS.format(name=target.name)
|
||||||
|
|
||||||
|
fake = AstroidBuilder(MANAGER).string_build(classdef)[target.name]
|
||||||
|
fake.parent = target.parent
|
||||||
|
for method in node.mymethods():
|
||||||
|
fake.locals[method.name] = [method]
|
||||||
|
new_targets.append(fake.instantiate_class())
|
||||||
|
node.locals[local] = new_targets
|
||||||
|
break
|
||||||
|
return node
|
||||||
|
|
||||||
|
|
||||||
|
def infer_typing_namedtuple_class(class_node, context=None):
|
||||||
|
"""Infer a subclass of typing.NamedTuple"""
|
||||||
|
# Check if it has the corresponding bases
|
||||||
|
annassigns_fields = [
|
||||||
|
annassign.target.name
|
||||||
|
for annassign in class_node.body
|
||||||
|
if isinstance(annassign, nodes.AnnAssign)
|
||||||
|
]
|
||||||
|
code = dedent(
|
||||||
|
"""
|
||||||
|
from collections import namedtuple
|
||||||
|
namedtuple({typename!r}, {fields!r})
|
||||||
|
"""
|
||||||
|
).format(typename=class_node.name, fields=",".join(annassigns_fields))
|
||||||
|
node = extract_node(code)
|
||||||
|
generated_class_node = next(infer_named_tuple(node, context))
|
||||||
|
for method in class_node.mymethods():
|
||||||
|
generated_class_node.locals[method.name] = [method]
|
||||||
|
|
||||||
|
for assign in class_node.body:
|
||||||
|
if not isinstance(assign, nodes.Assign):
|
||||||
|
continue
|
||||||
|
|
||||||
|
for target in assign.targets:
|
||||||
|
attr = target.name
|
||||||
|
generated_class_node.locals[attr] = class_node.locals[attr]
|
||||||
|
|
||||||
|
return iter((generated_class_node,))
|
||||||
|
|
||||||
|
|
||||||
|
def infer_typing_namedtuple(node, context=None):
|
||||||
|
"""Infer a typing.NamedTuple(...) call."""
|
||||||
|
# This is essentially a namedtuple with different arguments
|
||||||
|
# so we extract the args and infer a named tuple.
|
||||||
|
try:
|
||||||
|
func = next(node.func.infer())
|
||||||
|
except InferenceError:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
if func.qname() != "typing.NamedTuple":
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
if len(node.args) != 2:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
if not isinstance(node.args[1], (nodes.List, nodes.Tuple)):
|
||||||
|
raise UseInferenceDefault
|
||||||
|
|
||||||
|
names = []
|
||||||
|
for elt in node.args[1].elts:
|
||||||
|
if not isinstance(elt, (nodes.List, nodes.Tuple)):
|
||||||
|
raise UseInferenceDefault
|
||||||
|
if len(elt.elts) != 2:
|
||||||
|
raise UseInferenceDefault
|
||||||
|
names.append(elt.elts[0].as_string())
|
||||||
|
|
||||||
|
typename = node.args[0].as_string()
|
||||||
|
if names:
|
||||||
|
field_names = "({},)".format(",".join(names))
|
||||||
|
else:
|
||||||
|
field_names = "''"
|
||||||
|
node = extract_node(
|
||||||
|
"namedtuple({typename}, {fields})".format(typename=typename, fields=field_names)
|
||||||
|
)
|
||||||
|
return infer_named_tuple(node, context)
|
||||||
|
|
||||||
|
|
||||||
|
MANAGER.register_transform(
|
||||||
|
nodes.Call, inference_tip(infer_named_tuple), _looks_like_namedtuple
|
||||||
|
)
|
||||||
|
MANAGER.register_transform(nodes.Call, inference_tip(infer_enum), _looks_like_enum)
|
||||||
|
MANAGER.register_transform(
|
||||||
|
nodes.ClassDef,
|
||||||
|
infer_enum_class,
|
||||||
|
predicate=lambda cls: any(
|
||||||
|
basename for basename in cls.basenames if basename in ENUM_BASE_NAMES
|
||||||
|
),
|
||||||
|
)
|
||||||
|
MANAGER.register_transform(
|
||||||
|
nodes.ClassDef, inference_tip(infer_typing_namedtuple_class), _has_namedtuple_base
|
||||||
|
)
|
||||||
|
MANAGER.register_transform(
|
||||||
|
nodes.Call, inference_tip(infer_typing_namedtuple), _looks_like_typing_namedtuple
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
# Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
|
||||||
|
"""Hooks for nose library."""
|
||||||
|
|
||||||
|
import re
|
||||||
|
import textwrap
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
import astroid.builder
|
||||||
|
|
||||||
|
_BUILDER = astroid.builder.AstroidBuilder(astroid.MANAGER)
|
||||||
|
|
||||||
|
|
||||||
|
def _pep8(name, caps=re.compile("([A-Z])")):
|
||||||
|
return caps.sub(lambda m: "_" + m.groups()[0].lower(), name)
|
||||||
|
|
||||||
|
|
||||||
|
def _nose_tools_functions():
|
||||||
|
"""Get an iterator of names and bound methods."""
|
||||||
|
module = _BUILDER.string_build(
|
||||||
|
textwrap.dedent(
|
||||||
|
"""
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
class Test(unittest.TestCase):
|
||||||
|
pass
|
||||||
|
a = Test()
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
case = next(module["a"].infer())
|
||||||
|
except astroid.InferenceError:
|
||||||
|
return
|
||||||
|
for method in case.methods():
|
||||||
|
if method.name.startswith("assert") and "_" not in method.name:
|
||||||
|
pep8_name = _pep8(method.name)
|
||||||
|
yield pep8_name, astroid.BoundMethod(method, case)
|
||||||
|
if method.name == "assertEqual":
|
||||||
|
# nose also exports assert_equals.
|
||||||
|
yield "assert_equals", astroid.BoundMethod(method, case)
|
||||||
|
|
||||||
|
|
||||||
|
def _nose_tools_transform(node):
|
||||||
|
for method_name, method in _nose_tools_functions():
|
||||||
|
node.locals[method_name] = [method]
|
||||||
|
|
||||||
|
|
||||||
|
def _nose_tools_trivial_transform():
|
||||||
|
"""Custom transform for the nose.tools module."""
|
||||||
|
stub = _BUILDER.string_build("""__all__ = []""")
|
||||||
|
all_entries = ["ok_", "eq_"]
|
||||||
|
|
||||||
|
for pep8_name, method in _nose_tools_functions():
|
||||||
|
all_entries.append(pep8_name)
|
||||||
|
stub[pep8_name] = method
|
||||||
|
|
||||||
|
# Update the __all__ variable, since nose.tools
|
||||||
|
# does this manually with .append.
|
||||||
|
all_assign = stub["__all__"].parent
|
||||||
|
all_object = astroid.List(all_entries)
|
||||||
|
all_object.parent = all_assign
|
||||||
|
all_assign.value = all_object
|
||||||
|
return stub
|
||||||
|
|
||||||
|
|
||||||
|
astroid.register_module_extender(
|
||||||
|
astroid.MANAGER, "nose.tools.trivial", _nose_tools_trivial_transform
|
||||||
|
)
|
||||||
|
astroid.MANAGER.register_transform(
|
||||||
|
astroid.Module, _nose_tools_transform, lambda n: n.name == "nose.tools"
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
# Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
|
||||||
|
"""Astroid hooks for numpy.core.fromnumeric module."""
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
|
||||||
|
|
||||||
|
def numpy_core_fromnumeric_transform():
|
||||||
|
return astroid.parse(
|
||||||
|
"""
|
||||||
|
def sum(a, axis=None, dtype=None, out=None, keepdims=None, initial=None):
|
||||||
|
return numpy.ndarray([0, 0])
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
astroid.register_module_extender(
|
||||||
|
astroid.MANAGER, "numpy.core.fromnumeric", numpy_core_fromnumeric_transform
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
|
||||||
|
"""Astroid hooks for numpy.core.function_base module."""
|
||||||
|
|
||||||
|
import functools
|
||||||
|
import astroid
|
||||||
|
from brain_numpy_utils import looks_like_numpy_member, infer_numpy_member
|
||||||
|
|
||||||
|
|
||||||
|
METHODS_TO_BE_INFERRED = {
|
||||||
|
"linspace": """def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
"logspace": """def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None, axis=0):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
"geomspace": """def geomspace(start, stop, num=50, endpoint=True, dtype=None, axis=0):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
}
|
||||||
|
|
||||||
|
for func_name, func_src in METHODS_TO_BE_INFERRED.items():
|
||||||
|
inference_function = functools.partial(infer_numpy_member, func_src)
|
||||||
|
astroid.MANAGER.register_transform(
|
||||||
|
astroid.Attribute,
|
||||||
|
astroid.inference_tip(inference_function),
|
||||||
|
functools.partial(looks_like_numpy_member, func_name),
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
# Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
|
||||||
|
"""Astroid hooks for numpy.core.multiarray module."""
|
||||||
|
|
||||||
|
import functools
|
||||||
|
import astroid
|
||||||
|
from brain_numpy_utils import looks_like_numpy_member, infer_numpy_member
|
||||||
|
|
||||||
|
|
||||||
|
def numpy_core_multiarray_transform():
|
||||||
|
return astroid.parse(
|
||||||
|
"""
|
||||||
|
# different functions defined in multiarray.py
|
||||||
|
def inner(a, b):
|
||||||
|
return numpy.ndarray([0, 0])
|
||||||
|
|
||||||
|
def vdot(a, b):
|
||||||
|
return numpy.ndarray([0, 0])
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
astroid.register_module_extender(
|
||||||
|
astroid.MANAGER, "numpy.core.multiarray", numpy_core_multiarray_transform
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
METHODS_TO_BE_INFERRED = {
|
||||||
|
"array": """def array(object, dtype=None, copy=True, order='K', subok=False, ndmin=0):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
"dot": """def dot(a, b, out=None):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
"empty_like": """def empty_like(a, dtype=None, order='K', subok=True):
|
||||||
|
return numpy.ndarray((0, 0))""",
|
||||||
|
"concatenate": """def concatenate(arrays, axis=None, out=None):
|
||||||
|
return numpy.ndarray((0, 0))""",
|
||||||
|
"where": """def where(condition, x=None, y=None):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
"empty": """def empty(shape, dtype=float, order='C'):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
"bincount": """def bincount(x, weights=None, minlength=0):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
"busday_count": """def busday_count(begindates, enddates, weekmask='1111100', holidays=[], busdaycal=None, out=None):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
"busday_offset": """def busday_offset(dates, offsets, roll='raise', weekmask='1111100', holidays=None, busdaycal=None, out=None):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
"can_cast": """def can_cast(from_, to, casting='safe'):
|
||||||
|
return True""",
|
||||||
|
"copyto": """def copyto(dst, src, casting='same_kind', where=True):
|
||||||
|
return None""",
|
||||||
|
"datetime_as_string": """def datetime_as_string(arr, unit=None, timezone='naive', casting='same_kind'):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
"is_busday": """def is_busday(dates, weekmask='1111100', holidays=None, busdaycal=None, out=None):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
"lexsort": """def lexsort(keys, axis=-1):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
"may_share_memory": """def may_share_memory(a, b, max_work=None):
|
||||||
|
return True""",
|
||||||
|
# Not yet available because dtype is not yet present in those brains
|
||||||
|
# "min_scalar_type": """def min_scalar_type(a):
|
||||||
|
# return numpy.dtype('int16')""",
|
||||||
|
"packbits": """def packbits(a, axis=None, bitorder='big'):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
# Not yet available because dtype is not yet present in those brains
|
||||||
|
# "result_type": """def result_type(*arrays_and_dtypes):
|
||||||
|
# return numpy.dtype('int16')""",
|
||||||
|
"shares_memory": """def shares_memory(a, b, max_work=None):
|
||||||
|
return True""",
|
||||||
|
"unpackbits": """def unpackbits(a, axis=None, count=None, bitorder='big'):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
"unravel_index": """def unravel_index(indices, shape, order='C'):
|
||||||
|
return (numpy.ndarray([0, 0]),)""",
|
||||||
|
"zeros": """def zeros(shape, dtype=float, order='C'):
|
||||||
|
return numpy.ndarray([0, 0])""",
|
||||||
|
}
|
||||||
|
|
||||||
|
for method_name, function_src in METHODS_TO_BE_INFERRED.items():
|
||||||
|
inference_function = functools.partial(infer_numpy_member, function_src)
|
||||||
|
astroid.MANAGER.register_transform(
|
||||||
|
astroid.Attribute,
|
||||||
|
astroid.inference_tip(inference_function),
|
||||||
|
functools.partial(looks_like_numpy_member, method_name),
|
||||||
|
)
|
||||||
|
astroid.MANAGER.register_transform(
|
||||||
|
astroid.Name,
|
||||||
|
astroid.inference_tip(inference_function),
|
||||||
|
functools.partial(looks_like_numpy_member, method_name),
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
# Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
|
||||||
|
"""Astroid hooks for numpy.core.numeric module."""
|
||||||
|
|
||||||
|
import functools
|
||||||
|
import astroid
|
||||||
|
from brain_numpy_utils import looks_like_numpy_member, infer_numpy_member
|
||||||
|
|
||||||
|
|
||||||
|
def numpy_core_numeric_transform():
|
||||||
|
return astroid.parse(
|
||||||
|
"""
|
||||||
|
# different functions defined in numeric.py
|
||||||
|
import numpy
|
||||||
|
def zeros_like(a, dtype=None, order='K', subok=True): return numpy.ndarray((0, 0))
|
||||||
|
def ones_like(a, dtype=None, order='K', subok=True): return numpy.ndarray((0, 0))
|
||||||
|
def full_like(a, fill_value, dtype=None, order='K', subok=True): return numpy.ndarray((0, 0))
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
astroid.register_module_extender(
|
||||||
|
astroid.MANAGER, "numpy.core.numeric", numpy_core_numeric_transform
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
METHODS_TO_BE_INFERRED = {
|
||||||
|
"ones": """def ones(shape, dtype=None, order='C'):
|
||||||
|
return numpy.ndarray([0, 0])"""
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for method_name, function_src in METHODS_TO_BE_INFERRED.items():
|
||||||
|
inference_function = functools.partial(infer_numpy_member, function_src)
|
||||||
|
astroid.MANAGER.register_transform(
|
||||||
|
astroid.Attribute,
|
||||||
|
astroid.inference_tip(inference_function),
|
||||||
|
functools.partial(looks_like_numpy_member, method_name),
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,254 @@
|
||||||
|
# Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
# TODO(hippo91) : correct the methods signature.
|
||||||
|
|
||||||
|
"""Astroid hooks for numpy.core.numerictypes module."""
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
|
||||||
|
|
||||||
|
def numpy_core_numerictypes_transform():
|
||||||
|
# TODO: Uniformize the generic API with the ndarray one.
|
||||||
|
# According to numpy doc the generic object should expose
|
||||||
|
# the same API than ndarray. This has been done here partially
|
||||||
|
# through the astype method.
|
||||||
|
return astroid.parse(
|
||||||
|
"""
|
||||||
|
# different types defined in numerictypes.py
|
||||||
|
class generic(object):
|
||||||
|
def __init__(self, value):
|
||||||
|
self.T = None
|
||||||
|
self.base = None
|
||||||
|
self.data = None
|
||||||
|
self.dtype = None
|
||||||
|
self.flags = None
|
||||||
|
self.flat = None
|
||||||
|
self.imag = None
|
||||||
|
self.itemsize = None
|
||||||
|
self.nbytes = None
|
||||||
|
self.ndim = None
|
||||||
|
self.real = None
|
||||||
|
self.size = None
|
||||||
|
self.strides = None
|
||||||
|
|
||||||
|
def all(self): return uninferable
|
||||||
|
def any(self): return uninferable
|
||||||
|
def argmax(self): return uninferable
|
||||||
|
def argmin(self): return uninferable
|
||||||
|
def argsort(self): return uninferable
|
||||||
|
def astype(self, dtype, order='K', casting='unsafe', subok=True, copy=True): return np.ndarray([0, 0])
|
||||||
|
def base(self): return uninferable
|
||||||
|
def byteswap(self): return uninferable
|
||||||
|
def choose(self): return uninferable
|
||||||
|
def clip(self): return uninferable
|
||||||
|
def compress(self): return uninferable
|
||||||
|
def conj(self): return uninferable
|
||||||
|
def conjugate(self): return uninferable
|
||||||
|
def copy(self): return uninferable
|
||||||
|
def cumprod(self): return uninferable
|
||||||
|
def cumsum(self): return uninferable
|
||||||
|
def data(self): return uninferable
|
||||||
|
def diagonal(self): return uninferable
|
||||||
|
def dtype(self): return uninferable
|
||||||
|
def dump(self): return uninferable
|
||||||
|
def dumps(self): return uninferable
|
||||||
|
def fill(self): return uninferable
|
||||||
|
def flags(self): return uninferable
|
||||||
|
def flat(self): return uninferable
|
||||||
|
def flatten(self): return uninferable
|
||||||
|
def getfield(self): return uninferable
|
||||||
|
def imag(self): return uninferable
|
||||||
|
def item(self): return uninferable
|
||||||
|
def itemset(self): return uninferable
|
||||||
|
def itemsize(self): return uninferable
|
||||||
|
def max(self): return uninferable
|
||||||
|
def mean(self): return uninferable
|
||||||
|
def min(self): return uninferable
|
||||||
|
def nbytes(self): return uninferable
|
||||||
|
def ndim(self): return uninferable
|
||||||
|
def newbyteorder(self): return uninferable
|
||||||
|
def nonzero(self): return uninferable
|
||||||
|
def prod(self): return uninferable
|
||||||
|
def ptp(self): return uninferable
|
||||||
|
def put(self): return uninferable
|
||||||
|
def ravel(self): return uninferable
|
||||||
|
def real(self): return uninferable
|
||||||
|
def repeat(self): return uninferable
|
||||||
|
def reshape(self): return uninferable
|
||||||
|
def resize(self): return uninferable
|
||||||
|
def round(self): return uninferable
|
||||||
|
def searchsorted(self): return uninferable
|
||||||
|
def setfield(self): return uninferable
|
||||||
|
def setflags(self): return uninferable
|
||||||
|
def shape(self): return uninferable
|
||||||
|
def size(self): return uninferable
|
||||||
|
def sort(self): return uninferable
|
||||||
|
def squeeze(self): return uninferable
|
||||||
|
def std(self): return uninferable
|
||||||
|
def strides(self): return uninferable
|
||||||
|
def sum(self): return uninferable
|
||||||
|
def swapaxes(self): return uninferable
|
||||||
|
def take(self): return uninferable
|
||||||
|
def tobytes(self): return uninferable
|
||||||
|
def tofile(self): return uninferable
|
||||||
|
def tolist(self): return uninferable
|
||||||
|
def tostring(self): return uninferable
|
||||||
|
def trace(self): return uninferable
|
||||||
|
def transpose(self): return uninferable
|
||||||
|
def var(self): return uninferable
|
||||||
|
def view(self): return uninferable
|
||||||
|
|
||||||
|
|
||||||
|
class dtype(object):
|
||||||
|
def __init__(self, obj, align=False, copy=False):
|
||||||
|
self.alignment = None
|
||||||
|
self.base = None
|
||||||
|
self.byteorder = None
|
||||||
|
self.char = None
|
||||||
|
self.descr = None
|
||||||
|
self.fields = None
|
||||||
|
self.flags = None
|
||||||
|
self.hasobject = None
|
||||||
|
self.isalignedstruct = None
|
||||||
|
self.isbuiltin = None
|
||||||
|
self.isnative = None
|
||||||
|
self.itemsize = None
|
||||||
|
self.kind = None
|
||||||
|
self.metadata = None
|
||||||
|
self.name = None
|
||||||
|
self.names = None
|
||||||
|
self.num = None
|
||||||
|
self.shape = None
|
||||||
|
self.str = None
|
||||||
|
self.subdtype = None
|
||||||
|
self.type = None
|
||||||
|
|
||||||
|
def newbyteorder(self, new_order='S'): return uninferable
|
||||||
|
def __neg__(self): return uninferable
|
||||||
|
|
||||||
|
class busdaycalendar(object):
|
||||||
|
def __init__(self, weekmask='1111100', holidays=None):
|
||||||
|
self.holidays = None
|
||||||
|
self.weekmask = None
|
||||||
|
|
||||||
|
class flexible(generic): pass
|
||||||
|
class bool_(generic): pass
|
||||||
|
class number(generic):
|
||||||
|
def __neg__(self): return uninferable
|
||||||
|
class datetime64(generic):
|
||||||
|
def __init__(self, nb, unit=None): pass
|
||||||
|
|
||||||
|
|
||||||
|
class void(flexible):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.base = None
|
||||||
|
self.dtype = None
|
||||||
|
self.flags = None
|
||||||
|
def getfield(self): return uninferable
|
||||||
|
def setfield(self): return uninferable
|
||||||
|
|
||||||
|
|
||||||
|
class character(flexible): pass
|
||||||
|
|
||||||
|
|
||||||
|
class integer(number):
|
||||||
|
def __init__(self, value):
|
||||||
|
self.denominator = None
|
||||||
|
self.numerator = None
|
||||||
|
|
||||||
|
|
||||||
|
class inexact(number): pass
|
||||||
|
|
||||||
|
|
||||||
|
class str_(str, character):
|
||||||
|
def maketrans(self, x, y=None, z=None): return uninferable
|
||||||
|
|
||||||
|
|
||||||
|
class bytes_(bytes, character):
|
||||||
|
def fromhex(self, string): return uninferable
|
||||||
|
def maketrans(self, frm, to): return uninferable
|
||||||
|
|
||||||
|
|
||||||
|
class signedinteger(integer): pass
|
||||||
|
|
||||||
|
|
||||||
|
class unsignedinteger(integer): pass
|
||||||
|
|
||||||
|
|
||||||
|
class complexfloating(inexact): pass
|
||||||
|
|
||||||
|
|
||||||
|
class floating(inexact): pass
|
||||||
|
|
||||||
|
|
||||||
|
class float64(floating, float):
|
||||||
|
def fromhex(self, string): return uninferable
|
||||||
|
|
||||||
|
|
||||||
|
class uint64(unsignedinteger): pass
|
||||||
|
class complex64(complexfloating): pass
|
||||||
|
class int16(signedinteger): pass
|
||||||
|
class float96(floating): pass
|
||||||
|
class int8(signedinteger): pass
|
||||||
|
class uint32(unsignedinteger): pass
|
||||||
|
class uint8(unsignedinteger): pass
|
||||||
|
class _typedict(dict): pass
|
||||||
|
class complex192(complexfloating): pass
|
||||||
|
class timedelta64(signedinteger):
|
||||||
|
def __init__(self, nb, unit=None): pass
|
||||||
|
class int32(signedinteger): pass
|
||||||
|
class uint16(unsignedinteger): pass
|
||||||
|
class float32(floating): pass
|
||||||
|
class complex128(complexfloating, complex): pass
|
||||||
|
class float16(floating): pass
|
||||||
|
class int64(signedinteger): pass
|
||||||
|
|
||||||
|
buffer_type = memoryview
|
||||||
|
bool8 = bool_
|
||||||
|
byte = int8
|
||||||
|
bytes0 = bytes_
|
||||||
|
cdouble = complex128
|
||||||
|
cfloat = complex128
|
||||||
|
clongdouble = complex192
|
||||||
|
clongfloat = complex192
|
||||||
|
complex_ = complex128
|
||||||
|
csingle = complex64
|
||||||
|
double = float64
|
||||||
|
float_ = float64
|
||||||
|
half = float16
|
||||||
|
int0 = int32
|
||||||
|
int_ = int32
|
||||||
|
intc = int32
|
||||||
|
intp = int32
|
||||||
|
long = int32
|
||||||
|
longcomplex = complex192
|
||||||
|
longdouble = float96
|
||||||
|
longfloat = float96
|
||||||
|
longlong = int64
|
||||||
|
object0 = object_
|
||||||
|
object_ = object_
|
||||||
|
short = int16
|
||||||
|
single = float32
|
||||||
|
singlecomplex = complex64
|
||||||
|
str0 = str_
|
||||||
|
string_ = bytes_
|
||||||
|
ubyte = uint8
|
||||||
|
uint = uint32
|
||||||
|
uint0 = uint32
|
||||||
|
uintc = uint32
|
||||||
|
uintp = uint32
|
||||||
|
ulonglong = uint64
|
||||||
|
unicode = str_
|
||||||
|
unicode_ = str_
|
||||||
|
ushort = uint16
|
||||||
|
void0 = void
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
astroid.register_module_extender(
|
||||||
|
astroid.MANAGER, "numpy.core.numerictypes", numpy_core_numerictypes_transform
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,147 @@
|
||||||
|
# Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
|
||||||
|
"""Astroid hooks for numpy.core.umath module."""
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
|
||||||
|
|
||||||
|
def numpy_core_umath_transform():
|
||||||
|
ufunc_optional_keyword_arguments = (
|
||||||
|
"""out=None, where=True, casting='same_kind', order='K', """
|
||||||
|
"""dtype=None, subok=True"""
|
||||||
|
)
|
||||||
|
return astroid.parse(
|
||||||
|
"""
|
||||||
|
class FakeUfunc:
|
||||||
|
def __init__(self):
|
||||||
|
self.__doc__ = str()
|
||||||
|
self.__name__ = str()
|
||||||
|
self.nin = 0
|
||||||
|
self.nout = 0
|
||||||
|
self.nargs = 0
|
||||||
|
self.ntypes = 0
|
||||||
|
self.types = None
|
||||||
|
self.identity = None
|
||||||
|
self.signature = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reduce(cls, a, axis=None, dtype=None, out=None):
|
||||||
|
return numpy.ndarray([0, 0])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def accumulate(cls, array, axis=None, dtype=None, out=None):
|
||||||
|
return numpy.ndarray([0, 0])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def reduceat(cls, a, indices, axis=None, dtype=None, out=None):
|
||||||
|
return numpy.ndarray([0, 0])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def outer(cls, A, B, **kwargs):
|
||||||
|
return numpy.ndarray([0, 0])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def at(cls, a, indices, b=None):
|
||||||
|
return numpy.ndarray([0, 0])
|
||||||
|
|
||||||
|
class FakeUfuncOneArg(FakeUfunc):
|
||||||
|
def __call__(self, x, {opt_args:s}):
|
||||||
|
return numpy.ndarray([0, 0])
|
||||||
|
|
||||||
|
class FakeUfuncOneArgBis(FakeUfunc):
|
||||||
|
def __call__(self, x, {opt_args:s}):
|
||||||
|
return numpy.ndarray([0, 0]), numpy.ndarray([0, 0])
|
||||||
|
|
||||||
|
class FakeUfuncTwoArgs(FakeUfunc):
|
||||||
|
def __call__(self, x1, x2, {opt_args:s}):
|
||||||
|
return numpy.ndarray([0, 0])
|
||||||
|
|
||||||
|
# Constants
|
||||||
|
e = 2.718281828459045
|
||||||
|
euler_gamma = 0.5772156649015329
|
||||||
|
|
||||||
|
# One arg functions with optional kwargs
|
||||||
|
arccos = FakeUfuncOneArg()
|
||||||
|
arccosh = FakeUfuncOneArg()
|
||||||
|
arcsin = FakeUfuncOneArg()
|
||||||
|
arcsinh = FakeUfuncOneArg()
|
||||||
|
arctan = FakeUfuncOneArg()
|
||||||
|
arctanh = FakeUfuncOneArg()
|
||||||
|
cbrt = FakeUfuncOneArg()
|
||||||
|
conj = FakeUfuncOneArg()
|
||||||
|
conjugate = FakeUfuncOneArg()
|
||||||
|
cosh = FakeUfuncOneArg()
|
||||||
|
deg2rad = FakeUfuncOneArg()
|
||||||
|
exp2 = FakeUfuncOneArg()
|
||||||
|
expm1 = FakeUfuncOneArg()
|
||||||
|
fabs = FakeUfuncOneArg()
|
||||||
|
frexp = FakeUfuncOneArgBis()
|
||||||
|
isfinite = FakeUfuncOneArg()
|
||||||
|
isinf = FakeUfuncOneArg()
|
||||||
|
log = FakeUfuncOneArg()
|
||||||
|
log1p = FakeUfuncOneArg()
|
||||||
|
log2 = FakeUfuncOneArg()
|
||||||
|
logical_not = FakeUfuncOneArg()
|
||||||
|
modf = FakeUfuncOneArgBis()
|
||||||
|
negative = FakeUfuncOneArg()
|
||||||
|
positive = FakeUfuncOneArg()
|
||||||
|
rad2deg = FakeUfuncOneArg()
|
||||||
|
reciprocal = FakeUfuncOneArg()
|
||||||
|
rint = FakeUfuncOneArg()
|
||||||
|
sign = FakeUfuncOneArg()
|
||||||
|
signbit = FakeUfuncOneArg()
|
||||||
|
sinh = FakeUfuncOneArg()
|
||||||
|
spacing = FakeUfuncOneArg()
|
||||||
|
square = FakeUfuncOneArg()
|
||||||
|
tan = FakeUfuncOneArg()
|
||||||
|
tanh = FakeUfuncOneArg()
|
||||||
|
trunc = FakeUfuncOneArg()
|
||||||
|
|
||||||
|
# Two args functions with optional kwargs
|
||||||
|
bitwise_and = FakeUfuncTwoArgs()
|
||||||
|
bitwise_or = FakeUfuncTwoArgs()
|
||||||
|
bitwise_xor = FakeUfuncTwoArgs()
|
||||||
|
copysign = FakeUfuncTwoArgs()
|
||||||
|
divide = FakeUfuncTwoArgs()
|
||||||
|
divmod = FakeUfuncTwoArgs()
|
||||||
|
equal = FakeUfuncTwoArgs()
|
||||||
|
float_power = FakeUfuncTwoArgs()
|
||||||
|
floor_divide = FakeUfuncTwoArgs()
|
||||||
|
fmax = FakeUfuncTwoArgs()
|
||||||
|
fmin = FakeUfuncTwoArgs()
|
||||||
|
fmod = FakeUfuncTwoArgs()
|
||||||
|
greater = FakeUfuncTwoArgs()
|
||||||
|
gcd = FakeUfuncTwoArgs()
|
||||||
|
hypot = FakeUfuncTwoArgs()
|
||||||
|
heaviside = FakeUfuncTwoArgs()
|
||||||
|
lcm = FakeUfuncTwoArgs()
|
||||||
|
ldexp = FakeUfuncTwoArgs()
|
||||||
|
left_shift = FakeUfuncTwoArgs()
|
||||||
|
less = FakeUfuncTwoArgs()
|
||||||
|
logaddexp = FakeUfuncTwoArgs()
|
||||||
|
logaddexp2 = FakeUfuncTwoArgs()
|
||||||
|
logical_and = FakeUfuncTwoArgs()
|
||||||
|
logical_or = FakeUfuncTwoArgs()
|
||||||
|
logical_xor = FakeUfuncTwoArgs()
|
||||||
|
maximum = FakeUfuncTwoArgs()
|
||||||
|
minimum = FakeUfuncTwoArgs()
|
||||||
|
nextafter = FakeUfuncTwoArgs()
|
||||||
|
not_equal = FakeUfuncTwoArgs()
|
||||||
|
power = FakeUfuncTwoArgs()
|
||||||
|
remainder = FakeUfuncTwoArgs()
|
||||||
|
right_shift = FakeUfuncTwoArgs()
|
||||||
|
subtract = FakeUfuncTwoArgs()
|
||||||
|
true_divide = FakeUfuncTwoArgs()
|
||||||
|
""".format(
|
||||||
|
opt_args=ufunc_optional_keyword_arguments
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
astroid.register_module_extender(
|
||||||
|
astroid.MANAGER, "numpy.core.umath", numpy_core_umath_transform
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
# Copyright (c) 2015-2016, 2018-2019 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
# Copyright (c) 2017-2020 hippo91 <guillaume.peillex@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
|
||||||
|
"""Astroid hooks for numpy ndarray class."""
|
||||||
|
|
||||||
|
import functools
|
||||||
|
import astroid
|
||||||
|
|
||||||
|
|
||||||
|
def infer_numpy_ndarray(node, context=None):
|
||||||
|
ndarray = """
|
||||||
|
class ndarray(object):
|
||||||
|
def __init__(self, shape, dtype=float, buffer=None, offset=0,
|
||||||
|
strides=None, order=None):
|
||||||
|
self.T = None
|
||||||
|
self.base = None
|
||||||
|
self.ctypes = None
|
||||||
|
self.data = None
|
||||||
|
self.dtype = None
|
||||||
|
self.flags = None
|
||||||
|
self.flat = None
|
||||||
|
self.imag = np.ndarray([0, 0])
|
||||||
|
self.itemsize = None
|
||||||
|
self.nbytes = None
|
||||||
|
self.ndim = None
|
||||||
|
self.real = np.ndarray([0, 0])
|
||||||
|
self.shape = numpy.ndarray([0, 0])
|
||||||
|
self.size = None
|
||||||
|
self.strides = None
|
||||||
|
|
||||||
|
def __abs__(self): return numpy.ndarray([0, 0])
|
||||||
|
def __add__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __and__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __array__(self, dtype=None): return numpy.ndarray([0, 0])
|
||||||
|
def __array_wrap__(self, obj): return numpy.ndarray([0, 0])
|
||||||
|
def __contains__(self, key): return True
|
||||||
|
def __copy__(self): return numpy.ndarray([0, 0])
|
||||||
|
def __deepcopy__(self, memo): return numpy.ndarray([0, 0])
|
||||||
|
def __divmod__(self, value): return (numpy.ndarray([0, 0]), numpy.ndarray([0, 0]))
|
||||||
|
def __eq__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __float__(self): return 0.
|
||||||
|
def __floordiv__(self): return numpy.ndarray([0, 0])
|
||||||
|
def __ge__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __getitem__(self, key): return uninferable
|
||||||
|
def __gt__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __iadd__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __iand__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __ifloordiv__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __ilshift__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __imod__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __imul__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __int__(self): return 0
|
||||||
|
def __invert__(self): return numpy.ndarray([0, 0])
|
||||||
|
def __ior__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __ipow__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __irshift__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __isub__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __itruediv__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __ixor__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __le__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __len__(self): return 1
|
||||||
|
def __lshift__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __lt__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __matmul__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __mod__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __mul__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __ne__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __neg__(self): return numpy.ndarray([0, 0])
|
||||||
|
def __or__(self): return numpy.ndarray([0, 0])
|
||||||
|
def __pos__(self): return numpy.ndarray([0, 0])
|
||||||
|
def __pow__(self): return numpy.ndarray([0, 0])
|
||||||
|
def __repr__(self): return str()
|
||||||
|
def __rshift__(self): return numpy.ndarray([0, 0])
|
||||||
|
def __setitem__(self, key, value): return uninferable
|
||||||
|
def __str__(self): return str()
|
||||||
|
def __sub__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __truediv__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def __xor__(self, value): return numpy.ndarray([0, 0])
|
||||||
|
def all(self, axis=None, out=None, keepdims=False): return np.ndarray([0, 0])
|
||||||
|
def any(self, axis=None, out=None, keepdims=False): return np.ndarray([0, 0])
|
||||||
|
def argmax(self, axis=None, out=None): return np.ndarray([0, 0])
|
||||||
|
def argmin(self, axis=None, out=None): return np.ndarray([0, 0])
|
||||||
|
def argpartition(self, kth, axis=-1, kind='introselect', order=None): return np.ndarray([0, 0])
|
||||||
|
def argsort(self, axis=-1, kind='quicksort', order=None): return np.ndarray([0, 0])
|
||||||
|
def astype(self, dtype, order='K', casting='unsafe', subok=True, copy=True): return np.ndarray([0, 0])
|
||||||
|
def byteswap(self, inplace=False): return np.ndarray([0, 0])
|
||||||
|
def choose(self, choices, out=None, mode='raise'): return np.ndarray([0, 0])
|
||||||
|
def clip(self, min=None, max=None, out=None): return np.ndarray([0, 0])
|
||||||
|
def compress(self, condition, axis=None, out=None): return np.ndarray([0, 0])
|
||||||
|
def conj(self): return np.ndarray([0, 0])
|
||||||
|
def conjugate(self): return np.ndarray([0, 0])
|
||||||
|
def copy(self, order='C'): return np.ndarray([0, 0])
|
||||||
|
def cumprod(self, axis=None, dtype=None, out=None): return np.ndarray([0, 0])
|
||||||
|
def cumsum(self, axis=None, dtype=None, out=None): return np.ndarray([0, 0])
|
||||||
|
def diagonal(self, offset=0, axis1=0, axis2=1): return np.ndarray([0, 0])
|
||||||
|
def dot(self, b, out=None): return np.ndarray([0, 0])
|
||||||
|
def dump(self, file): return None
|
||||||
|
def dumps(self): return str()
|
||||||
|
def fill(self, value): return None
|
||||||
|
def flatten(self, order='C'): return np.ndarray([0, 0])
|
||||||
|
def getfield(self, dtype, offset=0): return np.ndarray([0, 0])
|
||||||
|
def item(self, *args): return uninferable
|
||||||
|
def itemset(self, *args): return None
|
||||||
|
def max(self, axis=None, out=None): return np.ndarray([0, 0])
|
||||||
|
def mean(self, axis=None, dtype=None, out=None, keepdims=False): return np.ndarray([0, 0])
|
||||||
|
def min(self, axis=None, out=None, keepdims=False): return np.ndarray([0, 0])
|
||||||
|
def newbyteorder(self, new_order='S'): return np.ndarray([0, 0])
|
||||||
|
def nonzero(self): return (1,)
|
||||||
|
def partition(self, kth, axis=-1, kind='introselect', order=None): return None
|
||||||
|
def prod(self, axis=None, dtype=None, out=None, keepdims=False): return np.ndarray([0, 0])
|
||||||
|
def ptp(self, axis=None, out=None): return np.ndarray([0, 0])
|
||||||
|
def put(self, indices, values, mode='raise'): return None
|
||||||
|
def ravel(self, order='C'): return np.ndarray([0, 0])
|
||||||
|
def repeat(self, repeats, axis=None): return np.ndarray([0, 0])
|
||||||
|
def reshape(self, shape, order='C'): return np.ndarray([0, 0])
|
||||||
|
def resize(self, new_shape, refcheck=True): return None
|
||||||
|
def round(self, decimals=0, out=None): return np.ndarray([0, 0])
|
||||||
|
def searchsorted(self, v, side='left', sorter=None): return np.ndarray([0, 0])
|
||||||
|
def setfield(self, val, dtype, offset=0): return None
|
||||||
|
def setflags(self, write=None, align=None, uic=None): return None
|
||||||
|
def sort(self, axis=-1, kind='quicksort', order=None): return None
|
||||||
|
def squeeze(self, axis=None): return np.ndarray([0, 0])
|
||||||
|
def std(self, axis=None, dtype=None, out=None, ddof=0, keepdims=False): return np.ndarray([0, 0])
|
||||||
|
def sum(self, axis=None, dtype=None, out=None, keepdims=False): return np.ndarray([0, 0])
|
||||||
|
def swapaxes(self, axis1, axis2): return np.ndarray([0, 0])
|
||||||
|
def take(self, indices, axis=None, out=None, mode='raise'): return np.ndarray([0, 0])
|
||||||
|
def tobytes(self, order='C'): return b''
|
||||||
|
def tofile(self, fid, sep="", format="%s"): return None
|
||||||
|
def tolist(self, ): return []
|
||||||
|
def tostring(self, order='C'): return b''
|
||||||
|
def trace(self, offset=0, axis1=0, axis2=1, dtype=None, out=None): return np.ndarray([0, 0])
|
||||||
|
def transpose(self, *axes): return np.ndarray([0, 0])
|
||||||
|
def var(self, axis=None, dtype=None, out=None, ddof=0, keepdims=False): return np.ndarray([0, 0])
|
||||||
|
def view(self, dtype=None, type=None): return np.ndarray([0, 0])
|
||||||
|
"""
|
||||||
|
node = astroid.extract_node(ndarray)
|
||||||
|
return node.infer(context=context)
|
||||||
|
|
||||||
|
|
||||||
|
def _looks_like_numpy_ndarray(node):
|
||||||
|
return isinstance(node, astroid.Attribute) and node.attrname == "ndarray"
|
||||||
|
|
||||||
|
|
||||||
|
astroid.MANAGER.register_transform(
|
||||||
|
astroid.Attribute,
|
||||||
|
astroid.inference_tip(infer_numpy_ndarray),
|
||||||
|
_looks_like_numpy_ndarray,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
# Copyright (c) 2019 hippo91 <guillaume.peillex@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
# TODO(hippo91) : correct the functions return types
|
||||||
|
"""Astroid hooks for numpy.random.mtrand module."""
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
|
||||||
|
|
||||||
|
def numpy_random_mtrand_transform():
|
||||||
|
return astroid.parse(
|
||||||
|
"""
|
||||||
|
def beta(a, b, size=None): return uninferable
|
||||||
|
def binomial(n, p, size=None): return uninferable
|
||||||
|
def bytes(length): return uninferable
|
||||||
|
def chisquare(df, size=None): return uninferable
|
||||||
|
def choice(a, size=None, replace=True, p=None): return uninferable
|
||||||
|
def dirichlet(alpha, size=None): return uninferable
|
||||||
|
def exponential(scale=1.0, size=None): return uninferable
|
||||||
|
def f(dfnum, dfden, size=None): return uninferable
|
||||||
|
def gamma(shape, scale=1.0, size=None): return uninferable
|
||||||
|
def geometric(p, size=None): return uninferable
|
||||||
|
def get_state(): return uninferable
|
||||||
|
def gumbel(loc=0.0, scale=1.0, size=None): return uninferable
|
||||||
|
def hypergeometric(ngood, nbad, nsample, size=None): return uninferable
|
||||||
|
def laplace(loc=0.0, scale=1.0, size=None): return uninferable
|
||||||
|
def logistic(loc=0.0, scale=1.0, size=None): return uninferable
|
||||||
|
def lognormal(mean=0.0, sigma=1.0, size=None): return uninferable
|
||||||
|
def logseries(p, size=None): return uninferable
|
||||||
|
def multinomial(n, pvals, size=None): return uninferable
|
||||||
|
def multivariate_normal(mean, cov, size=None): return uninferable
|
||||||
|
def negative_binomial(n, p, size=None): return uninferable
|
||||||
|
def noncentral_chisquare(df, nonc, size=None): return uninferable
|
||||||
|
def noncentral_f(dfnum, dfden, nonc, size=None): return uninferable
|
||||||
|
def normal(loc=0.0, scale=1.0, size=None): return uninferable
|
||||||
|
def pareto(a, size=None): return uninferable
|
||||||
|
def permutation(x): return uninferable
|
||||||
|
def poisson(lam=1.0, size=None): return uninferable
|
||||||
|
def power(a, size=None): return uninferable
|
||||||
|
def rand(*args): return uninferable
|
||||||
|
def randint(low, high=None, size=None, dtype='l'):
|
||||||
|
import numpy
|
||||||
|
return numpy.ndarray((1,1))
|
||||||
|
def randn(*args): return uninferable
|
||||||
|
def random_integers(low, high=None, size=None): return uninferable
|
||||||
|
def random_sample(size=None): return uninferable
|
||||||
|
def rayleigh(scale=1.0, size=None): return uninferable
|
||||||
|
def seed(seed=None): return uninferable
|
||||||
|
def set_state(state): return uninferable
|
||||||
|
def shuffle(x): return uninferable
|
||||||
|
def standard_cauchy(size=None): return uninferable
|
||||||
|
def standard_exponential(size=None): return uninferable
|
||||||
|
def standard_gamma(shape, size=None): return uninferable
|
||||||
|
def standard_normal(size=None): return uninferable
|
||||||
|
def standard_t(df, size=None): return uninferable
|
||||||
|
def triangular(left, mode, right, size=None): return uninferable
|
||||||
|
def uniform(low=0.0, high=1.0, size=None): return uninferable
|
||||||
|
def vonmises(mu, kappa, size=None): return uninferable
|
||||||
|
def wald(mean, scale, size=None): return uninferable
|
||||||
|
def weibull(a, size=None): return uninferable
|
||||||
|
def zipf(a, size=None): return uninferable
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
astroid.register_module_extender(
|
||||||
|
astroid.MANAGER, "numpy.random.mtrand", numpy_random_mtrand_transform
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
# Copyright (c) 2019-2020 hippo91 <guillaume.peillex@gmail.com>
|
||||||
|
# Copyright (c) 2019 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
|
||||||
|
"""Different utilities for the numpy brains"""
|
||||||
|
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
|
||||||
|
|
||||||
|
def infer_numpy_member(src, node, context=None):
|
||||||
|
node = astroid.extract_node(src)
|
||||||
|
return node.infer(context=context)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_a_numpy_module(node: astroid.node_classes.Name) -> bool:
|
||||||
|
"""
|
||||||
|
Returns True if the node is a representation of a numpy module.
|
||||||
|
|
||||||
|
For example in :
|
||||||
|
import numpy as np
|
||||||
|
x = np.linspace(1, 2)
|
||||||
|
The node <Name.np> is a representation of the numpy module.
|
||||||
|
|
||||||
|
:param node: node to test
|
||||||
|
:return: True if the node is a representation of the numpy module.
|
||||||
|
"""
|
||||||
|
module_nickname = node.name
|
||||||
|
potential_import_target = [
|
||||||
|
x for x in node.lookup(module_nickname)[1] if isinstance(x, astroid.Import)
|
||||||
|
]
|
||||||
|
for target in potential_import_target:
|
||||||
|
if ("numpy", module_nickname) in target.names:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def looks_like_numpy_member(
|
||||||
|
member_name: str, node: astroid.node_classes.NodeNG
|
||||||
|
) -> bool:
|
||||||
|
"""
|
||||||
|
Returns True if the node is a member of numpy whose
|
||||||
|
name is member_name.
|
||||||
|
|
||||||
|
:param member_name: name of the member
|
||||||
|
:param node: node to test
|
||||||
|
:return: True if the node is a member of numpy
|
||||||
|
"""
|
||||||
|
if (
|
||||||
|
isinstance(node, astroid.Attribute)
|
||||||
|
and node.attrname == member_name
|
||||||
|
and isinstance(node.expr, astroid.Name)
|
||||||
|
and _is_a_numpy_module(node.expr)
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
if (
|
||||||
|
isinstance(node, astroid.Name)
|
||||||
|
and node.name == member_name
|
||||||
|
and node.root().name.startswith("numpy")
|
||||||
|
):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
# Copyright (c) 2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
|
||||||
|
import astroid
|
||||||
|
from astroid import parse
|
||||||
|
from astroid import inference_tip
|
||||||
|
from astroid import register_module_extender
|
||||||
|
from astroid import MANAGER
|
||||||
|
|
||||||
|
|
||||||
|
def pkg_resources_transform():
|
||||||
|
return parse(
|
||||||
|
"""
|
||||||
|
def require(*requirements):
|
||||||
|
return pkg_resources.working_set.require(*requirements)
|
||||||
|
|
||||||
|
def run_script(requires, script_name):
|
||||||
|
return pkg_resources.working_set.run_script(requires, script_name)
|
||||||
|
|
||||||
|
def iter_entry_points(group, name=None):
|
||||||
|
return pkg_resources.working_set.iter_entry_points(group, name)
|
||||||
|
|
||||||
|
def resource_exists(package_or_requirement, resource_name):
|
||||||
|
return get_provider(package_or_requirement).has_resource(resource_name)
|
||||||
|
|
||||||
|
def resource_isdir(package_or_requirement, resource_name):
|
||||||
|
return get_provider(package_or_requirement).resource_isdir(
|
||||||
|
resource_name)
|
||||||
|
|
||||||
|
def resource_filename(package_or_requirement, resource_name):
|
||||||
|
return get_provider(package_or_requirement).get_resource_filename(
|
||||||
|
self, resource_name)
|
||||||
|
|
||||||
|
def resource_stream(package_or_requirement, resource_name):
|
||||||
|
return get_provider(package_or_requirement).get_resource_stream(
|
||||||
|
self, resource_name)
|
||||||
|
|
||||||
|
def resource_string(package_or_requirement, resource_name):
|
||||||
|
return get_provider(package_or_requirement).get_resource_string(
|
||||||
|
self, resource_name)
|
||||||
|
|
||||||
|
def resource_listdir(package_or_requirement, resource_name):
|
||||||
|
return get_provider(package_or_requirement).resource_listdir(
|
||||||
|
resource_name)
|
||||||
|
|
||||||
|
def extraction_error():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_cache_path(archive_name, names=()):
|
||||||
|
extract_path = self.extraction_path or get_default_cache()
|
||||||
|
target_path = os.path.join(extract_path, archive_name+'-tmp', *names)
|
||||||
|
return target_path
|
||||||
|
|
||||||
|
def postprocess(tempname, filename):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_extraction_path(path):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def cleanup_resources(force=False):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_distribution(dist):
|
||||||
|
return Distribution(dist)
|
||||||
|
|
||||||
|
_namespace_packages = {}
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
register_module_extender(MANAGER, "pkg_resources", pkg_resources_transform)
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
# Copyright (c) 2014-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2014 Jeff Quast <contact@jeffquast.com>
|
||||||
|
# Copyright (c) 2014 Google, Inc.
|
||||||
|
# Copyright (c) 2016 Florian Bruhin <me@the-compiler.org>
|
||||||
|
# Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
"""Astroid hooks for pytest."""
|
||||||
|
from __future__ import absolute_import
|
||||||
|
from astroid import MANAGER, register_module_extender
|
||||||
|
from astroid.builder import AstroidBuilder
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_transform():
|
||||||
|
return AstroidBuilder(MANAGER).string_build(
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
import _pytest.mark
|
||||||
|
import _pytest.recwarn
|
||||||
|
import _pytest.runner
|
||||||
|
import _pytest.python
|
||||||
|
import _pytest.skipping
|
||||||
|
import _pytest.assertion
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
deprecated_call = _pytest.recwarn.deprecated_call
|
||||||
|
warns = _pytest.recwarn.warns
|
||||||
|
|
||||||
|
exit = _pytest.runner.exit
|
||||||
|
fail = _pytest.runner.fail
|
||||||
|
skip = _pytest.runner.skip
|
||||||
|
importorskip = _pytest.runner.importorskip
|
||||||
|
|
||||||
|
xfail = _pytest.skipping.xfail
|
||||||
|
mark = _pytest.mark.MarkGenerator()
|
||||||
|
raises = _pytest.python.raises
|
||||||
|
|
||||||
|
# New in pytest 3.0
|
||||||
|
try:
|
||||||
|
approx = _pytest.python.approx
|
||||||
|
register_assert_rewrite = _pytest.assertion.register_assert_rewrite
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# Moved in pytest 3.0
|
||||||
|
|
||||||
|
try:
|
||||||
|
import _pytest.freeze_support
|
||||||
|
freeze_includes = _pytest.freeze_support.freeze_includes
|
||||||
|
except ImportError:
|
||||||
|
try:
|
||||||
|
import _pytest.genscript
|
||||||
|
freeze_includes = _pytest.genscript.freeze_includes
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
import _pytest.debugging
|
||||||
|
set_trace = _pytest.debugging.pytestPDB().set_trace
|
||||||
|
except ImportError:
|
||||||
|
try:
|
||||||
|
import _pytest.pdb
|
||||||
|
set_trace = _pytest.pdb.pytestPDB().set_trace
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
import _pytest.fixtures
|
||||||
|
fixture = _pytest.fixtures.fixture
|
||||||
|
yield_fixture = _pytest.fixtures.yield_fixture
|
||||||
|
except ImportError:
|
||||||
|
try:
|
||||||
|
import _pytest.python
|
||||||
|
fixture = _pytest.python.fixture
|
||||||
|
yield_fixture = _pytest.python.yield_fixture
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
register_module_extender(MANAGER, "pytest", pytest_transform)
|
||||||
|
register_module_extender(MANAGER, "py.test", pytest_transform)
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
# Copyright (c) 2015-2016, 2018 Claudiu Popa <pcmanticore@gmail.com>
|
||||||
|
# Copyright (c) 2016 Ceridwen <ceridwenv@gmail.com>
|
||||||
|
# Copyright (c) 2017 Roy Wright <roy@wright.org>
|
||||||
|
# Copyright (c) 2018 Ashley Whetter <ashley@awhetter.co.uk>
|
||||||
|
# Copyright (c) 2019 Antoine Boellinger <aboellinger@hotmail.com>
|
||||||
|
|
||||||
|
# Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
|
||||||
|
# For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
|
||||||
|
|
||||||
|
"""Astroid hooks for the PyQT library."""
|
||||||
|
|
||||||
|
from astroid import MANAGER, register_module_extender
|
||||||
|
from astroid.builder import AstroidBuilder
|
||||||
|
from astroid import nodes
|
||||||
|
from astroid import parse
|
||||||
|
|
||||||
|
|
||||||
|
def _looks_like_signal(node, signal_name="pyqtSignal"):
|
||||||
|
if "__class__" in node.instance_attrs:
|
||||||
|
try:
|
||||||
|
cls = node.instance_attrs["__class__"][0]
|
||||||
|
return cls.name == signal_name
|
||||||
|
except AttributeError:
|
||||||
|
# return False if the cls does not have a name attribute
|
||||||
|
pass
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def transform_pyqt_signal(node):
|
||||||
|
module = parse(
|
||||||
|
"""
|
||||||
|
class pyqtSignal(object):
|
||||||
|
def connect(self, slot, type=None, no_receiver_check=False):
|
||||||
|
pass
|
||||||
|
def disconnect(self, slot):
|
||||||
|
pass
|
||||||
|
def emit(self, *args):
|
||||||
|
pass
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
signal_cls = module["pyqtSignal"]
|
||||||
|
node.instance_attrs["emit"] = signal_cls["emit"]
|
||||||
|
node.instance_attrs["disconnect"] = signal_cls["disconnect"]
|
||||||
|
node.instance_attrs["connect"] = signal_cls["connect"]
|
||||||
|
|
||||||
|
|
||||||
|
def transform_pyside_signal(node):
|
||||||
|
module = parse(
|
||||||
|
"""
|
||||||
|
class NotPySideSignal(object):
|
||||||
|
def connect(self, receiver, type=None):
|
||||||
|
pass
|
||||||
|
def disconnect(self, receiver):
|
||||||
|
pass
|
||||||
|
def emit(self, *args):
|
||||||
|
pass
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
signal_cls = module["NotPySideSignal"]
|
||||||
|
node.instance_attrs["connect"] = signal_cls["connect"]
|
||||||
|
node.instance_attrs["disconnect"] = signal_cls["disconnect"]
|
||||||
|
node.instance_attrs["emit"] = signal_cls["emit"]
|
||||||
|
|
||||||
|
|
||||||
|
def pyqt4_qtcore_transform():
|
||||||
|
return AstroidBuilder(MANAGER).string_build(
|
||||||
|
"""
|
||||||
|
|
||||||
|
def SIGNAL(signal_name): pass
|
||||||
|
|
||||||
|
class QObject(object):
|
||||||
|
def emit(self, signal): pass
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
register_module_extender(MANAGER, "PyQt4.QtCore", pyqt4_qtcore_transform)
|
||||||
|
MANAGER.register_transform(nodes.FunctionDef, transform_pyqt_signal, _looks_like_signal)
|
||||||
|
MANAGER.register_transform(
|
||||||
|
nodes.ClassDef,
|
||||||
|
transform_pyside_signal,
|
||||||
|
lambda node: node.qname() in ("PySide.QtCore.Signal", "PySide2.QtCore.Signal"),
|
||||||
|
)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue